/[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 942 by astrand, Tue Aug 2 09:27:46 2005 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    static int g_waiting_for_INCR = 0;
40    static uint8 *g_clip_buffer = 0;
41    static uint32 g_clip_buflen = 0;
42    
43    /* Replace CR-LF to LF (well, rather removing all CR:s) This is done
44       in-place. The length is updated. Handles embedded nulls */
45    static void
46    crlf2lf(uint8 * data, uint32 * length)
47    {
48            uint8 *dst, *src;
49            src = dst = data;
50            while (src < data + *length)
51            {
52                    if (*src != '\x0d')
53                            *dst++ = *src;
54                    src++;
55            }
56            *length = dst - data;
57    }
58    
59    /* Translate LF to CR-LF. To do this, we must allocate more memory.  
60       The length is updated. */
61    static uint8 *
62    lf2crlf(uint8 * data, uint32 * length)
63    {
64            uint8 *result, *p, *o;
65    
66            /* Worst case: Every char is LF */
67            result = xmalloc(*length * 2);
68    
69            p = data;
70            o = result;
71    
72            while (p < data + *length)
73            {
74                    if (*p == '\x0a')
75                            *o++ = '\x0d';
76                    *o++ = *p++;
77            }
78            *length = o - result;
79    
80            /* Convenience */
81            *o++ = '\0';
82    
83            return result;
84    }
85    
86    
87  static void  static void
88  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,
89                            uint32 length)
90  {  {
91          XEvent xev;          XEvent xev;
92    
93          XChangeProperty(display, req->requestor, req->property,          XChangeProperty(g_display, req->requestor, req->property,
94                          type, format, PropModeReplace, data, length);                          type, format, PropModeReplace, data, length);
95    
96          xev.xselection.type = SelectionNotify;          xev.xselection.type = SelectionNotify;
# Line 52  xclip_provide_selection(XSelectionReques Line 101  xclip_provide_selection(XSelectionReques
101          xev.xselection.target = req->target;          xev.xselection.target = req->target;
102          xev.xselection.property = req->property;          xev.xselection.property = req->property;
103          xev.xselection.time = req->time;          xev.xselection.time = req->time;
104          XSendEvent(display, req->requestor, False, NoEventMask, &xev);          XSendEvent(g_display, req->requestor, False, NoEventMask, &xev);
105  }  }
106    
107    #ifndef MAKE_PROTO
108  void  void
109  xclip_handle_SelectionNotify(XSelectionEvent * event)  xclip_handle_SelectionNotify(XSelectionEvent * event)
110  {  {
111          unsigned long nitems, bytes_left;          unsigned long nitems, bytes_left;
112            XWindowAttributes wa;
113          Atom type, best_target, text_target;          Atom type, best_target, text_target;
114          Atom *supported_targets;          Atom *supported_targets;
115          int res, i, format;          int res, i, format;
# Line 68  xclip_handle_SelectionNotify(XSelectionE Line 119  xclip_handle_SelectionNotify(XSelectionE
119                  goto fail;                  goto fail;
120    
121          DEBUG_CLIPBOARD(("xclip_handle_SelectionNotify: selection=%s, target=%s, property=%s\n",          DEBUG_CLIPBOARD(("xclip_handle_SelectionNotify: selection=%s, target=%s, property=%s\n",
122                           XGetAtomName(display, event->selection),                           XGetAtomName(g_display, event->selection),
123                           XGetAtomName(display, event->target),                           XGetAtomName(g_display, event->target),
124                           XGetAtomName(display, event->property)));                           XGetAtomName(g_display, event->property)));
125    
126          if (event->property == None)          if (event->property == None)
127                  goto fail;                  goto fail;
128    
129          res = XGetWindowProperty(display, wnd, rdesktop_clipboard_target_atom,          res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
130                                   0, XMaxRequestSize(display), True, AnyPropertyType,                                   0, XMaxRequestSize(g_display), True, AnyPropertyType,
131                                   &type, &format, &nitems, &bytes_left, &data);                                   &type, &format, &nitems, &bytes_left, &data);
132    
133          if (res != Success)          if (res != Success)
# Line 85  xclip_handle_SelectionNotify(XSelectionE Line 136  xclip_handle_SelectionNotify(XSelectionE
136                  goto fail;                  goto fail;
137          }          }
138    
139            /* Negotiate target format */
140          if (event->target == targets_atom)          if (event->target == targets_atom)
141          {          {
142                  /* 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 144  xclip_handle_SelectionNotify(XSelectionE
144                  if (type != None)                  if (type != None)
145                  {                  {
146                          supported_targets = (Atom *) data;                          supported_targets = (Atom *) data;
147                          text_target = XInternAtom(display, "TEXT", False);                          text_target = XInternAtom(g_display, "TEXT", False);
148                          for (i = 0; i < nitems; i++)                          for (i = 0; i < nitems; i++)
149                          {                          {
150                                  DEBUG_CLIPBOARD(("Target %d: %s\n", i, XGetAtomName(display, supported_targets[i])));                                  DEBUG_CLIPBOARD(("Target %d: %s\n", i,
151                                                     XGetAtomName(g_display, supported_targets[i])));
152                                  if (supported_targets[i] == text_target)                                  if (supported_targets[i] == text_target)
153                                  {                                  {
154                                          DEBUG_CLIPBOARD(("Other party supports TEXT, choosing that as best_target\n"));                                          DEBUG_CLIPBOARD(("Other party supports TEXT, choosing that as best_target\n"));
155                                          best_target = text_target;                                          best_target = text_target;
156                                            break;
157                                  }                                  }
158                          }                          }
159                          XFree(data);                          XFree(data);
160                  }                  }
161    
162                  XConvertSelection(display, primary_atom, best_target, rdesktop_clipboard_target_atom, wnd, event->time);                  XConvertSelection(g_display, primary_atom, best_target,
163                                      rdesktop_clipboard_target_atom, g_wnd, event->time);
164                  return;                  return;
165          }          }
166    
167          if (type == incr_atom)          if (type == incr_atom)
168          {          {
169                  warning("We don't support INCR transfers at this time. Try cutting less data.\n");                  DEBUG_CLIPBOARD(("Received INCR.\n"));
170                  goto fail;  
171                    XGetWindowAttributes(g_display, g_wnd, &wa);
172                    if ((wa.your_event_mask | PropertyChangeMask) != wa.your_event_mask)
173                    {
174                            XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask));
175                    }
176                    XDeleteProperty(g_display, g_wnd, type);
177                    XFree(data);
178                    g_waiting_for_INCR = 1;
179    
180                    if ((XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, 0,
181                                            4096L, True, AnyPropertyType,
182                                            &type, &format, &nitems, &bytes_left, &data) != Success))
183                    {
184                            DEBUG_CLIPBOARD(("XGetWindowProperty failed.\n"));
185                            goto fail;
186                    }
187                    else
188                    {
189                            uint8 *translated_data;
190                            uint32 length = nitems;
191    
192                            translated_data = lf2crlf(data, &length);
193    
194                            g_clip_buffer = (uint8 *) xmalloc(length);
195                            strncpy((char *) g_clip_buffer, (char *) translated_data, length);
196                            xfree(translated_data);
197                            g_clip_buflen = length;
198    
199                            XFree(data);
200                            return;
201                    }
202          }          }
203    
204          cliprdr_send_data(data, nitems+1);          /* Translate linebreaks, but only if not getting data from
205               other rdesktop instance */
206            if (event->target != rdesktop_clipboard_formats_atom)
207            {
208                    uint8 *translated_data;
209                    uint32 length = nitems;
210    
211                    DEBUG_CLIPBOARD(("Translating linebreaks before sending data\n"));
212                    translated_data = lf2crlf(data, &length);
213                    cliprdr_send_data(translated_data, length + 1);
214                    xfree(translated_data); /* Not the same thing as XFree! */
215            }
216            else
217            {
218                    cliprdr_send_data(data, nitems + 1);
219            }
220          XFree(data);          XFree(data);
221    
222          if (!rdesktop_is_selection_owner)          if (!rdesktop_is_selection_owner)
223                  cliprdr_send_text_format_announce();                  cliprdr_send_text_format_announce();
224          return;          return;
225    
226  fail:        fail:
227          cliprdr_send_data(NULL, 0);          cliprdr_send_data(NULL, 0);
228  }  }
229    
230  void  void
231  xclip_handle_SelectionRequest(XSelectionRequestEvent *event)  xclip_handle_SelectionRequest(XSelectionRequestEvent * event)
232  {  {
233          unsigned long nitems, bytes_left;          unsigned long nitems, bytes_left;
234            unsigned char *prop_return;
235          uint32 *wanted_format;          uint32 *wanted_format;
236          int format, res;          int format, res;
237          Atom type;          Atom type;
238    
239          DEBUG_CLIPBOARD(("xclip_handle_SelectionRequest: selection=%s, target=%s, property=%s\n",          DEBUG_CLIPBOARD(("xclip_handle_SelectionRequest: selection=%s, target=%s, property=%s\n",
240                           XGetAtomName(display, event->selection),                           XGetAtomName(g_display, event->selection),
241                           XGetAtomName(display, event->target),                           XGetAtomName(g_display, event->target),
242                           XGetAtomName(display, event->property)));                           XGetAtomName(g_display, event->property)));
243    
244          if (event->target == targets_atom)          if (event->target == targets_atom)
245          {          {
246                  xclip_provide_selection(event, XA_ATOM, 32, (uint8 *)&targets, NUM_TARGETS);                  xclip_provide_selection(event, XA_ATOM, 32, (uint8 *) & targets, NUM_TARGETS);
247                  return;                  return;
248          }          }
249          else if (event->target == timestamp_atom)          else if (event->target == timestamp_atom)
250          {          {
251                  xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *)&last_gesturetime, 1);                  xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *) & g_last_gesturetime, 1);
252                  return;                  return;
253          }          }
254          else if (event->target == rdesktop_clipboard_formats_atom)          else if (event->target == rdesktop_clipboard_formats_atom)
255          {          {
256                  res = XGetWindowProperty(display, event->requestor,                  res = XGetWindowProperty(g_display, event->requestor,
257                                  rdesktop_clipboard_target_atom, 0, 1, True, XA_INTEGER,                                           rdesktop_clipboard_target_atom, 0, 1, True, XA_INTEGER,
258                                  &type, &format, &nitems, &bytes_left, (unsigned char **) &wanted_format);                                           &type, &format, &nitems, &bytes_left, &prop_return);
259                    wanted_format = (uint32 *) prop_return;
260                  format = (res == Success) ? *wanted_format : CF_TEXT;                  format = (res == Success) ? *wanted_format : CF_TEXT;
261                    /* FIXME: Need to free returned data? */
262          }          }
263          else          else
264          {          {
# Line 171  xclip_handle_SelectionClear(void) Line 275  xclip_handle_SelectionClear(void)
275  {  {
276          DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));          DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));
277          have_primary = 0;          have_primary = 0;
278          XDeleteProperty(display, DefaultRootWindow(display), rdesktop_clipboard_formats_atom);          XDeleteProperty(g_display, DefaultRootWindow(g_display), rdesktop_clipboard_formats_atom);
279          cliprdr_send_text_format_announce();          cliprdr_send_text_format_announce();
280  }  }
281    
282  void  void
283  xclip_handle_PropertyNotify(XPropertyEvent *event)  xclip_handle_PropertyNotify(XPropertyEvent * event)
284  {  {
285          unsigned long nitems, bytes_left;          unsigned long nitems, bytes_left;
286          int format, res;          int format, res;
287            XWindowAttributes wa;
288          uint8 *data;          uint8 *data;
289          Atom type;          Atom type;
290    
291            if (event->state == PropertyNewValue && g_waiting_for_INCR)
292            {
293                    DEBUG_CLIPBOARD(("x_clip_handle_PropertyNotify: g_waiting_for_INCR != 0\n"));
294                    if ((XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, 0,
295                                            4096L, True, AnyPropertyType,
296                                            &type, &format, &nitems, &bytes_left, &data) != Success))
297                    {
298                            XFree(data);
299                            return;
300                    }
301    
302                    if (nitems == 0)
303                    {
304                            XGetWindowAttributes(g_display, g_wnd, &wa);
305                            XSelectInput(g_display, g_wnd, (wa.your_event_mask ^ PropertyChangeMask));
306                            XFree(data);
307                            g_waiting_for_INCR = 0;
308    
309                            if (g_clip_buflen > 0)
310                            {
311                                    cliprdr_send_data(g_clip_buffer, g_clip_buflen + 1);
312    
313                                    if (!rdesktop_is_selection_owner)
314                                            cliprdr_send_text_format_announce();
315    
316                                    xfree(g_clip_buffer);
317                                    g_clip_buffer = 0;
318                                    g_clip_buflen = 0;
319                            }
320                    }
321                    else
322                    {
323                            uint8 *translated_data;
324                            uint32 length = nitems;
325                            uint8 *tmp;
326    
327                            DEBUG_CLIPBOARD(("Translating linebreaks before sending data\n"));
328                            translated_data = lf2crlf(data, &length);
329    
330                            tmp = xmalloc(length + g_clip_buflen);
331                            strncpy((char *) tmp, (char *) g_clip_buffer, g_clip_buflen);
332                            xfree(g_clip_buffer);
333    
334                            strncpy((char *) (tmp + g_clip_buflen), (char *) translated_data, length);
335                            xfree(translated_data);
336    
337                            g_clip_buffer = tmp;
338                            g_clip_buflen += length;
339    
340                            XFree(data);
341                            return;
342                    }
343            }
344    
345          if (event->atom != rdesktop_clipboard_formats_atom)          if (event->atom != rdesktop_clipboard_formats_atom)
346                  return;                  return;
347    
348          if (have_primary) /* from us */          if (have_primary)       /* from us */
349                  return;                  return;
350    
351          if (event->state == PropertyNewValue)          if (event->state == PropertyNewValue)
352          {          {
353                  res = XGetWindowProperty(display, DefaultRootWindow(display),                  res = XGetWindowProperty(g_display, DefaultRootWindow(g_display),
354                          rdesktop_clipboard_formats_atom, 0, XMaxRequestSize(display), False, XA_STRING,                                           rdesktop_clipboard_formats_atom, 0,
355                          &type, &format, &nitems, &bytes_left, &data);                                           XMaxRequestSize(g_display), False, XA_STRING, &type,
356                                             &format, &nitems, &bytes_left, &data);
357    
358                  if ((res == Success) && (nitems > 0))                  if ((res == Success) && (nitems > 0))
359                  {                  {
# Line 207  xclip_handle_PropertyNotify(XPropertyEve Line 367  xclip_handle_PropertyNotify(XPropertyEve
367          cliprdr_send_text_format_announce();          cliprdr_send_text_format_announce();
368          rdesktop_is_selection_owner = 0;          rdesktop_is_selection_owner = 0;
369  }  }
370    #endif
371    
372    
373  void  void
374  ui_clip_format_announce(char *data, uint32 length)  ui_clip_format_announce(uint8 * data, uint32 length)
375  {  {
376          XSetSelectionOwner(display, primary_atom, wnd, last_gesturetime);          XSetSelectionOwner(g_display, primary_atom, g_wnd, g_last_gesturetime);
377          if (XGetSelectionOwner(display, primary_atom) != wnd)          if (XGetSelectionOwner(g_display, primary_atom) != g_wnd)
378          {          {
379                  warning("Failed to aquire ownership of PRIMARY clipboard\n");                  warning("Failed to aquire ownership of PRIMARY clipboard\n");
380                  return;                  return;
381          }          }
382    
383          have_primary = 1;          have_primary = 1;
384          XChangeProperty(display, DefaultRootWindow(display),          XChangeProperty(g_display, DefaultRootWindow(g_display),
385                          rdesktop_clipboard_formats_atom, XA_STRING, 8, PropModeReplace, data, length);                          rdesktop_clipboard_formats_atom, XA_STRING, 8, PropModeReplace, data,
386                            length);
387    
388          XSetSelectionOwner(display, clipboard_atom, wnd, last_gesturetime);          XSetSelectionOwner(g_display, clipboard_atom, g_wnd, g_last_gesturetime);
389          if (XGetSelectionOwner(display, clipboard_atom) != wnd)          if (XGetSelectionOwner(g_display, clipboard_atom) != g_wnd)
390                  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");                  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
391  }  }
392    
393    
394  void  void
395  ui_clip_handle_data(char *data, uint32 length)  ui_clip_handle_data(uint8 * data, uint32 length)
396  {  {
397          xclip_provide_selection(&selection_request, XA_STRING, 8, data, length-1);          if (selection_request.target != rdesktop_clipboard_formats_atom)
398            {
399                    uint8 *firstnull;
400    
401                    /* translate linebreaks */
402                    crlf2lf(data, &length);
403    
404                    /* Only send data up to null byte, if any */
405                    firstnull = (uint8 *) strchr((char *) data, '\0');
406                    if (firstnull)
407                    {
408                            length = firstnull - data + 1;
409                    }
410            }
411    
412            xclip_provide_selection(&selection_request, XA_STRING, 8, data, length - 1);
413  }  }
414    
415  void  void
# Line 244  ui_clip_request_data(uint32 format) Line 421  ui_clip_request_data(uint32 format)
421    
422          if (rdesktop_is_selection_owner)          if (rdesktop_is_selection_owner)
423          {          {
424                  XChangeProperty(display, wnd, rdesktop_clipboard_target_atom,                  XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
425                                  XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);                                  XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);
426    
427                  XConvertSelection(display, primary_atom, rdesktop_clipboard_formats_atom,                  XConvertSelection(g_display, primary_atom, rdesktop_clipboard_formats_atom,
428                                          rdesktop_clipboard_target_atom, wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
429                  return;                  return;
430          }          }
431    
432          selectionowner = XGetSelectionOwner(display, primary_atom);          selectionowner = XGetSelectionOwner(g_display, primary_atom);
433          if (selectionowner != None)          if (selectionowner != None)
434          {          {
435                  XConvertSelection(display, primary_atom, targets_atom,                  XConvertSelection(g_display, primary_atom, targets_atom,
436                                          rdesktop_clipboard_target_atom, wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
437                  return;                  return;
438          }          }
439    
440          /* No PRIMARY, try CLIPBOARD */          /* No PRIMARY, try CLIPBOARD */
441          selectionowner = XGetSelectionOwner(display, clipboard_atom);          selectionowner = XGetSelectionOwner(g_display, clipboard_atom);
442          if (selectionowner != None)          if (selectionowner != None)
443          {          {
444                  XConvertSelection(display, clipboard_atom, targets_atom,                  XConvertSelection(g_display, clipboard_atom, targets_atom,
445                                          rdesktop_clipboard_target_atom, wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
446                  return;                  return;
447          }          }
448    
# Line 286  xclip_init(void) Line 463  xclip_init(void)
463          if (!cliprdr_init())          if (!cliprdr_init())
464                  return;                  return;
465    
466          primary_atom = XInternAtom(display, "PRIMARY", False);          primary_atom = XInternAtom(g_display, "PRIMARY", False);
467          clipboard_atom = XInternAtom(display, "CLIPBOARD", False);          clipboard_atom = XInternAtom(g_display, "CLIPBOARD", False);
468          targets_atom = XInternAtom(display, "TARGETS", False);          targets_atom = XInternAtom(g_display, "TARGETS", False);
469          timestamp_atom = XInternAtom(display, "TIMESTAMP", False);          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
470          rdesktop_clipboard_target_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_TARGET", False);          rdesktop_clipboard_target_atom =
471          incr_atom = XInternAtom(display, "INCR", False);                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
472            incr_atom = XInternAtom(g_display, "INCR", False);
473          targets[0] = targets_atom;          targets[0] = targets_atom;
474          targets[1] = XInternAtom(display, "TEXT", False);          targets[1] = XInternAtom(g_display, "TEXT", False);
475          targets[2] = XInternAtom(display, "UTF8_STRING", False);          targets[2] = XInternAtom(g_display, "STRING", False);
476          targets[3] = XInternAtom(display, "text/unicode", False);          targets[3] = XInternAtom(g_display, "text/unicode", False);
477          targets[4] = XInternAtom(display, "TIMESTAMP", False);          targets[4] = XInternAtom(g_display, "TIMESTAMP", False);
478          targets[5] = XA_STRING;          targets[5] = XA_STRING;
479    
480          /* 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.
481             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. */
482          rdesktop_clipboard_formats_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_FORMATS", False);          rdesktop_clipboard_formats_atom =
483          XSelectInput(display, DefaultRootWindow(display), PropertyChangeMask);                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
484            XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);
485  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26