/[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 1037 by forsberg, Mon Jan 2 15:55:59 2006 UTC revision 1207 by ossman_, Mon Mar 27 09:20:24 2006 UTC
# Line 53  Line 53 
53  extern Display *g_display;  extern Display *g_display;
54  extern Window g_wnd;  extern Window g_wnd;
55  extern Time g_last_gesturetime;  extern Time g_last_gesturetime;
56    extern BOOL g_rdpclip;
57    
58    /* Mode of operation.
59       - Auto: Look at both PRIMARY and CLIPBOARD and use the most recent.
60       - Non-auto: Look at just CLIPBOARD. */
61    static BOOL auto_mode = True;
62  /* Atoms of the two X selections we're dealing with: CLIPBOARD (explicit-copy) and PRIMARY (selection-copy) */  /* Atoms of the two X selections we're dealing with: CLIPBOARD (explicit-copy) and PRIMARY (selection-copy) */
63  static Atom clipboard_atom, primary_atom;  static Atom clipboard_atom, primary_atom;
64  /* Atom of the TARGETS clipboard target */  /* Atom of the TARGETS clipboard target */
# Line 69  static Atom timestamp_atom; Line 74  static Atom timestamp_atom;
74       before requesting clipboard data from a fellow rdesktop using       before requesting clipboard data from a fellow rdesktop using
75       the _RDESKTOP_CLIPBOARD_FORMATS target. */       the _RDESKTOP_CLIPBOARD_FORMATS target. */
76  static Atom rdesktop_clipboard_target_atom;  static Atom rdesktop_clipboard_target_atom;
77    /* Atoms _RDESKTOP_PRIMARY_TIMESTAMP_TARGET and _RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET
78       are used to store the timestamps for when a window got ownership of the selections.
79       We use these to determine which is more recent and should be used. */
80    static Atom rdesktop_primary_timestamp_target_atom, rdesktop_clipboard_timestamp_target_atom;
81    /* Storage for timestamps since we get them in two separate notifications. */
82    static Time primary_timestamp, clipboard_timestamp;
83  /* Atom _RDESKTOP_CLIPBOARD_FORMATS which has multiple uses:  /* Atom _RDESKTOP_CLIPBOARD_FORMATS which has multiple uses:
84     - The clipboard target (X jargon for "clipboard format") for rdesktop-to-rdesktop interchange     - The clipboard target (X jargon for "clipboard format") for rdesktop-to-rdesktop interchange
85       of Windows native clipboard data.       of Windows native clipboard data.
# Line 146  utf16_lf2crlf(uint8 * data, uint32 * siz Line 157  utf16_lf2crlf(uint8 * data, uint32 * siz
157          if (result == NULL)          if (result == NULL)
158                  return NULL;                  return NULL;
159    
160          inptr = (uint16*)data;          inptr = (uint16 *) data;
161          outptr = (uint16*)result;          outptr = (uint16 *) result;
162    
163          /* Check for a reversed BOM */          /* Check for a reversed BOM */
164          Bool swap_endianess = (*inptr == 0xfffe);          Bool swap_endianess = (*inptr == 0xfffe);
165    
166          while ((uint8*)inptr < data + *size)          while ((uint8 *) inptr < data + *size)
167          {          {
168                  uint16 uvalue = *inptr;                  uint16 uvalue = *inptr;
169                  if (swap_endianess)                  if (swap_endianess)
# Line 161  utf16_lf2crlf(uint8 * data, uint32 * siz Line 172  utf16_lf2crlf(uint8 * data, uint32 * siz
172                          *outptr++ = swap_endianess ? 0x0d00 : 0x0d;                          *outptr++ = swap_endianess ? 0x0d00 : 0x0d;
173                  *outptr++ = *inptr++;                  *outptr++ = *inptr++;
174          }          }
175          *outptr++ = 0; /* null termination */          *outptr++ = 0;          /* null termination */
176          *size = (uint8*)outptr - result;          *size = (uint8 *) outptr - result;
177    
178          return result;          return result;
179  }  }
# Line 260  helper_cliprdr_send_empty_response() Line 271  helper_cliprdr_send_empty_response()
271     to the expected RDP format as necessary. Returns true if data was sent.     to the expected RDP format as necessary. Returns true if data was sent.
272   */   */
273  static Bool  static Bool
274  xclip_send_data_with_convert(uint8* source, size_t source_size, Atom target)  xclip_send_data_with_convert(uint8 * source, size_t source_size, Atom target)
275  {  {
276          #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
277          if (target == format_string_atom ||          if (target == format_string_atom ||
278              target == format_unicode_atom ||              target == format_unicode_atom || target == format_utf8_string_atom)
             target == format_utf8_string_atom)  
279          {          {
280                  if (rdp_clipboard_request_format != RDP_CF_TEXT)                  if (rdp_clipboard_request_format != RDP_CF_TEXT)
281                          return False;                          return False;
# Line 276  xclip_send_data_with_convert(uint8* sour Line 286  xclip_send_data_with_convert(uint8* sour
286                     WinNT versions are Unicode-minded).                     WinNT versions are Unicode-minded).
287                   */                   */
288                  size_t unicode_buffer_size;                  size_t unicode_buffer_size;
289                  char* unicode_buffer;                  char *unicode_buffer;
290                  iconv_t cd;                  iconv_t cd;
291    
292                  if (target == format_string_atom)                  if (target == format_string_atom)
293                  {                  {
294                          char* locale_charset = nl_langinfo(CODESET);                          char *locale_charset = nl_langinfo(CODESET);
295                          cd = iconv_open(WINDOWS_CODEPAGE, locale_charset);                          cd = iconv_open(WINDOWS_CODEPAGE, locale_charset);
296                          if (cd == (iconv_t)-1)                          if (cd == (iconv_t) - 1)
297                          {                          {
298                                  DEBUG_CLIPBOARD(("Locale charset %s not found in iconv. Unable to convert clipboard text.\n", locale_charset));                                  DEBUG_CLIPBOARD(("Locale charset %s not found in iconv. Unable to convert clipboard text.\n", locale_charset));
299                                  return False;                                  return False;
# Line 293  xclip_send_data_with_convert(uint8* sour Line 303  xclip_send_data_with_convert(uint8* sour
303                  else if (target == format_unicode_atom)                  else if (target == format_unicode_atom)
304                  {                  {
305                          cd = iconv_open(WINDOWS_CODEPAGE, "UCS-2");                          cd = iconv_open(WINDOWS_CODEPAGE, "UCS-2");
306                          if (cd == (iconv_t)-1)                          if (cd == (iconv_t) - 1)
307                          {                          {
308                                  return False;                                  return False;
309                          }                          }
# Line 302  xclip_send_data_with_convert(uint8* sour Line 312  xclip_send_data_with_convert(uint8* sour
312                  else if (target == format_utf8_string_atom)                  else if (target == format_utf8_string_atom)
313                  {                  {
314                          cd = iconv_open(WINDOWS_CODEPAGE, "UTF-8");                          cd = iconv_open(WINDOWS_CODEPAGE, "UTF-8");
315                          if (cd == (iconv_t)-1)                          if (cd == (iconv_t) - 1)
316                          {                          {
317                                  return False;                                  return False;
318                          }                          }
# Line 318  xclip_send_data_with_convert(uint8* sour Line 328  xclip_send_data_with_convert(uint8* sour
328    
329                  unicode_buffer = xmalloc(unicode_buffer_size);                  unicode_buffer = xmalloc(unicode_buffer_size);
330                  size_t unicode_buffer_size_remaining = unicode_buffer_size;                  size_t unicode_buffer_size_remaining = unicode_buffer_size;
331                  char* unicode_buffer_remaining = unicode_buffer;                  char *unicode_buffer_remaining = unicode_buffer;
332                  char* data_remaining = (char*)source;                  char *data_remaining = (char *) source;
333                  size_t data_size_remaining = source_size;                  size_t data_size_remaining = source_size;
334                  iconv(cd, &data_remaining, &data_size_remaining, &unicode_buffer_remaining, &unicode_buffer_size_remaining);                  iconv(cd, (ICONV_CONST char **) &data_remaining, &data_size_remaining,
335                          &unicode_buffer_remaining, &unicode_buffer_size_remaining);
336                  iconv_close(cd);                  iconv_close(cd);
337    
338                  /* translate linebreaks */                  /* translate linebreaks */
339                  uint32 translated_data_size = unicode_buffer_size - unicode_buffer_size_remaining;                  uint32 translated_data_size = unicode_buffer_size - unicode_buffer_size_remaining;
340                  uint8* translated_data = utf16_lf2crlf((uint8*)unicode_buffer, &translated_data_size);                  uint8 *translated_data =
341                            utf16_lf2crlf((uint8 *) unicode_buffer, &translated_data_size);
342                  if (translated_data != NULL)                  if (translated_data != NULL)
343                  {                  {
344                          DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n", translated_data_size));                          DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n",
345                          cliprdr_send_data(translated_data, translated_data_size);                                           translated_data_size));
346                            helper_cliprdr_send_response(translated_data, translated_data_size);
347                          xfree(translated_data); /* Not the same thing as XFree! */                          xfree(translated_data); /* Not the same thing as XFree! */
348                  }                  }
349    
# Line 338  xclip_send_data_with_convert(uint8* sour Line 351  xclip_send_data_with_convert(uint8* sour
351    
352                  return True;                  return True;
353          }          }
354          #else  #else
355          if (target == format_string_atom)          if (target == format_string_atom)
356          {          {
357                  uint8 *translated_data;                  uint8 *translated_data;
# Line 351  xclip_send_data_with_convert(uint8* sour Line 364  xclip_send_data_with_convert(uint8* sour
364                  translated_data = lf2crlf(source, &length);                  translated_data = lf2crlf(source, &length);
365                  if (translated_data != NULL)                  if (translated_data != NULL)
366                  {                  {
367                          cliprdr_send_data(translated_data, length);                          helper_cliprdr_send_response(translated_data, length);
368                          xfree(translated_data); /* Not the same thing as XFree! */                          xfree(translated_data); /* Not the same thing as XFree! */
369                  }                  }
370    
371                  return True;                  return True;
372          }          }
373          #endif  #endif
374          else if (target == rdesktop_clipboard_formats_atom)          else if (target == rdesktop_clipboard_formats_atom)
375          {          {
376                  helper_cliprdr_send_response(source, source_size + 1);                  helper_cliprdr_send_response(source, source_size + 1);
# Line 370  xclip_send_data_with_convert(uint8* sour Line 383  xclip_send_data_with_convert(uint8* sour
383          }          }
384  }  }
385    
386    static void
387    xclip_clear_target_props()
388    {
389            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);
390            XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom);
391            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom);
392    }
393    
394  /* This function is called for SelectionNotify events.  /* This function is called for SelectionNotify events.
395     The SelectionNotify event is sent from the clipboard owner to the requestor     The SelectionNotify event is sent from the clipboard owner to the requestor
396     after his request was satisfied.     after his request was satisfied.
# Line 383  xclip_handle_SelectionNotify(XSelectionE Line 404  xclip_handle_SelectionNotify(XSelectionE
404          Atom type;          Atom type;
405          Atom *supported_targets;          Atom *supported_targets;
406          int res, i, format;          int res, i, format;
407          uint8 *data;          uint8 *data = NULL;
408    
409          if (event->property == None)          if (event->property == None)
410                  goto fail;                  goto fail;
# Line 393  xclip_handle_SelectionNotify(XSelectionE Line 414  xclip_handle_SelectionNotify(XSelectionE
414                           XGetAtomName(g_display, event->target),                           XGetAtomName(g_display, event->target),
415                           XGetAtomName(g_display, event->property)));                           XGetAtomName(g_display, event->property)));
416    
417          if (event->property == None)          if (event->target == timestamp_atom)
418                  goto fail;          {
419                    if (event->selection == primary_atom)
420                    {
421                            res = XGetWindowProperty(g_display, g_wnd,
422                                                     rdesktop_primary_timestamp_target_atom, 0,
423                                                     XMaxRequestSize(g_display), False, XA_INTEGER,
424                                                     &type, &format, &nitems, &bytes_left, &data);
425                    }
426                    else
427                    {
428                            res = XGetWindowProperty(g_display, g_wnd,
429                                                     rdesktop_clipboard_timestamp_target_atom, 0,
430                                                     XMaxRequestSize(g_display), False, XA_INTEGER,
431                                                     &type, &format, &nitems, &bytes_left, &data);
432                    }
433    
434    
435                    if ((res != Success) || (nitems != 1))
436                    {
437                            DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
438                            goto fail;
439                    }
440    
441                    if (event->selection == primary_atom)
442                    {
443                            primary_timestamp = *(Time *) data;
444                            if (primary_timestamp == 0)
445                                    primary_timestamp++;
446                            XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom);
447                            DEBUG_CLIPBOARD(("Got PRIMARY timestamp: %u\n",
448                                             (unsigned) primary_timestamp));
449                    }
450                    else
451                    {
452                            clipboard_timestamp = *(Time *) data;
453                            if (clipboard_timestamp == 0)
454                                    clipboard_timestamp++;
455                            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom);
456                            DEBUG_CLIPBOARD(("Got CLIPBOARD timestamp: %u\n",
457                                             (unsigned) clipboard_timestamp));
458                    }
459    
460                    XFree(data);
461    
462                    if (primary_timestamp && clipboard_timestamp)
463                    {
464                            if (primary_timestamp > clipboard_timestamp)
465                            {
466                                    DEBUG_CLIPBOARD(("PRIMARY is most recent selection.\n"));
467                                    XConvertSelection(g_display, primary_atom, targets_atom,
468                                                      rdesktop_clipboard_target_atom, g_wnd,
469                                                      event->time);
470                            }
471                            else
472                            {
473                                    DEBUG_CLIPBOARD(("CLIPBOARD is most recent selection.\n"));
474                                    XConvertSelection(g_display, clipboard_atom, targets_atom,
475                                                      rdesktop_clipboard_target_atom, g_wnd,
476                                                      event->time);
477                            }
478                    }
479    
480                    return;
481            }
482    
483          res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,          res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
484                                   0, XMaxRequestSize(g_display), False, AnyPropertyType,                                   0, XMaxRequestSize(g_display), False, AnyPropertyType,
485                                   &type, &format, &nitems, &bytes_left, &data);                                   &type, &format, &nitems, &bytes_left, &data);
486    
487            xclip_clear_target_props();
488    
489          if (res != Success)          if (res != Success)
490          {          {
491                  DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));                  DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
# Line 415  xclip_handle_SelectionNotify(XSelectionE Line 501  xclip_handle_SelectionNotify(XSelectionE
501                  {                  {
502                          XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask));                          XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask));
503                  }                  }
                 XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);  
504                  XFree(data);                  XFree(data);
505                  g_incr_target = event->target;                  g_incr_target = event->target;
506                  g_waiting_for_INCR = 1;                  g_waiting_for_INCR = 1;
507                  return;                  return;
508          }          }
509    
         XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);  
   
510          /* Negotiate target format */          /* Negotiate target format */
511          if (event->target == targets_atom)          if (event->target == targets_atom)
512          {          {
# Line 432  xclip_handle_SelectionNotify(XSelectionE Line 515  xclip_handle_SelectionNotify(XSelectionE
515                     (ignore TEXT and COMPOUND_TEXT because we don't have code to handle them)                     (ignore TEXT and COMPOUND_TEXT because we don't have code to handle them)
516                   */                   */
517                  int text_target_satisfaction = 0;                  int text_target_satisfaction = 0;
518                  Atom best_text_target = 0; /* measures how much we're satisfied with what we found */                  Atom best_text_target = 0;      /* measures how much we're satisfied with what we found */
519                  if (type != None)                  if (type != None)
520                  {                  {
521                          supported_targets = (Atom *) data;                          supported_targets = (Atom *) data;
# Line 449  xclip_handle_SelectionNotify(XSelectionE Line 532  xclip_handle_SelectionNotify(XSelectionE
532                                                  text_target_satisfaction = 1;                                                  text_target_satisfaction = 1;
533                                          }                                          }
534                                  }                                  }
535                                  #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
536                                  else if (supported_targets[i] == format_unicode_atom)                                  else if (supported_targets[i] == format_unicode_atom)
537                                  {                                  {
538                                          if (text_target_satisfaction < 2)                                          if (text_target_satisfaction < 2)
# Line 468  xclip_handle_SelectionNotify(XSelectionE Line 551  xclip_handle_SelectionNotify(XSelectionE
551                                                  text_target_satisfaction = 3;                                                  text_target_satisfaction = 3;
552                                          }                                          }
553                                  }                                  }
554                                  #endif  #endif
555                          }                          }
556                  }                  }
557    
# Line 477  xclip_handle_SelectionNotify(XSelectionE Line 560  xclip_handle_SelectionNotify(XSelectionE
560                   */                   */
561                  if (best_text_target != 0)                  if (best_text_target != 0)
562                  {                  {
563                          XConvertSelection(g_display, clipboard_atom, best_text_target, rdesktop_clipboard_target_atom, g_wnd, event->time);                          XConvertSelection(g_display, event->selection, best_text_target,
564                                              rdesktop_clipboard_target_atom, g_wnd, event->time);
565                          return;                          return;
566                  }                  }
567                  else                  else
# Line 499  xclip_handle_SelectionNotify(XSelectionE Line 583  xclip_handle_SelectionNotify(XSelectionE
583          return;          return;
584    
585        fail:        fail:
586          XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);          xclip_clear_target_props();
587          XFree(data);          if (data)
588                    XFree(data);
589          helper_cliprdr_send_empty_response();          helper_cliprdr_send_empty_response();
590  }  }
591    
# Line 550  xclip_handle_SelectionRequest(XSelection Line 635  xclip_handle_SelectionRequest(XSelection
635                             Otherwise, we default to RDP_CF_TEXT.                             Otherwise, we default to RDP_CF_TEXT.
636                           */                           */
637                          res = XGetWindowProperty(g_display, event->requestor,                          res = XGetWindowProperty(g_display, event->requestor,
638                                                   rdesktop_clipboard_target_atom, 0, 1, True, XA_INTEGER,                                                   rdesktop_clipboard_target_atom, 0, 1, True,
639                                                   &type, &format, &nitems, &bytes_left, &prop_return);                                                   XA_INTEGER, &type, &format, &nitems, &bytes_left,
640                                                     &prop_return);
641                          wanted_format = (uint32 *) prop_return;                          wanted_format = (uint32 *) prop_return;
642                          format = (res == Success) ? *wanted_format : RDP_CF_TEXT;                          format = (res == Success) ? *wanted_format : RDP_CF_TEXT;
643                          XFree(prop_return);                          XFree(prop_return);
644                  }                  }
645                  else if (event->target == format_string_atom ||                  else if (event->target == format_string_atom || event->target == XA_STRING)
                          event->target == XA_STRING)  
646                  {                  {
647                          /* STRING and XA_STRING are defined to be ISO8859-1 */                          /* STRING and XA_STRING are defined to be ISO8859-1 */
648                          format = CF_TEXT;                          format = CF_TEXT;
649                  }                  }
650                  else if (event->target == format_utf8_string_atom)                  else if (event->target == format_utf8_string_atom)
651                  {                  {
652                          #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
653                          format = CF_UNICODETEXT;                          format = CF_UNICODETEXT;
654                          #else  #else
655                          DEBUG_CLIPBOARD(("Requested target unavailable due to lack of Unicode support. (It was not in TARGETS, so why did you ask for it?!)\n"));                          DEBUG_CLIPBOARD(("Requested target unavailable due to lack of Unicode support. (It was not in TARGETS, so why did you ask for it?!)\n"));
656                          xclip_refuse_selection(event);                          xclip_refuse_selection(event);
657                          return;                          return;
658                          #endif  #endif
659                  }                  }
660                  else if (event->target == format_unicode_atom)                  else if (event->target == format_unicode_atom)
661                  {                  {
# Line 587  xclip_handle_SelectionRequest(XSelection Line 672  xclip_handle_SelectionRequest(XSelection
672                  cliprdr_send_data_request(format);                  cliprdr_send_data_request(format);
673                  selection_request = *event;                  selection_request = *event;
674                  has_selection_request = True;                  has_selection_request = True;
675                  return; /* wait for data */                  return;         /* wait for data */
676          }          }
677  }  }
678    
# Line 651  xclip_handle_PropertyNotify(XPropertyEve Line 736  xclip_handle_PropertyNotify(XPropertyEve
736    
737                                  if (g_clip_buflen > 0)                                  if (g_clip_buflen > 0)
738                                  {                                  {
739                                          if (!xclip_send_data_with_convert(g_clip_buffer, g_clip_buflen, g_incr_target))                                          if (!xclip_send_data_with_convert
740                                                (g_clip_buffer, g_clip_buflen, g_incr_target))
741                                          {                                          {
742                                                  helper_cliprdr_send_empty_response();                                                  helper_cliprdr_send_empty_response();
743                                          }                                          }
# Line 663  xclip_handle_PropertyNotify(XPropertyEve Line 749  xclip_handle_PropertyNotify(XPropertyEve
749                          else                          else
750                          {                          {
751                                  /* Another chunk in the INCR transfer */                                  /* Another chunk in the INCR transfer */
752                                  offset += (nitems / 4); /* offset at which to begin the next slurp */                                  offset += (nitems / 4); /* offset at which to begin the next slurp */
753                                  g_clip_buffer = xrealloc(g_clip_buffer, g_clip_buflen + nitems);                                  g_clip_buffer = xrealloc(g_clip_buffer, g_clip_buflen + nitems);
754                                  memcpy(g_clip_buffer + g_clip_buflen, data, nitems);                                  memcpy(g_clip_buffer + g_clip_buflen, data, nitems);
755                                  g_clip_buflen += nitems;                                  g_clip_buflen += nitems;
# Line 677  xclip_handle_PropertyNotify(XPropertyEve Line 763  xclip_handle_PropertyNotify(XPropertyEve
763    
764          if ((event->atom == rdesktop_clipboard_formats_atom) &&          if ((event->atom == rdesktop_clipboard_formats_atom) &&
765              (event->window == DefaultRootWindow(g_display)) &&              (event->window == DefaultRootWindow(g_display)) &&
766              !have_primary /* not interested in our own events */)              !have_primary /* not interested in our own events */ )
767          {          {
768                  if (event->state == PropertyNewValue)                  if (event->state == PropertyNewValue)
769                  {                  {
# Line 685  xclip_handle_PropertyNotify(XPropertyEve Line 771  xclip_handle_PropertyNotify(XPropertyEve
771    
772                          res = XGetWindowProperty(g_display, DefaultRootWindow(g_display),                          res = XGetWindowProperty(g_display, DefaultRootWindow(g_display),
773                                                   rdesktop_clipboard_formats_atom, 0,                                                   rdesktop_clipboard_formats_atom, 0,
774                                                   XMaxRequestSize(g_display), False, XA_STRING, &type,                                                   XMaxRequestSize(g_display), False, XA_STRING,
775                                                   &format, &nitems, &bytes_left, &data);                                                   &type, &format, &nitems, &bytes_left, &data);
776    
777                          if ((res == Success) && (nitems > 0))                          if ((res == Success) && (nitems > 0))
778                          {                          {
# Line 735  ui_clip_handle_data(uint8 * data, uint32 Line 821  ui_clip_handle_data(uint8 * data, uint32
821  {  {
822          BOOL free_data = False;          BOOL free_data = False;
823    
824          if (selection_request.target == format_string_atom ||          if (selection_request.target == format_string_atom || selection_request.target == XA_STRING)
825              selection_request.target == XA_STRING)          {
         {  
826                  /* We're expecting a CF_TEXT response */                  /* We're expecting a CF_TEXT response */
827                  uint8 *firstnull;                  uint8 *firstnull;
828    
829                  /* translate linebreaks */                  /* translate linebreaks */
830                  crlf2lf(data, &length);                  crlf2lf(data, &length);
831    
832                  /* Only send data up to null byte, if any */                  /* Only send data up to null byte, if any */
833                  firstnull = (uint8 *) strchr((char *) data, '\0');                  firstnull = (uint8 *) strchr((char *) data, '\0');
834                  if (firstnull)                  if (firstnull)
835                  {                  {
836                          length = firstnull - data + 1;                          length = firstnull - data + 1;
837                  }                  }
838          }          }
839  #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
840          else if (selection_request.target == format_utf8_string_atom)          else if (selection_request.target == format_utf8_string_atom)
841          {          {
842                  /* We're expecting a CF_UNICODETEXT response */                  /* We're expecting a CF_UNICODETEXT response */
843                  iconv_t cd = iconv_open("UTF-8", WINDOWS_CODEPAGE);                  iconv_t cd = iconv_open("UTF-8", WINDOWS_CODEPAGE);
844                  if (cd != (iconv_t)-1)                  if (cd != (iconv_t) - 1)
845                  {                  {
846                          size_t utf8_length = length * 2;                          size_t utf8_length = length * 2;
847                          char* utf8_data = malloc(utf8_length);                          char *utf8_data = malloc(utf8_length);
848                          size_t utf8_length_remaining = utf8_length;                          size_t utf8_length_remaining = utf8_length;
849                          char* utf8_data_remaining = utf8_data;                          char *utf8_data_remaining = utf8_data;
850                          char* data_remaining = (char*)data;                          char *data_remaining = (char *) data;
851                          size_t length_remaining = (size_t)length;                          size_t length_remaining = (size_t) length;
852                          if (utf8_data == NULL)                          if (utf8_data == NULL)
853                          {                          {
854                                  iconv_close(cd);                                  iconv_close(cd);
855                                  return;                                  return;
856                          }                          }
857                          iconv(cd, &data_remaining, &length_remaining, &utf8_data_remaining, &utf8_length_remaining);                          iconv(cd, (ICONV_CONST char **) &data_remaining, &length_remaining,
858                                  &utf8_data_remaining, &utf8_length_remaining);
859                          iconv_close(cd);                          iconv_close(cd);
860                          free_data = True;                          free_data = True;
861                          data = (uint8*)utf8_data;                          data = (uint8 *) utf8_data;
862                          length = utf8_length - utf8_length_remaining;                          length = utf8_length - utf8_length_remaining;
863                  }                  }
864          }          }
# Line 804  ui_clip_handle_data(uint8 * data, uint32 Line 890  ui_clip_handle_data(uint8 * data, uint32
890  void  void
891  ui_clip_request_data(uint32 format)  ui_clip_request_data(uint32 format)
892  {  {
893          Window selectionowner;          Window primary_owner, clipboard_owner;
894    
895          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
896          rdp_clipboard_request_format = format;          rdp_clipboard_request_format = format;
897    
898            xclip_clear_target_props();
899    
900          if (rdesktop_is_selection_owner)          if (rdesktop_is_selection_owner)
901          {          {
902                  XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,                  XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
# Line 819  ui_clip_request_data(uint32 format) Line 907  ui_clip_request_data(uint32 format)
907                  return;                  return;
908          }          }
909    
910          selectionowner = XGetSelectionOwner(g_display, primary_atom);          if (auto_mode)
911          if (selectionowner != None)                  primary_owner = XGetSelectionOwner(g_display, primary_atom);
912            else
913                    primary_owner = None;
914    
915            clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
916    
917            /* Both available */
918            if ((primary_owner != None) && (clipboard_owner != None))
919            {
920                    primary_timestamp = 0;
921                    clipboard_timestamp = 0;
922                    XConvertSelection(g_display, primary_atom, timestamp_atom,
923                                      rdesktop_primary_timestamp_target_atom, g_wnd, CurrentTime);
924                    XConvertSelection(g_display, clipboard_atom, timestamp_atom,
925                                      rdesktop_clipboard_timestamp_target_atom, g_wnd, CurrentTime);
926                    return;
927            }
928    
929            /* Just PRIMARY */
930            if (primary_owner != None)
931          {          {
932                  XConvertSelection(g_display, primary_atom, targets_atom,                  XConvertSelection(g_display, primary_atom, targets_atom,
933                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
934                  return;                  return;
935          }          }
936    
937          /* No PRIMARY, try CLIPBOARD */          /* Just CLIPBOARD */
938          selectionowner = XGetSelectionOwner(g_display, clipboard_atom);          if (clipboard_owner != None)
         if (selectionowner != None)  
939          {          {
940                  XConvertSelection(g_display, clipboard_atom, targets_atom,                  XConvertSelection(g_display, clipboard_atom, targets_atom,
941                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
# Line 837  ui_clip_request_data(uint32 format) Line 943  ui_clip_request_data(uint32 format)
943          }          }
944    
945          /* No data available */          /* No data available */
946          cliprdr_send_data(NULL, 0);          helper_cliprdr_send_empty_response();
947  }  }
948    
949  void  void
# Line 846  ui_clip_sync(void) Line 952  ui_clip_sync(void)
952          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);
953  }  }
954    
955    void
956    ui_clip_set_mode(const char *optarg)
957    {
958            g_rdpclip = True;
959    
960            if (str_startswith(optarg, "auto") || str_startswith(optarg, "on")
961                || str_startswith(optarg, "PRIMARYCLIPBOARD"))
962                    auto_mode = True;
963            else if (str_startswith(optarg, "CLIPBOARD"))
964                    auto_mode = False;
965            else
966            {
967                    warning("Invalid clipboard mode '%s'.\n", optarg);
968                    g_rdpclip = False;
969            }
970    }
971    
972  void  void
973  xclip_init(void)  xclip_init(void)
974  {  {
975            if (!g_rdpclip)
976                    return;
977    
978          if (!cliprdr_init())          if (!cliprdr_init())
979                  return;                  return;
980    
# Line 859  xclip_init(void) Line 984  xclip_init(void)
984          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
985          rdesktop_clipboard_target_atom =          rdesktop_clipboard_target_atom =
986                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
987            rdesktop_primary_timestamp_target_atom =
988                    XInternAtom(g_display, "_RDESKTOP_PRIMARY_TIMESTAMP_TARGET", False);
989            rdesktop_clipboard_timestamp_target_atom =
990                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET", False);
991          incr_atom = XInternAtom(g_display, "INCR", False);          incr_atom = XInternAtom(g_display, "INCR", False);
992          format_string_atom = XInternAtom(g_display, "STRING", False);          format_string_atom = XInternAtom(g_display, "STRING", False);
993          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);
# Line 868  xclip_init(void) Line 997  xclip_init(void)
997          targets[num_targets++] = timestamp_atom;          targets[num_targets++] = timestamp_atom;
998          targets[num_targets++] = rdesktop_clipboard_formats_atom;          targets[num_targets++] = rdesktop_clipboard_formats_atom;
999          targets[num_targets++] = format_string_atom;          targets[num_targets++] = format_string_atom;
1000          #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
1001          targets[num_targets++] = format_utf8_string_atom;          targets[num_targets++] = format_utf8_string_atom;
1002          #endif  #endif
1003          targets[num_targets++] = format_unicode_atom;          targets[num_targets++] = format_unicode_atom;
1004          targets[num_targets++] = XA_STRING;          targets[num_targets++] = XA_STRING;
1005    

Legend:
Removed from v.1037  
changed lines
  Added in v.1207

  ViewVC Help
Powered by ViewVC 1.1.26