/[rdesktop]/sourceforge.net/trunk/rdesktop/xclip.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xclip.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 432 by matthewc, Tue Jul 1 09:31:25 2003 UTC revision 707 by forsberg, Fri Jun 4 08:42:11 2004 UTC
# Line 25  Line 25 
25    
26  #define NUM_TARGETS 6  #define NUM_TARGETS 6
27    
28  extern Display *display;  extern Display *g_display;
29  extern Window wnd;  extern Window g_wnd;
30  extern Time last_gesturetime;  extern Time g_last_gesturetime;
31    
32  static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;  static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;
33  static Atom rdesktop_clipboard_target_atom, rdesktop_clipboard_formats_atom, incr_atom;  static Atom rdesktop_clipboard_target_atom, rdesktop_clipboard_formats_atom, incr_atom;
# Line 36  static Atom targets[NUM_TARGETS]; Line 36  static Atom targets[NUM_TARGETS];
36  static int have_primary = 0;  static int have_primary = 0;
37  static int rdesktop_is_selection_owner = 0;  static int rdesktop_is_selection_owner = 0;
38    
39    
40    /* Replace CR-LF to LF (well, rather removing all CR:s) This is done
41       in-place. The length is updated. Handles embedded nulls */
42    static void
43    crlf2lf(uint8 * data, uint32 * length)
44    {
45            uint8 *dst, *src;
46            src = dst = data;
47            while (src < data + *length)
48            {
49                    if (*src != '\x0d')
50                            *dst++ = *src;
51                    src++;
52            }
53            *length = dst - data;
54    }
55    
56    /* Translate LF to CR-LF. To do this, we must allocate more memory.  
57       The length is updated. */
58    static uint8 *
59    lf2crlf(uint8 * data, uint32 * length)
60    {
61            uint8 *result, *p, *o;
62    
63            /* Worst case: Every char is LF */
64            result = xmalloc(*length * 2);
65    
66            p = data;
67            o = result;
68    
69            while (p < data + *length)
70            {
71                    if (*p == '\x0a')
72                            *o++ = '\x0d';
73                    *o++ = *p++;
74            }
75            *length = o - result;
76    
77            /* Convenience */
78            *o++ = '\0';
79    
80            return result;
81    }
82    
83    
84  static void  static void
85  xclip_provide_selection(XSelectionRequestEvent *req, Atom type, unsigned int format, uint8 *data, uint32 length)  xclip_provide_selection(XSelectionRequestEvent * req, Atom type, unsigned int format, uint8 * data,
86                            uint32 length)
87  {  {
88          XEvent xev;          XEvent xev;
89    
90          XChangeProperty(display, req->requestor, req->property,          XChangeProperty(g_display, req->requestor, req->property,
91                          type, format, PropModeReplace, data, length);                          type, format, PropModeReplace, data, length);
92    
93          xev.xselection.type = SelectionNotify;          xev.xselection.type = SelectionNotify;
# Line 52  xclip_provide_selection(XSelectionReques Line 98  xclip_provide_selection(XSelectionReques
98          xev.xselection.target = req->target;          xev.xselection.target = req->target;
99          xev.xselection.property = req->property;          xev.xselection.property = req->property;
100          xev.xselection.time = req->time;          xev.xselection.time = req->time;
101          XSendEvent(display, req->requestor, False, NoEventMask, &xev);          XSendEvent(g_display, req->requestor, False, NoEventMask, &xev);
102  }  }
103    
104  void  void
# Line 68  xclip_handle_SelectionNotify(XSelectionE Line 114  xclip_handle_SelectionNotify(XSelectionE
114                  goto fail;                  goto fail;
115    
116          DEBUG_CLIPBOARD(("xclip_handle_SelectionNotify: selection=%s, target=%s, property=%s\n",          DEBUG_CLIPBOARD(("xclip_handle_SelectionNotify: selection=%s, target=%s, property=%s\n",
117                           XGetAtomName(display, event->selection),                           XGetAtomName(g_display, event->selection),
118                           XGetAtomName(display, event->target),                           XGetAtomName(g_display, event->target),
119                           XGetAtomName(display, event->property)));                           XGetAtomName(g_display, event->property)));
120    
121          if (event->property == None)          if (event->property == None)
122                  goto fail;                  goto fail;
123    
124          res = XGetWindowProperty(display, wnd, rdesktop_clipboard_target_atom,          res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
125                                   0, XMaxRequestSize(display), True, AnyPropertyType,                                   0, XMaxRequestSize(g_display), True, AnyPropertyType,
126                                   &type, &format, &nitems, &bytes_left, &data);                                   &type, &format, &nitems, &bytes_left, &data);
127    
128          if (res != Success)          if (res != Success)
# Line 85  xclip_handle_SelectionNotify(XSelectionE Line 131  xclip_handle_SelectionNotify(XSelectionE
131                  goto fail;                  goto fail;
132          }          }
133    
134            /* Negotiate target format */
135          if (event->target == targets_atom)          if (event->target == targets_atom)
136          {          {
137                  /* FIXME: We should choose format here based on what the server wanted */                  /* FIXME: We should choose format here based on what the server wanted */
# Line 92  xclip_handle_SelectionNotify(XSelectionE Line 139  xclip_handle_SelectionNotify(XSelectionE
139                  if (type != None)                  if (type != None)
140                  {                  {
141                          supported_targets = (Atom *) data;                          supported_targets = (Atom *) data;
142                          text_target = XInternAtom(display, "TEXT", False);                          text_target = XInternAtom(g_display, "TEXT", False);
143                          for (i = 0; i < nitems; i++)                          for (i = 0; i < nitems; i++)
144                          {                          {
145                                  DEBUG_CLIPBOARD(("Target %d: %s\n", i, XGetAtomName(display, supported_targets[i])));                                  DEBUG_CLIPBOARD(("Target %d: %s\n", i,
146                                                     XGetAtomName(g_display, supported_targets[i])));
147                                  if (supported_targets[i] == text_target)                                  if (supported_targets[i] == text_target)
148                                  {                                  {
149                                          DEBUG_CLIPBOARD(("Other party supports TEXT, choosing that as best_target\n"));                                          DEBUG_CLIPBOARD(("Other party supports TEXT, choosing that as best_target\n"));
150                                          best_target = text_target;                                          best_target = text_target;
151                                            break;
152                                  }                                  }
153                          }                          }
154                          XFree(data);                          XFree(data);
155                  }                  }
156    
157                  XConvertSelection(display, primary_atom, best_target, rdesktop_clipboard_target_atom, wnd, event->time);                  XConvertSelection(g_display, primary_atom, best_target,
158                                      rdesktop_clipboard_target_atom, g_wnd, event->time);
159                  return;                  return;
160          }          }
161    
# Line 115  xclip_handle_SelectionNotify(XSelectionE Line 165  xclip_handle_SelectionNotify(XSelectionE
165                  goto fail;                  goto fail;
166          }          }
167    
168          cliprdr_send_data(data, nitems+1);          /* Translate linebreaks, but only if not getting data from
169               other rdesktop instance */
170            if (event->target != rdesktop_clipboard_formats_atom)
171            {
172                    uint8 *translated_data;
173                    uint32 length = nitems;
174    
175                    DEBUG_CLIPBOARD(("Translating linebreaks before sending data\n"));
176                    translated_data = lf2crlf(data, &length);
177                    cliprdr_send_data(translated_data, length + 1);
178                    xfree(translated_data); /* Not the same thing as XFree! */
179            }
180            else
181            {
182                    cliprdr_send_data(data, nitems + 1);
183            }
184          XFree(data);          XFree(data);
185    
186          if (!rdesktop_is_selection_owner)          if (!rdesktop_is_selection_owner)
187                  cliprdr_send_text_format_announce();                  cliprdr_send_text_format_announce();
188          return;          return;
189    
190  fail:        fail:
191          cliprdr_send_data(NULL, 0);          cliprdr_send_data(NULL, 0);
192  }  }
193    
194  void  void
195  xclip_handle_SelectionRequest(XSelectionRequestEvent *event)  xclip_handle_SelectionRequest(XSelectionRequestEvent * event)
196  {  {
197          unsigned long nitems, bytes_left;          unsigned long nitems, bytes_left;
198            unsigned char *prop_return;
199          uint32 *wanted_format;          uint32 *wanted_format;
200          int format, res;          int format, res;
201          Atom type;          Atom type;
202    
203          DEBUG_CLIPBOARD(("xclip_handle_SelectionRequest: selection=%s, target=%s, property=%s\n",          DEBUG_CLIPBOARD(("xclip_handle_SelectionRequest: selection=%s, target=%s, property=%s\n",
204                           XGetAtomName(display, event->selection),                           XGetAtomName(g_display, event->selection),
205                           XGetAtomName(display, event->target),                           XGetAtomName(g_display, event->target),
206                           XGetAtomName(display, event->property)));                           XGetAtomName(g_display, event->property)));
207    
208          if (event->target == targets_atom)          if (event->target == targets_atom)
209          {          {
210                  xclip_provide_selection(event, XA_ATOM, 32, (uint8 *)&targets, NUM_TARGETS);                  xclip_provide_selection(event, XA_ATOM, 32, (uint8 *) & targets, NUM_TARGETS);
211                  return;                  return;
212          }          }
213          else if (event->target == timestamp_atom)          else if (event->target == timestamp_atom)
214          {          {
215                  xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *)&last_gesturetime, 1);                  xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *) & g_last_gesturetime, 1);
216                  return;                  return;
217          }          }
218          else if (event->target == rdesktop_clipboard_formats_atom)          else if (event->target == rdesktop_clipboard_formats_atom)
219          {          {
220                  res = XGetWindowProperty(display, event->requestor,                  res = XGetWindowProperty(g_display, event->requestor,
221                                  rdesktop_clipboard_target_atom, 0, 1, True, XA_INTEGER,                                           rdesktop_clipboard_target_atom, 0, 1, True, XA_INTEGER,
222                                  &type, &format, &nitems, &bytes_left, (unsigned char **) &wanted_format);                                           &type, &format, &nitems, &bytes_left, &prop_return);
223                    wanted_format = (uint32 *) prop_return;
224                  format = (res == Success) ? *wanted_format : CF_TEXT;                  format = (res == Success) ? *wanted_format : CF_TEXT;
225                    /* FIXME: Need to free returned data? */
226          }          }
227          else          else
228          {          {
# Line 171  xclip_handle_SelectionClear(void) Line 239  xclip_handle_SelectionClear(void)
239  {  {
240          DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));          DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));
241          have_primary = 0;          have_primary = 0;
242          XDeleteProperty(display, DefaultRootWindow(display), rdesktop_clipboard_formats_atom);          XDeleteProperty(g_display, DefaultRootWindow(g_display), rdesktop_clipboard_formats_atom);
243          cliprdr_send_text_format_announce();          cliprdr_send_text_format_announce();
244  }  }
245    
246  void  void
247  xclip_handle_PropertyNotify(XPropertyEvent *event)  xclip_handle_PropertyNotify(XPropertyEvent * event)
248  {  {
249          unsigned long nitems, bytes_left;          unsigned long nitems, bytes_left;
250          int format, res;          int format, res;
# Line 186  xclip_handle_PropertyNotify(XPropertyEve Line 254  xclip_handle_PropertyNotify(XPropertyEve
254          if (event->atom != rdesktop_clipboard_formats_atom)          if (event->atom != rdesktop_clipboard_formats_atom)
255                  return;                  return;
256    
257          if (have_primary) /* from us */          if (have_primary)       /* from us */
258                  return;                  return;
259    
260          if (event->state == PropertyNewValue)          if (event->state == PropertyNewValue)
261          {          {
262                  res = XGetWindowProperty(display, DefaultRootWindow(display),                  res = XGetWindowProperty(g_display, DefaultRootWindow(g_display),
263                          rdesktop_clipboard_formats_atom, 0, XMaxRequestSize(display), False, XA_STRING,                                           rdesktop_clipboard_formats_atom, 0,
264                          &type, &format, &nitems, &bytes_left, &data);                                           XMaxRequestSize(g_display), False, XA_STRING, &type,
265                                             &format, &nitems, &bytes_left, &data);
266    
267                  if ((res == Success) && (nitems > 0))                  if ((res == Success) && (nitems > 0))
268                  {                  {
# Line 210  xclip_handle_PropertyNotify(XPropertyEve Line 279  xclip_handle_PropertyNotify(XPropertyEve
279    
280    
281  void  void
282  ui_clip_format_announce(char *data, uint32 length)  ui_clip_format_announce(uint8 * data, uint32 length)
283  {  {
284          XSetSelectionOwner(display, primary_atom, wnd, last_gesturetime);          XSetSelectionOwner(g_display, primary_atom, g_wnd, g_last_gesturetime);
285          if (XGetSelectionOwner(display, primary_atom) != wnd)          if (XGetSelectionOwner(g_display, primary_atom) != g_wnd)
286          {          {
287                  warning("Failed to aquire ownership of PRIMARY clipboard\n");                  warning("Failed to aquire ownership of PRIMARY clipboard\n");
288                  return;                  return;
289          }          }
290    
291          have_primary = 1;          have_primary = 1;
292          XChangeProperty(display, DefaultRootWindow(display),          XChangeProperty(g_display, DefaultRootWindow(g_display),
293                          rdesktop_clipboard_formats_atom, XA_STRING, 8, PropModeReplace, data, length);                          rdesktop_clipboard_formats_atom, XA_STRING, 8, PropModeReplace, data,
294                            length);
295    
296          XSetSelectionOwner(display, clipboard_atom, wnd, last_gesturetime);          XSetSelectionOwner(g_display, clipboard_atom, g_wnd, g_last_gesturetime);
297          if (XGetSelectionOwner(display, clipboard_atom) != wnd)          if (XGetSelectionOwner(g_display, clipboard_atom) != g_wnd)
298                  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");                  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
299  }  }
300    
301    
302  void  void
303  ui_clip_handle_data(char *data, uint32 length)  ui_clip_handle_data(uint8 * data, uint32 length)
304  {  {
305          xclip_provide_selection(&selection_request, XA_STRING, 8, data, length-1);          if (selection_request.target != rdesktop_clipboard_formats_atom)
306            {
307                    uint8 *firstnull;
308    
309                    /* translate linebreaks */
310                    crlf2lf(data, &length);
311    
312                    /* Only send data up to null byte, if any */
313                    firstnull = (uint8 *) strchr((char *) data, '\0');
314                    if (firstnull)
315                    {
316                            length = firstnull - data + 1;
317                    }
318            }
319    
320            xclip_provide_selection(&selection_request, XA_STRING, 8, data, length - 1);
321  }  }
322    
323  void  void
# Line 244  ui_clip_request_data(uint32 format) Line 329  ui_clip_request_data(uint32 format)
329    
330          if (rdesktop_is_selection_owner)          if (rdesktop_is_selection_owner)
331          {          {
332                  XChangeProperty(display, wnd, rdesktop_clipboard_target_atom,                  XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
333                                  XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);                                  XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);
334    
335                  XConvertSelection(display, primary_atom, rdesktop_clipboard_formats_atom,                  XConvertSelection(g_display, primary_atom, rdesktop_clipboard_formats_atom,
336                                          rdesktop_clipboard_target_atom, wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
337                  return;                  return;
338          }          }
339    
340          selectionowner = XGetSelectionOwner(display, primary_atom);          selectionowner = XGetSelectionOwner(g_display, primary_atom);
341          if (selectionowner != None)          if (selectionowner != None)
342          {          {
343                  XConvertSelection(display, primary_atom, targets_atom,                  XConvertSelection(g_display, primary_atom, targets_atom,
344                                          rdesktop_clipboard_target_atom, wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
345                  return;                  return;
346          }          }
347    
348          /* No PRIMARY, try CLIPBOARD */          /* No PRIMARY, try CLIPBOARD */
349          selectionowner = XGetSelectionOwner(display, clipboard_atom);          selectionowner = XGetSelectionOwner(g_display, clipboard_atom);
350          if (selectionowner != None)          if (selectionowner != None)
351          {          {
352                  XConvertSelection(display, clipboard_atom, targets_atom,                  XConvertSelection(g_display, clipboard_atom, targets_atom,
353                                          rdesktop_clipboard_target_atom, wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
354                  return;                  return;
355          }          }
356    
# Line 286  xclip_init(void) Line 371  xclip_init(void)
371          if (!cliprdr_init())          if (!cliprdr_init())
372                  return;                  return;
373    
374          primary_atom = XInternAtom(display, "PRIMARY", False);          primary_atom = XInternAtom(g_display, "PRIMARY", False);
375          clipboard_atom = XInternAtom(display, "CLIPBOARD", False);          clipboard_atom = XInternAtom(g_display, "CLIPBOARD", False);
376          targets_atom = XInternAtom(display, "TARGETS", False);          targets_atom = XInternAtom(g_display, "TARGETS", False);
377          timestamp_atom = XInternAtom(display, "TIMESTAMP", False);          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
378          rdesktop_clipboard_target_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_TARGET", False);          rdesktop_clipboard_target_atom =
379          incr_atom = XInternAtom(display, "INCR", False);                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
380            incr_atom = XInternAtom(g_display, "INCR", False);
381          targets[0] = targets_atom;          targets[0] = targets_atom;
382          targets[1] = XInternAtom(display, "TEXT", False);          targets[1] = XInternAtom(g_display, "TEXT", False);
383          targets[2] = XInternAtom(display, "UTF8_STRING", False);          targets[2] = XInternAtom(g_display, "STRING", False);
384          targets[3] = XInternAtom(display, "text/unicode", False);          targets[3] = XInternAtom(g_display, "text/unicode", False);
385          targets[4] = XInternAtom(display, "TIMESTAMP", False);          targets[4] = XInternAtom(g_display, "TIMESTAMP", False);
386          targets[5] = XA_STRING;          targets[5] = XA_STRING;
387    
388          /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.          /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.
389             Other interested rdesktops can use this to notify their server of the available formats. */             Other interested rdesktops can use this to notify their server of the available formats. */
390          rdesktop_clipboard_formats_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_FORMATS", False);          rdesktop_clipboard_formats_atom =
391          XSelectInput(display, DefaultRootWindow(display), PropertyChangeMask);                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
392            XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);
393  }  }

Legend:
Removed from v.432  
changed lines
  Added in v.707

  ViewVC Help
Powered by ViewVC 1.1.26