/[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 1214 by ossman_, Tue Mar 28 13:56:08 2006 UTC revision 1404 by astrand, Wed Apr 25 12:44:26 2007 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - Clipboard functions     Protocol services - Clipboard functions
4     Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003     Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003-2007
5     Copyright (C) Matthew Chapman 2003     Copyright (C) Matthew Chapman 2003-2007
6    
7     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# 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;  extern RD_BOOL g_rdpclip;
57    
58  /* Mode of operation.  /* Mode of operation.
59     - Auto: Look at both PRIMARY and CLIPBOARD and use the most recent.     - Auto: Look at both PRIMARY and CLIPBOARD and use the most recent.
60     - Non-auto: Look at just CLIPBOARD. */     - Non-auto: Look at just CLIPBOARD. */
61  static BOOL auto_mode = True;  static RD_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 92  static Atom rdesktop_selection_notify_at Line 92  static Atom rdesktop_selection_notify_at
92  /* State variables that indicate if we're currently probing the targets of the  /* State variables that indicate if we're currently probing the targets of the
93     selection owner. reprobe_selections indicate that the ownership changed in     selection owner. reprobe_selections indicate that the ownership changed in
94     the middle of the current probe so it should be restarted. */     the middle of the current probe so it should be restarted. */
95  static BOOL probing_selections, reprobe_selections;  static RD_BOOL probing_selections, reprobe_selections;
96  /* Atoms _RDESKTOP_PRIMARY_OWNER and _RDESKTOP_CLIPBOARD_OWNER. Used as properties  /* Atoms _RDESKTOP_PRIMARY_OWNER and _RDESKTOP_CLIPBOARD_OWNER. Used as properties
97     on the root window to indicate which selections that are owned by rdesktop. */     on the root window to indicate which selections that are owned by rdesktop. */
98  static Atom rdesktop_primary_owner_atom, rdesktop_clipboard_owner_atom;  static Atom rdesktop_primary_owner_atom, rdesktop_clipboard_owner_atom;
# Line 105  static Atom incr_atom; Line 105  static Atom incr_atom;
105     the context to proceed. */     the context to proceed. */
106  static XSelectionRequestEvent selection_request;  static XSelectionRequestEvent selection_request;
107  /* Denotes we have a pending selection request. */  /* Denotes we have a pending selection request. */
108  static Bool has_selection_request;  static RD_BOOL has_selection_request;
109  /* Stores the clipboard format (CF_TEXT, CF_UNICODETEXT etc.) requested in the last  /* Stores the clipboard format (CF_TEXT, CF_UNICODETEXT etc.) requested in the last
110     CLIPDR_DATA_REQUEST (= the RDP server requesting clipboard data from us).     CLIPDR_DATA_REQUEST (= the RDP server requesting clipboard data from us).
111     When we receive this data from whatever X client offering it, this variable gives us     When we receive this data from whatever X client offering it, this variable gives us
# Line 117  static Atom targets[MAX_TARGETS]; Line 117  static Atom targets[MAX_TARGETS];
117  static int num_targets;  static int num_targets;
118  /* Denotes that an rdesktop (not this rdesktop) is owning the selection,  /* Denotes that an rdesktop (not this rdesktop) is owning the selection,
119     allowing us to interchange Windows native clipboard data directly. */     allowing us to interchange Windows native clipboard data directly. */
120  static BOOL rdesktop_is_selection_owner = False;  static RD_BOOL rdesktop_is_selection_owner = False;
121  /* Time when we acquired the selection. */  /* Time when we acquired the selection. */
122  static Time acquire_time = 0;  static Time acquire_time = 0;
123    
# Line 130  static uint8 *g_clip_buffer = 0; Line 130  static uint8 *g_clip_buffer = 0;
130  /* Denotes the size of g_clip_buffer. */  /* Denotes the size of g_clip_buffer. */
131  static uint32 g_clip_buflen = 0;  static uint32 g_clip_buflen = 0;
132    
133  /* Translate LF to CR-LF. To do this, we must allocate more memory.  /* Translates CR-LF to LF.
134     The returned string is null-terminated, as required by CF_TEXT.     Changes the string in-place.
135     Does not stop on embedded nulls.     Does not stop on embedded nulls.
136     The length is updated. */     The length is updated. */
137  static void  static void
# Line 157  utf16_lf2crlf(uint8 * data, uint32 * siz Line 157  utf16_lf2crlf(uint8 * data, uint32 * siz
157  {  {
158          uint8 *result;          uint8 *result;
159          uint16 *inptr, *outptr;          uint16 *inptr, *outptr;
160            RD_BOOL swap_endianess;
161    
162          /* Worst case: Every char is LF */          /* Worst case: Every char is LF */
163          result = xmalloc((*size * 2) + 2);          result = xmalloc((*size * 2) + 2);
# Line 167  utf16_lf2crlf(uint8 * data, uint32 * siz Line 168  utf16_lf2crlf(uint8 * data, uint32 * siz
168          outptr = (uint16 *) result;          outptr = (uint16 *) result;
169    
170          /* Check for a reversed BOM */          /* Check for a reversed BOM */
171          Bool swap_endianess = (*inptr == 0xfffe);          swap_endianess = (*inptr == 0xfffe);
172    
173            uint16 uvalue_previous = 0;     /* Kept so we'll avoid translating CR-LF to CR-CR-LF */
174          while ((uint8 *) inptr < data + *size)          while ((uint8 *) inptr < data + *size)
175          {          {
176                  uint16 uvalue = *inptr;                  uint16 uvalue = *inptr;
177                  if (swap_endianess)                  if (swap_endianess)
178                          uvalue = ((uvalue << 8) & 0xff00) + (uvalue >> 8);                          uvalue = ((uvalue << 8) & 0xff00) + (uvalue >> 8);
179                  if (uvalue == 0x0a)                  if ((uvalue == 0x0a) && (uvalue_previous != 0x0d))
180                          *outptr++ = swap_endianess ? 0x0d00 : 0x0d;                          *outptr++ = swap_endianess ? 0x0d00 : 0x0d;
181                    uvalue_previous = uvalue;
182                  *outptr++ = *inptr++;                  *outptr++ = *inptr++;
183          }          }
184          *outptr++ = 0;          /* null termination */          *outptr++ = 0;          /* null termination */
# Line 197  lf2crlf(uint8 * data, uint32 * length) Line 200  lf2crlf(uint8 * data, uint32 * length)
200          p = data;          p = data;
201          o = result;          o = result;
202    
203            uint8 previous = '\0';  /* Kept to avoid translating CR-LF to CR-CR-LF */
204          while (p < data + *length)          while (p < data + *length)
205          {          {
206                  if (*p == '\x0a')                  if ((*p == '\x0a') && (previous != '\x0d'))
207                          *o++ = '\x0d';                          *o++ = '\x0d';
208                    previous = *p;
209                  *o++ = *p++;                  *o++ = *p++;
210          }          }
211          *length = o - result;          *length = o - result;
# Line 282  helper_cliprdr_send_empty_response() Line 287  helper_cliprdr_send_empty_response()
287  /* Replies with clipboard data to RDP, converting it from the target format  /* Replies with clipboard data to RDP, converting it from the target format
288     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.
289   */   */
290  static Bool  static RD_BOOL
291  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)
292  {  {
293          DEBUG_CLIPBOARD(("xclip_send_data_with_convert: target=%s, size=%u\n",          DEBUG_CLIPBOARD(("xclip_send_data_with_convert: target=%s, size=%u\n",
# Line 292  xclip_send_data_with_convert(uint8 * sou Line 297  xclip_send_data_with_convert(uint8 * sou
297          if (target == format_string_atom ||          if (target == format_string_atom ||
298              target == format_unicode_atom || target == format_utf8_string_atom)              target == format_unicode_atom || target == format_utf8_string_atom)
299          {          {
300                    size_t unicode_buffer_size;
301                    char *unicode_buffer;
302                    iconv_t cd;
303                    size_t unicode_buffer_size_remaining;
304                    char *unicode_buffer_remaining;
305                    char *data_remaining;
306                    size_t data_size_remaining;
307                    uint32 translated_data_size;
308                    uint8 *translated_data;
309    
310                  if (rdp_clipboard_request_format != RDP_CF_TEXT)                  if (rdp_clipboard_request_format != RDP_CF_TEXT)
311                          return False;                          return False;
312    
# Line 300  xclip_send_data_with_convert(uint8 * sou Line 315  xclip_send_data_with_convert(uint8 * sou
315                     to it, so using CF_TEXT is not safe (and is unnecessary, since all                     to it, so using CF_TEXT is not safe (and is unnecessary, since all
316                     WinNT versions are Unicode-minded).                     WinNT versions are Unicode-minded).
317                   */                   */
                 size_t unicode_buffer_size;  
                 char *unicode_buffer;  
                 iconv_t cd;  
   
318                  if (target == format_string_atom)                  if (target == format_string_atom)
319                  {                  {
320                          char *locale_charset = nl_langinfo(CODESET);                          char *locale_charset = nl_langinfo(CODESET);
# Line 342  xclip_send_data_with_convert(uint8 * sou Line 353  xclip_send_data_with_convert(uint8 * sou
353                  }                  }
354    
355                  unicode_buffer = xmalloc(unicode_buffer_size);                  unicode_buffer = xmalloc(unicode_buffer_size);
356                  size_t unicode_buffer_size_remaining = unicode_buffer_size;                  unicode_buffer_size_remaining = unicode_buffer_size;
357                  char *unicode_buffer_remaining = unicode_buffer;                  unicode_buffer_remaining = unicode_buffer;
358                  char *data_remaining = (char *) source;                  data_remaining = (char *) source;
359                  size_t data_size_remaining = source_size;                  data_size_remaining = source_size;
360                  iconv(cd, (ICONV_CONST char **) &data_remaining, &data_size_remaining,                  iconv(cd, (ICONV_CONST char **) &data_remaining, &data_size_remaining,
361                        &unicode_buffer_remaining, &unicode_buffer_size_remaining);                        &unicode_buffer_remaining, &unicode_buffer_size_remaining);
362                  iconv_close(cd);                  iconv_close(cd);
363    
364                  /* translate linebreaks */                  /* translate linebreaks */
365                  uint32 translated_data_size = unicode_buffer_size - unicode_buffer_size_remaining;                  translated_data_size = unicode_buffer_size - unicode_buffer_size_remaining;
366                  uint8 *translated_data =                  translated_data = utf16_lf2crlf((uint8 *) unicode_buffer, &translated_data_size);
                         utf16_lf2crlf((uint8 *) unicode_buffer, &translated_data_size);  
367                  if (translated_data != NULL)                  if (translated_data != NULL)
368                  {                  {
369                          DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n",                          DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n",
# Line 512  xclip_handle_SelectionNotify(XSelectionE Line 522  xclip_handle_SelectionNotify(XSelectionE
522                  {                  {
523                          res = XGetWindowProperty(g_display, g_wnd,                          res = XGetWindowProperty(g_display, g_wnd,
524                                                   rdesktop_primary_timestamp_target_atom, 0,                                                   rdesktop_primary_timestamp_target_atom, 0,
525                                                   XMaxRequestSize(g_display), False, XA_INTEGER,                                                   XMaxRequestSize(g_display), False, AnyPropertyType,
526                                                   &type, &format, &nitems, &bytes_left, &data);                                                   &type, &format, &nitems, &bytes_left, &data);
527                  }                  }
528                  else                  else
529                  {                  {
530                          res = XGetWindowProperty(g_display, g_wnd,                          res = XGetWindowProperty(g_display, g_wnd,
531                                                   rdesktop_clipboard_timestamp_target_atom, 0,                                                   rdesktop_clipboard_timestamp_target_atom, 0,
532                                                   XMaxRequestSize(g_display), False, XA_INTEGER,                                                   XMaxRequestSize(g_display), False, AnyPropertyType,
533                                                   &type, &format, &nitems, &bytes_left, &data);                                                   &type, &format, &nitems, &bytes_left, &data);
534                  }                  }
535    
536    
537                  if ((res != Success) || (nitems != 1))                  if ((res != Success) || (nitems != 1) || (format != 32))
538                  {                  {
539                          DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));                          DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
540                          goto fail;                          goto fail;
# Line 707  xclip_handle_SelectionNotify(XSelectionE Line 717  xclip_handle_SelectionNotify(XSelectionE
717                          rdesktop_is_selection_owner = True;                          rdesktop_is_selection_owner = True;
718                          cliprdr_send_native_format_announce(data, nitems);                          cliprdr_send_native_format_announce(data, nitems);
719                  }                  }
720                  else if (!xclip_send_data_with_convert(data, nitems, event->target))                  else if ((!nitems) || (!xclip_send_data_with_convert(data, nitems, event->target)))
721                  {                  {
722                          goto fail;                          goto fail;
723                  }                  }
# Line 748  void Line 758  void
758  xclip_handle_SelectionRequest(XSelectionRequestEvent * event)  xclip_handle_SelectionRequest(XSelectionRequestEvent * event)
759  {  {
760          unsigned long nitems, bytes_left;          unsigned long nitems, bytes_left;
761          unsigned char *prop_return;          unsigned char *prop_return = NULL;
762          int format, res;          int format, res;
763          Atom type;          Atom type;
764    
# Line 790  xclip_handle_SelectionRequest(XSelection Line 800  xclip_handle_SelectionRequest(XSelection
800                                                   event->property, 0, 1, True,                                                   event->property, 0, 1, True,
801                                                   XA_INTEGER, &type, &format, &nitems, &bytes_left,                                                   XA_INTEGER, &type, &format, &nitems, &bytes_left,
802                                                   &prop_return);                                                   &prop_return);
803                          if (res != Success)                          if (res != Success || (!prop_return))
804                          {                          {
805                                  DEBUG_CLIPBOARD(("Requested native format but didn't specifiy which.\n"));                                  DEBUG_CLIPBOARD(("Requested native format but didn't specifiy which.\n"));
806                                  xclip_refuse_selection(event);                                  xclip_refuse_selection(event);
# Line 952  ui_clip_format_announce(uint8 * data, ui Line 962  ui_clip_format_announce(uint8 * data, ui
962  void  void
963  ui_clip_handle_data(uint8 * data, uint32 length)  ui_clip_handle_data(uint8 * data, uint32 length)
964  {  {
965          BOOL free_data = False;          RD_BOOL free_data = False;
966    
967          if (length == 0)          if (length == 0)
968          {          {
# Line 1000  ui_clip_handle_data(uint8 * data, uint32 Line 1010  ui_clip_handle_data(uint8 * data, uint32
1010                          free_data = True;                          free_data = True;
1011                          data = (uint8 *) utf8_data;                          data = (uint8 *) utf8_data;
1012                          length = utf8_length - utf8_length_remaining;                          length = utf8_length - utf8_length_remaining;
1013                            /* translate linebreaks (works just as well on UTF-8) */
1014                            crlf2lf(data, &length);
1015                  }                  }
1016          }          }
1017          else if (selection_request.target == format_unicode_atom)          else if (selection_request.target == format_unicode_atom)
# Line 1112  ui_clip_set_mode(const char *optarg) Line 1124  ui_clip_set_mode(const char *optarg)
1124  {  {
1125          g_rdpclip = True;          g_rdpclip = True;
1126    
1127          if (str_startswith(optarg, "auto") || str_startswith(optarg, "on")          if (str_startswith(optarg, "PRIMARYCLIPBOARD"))
             || str_startswith(optarg, "PRIMARYCLIPBOARD"))  
1128                  auto_mode = True;                  auto_mode = True;
1129          else if (str_startswith(optarg, "CLIPBOARD"))          else if (str_startswith(optarg, "CLIPBOARD"))
1130                  auto_mode = False;                  auto_mode = False;

Legend:
Removed from v.1214  
changed lines
  Added in v.1404

  ViewVC Help
Powered by ViewVC 1.1.26