ReactOS  0.4.13-dev-259-g5ca9c9c
xclip.c File Reference
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "rdesktop.h"
Include dependency graph for xclip.c:

Go to the source code of this file.

Macros

#define RDP_CF_TEXT   CF_TEXT
 

Functions

static void crlf2lf (uint8 *data, uint32 *length)
 
static uint8lf2crlf (uint8 *data, uint32 *length)
 
static void xclip_provide_selection (RDPCLIENT *This, XSelectionRequestEvent *req, Atom type, unsigned int format, uint8 *data, uint32 length)
 
static void xclip_refuse_selection (RDPCLIENT *This, XSelectionRequestEvent *req)
 
static void helper_cliprdr_send_response (RDPCLIENT *This, uint8 *data, uint32 length)
 
static void helper_cliprdr_send_empty_response (RDPCLIENT *This)
 
static Bool xclip_send_data_with_convert (RDPCLIENT *This, uint8 *source, size_t source_size, Atom target)
 
static void xclip_clear_target_props (RDPCLIENT *This)
 
static void xclip_notify_change (RDPCLIENT *This)
 
static void xclip_probe_selections (RDPCLIENT *This)
 
void xclip_handle_SelectionNotify (RDPCLIENT *This, XSelectionEvent *event)
 
void xclip_handle_SelectionRequest (RDPCLIENT *This, XSelectionRequestEvent *event)
 
void xclip_handle_SelectionClear (RDPCLIENT *This)
 
void xclip_handle_PropertyNotify (RDPCLIENT *This, XPropertyEvent *event)
 
void ui_clip_format_announce (RDPCLIENT *This, uint8 *data, uint32 length)
 
void ui_clip_handle_data (RDPCLIENT *This, uint8 *data, uint32 length)
 
void ui_clip_request_failed (RDPCLIENT *This)
 
void ui_clip_request_data (RDPCLIENT *This, uint32 format)
 
void ui_clip_sync (RDPCLIENT *This)
 
void ui_clip_set_mode (RDPCLIENT *This, const char *optarg)
 
void xclip_init (RDPCLIENT *This)
 
void xclip_deinit (RDPCLIENT *This)
 

Macro Definition Documentation

◆ RDP_CF_TEXT

#define RDP_CF_TEXT   CF_TEXT

Definition at line 48 of file xclip.c.

Function Documentation

◆ crlf2lf()

static void crlf2lf ( uint8 data,
uint32 length 
)
static

Definition at line 57 of file xclip.c.

58 {
59  uint8 *dst, *src;
60  src = dst = data;
61  while (src < data + *length)
62  {
63  if (*src != '\x0d')
64  *dst++ = *src;
65  src++;
66  }
67  *length = dst - data;
68 }
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
unsigned char uint8
Definition: types.h:28
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum src
Definition: glext.h:6340
GLenum GLenum dst
Definition: glext.h:6340

Referenced by ui_clip_handle_data().

◆ helper_cliprdr_send_empty_response()

static void helper_cliprdr_send_empty_response ( RDPCLIENT This)
static

Definition at line 197 of file xclip.c.

198 {
200 }
smooth NULL
Definition: ftsmooth.c:416
static void helper_cliprdr_send_response(RDPCLIENT *This, uint8 *data, uint32 length)
Definition: xclip.c:182

Referenced by ui_clip_request_data(), xclip_handle_PropertyNotify(), and xclip_handle_SelectionNotify().

◆ helper_cliprdr_send_response()

static void helper_cliprdr_send_response ( RDPCLIENT This,
uint8 data,
uint32  length 
)
static

Definition at line 182 of file xclip.c.

183 {
184  if (This->xclip.rdp_clipboard_request_format != 0)
185  {
187  This->xclip.rdp_clipboard_request_format = 0;
188  if (!This->xclip.rdesktop_is_selection_owner)
190  }
191 }
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
void cliprdr_send_data(uint8 *data, uint32 length)
#define RDP_CF_TEXT
Definition: xclip.c:48
void cliprdr_send_simple_native_format_announce(uint32 format)

Referenced by helper_cliprdr_send_empty_response(), and xclip_send_data_with_convert().

◆ lf2crlf()

static uint8* lf2crlf ( uint8 data,
uint32 length 
)
static

Definition at line 110 of file xclip.c.

111 {
112  uint8 *result, *p, *o;
113 
114  /* Worst case: Every char is LF */
115  result = xmalloc(*length * 2);
116 
117  p = data;
118  o = result;
119 
120  while (p < data + *length)
121  {
122  if (*p == '\x0a')
123  *o++ = '\x0d';
124  *o++ = *p++;
125  }
126  *length = o - result;
127 
128  /* Convenience */
129  *o++ = '\0';
130 
131  return result;
132 }
void * xmalloc(int size)
Definition: uimain.c:747
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
unsigned char uint8
Definition: types.h:28
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLfloat GLfloat p
Definition: glext.h:8902
GLuint64EXT * result
Definition: glext.h:11304

Referenced by xclip_send_data_with_convert().

◆ ui_clip_format_announce()

void ui_clip_format_announce ( RDPCLIENT This,
uint8 data,
uint32  length 
)

Definition at line 855 of file xclip.c.

856 {
857  This->xclip.acquire_time = This->last_gesturetime;
858 
859  XSetSelectionOwner(This->display, This->xclip.primary_atom, This->wnd, This->xclip.acquire_time);
860  if (XGetSelectionOwner(This->display, This->xclip.primary_atom) != This->wnd)
861  warning("Failed to aquire ownership of PRIMARY clipboard\n");
862 
863  XSetSelectionOwner(This->display, This->xclip.clipboard_atom, This->wnd, This->xclip.acquire_time);
864  if (XGetSelectionOwner(This->display, This->xclip.clipboard_atom) != This->wnd)
865  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
866 
867  if (This->xclip.formats_data)
868  xfree(This->xclip.formats_data);
869  This->xclip.formats_data = xmalloc(length);
870  memcpy(This->xclip.formats_data, data, length);
871  This->xclip.formats_data_length = length;
872 
874 }
void * xmalloc(int size)
Definition: uimain.c:747
void xfree(void *mem)
Definition: uimain.c:758
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static void xclip_notify_change(RDPCLIENT *This)
Definition: xclip.c:335
#define warning(s)
Definition: debug.h:71

◆ ui_clip_handle_data()

void ui_clip_handle_data ( RDPCLIENT This,
uint8 data,
uint32  length 
)

Definition at line 878 of file xclip.c.

879 {
880  BOOL free_data = False;
881 
882  if (length == 0)
883  {
884  xclip_refuse_selection(This, &This->xclip.selection_request);
885  This->xclip.has_selection_request = False;
886  return;
887  }
888 
889  if (This->xclip.selection_request.target == This->xclip.format_string_atom || This->xclip.selection_request.target == XA_STRING)
890  {
891  /* We're expecting a CF_TEXT response */
892  uint8 *firstnull;
893 
894  /* translate linebreaks */
895  crlf2lf(data, &length);
896 
897  /* Only send data up to null byte, if any */
898  firstnull = (uint8 *) strchr((char *) data, '\0');
899  if (firstnull)
900  {
901  length = firstnull - data + 1;
902  }
903  }
904 #ifdef USE_UNICODE_CLIPBOARD
905  else if (This->xclip.selection_request.target == This->xclip.format_utf8_string_atom)
906  {
907  /* We're expecting a CF_UNICODETEXT response */
909  if (cd != (iconv_t) - 1)
910  {
911  size_t utf8_length = length * 2;
912  char *utf8_data = malloc(utf8_length);
913  size_t utf8_length_remaining = utf8_length;
914  char *utf8_data_remaining = utf8_data;
915  char *data_remaining = (char *) data;
916  size_t length_remaining = (size_t) length;
917  if (utf8_data == NULL)
918  {
919  iconv_close(cd);
920  return;
921  }
922  iconv(cd, (ICONV_CONST char **) &data_remaining, &length_remaining,
923  &utf8_data_remaining, &utf8_length_remaining);
924  iconv_close(cd);
925  free_data = True;
926  data = (uint8 *) utf8_data;
927  length = utf8_length - utf8_length_remaining;
928  }
929  }
930  else if (This->xclip.selection_request.target == This->xclip.format_unicode_atom)
931  {
932  /* We're expecting a CF_UNICODETEXT response, so what we're
933  receiving matches our requirements and there's no need
934  for further conversions. */
935  }
936 #endif
937  else if (This->xclip.selection_request.target == This->xclip.rdesktop_native_atom)
938  {
939  /* Pass as-is */
940  }
941  else
942  {
943  DEBUG_CLIPBOARD(("ui_clip_handle_data: BUG! I don't know how to convert selection target %s!\n", XGetAtomName(This->display, This->xclip.selection_request.target)));
944  xclip_refuse_selection(This, &This->xclip.selection_request);
945  This->xclip.has_selection_request = False;
946  return;
947  }
948 
949  xclip_provide_selection(This, &This->xclip.selection_request, This->xclip.selection_request.target, 8, data, length - 1);
950  This->xclip.has_selection_request = False;
951 
952  if (free_data)
953  free(data);
954 }
static struct cd_image cd
Definition: cdmake.c:182
#define free
Definition: debug_ros.c:5
static const char utf8_length[128]
Definition: utf8.c:28
static void xclip_provide_selection(RDPCLIENT *This, XSelectionRequestEvent *req, Atom type, unsigned int format, uint8 *data, uint32 length)
Definition: xclip.c:136
size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
Definition: win_iconv.c:771
unsigned int BOOL
Definition: ntddk_ex.h:94
#define DEBUG_CLIPBOARD(args)
Definition: rdesktop.h:147
smooth NULL
Definition: ftsmooth.c:416
__kernel_size_t size_t
Definition: linux.h:237
#define True
Definition: types.h:24
#define False
Definition: types.h:25
#define WINDOWS_CODEPAGE
Definition: constants.h:24
#define ICONV_CONST
Definition: win32config.h:27
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
unsigned char uint8
Definition: types.h:28
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
iconv_t iconv_open(const char *tocode, const char *fromcode)
Definition: win_iconv.c:730
static void xclip_refuse_selection(RDPCLIENT *This, XSelectionRequestEvent *req)
Definition: xclip.c:161
static void crlf2lf(uint8 *data, uint32 *length)
Definition: xclip.c:57
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define malloc
Definition: debug_ros.c:4
int iconv_close(iconv_t cd)
Definition: win_iconv.c:756

◆ ui_clip_request_data()

void ui_clip_request_data ( RDPCLIENT This,
uint32  format 
)

Definition at line 964 of file xclip.c.

965 {
966  Window primary_owner, clipboard_owner;
967 
968  DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
969  This->xclip.rdp_clipboard_request_format = format;
970 
971  if (This->xclip.probing_selections)
972  {
973  DEBUG_CLIPBOARD(("ui_clip_request_data: Selection probe in progress. Cannot handle request.\n"));
975  return;
976  }
977 
979 
980  if (This->xclip.rdesktop_is_selection_owner)
981  {
982  XChangeProperty(This->display, This->wnd, This->xclip.rdesktop_clipboard_target_atom,
983  XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);
984 
985  XConvertSelection(This->display, This->xclip.primary_atom, This->xclip.rdesktop_native_atom,
986  This->xclip.rdesktop_clipboard_target_atom, This->wnd, CurrentTime);
987  return;
988  }
989 
990  if (This->xclip.auto_mode)
991  primary_owner = XGetSelectionOwner(This->display, This->xclip.primary_atom);
992  else
993  primary_owner = None;
994 
995  clipboard_owner = XGetSelectionOwner(This->display, This->xclip.clipboard_atom);
996 
997  /* Both available */
998  if ((primary_owner != None) && (clipboard_owner != None))
999  {
1000  This->xclip.primary_timestamp = 0;
1001  This->xclip.clipboard_timestamp = 0;
1002  XConvertSelection(This->display, This->xclip.primary_atom, This->xclip.timestamp_atom,
1003  This->xclip.rdesktop_primary_timestamp_target_atom, This->wnd, CurrentTime);
1004  XConvertSelection(This->display, This->xclip.clipboard_atom, This->xclip.timestamp_atom,
1005  This->xclip.rdesktop_clipboard_timestamp_target_atom, This->wnd, CurrentTime);
1006  return;
1007  }
1008 
1009  /* Just PRIMARY */
1010  if (primary_owner != None)
1011  {
1012  XConvertSelection(This->display, This->xclip.primary_atom, This->xclip.targets_atom,
1013  This->xclip.rdesktop_clipboard_target_atom, This->wnd, CurrentTime);
1014  return;
1015  }
1016 
1017  /* Just CLIPBOARD */
1018  if (clipboard_owner != None)
1019  {
1020  XConvertSelection(This->display, This->xclip.clipboard_atom, This->xclip.targets_atom,
1021  This->xclip.rdesktop_clipboard_target_atom, This->wnd, CurrentTime);
1022  return;
1023  }
1024 
1025  /* No data available */
1027 }
static void xclip_clear_target_props(RDPCLIENT *This)
Definition: xclip.c:327
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static void helper_cliprdr_send_empty_response(RDPCLIENT *This)
Definition: xclip.c:197
Definition: window.c:29
#define None
Definition: i386-dis.c:444
#define DEBUG_CLIPBOARD(args)
Definition: rdesktop.h:147

◆ ui_clip_request_failed()

void ui_clip_request_failed ( RDPCLIENT This)

Definition at line 957 of file xclip.c.

958 {
959  xclip_refuse_selection(This, &This->xclip.selection_request);
960  This->xclip.has_selection_request = False;
961 }
#define False
Definition: types.h:25
static void xclip_refuse_selection(RDPCLIENT *This, XSelectionRequestEvent *req)
Definition: xclip.c:161

◆ ui_clip_set_mode()

void ui_clip_set_mode ( RDPCLIENT This,
const char optarg 
)

Definition at line 1036 of file xclip.c.

1037 {
1038  This->rdpclip = True;
1039 
1040  if (str_startswith(optarg, "PRIMARYCLIPBOARD"))
1041  This->xclip.auto_mode = True;
1042  else if (str_startswith(optarg, "CLIPBOARD"))
1043  This->xclip.auto_mode = False;
1044  else
1045  {
1046  warning("Invalid clipboard mode '%s'.\n", optarg);
1047  This->rdpclip = False;
1048  }
1049 }
RD_BOOL str_startswith(const char *s, const char *prefix)
Definition: rdesktop.c:1235
#define True
Definition: types.h:24
#define False
Definition: types.h:25
const char * optarg
Definition: getopt.c:49
#define warning(s)
Definition: debug.h:71

◆ ui_clip_sync()

void ui_clip_sync ( RDPCLIENT This)

Definition at line 1030 of file xclip.c.

1031 {
1033 }
static void xclip_probe_selections(RDPCLIENT *This)
Definition: xclip.c:342

◆ xclip_clear_target_props()

static void xclip_clear_target_props ( RDPCLIENT This)
static

Definition at line 327 of file xclip.c.

328 {
329  XDeleteProperty(This->display, This->wnd, This->xclip.rdesktop_clipboard_target_atom);
330  XDeleteProperty(This->display, This->wnd, This->xclip.rdesktop_primary_timestamp_target_atom);
331  XDeleteProperty(This->display, This->wnd, This->xclip.rdesktop_clipboard_timestamp_target_atom);
332 }

Referenced by ui_clip_request_data(), xclip_handle_SelectionNotify(), and xclip_probe_selections().

◆ xclip_deinit()

void xclip_deinit ( RDPCLIENT This)

Definition at line 1102 of file xclip.c.

1103 {
1104  if (XGetSelectionOwner(This->display, This->xclip.primary_atom) == This->wnd)
1105  XSetSelectionOwner(This->display, This->xclip.primary_atom, None, This->xclip.acquire_time);
1106  if (XGetSelectionOwner(This->display, This->xclip.clipboard_atom) == This->wnd)
1107  XSetSelectionOwner(This->display, This->xclip.clipboard_atom, None, This->xclip.acquire_time);
1109 }
#define None
Definition: i386-dis.c:444
static void xclip_notify_change(RDPCLIENT *This)
Definition: xclip.c:335

◆ xclip_handle_PropertyNotify()

void xclip_handle_PropertyNotify ( RDPCLIENT This,
XPropertyEvent *  event 
)

Definition at line 779 of file xclip.c.

780 {
781  unsigned long nitems;
782  unsigned long offset = 0;
783  unsigned long bytes_left = 1;
784  int format;
785  XWindowAttributes wa;
786  uint8 *data;
787  Atom type;
788 
789  if (event->state == PropertyNewValue && This->xclip.waiting_for_INCR)
790  {
791  DEBUG_CLIPBOARD(("x_clip_handle_PropertyNotify: This->xclip.waiting_for_INCR != 0\n"));
792 
793  while (bytes_left > 0)
794  {
795  /* Unlike the specification, we don't set the 'delete' arugment to True
796  since we slurp the INCR's chunks in even-smaller chunks of 4096 bytes. */
797  if ((XGetWindowProperty
798  (This->display, This->wnd, This->xclip.rdesktop_clipboard_target_atom, offset, 4096L,
799  False, AnyPropertyType, &type, &format, &nitems, &bytes_left,
800  &data) != Success))
801  {
802  XFree(data);
803  return;
804  }
805 
806  if (nitems == 0)
807  {
808  /* INCR transfer finished */
809  XGetWindowAttributes(This->display, This->wnd, &wa);
810  XSelectInput(This->display, This->wnd,
811  (wa.your_event_mask ^ PropertyChangeMask));
812  XFree(data);
813  This->xclip.waiting_for_INCR = 0;
814 
815  if (This->xclip.clip_buflen > 0)
816  {
818  (This, This->xclip.clip_buffer, This->xclip.clip_buflen, This->xclip.incr_target))
819  {
821  }
822  xfree(This->xclip.clip_buffer);
823  This->xclip.clip_buffer = NULL;
824  This->xclip.clip_buflen = 0;
825  }
826  }
827  else
828  {
829  /* Another chunk in the INCR transfer */
830  offset += (nitems / 4); /* offset at which to begin the next slurp */
831  This->xclip.clip_buffer = xrealloc(This->xclip.clip_buffer, This->xclip.clip_buflen + nitems);
832  memcpy(This->xclip.clip_buffer + This->xclip.clip_buflen, data, nitems);
833  This->xclip.clip_buflen += nitems;
834 
835  XFree(data);
836  }
837  }
838  XDeleteProperty(This->display, This->wnd, This->xclip.rdesktop_clipboard_target_atom);
839  return;
840  }
841 
842  if ((event->atom == This->xclip.rdesktop_selection_notify_atom) &&
843  (event->window == DefaultRootWindow(This->display)))
845 }
static void xclip_probe_selections(RDPCLIENT *This)
Definition: xclip.c:342
GLintptr offset
Definition: glext.h:5920
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
_Out_ RTL_ATOM * Atom
Definition: class.h:54
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static void helper_cliprdr_send_empty_response(RDPCLIENT *This)
Definition: xclip.c:197
void * xrealloc(void *oldmem, size_t size)
Definition: uimain.c:736
#define DEBUG_CLIPBOARD(args)
Definition: rdesktop.h:147
smooth NULL
Definition: ftsmooth.c:416
#define False
Definition: types.h:25
void xfree(void *mem)
Definition: uimain.c:758
static Bool xclip_send_data_with_convert(RDPCLIENT *This, uint8 *source, size_t source_size, Atom target)
Definition: xclip.c:206
unsigned char uint8
Definition: types.h:28
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static const WCHAR L[]
Definition: oid.c:1250
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
struct _cl_event * event
Definition: glext.h:7739

Referenced by xwin_process_events().

◆ xclip_handle_SelectionClear()

void xclip_handle_SelectionClear ( RDPCLIENT This)

Definition at line 770 of file xclip.c.

771 {
772  DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));
775 }
static void xclip_probe_selections(RDPCLIENT *This)
Definition: xclip.c:342
#define DEBUG_CLIPBOARD(args)
Definition: rdesktop.h:147
static void xclip_notify_change(RDPCLIENT *This)
Definition: xclip.c:335

Referenced by xwin_process_events().

◆ xclip_handle_SelectionNotify()

void xclip_handle_SelectionNotify ( RDPCLIENT This,
XSelectionEvent *  event 
)

Definition at line 417 of file xclip.c.

418 {
419  unsigned long nitems, bytes_left;
420  XWindowAttributes wa;
421  Atom type;
422  Atom *supported_targets;
423  int res, i, format;
424  uint8 *data = NULL;
425 
426  if (event->property == None)
427  goto fail;
428 
429  DEBUG_CLIPBOARD(("xclip_handle_SelectionNotify: selection=%s, target=%s, property=%s\n",
430  XGetAtomName(This->display, event->selection),
431  XGetAtomName(This->display, event->target),
432  XGetAtomName(This->display, event->property)));
433 
434  if (event->target == This->xclip.timestamp_atom)
435  {
436  if (event->selection == This->xclip.primary_atom)
437  {
438  res = XGetWindowProperty(This->display, This->wnd,
439  This->xclip.rdesktop_primary_timestamp_target_atom, 0,
440  XMaxRequestSize(This->display), False, AnyPropertyType,
441  &type, &format, &nitems, &bytes_left, &data);
442  }
443  else
444  {
445  res = XGetWindowProperty(This->display, This->wnd,
446  This->xclip.rdesktop_clipboard_timestamp_target_atom, 0,
447  XMaxRequestSize(This->display), False, AnyPropertyType,
448  &type, &format, &nitems, &bytes_left, &data);
449  }
450 
451 
452  if ((res != Success) || (nitems != 1) || (format != 32))
453  {
454  DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
455  goto fail;
456  }
457 
458  if (event->selection == This->xclip.primary_atom)
459  {
460  This->xclip.primary_timestamp = *(Time *) data;
461  if (This->xclip.primary_timestamp == 0)
462  This->xclip.primary_timestamp++;
463  XDeleteProperty(This->display, This->wnd, This->xclip.rdesktop_primary_timestamp_target_atom);
464  DEBUG_CLIPBOARD(("Got PRIMARY timestamp: %u\n",
465  (unsigned) This->xclip.primary_timestamp));
466  }
467  else
468  {
469  This->xclip.clipboard_timestamp = *(Time *) data;
470  if (This->xclip.clipboard_timestamp == 0)
471  This->xclip.clipboard_timestamp++;
472  XDeleteProperty(This->display, This->wnd, This->xclip.rdesktop_clipboard_timestamp_target_atom);
473  DEBUG_CLIPBOARD(("Got CLIPBOARD timestamp: %u\n",
474  (unsigned) This->xclip.clipboard_timestamp));
475  }
476 
477  XFree(data);
478 
479  if (This->xclip.primary_timestamp && This->xclip.clipboard_timestamp)
480  {
481  if (This->xclip.primary_timestamp > This->xclip.clipboard_timestamp)
482  {
483  DEBUG_CLIPBOARD(("PRIMARY is most recent selection.\n"));
484  XConvertSelection(This->display, This->xclip.primary_atom, This->xclip.targets_atom,
485  This->xclip.rdesktop_clipboard_target_atom, This->wnd,
486  event->time);
487  }
488  else
489  {
490  DEBUG_CLIPBOARD(("CLIPBOARD is most recent selection.\n"));
491  XConvertSelection(This->display, This->xclip.clipboard_atom, This->xclip.targets_atom,
492  This->xclip.rdesktop_clipboard_target_atom, This->wnd,
493  event->time);
494  }
495  }
496 
497  return;
498  }
499 
500  if (This->xclip.probing_selections && This->xclip.reprobe_selections)
501  {
502  This->xclip.probing_selections = False;
504  return;
505  }
506 
507  res = XGetWindowProperty(This->display, This->wnd, This->xclip.rdesktop_clipboard_target_atom,
508  0, XMaxRequestSize(This->display), False, AnyPropertyType,
509  &type, &format, &nitems, &bytes_left, &data);
510 
512 
513  if (res != Success)
514  {
515  DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
516  goto fail;
517  }
518 
519  if (type == This->xclip.incr_atom)
520  {
521  DEBUG_CLIPBOARD(("Received INCR.\n"));
522 
523  XGetWindowAttributes(This->display, This->wnd, &wa);
524  if ((wa.your_event_mask | PropertyChangeMask) != wa.your_event_mask)
525  {
526  XSelectInput(This->display, This->wnd, (wa.your_event_mask | PropertyChangeMask));
527  }
528  XFree(data);
529  This->xclip.incr_target = event->target;
530  This->xclip.waiting_for_INCR = 1;
531  goto end;
532  }
533 
534  /* Negotiate target format */
535  if (event->target == This->xclip.targets_atom)
536  {
537  /* Determine the best of text This->xclip.targets that we have available:
538  Prefer UTF8_STRING > text/unicode (unspecified encoding) > STRING
539  (ignore TEXT and COMPOUND_TEXT because we don't have code to handle them)
540  */
541  int text_target_satisfaction = 0;
542  Atom best_text_target = 0; /* measures how much we're satisfied with what we found */
543  if (type != None)
544  {
545  supported_targets = (Atom *) data;
546  for (i = 0; i < nitems; i++)
547  {
548  DEBUG_CLIPBOARD(("Target %d: %s\n", i,
549  XGetAtomName(This->display, supported_targets[i])));
550  if (supported_targets[i] == This->xclip.format_string_atom)
551  {
552  if (text_target_satisfaction < 1)
553  {
554  DEBUG_CLIPBOARD(("Other party supports STRING, choosing that as best_target\n"));
555  best_text_target = supported_targets[i];
556  text_target_satisfaction = 1;
557  }
558  }
559 #ifdef USE_UNICODE_CLIPBOARD
560  else if (supported_targets[i] == This->xclip.format_unicode_atom)
561  {
562  if (text_target_satisfaction < 2)
563  {
564  DEBUG_CLIPBOARD(("Other party supports text/unicode, choosing that as best_target\n"));
565  best_text_target = supported_targets[i];
566  text_target_satisfaction = 2;
567  }
568  }
569  else if (supported_targets[i] == This->xclip.format_utf8_string_atom)
570  {
571  if (text_target_satisfaction < 3)
572  {
573  DEBUG_CLIPBOARD(("Other party supports UTF8_STRING, choosing that as best_target\n"));
574  best_text_target = supported_targets[i];
575  text_target_satisfaction = 3;
576  }
577  }
578 #endif
579  else if (supported_targets[i] == This->xclip.rdesktop_clipboard_formats_atom)
580  {
581  if (This->xclip.probing_selections && (text_target_satisfaction < 4))
582  {
583  DEBUG_CLIPBOARD(("Other party supports native formats, choosing that as best_target\n"));
584  best_text_target = supported_targets[i];
585  text_target_satisfaction = 4;
586  }
587  }
588  }
589  }
590 
591  /* Kickstarting the next step in the process of satisfying RDP's
592  clipboard request -- specifically, requesting the actual clipboard data.
593  */
594  if ((best_text_target != 0)
595  && (!This->xclip.probing_selections
596  || (best_text_target == This->xclip.rdesktop_clipboard_formats_atom)))
597  {
598  XConvertSelection(This->display, event->selection, best_text_target,
599  This->xclip.rdesktop_clipboard_target_atom, This->wnd, event->time);
600  goto end;
601  }
602  else
603  {
604  DEBUG_CLIPBOARD(("Unable to find a textual target to satisfy RDP clipboard text request\n"));
605  goto fail;
606  }
607  }
608  else
609  {
610  if (This->xclip.probing_selections)
611  {
612  Window primary_owner, clipboard_owner;
613 
614  /* FIXME:
615  Without XFIXES, we must make sure that the other
616  rdesktop owns all relevant selections or we might try
617  to get a native format from non-rdesktop window later
618  on. */
619 
620  clipboard_owner = XGetSelectionOwner(This->display, This->xclip.clipboard_atom);
621 
622  if (This->xclip.auto_mode)
623  primary_owner = XGetSelectionOwner(This->display, This->xclip.primary_atom);
624  else
625  primary_owner = clipboard_owner;
626 
627  if (primary_owner != clipboard_owner)
628  goto fail;
629 
630  DEBUG_CLIPBOARD(("Got fellow rdesktop formats\n"));
631  This->xclip.probing_selections = False;
632  This->xclip.rdesktop_is_selection_owner = True;
634  }
635  else if (!xclip_send_data_with_convert(This, data, nitems, event->target))
636  {
637  goto fail;
638  }
639  }
640 
641  end:
642  if (data)
643  XFree(data);
644 
645  return;
646 
647  fail:
649  if (This->xclip.probing_selections)
650  {
651  DEBUG_CLIPBOARD(("Unable to find suitable target. Using default text format.\n"));
652  This->xclip.probing_selections = False;
653  This->xclip.rdesktop_is_selection_owner = False;
654 
655  /* FIXME:
656  Without XFIXES, we cannot reliably know the formats offered by an
657  upcoming selection owner, so we just lie about him offering
658  RDP_CF_TEXT. */
660  }
661  else
662  {
664  }
665  goto end;
666 }
static void xclip_probe_selections(RDPCLIENT *This)
Definition: xclip.c:342
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
_Out_ RTL_ATOM * Atom
Definition: class.h:54
static void xclip_clear_target_props(RDPCLIENT *This)
Definition: xclip.c:327
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static void helper_cliprdr_send_empty_response(RDPCLIENT *This)
Definition: xclip.c:197
void cliprdr_send_native_format_announce(uint8 *formats_data, uint32 formats_data_length)
Definition: window.c:29
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define None
Definition: i386-dis.c:444
#define DEBUG_CLIPBOARD(args)
Definition: rdesktop.h:147
smooth NULL
Definition: ftsmooth.c:416
#define True
Definition: types.h:24
#define False
Definition: types.h:25
static Bool xclip_send_data_with_convert(RDPCLIENT *This, uint8 *source, size_t source_size, Atom target)
Definition: xclip.c:206
unsigned char uint8
Definition: types.h:28
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
struct _cl_event * event
Definition: glext.h:7739
#define RDP_CF_TEXT
Definition: xclip.c:48
void cliprdr_send_simple_native_format_announce(uint32 format)
GLuint res
Definition: glext.h:9613
static PLARGE_INTEGER Time
Definition: time.c:105

Referenced by xwin_process_events().

◆ xclip_handle_SelectionRequest()

void xclip_handle_SelectionRequest ( RDPCLIENT This,
XSelectionRequestEvent *  event 
)

Definition at line 673 of file xclip.c.

674 {
675  unsigned long nitems, bytes_left;
676  unsigned char *prop_return;
677  int format, res;
678  Atom type;
679 
680  DEBUG_CLIPBOARD(("xclip_handle_SelectionRequest: selection=%s, target=%s, property=%s\n",
681  XGetAtomName(This->display, event->selection),
682  XGetAtomName(This->display, event->target),
683  XGetAtomName(This->display, event->property)));
684 
685  if (event->target == This->xclip.targets_atom)
686  {
687  xclip_provide_selection(This, event, XA_ATOM, 32, (uint8 *) & This->xclip.targets, This->xclip.num_targets);
688  return;
689  }
690  else if (event->target == This->xclip.timestamp_atom)
691  {
692  xclip_provide_selection(This, event, XA_INTEGER, 32, (uint8 *) & This->xclip.acquire_time, 1);
693  return;
694  }
695  else if (event->target == This->xclip.rdesktop_clipboard_formats_atom)
696  {
697  xclip_provide_selection(This, event, XA_STRING, 8, This->xclip.formats_data, This->xclip.formats_data_length);
698  }
699  else
700  {
701  /* All the following This->xclip.targets require an async operation with the RDP server
702  and currently we don't do X clipboard request queueing so we can only
703  handle one such request at a time. */
704  if (This->xclip.has_selection_request)
705  {
706  DEBUG_CLIPBOARD(("Error: Another clipboard request was already sent to the RDP server and not yet responded. Refusing this request.\n"));
708  return;
709  }
710  if (event->target == This->xclip.rdesktop_native_atom)
711  {
712  /* Before the requestor makes a request for the _RDESKTOP_NATIVE target,
713  he should declare requestor[property] = CF_SOMETHING. */
714  res = XGetWindowProperty(This->display, event->requestor,
715  event->property, 0, 1, True,
716  XA_INTEGER, &type, &format, &nitems, &bytes_left,
717  &prop_return);
718  if (res != Success)
719  {
720  DEBUG_CLIPBOARD(("Requested native format but didn't specifiy which.\n"));
722  return;
723  }
724 
725  format = *(uint32 *) prop_return;
726  XFree(prop_return);
727  }
728  else if (event->target == This->xclip.format_string_atom || event->target == XA_STRING)
729  {
730  /* STRING and XA_STRING are defined to be ISO8859-1 */
731  format = CF_TEXT;
732  }
733  else if (event->target == This->xclip.format_utf8_string_atom)
734  {
735 #ifdef USE_UNICODE_CLIPBOARD
737 #else
738  DEBUG_CLIPBOARD(("Requested target unavailable due to lack of Unicode support. (It was not in TARGETS, so why did you ask for it?!)\n"));
740  return;
741 #endif
742  }
743  else if (event->target == This->xclip.format_unicode_atom)
744  {
745  /* Assuming text/unicode to be UTF-16 */
747  }
748  else
749  {
750  DEBUG_CLIPBOARD(("Requested target unavailable. (It was not in TARGETS, so why did you ask for it?!)\n"));
752  return;
753  }
754 
756  This->xclip.selection_request = *event;
757  This->xclip.has_selection_request = True;
758  return; /* wait for data */
759  }
760 }
unsigned int uint32
Definition: types.h:32
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
_Out_ RTL_ATOM * Atom
Definition: class.h:54
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static void xclip_provide_selection(RDPCLIENT *This, XSelectionRequestEvent *req, Atom type, unsigned int format, uint8 *data, uint32 length)
Definition: xclip.c:136
void cliprdr_send_data_request(uint32 format)
#define DEBUG_CLIPBOARD(args)
Definition: rdesktop.h:147
#define CF_UNICODETEXT
Definition: constants.h:408
#define CF_TEXT
Definition: constants.h:396
#define True
Definition: types.h:24
unsigned char uint8
Definition: types.h:28
struct _cl_event * event
Definition: glext.h:7739
static void xclip_refuse_selection(RDPCLIENT *This, XSelectionRequestEvent *req)
Definition: xclip.c:161
GLuint res
Definition: glext.h:9613

Referenced by xwin_process_events().

◆ xclip_init()

void xclip_init ( RDPCLIENT This)

Definition at line 1052 of file xclip.c.

1053 {
1054  if (!This->rdpclip)
1055  return;
1056 
1057  if (!cliprdr_init(This))
1058  return;
1059 
1060  This->xclip.primary_atom = XInternAtom(This->display, "PRIMARY", False);
1061  This->xclip.clipboard_atom = XInternAtom(This->display, "CLIPBOARD", False);
1062  This->xclip.targets_atom = XInternAtom(This->display, "TARGETS", False);
1063  This->xclip.timestamp_atom = XInternAtom(This->display, "TIMESTAMP", False);
1064  This->xclip.rdesktop_clipboard_target_atom =
1065  XInternAtom(This->display, "_RDESKTOP_CLIPBOARD_TARGET", False);
1066  This->xclip.rdesktop_primary_timestamp_target_atom =
1067  XInternAtom(This->display, "_RDESKTOP_PRIMARY_TIMESTAMP_TARGET", False);
1068  This->xclip.rdesktop_clipboard_timestamp_target_atom =
1069  XInternAtom(This->display, "_RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET", False);
1070  This->xclip.incr_atom = XInternAtom(This->display, "INCR", False);
1071  This->xclip.format_string_atom = XInternAtom(This->display, "STRING", False);
1072  This->xclip.format_utf8_string_atom = XInternAtom(This->display, "UTF8_STRING", False);
1073  This->xclip.format_unicode_atom = XInternAtom(This->display, "text/unicode", False);
1074 
1075  /* rdesktop sets _RDESKTOP_SELECTION_NOTIFY on the root window when acquiring the clipboard.
1076  Other interested rdesktops can use this to notify their server of the available formats. */
1077  This->xclip.rdesktop_selection_notify_atom =
1078  XInternAtom(This->display, "_RDESKTOP_SELECTION_NOTIFY", False);
1079  XSelectInput(This->display, DefaultRootWindow(This->display), PropertyChangeMask);
1080  This->xclip.probing_selections = False;
1081 
1082  This->xclip.rdesktop_native_atom = XInternAtom(This->display, "_RDESKTOP_NATIVE", False);
1083  This->xclip.rdesktop_clipboard_formats_atom =
1084  XInternAtom(This->display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
1085  This->xclip.rdesktop_primary_owner_atom = XInternAtom(This->display, "_RDESKTOP_PRIMARY_OWNER", False);
1086  This->xclip.rdesktop_clipboard_owner_atom = XInternAtom(This->display, "_RDESKTOP_CLIPBOARD_OWNER", False);
1087 
1088  This->xclip.num_targets = 0;
1089  This->xclip.targets[This->xclip.num_targets++] = This->xclip.targets_atom;
1090  This->xclip.targets[This->xclip.num_targets++] = This->xclip.timestamp_atom;
1091  This->xclip.targets[This->xclip.num_targets++] = This->xclip.rdesktop_native_atom;
1092  This->xclip.targets[This->xclip.num_targets++] = This->xclip.rdesktop_clipboard_formats_atom;
1093 #ifdef USE_UNICODE_CLIPBOARD
1094  This->xclip.targets[This->xclip.num_targets++] = This->xclip.format_utf8_string_atom;
1095 #endif
1096  This->xclip.targets[This->xclip.num_targets++] = This->xclip.format_unicode_atom;
1097  This->xclip.targets[This->xclip.num_targets++] = This->xclip.format_string_atom;
1098  This->xclip.targets[This->xclip.num_targets++] = XA_STRING;
1099 }
RD_BOOL cliprdr_init(void)
#define False
Definition: types.h:25

◆ xclip_notify_change()

static void xclip_notify_change ( RDPCLIENT This)
static

Definition at line 335 of file xclip.c.

336 {
337  XChangeProperty(This->display, DefaultRootWindow(This->display),
338  This->xclip.rdesktop_selection_notify_atom, XA_INTEGER, 32, PropModeReplace, NULL, 0);
339 }
smooth NULL
Definition: ftsmooth.c:416

Referenced by ui_clip_format_announce(), xclip_deinit(), and xclip_handle_SelectionClear().

◆ xclip_probe_selections()

static void xclip_probe_selections ( RDPCLIENT This)
static

Definition at line 342 of file xclip.c.

343 {
344  Window primary_owner, clipboard_owner;
345 
346  if (This->xclip.probing_selections)
347  {
348  DEBUG_CLIPBOARD(("Already probing selections. Scheduling reprobe.\n"));
349  This->xclip.reprobe_selections = True;
350  return;
351  }
352 
353  DEBUG_CLIPBOARD(("Probing selections.\n"));
354 
355  This->xclip.probing_selections = True;
356  This->xclip.reprobe_selections = False;
357 
359 
360  if (This->xclip.auto_mode)
361  primary_owner = XGetSelectionOwner(This->display, This->xclip.primary_atom);
362  else
363  primary_owner = None;
364 
365  clipboard_owner = XGetSelectionOwner(This->display, This->xclip.clipboard_atom);
366 
367  /* If we own all relevant selections then don't do anything. */
368  if (((primary_owner == This->wnd) || !This->xclip.auto_mode) && (clipboard_owner == This->wnd))
369  goto end;
370 
371  /* Both available */
372  if ((primary_owner != None) && (clipboard_owner != None))
373  {
374  This->xclip.primary_timestamp = 0;
375  This->xclip.clipboard_timestamp = 0;
376  XConvertSelection(This->display, This->xclip.primary_atom, This->xclip.timestamp_atom,
377  This->xclip.rdesktop_primary_timestamp_target_atom, This->wnd, CurrentTime);
378  XConvertSelection(This->display, This->xclip.clipboard_atom, This->xclip.timestamp_atom,
379  This->xclip.rdesktop_clipboard_timestamp_target_atom, This->wnd, CurrentTime);
380  return;
381  }
382 
383  /* Just PRIMARY */
384  if (primary_owner != None)
385  {
386  XConvertSelection(This->display, This->xclip.primary_atom, This->xclip.targets_atom,
387  This->xclip.rdesktop_clipboard_target_atom, This->wnd, CurrentTime);
388  return;
389  }
390 
391  /* Just CLIPBOARD */
392  if (clipboard_owner != None)
393  {
394  XConvertSelection(This->display, This->xclip.clipboard_atom, This->xclip.targets_atom,
395  This->xclip.rdesktop_clipboard_target_atom, This->wnd, CurrentTime);
396  return;
397  }
398 
399  DEBUG_CLIPBOARD(("No owner of any selection.\n"));
400 
401  /* FIXME:
402  Without XFIXES, we cannot reliably know the formats offered by an
403  upcoming selection owner, so we just lie about him offering
404  RDP_CF_TEXT. */
406 
407  end:
408  This->xclip.probing_selections = False;
409 }
GLuint GLuint end
Definition: gl.h:1545
static void xclip_clear_target_props(RDPCLIENT *This)
Definition: xclip.c:327
Definition: window.c:29
#define None
Definition: i386-dis.c:444
#define DEBUG_CLIPBOARD(args)
Definition: rdesktop.h:147
#define True
Definition: types.h:24
#define False
Definition: types.h:25
#define RDP_CF_TEXT
Definition: xclip.c:48
void cliprdr_send_simple_native_format_announce(uint32 format)

Referenced by ui_clip_sync(), xclip_handle_PropertyNotify(), xclip_handle_SelectionClear(), and xclip_handle_SelectionNotify().

◆ xclip_provide_selection()

static void xclip_provide_selection ( RDPCLIENT This,
XSelectionRequestEvent *  req,
Atom  type,
unsigned int  format,
uint8 data,
uint32  length 
)
static

Definition at line 136 of file xclip.c.

138 {
139  XEvent xev;
140 
141  DEBUG_CLIPBOARD(("xclip_provide_selection: requestor=0x%08x, target=%s, property=%s, length=%u\n", (unsigned) req->requestor, XGetAtomName(This->display, req->target), XGetAtomName(This->display, req->property), (unsigned) length));
142 
143  XChangeProperty(This->display, req->requestor, req->property,
144  type, format, PropModeReplace, data, length);
145 
146  xev.xselection.type = SelectionNotify;
147  xev.xselection.serial = 0;
148  xev.xselection.send_event = True;
149  xev.xselection.requestor = req->requestor;
150  xev.xselection.selection = req->selection;
151  xev.xselection.target = req->target;
152  xev.xselection.property = req->property;
153  xev.xselection.time = req->time;
154  XSendEvent(This->display, req->requestor, False, NoEventMask, &xev);
155 }
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define DEBUG_CLIPBOARD(args)
Definition: rdesktop.h:147
#define True
Definition: types.h:24
#define False
Definition: types.h:25
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950

Referenced by ui_clip_handle_data(), and xclip_handle_SelectionRequest().

◆ xclip_refuse_selection()

static void xclip_refuse_selection ( RDPCLIENT This,
XSelectionRequestEvent *  req 
)
static

Definition at line 161 of file xclip.c.

162 {
163  XEvent xev;
164 
165  DEBUG_CLIPBOARD(("xclip_refuse_selection: requestor=0x%08x, target=%s, property=%s\n",
166  (unsigned) req->requestor, XGetAtomName(This->display, req->target),
167  XGetAtomName(This->display, req->property)));
168 
169  xev.xselection.type = SelectionNotify;
170  xev.xselection.serial = 0;
171  xev.xselection.send_event = True;
172  xev.xselection.requestor = req->requestor;
173  xev.xselection.selection = req->selection;
174  xev.xselection.target = req->target;
175  xev.xselection.property = None;
176  xev.xselection.time = req->time;
177  XSendEvent(This->display, req->requestor, False, NoEventMask, &xev);
178 }
#define None
Definition: i386-dis.c:444
#define DEBUG_CLIPBOARD(args)
Definition: rdesktop.h:147
#define True
Definition: types.h:24
#define False
Definition: types.h:25

Referenced by ui_clip_handle_data(), ui_clip_request_failed(), and xclip_handle_SelectionRequest().

◆ xclip_send_data_with_convert()

static Bool xclip_send_data_with_convert ( RDPCLIENT This,
uint8 source,
size_t  source_size,
Atom  target 
)
static

Definition at line 206 of file xclip.c.

207 {
208  DEBUG_CLIPBOARD(("xclip_send_data_with_convert: target=%s, size=%u\n",
209  XGetAtomName(This->display, target), (unsigned) source_size));
210 
211 #ifdef USE_UNICODE_CLIPBOARD
212  if (target == This->xclip.format_string_atom ||
213  target == This->xclip.format_unicode_atom || target == This->xclip.format_utf8_string_atom)
214  {
215  size_t unicode_buffer_size;
216  char *unicode_buffer;
217  iconv_t cd;
218  size_t unicode_buffer_size_remaining;
219  char *unicode_buffer_remaining;
220  char *data_remaining;
221  size_t data_size_remaining;
222  uint32 translated_data_size;
223  uint8 *translated_data;
224 
225  if (This->xclip.rdp_clipboard_request_format != RDP_CF_TEXT)
226  return False;
227 
228  /* Make an attempt to convert any string we send to Unicode.
229  We don't know what the RDP server's ANSI Codepage is, or how to convert
230  to it, so using CF_TEXT is not safe (and is unnecessary, since all
231  WinNT versions are Unicode-minded).
232  */
233  if (target == This->xclip.format_string_atom)
234  {
235  char *locale_charset = nl_langinfo(CODESET);
236  cd = iconv_open(WINDOWS_CODEPAGE, locale_charset);
237  if (cd == (iconv_t) - 1)
238  {
239  DEBUG_CLIPBOARD(("Locale charset %s not found in iconv. Unable to convert clipboard text.\n", locale_charset));
240  return False;
241  }
242  unicode_buffer_size = source_size * 4;
243  }
244  else if (target == This->xclip.format_unicode_atom)
245  {
246  cd = iconv_open(WINDOWS_CODEPAGE, "UCS-2");
247  if (cd == (iconv_t) - 1)
248  {
249  return False;
250  }
251  unicode_buffer_size = source_size;
252  }
253  else if (target == This->xclip.format_utf8_string_atom)
254  {
255  cd = iconv_open(WINDOWS_CODEPAGE, "UTF-8");
256  if (cd == (iconv_t) - 1)
257  {
258  return False;
259  }
260  /* UTF-8 is guaranteed to be less or equally compact
261  as UTF-16 for all Unicode chars >=2 bytes.
262  */
263  unicode_buffer_size = source_size * 2;
264  }
265  else
266  {
267  return False;
268  }
269 
270  unicode_buffer = xmalloc(unicode_buffer_size);
271  unicode_buffer_size_remaining = unicode_buffer_size;
272  unicode_buffer_remaining = unicode_buffer;
273  data_remaining = (char *) source;
274  data_size_remaining = source_size;
275  iconv(cd, (ICONV_CONST char **) &data_remaining, &data_size_remaining,
276  &unicode_buffer_remaining, &unicode_buffer_size_remaining);
277  iconv_close(cd);
278 
279  /* translate linebreaks */
280  translated_data_size = unicode_buffer_size - unicode_buffer_size_remaining;
281  translated_data = utf16_lf2crlf((uint8 *) unicode_buffer, &translated_data_size);
282  if (translated_data != NULL)
283  {
284  DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n",
285  translated_data_size));
286  helper_cliprdr_send_response(This, translated_data, translated_data_size);
287  xfree(translated_data); /* Not the same thing as XFree! */
288  }
289 
290  xfree(unicode_buffer);
291 
292  return True;
293  }
294 #else
295  if (target == This->xclip.format_string_atom)
296  {
297  uint8 *translated_data;
298  uint32 length = source_size;
299 
300  if (This->xclip.rdp_clipboard_request_format != RDP_CF_TEXT)
301  return False;
302 
303  DEBUG_CLIPBOARD(("Translating linebreaks before sending data\n"));
304  translated_data = lf2crlf(source, &length);
305  if (translated_data != NULL)
306  {
307  helper_cliprdr_send_response(This, translated_data, length);
308  xfree(translated_data); /* Not the same thing as XFree! */
309  }
310 
311  return True;
312  }
313 #endif
314  else if (target == This->xclip.rdesktop_native_atom)
315  {
316  helper_cliprdr_send_response(This, source, source_size + 1);
317 
318  return True;
319  }
320  else
321  {
322  return False;
323  }
324 }
static uint8 * lf2crlf(uint8 *data, uint32 *length)
Definition: xclip.c:110
static struct cd_image cd
Definition: cdmake.c:182
unsigned int uint32
Definition: types.h:32
size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
Definition: win_iconv.c:771
void * xmalloc(int size)
Definition: uimain.c:747
#define DEBUG_CLIPBOARD(args)
Definition: rdesktop.h:147
smooth NULL
Definition: ftsmooth.c:416
#define True
Definition: types.h:24
#define False
Definition: types.h:25
void xfree(void *mem)
Definition: uimain.c:758
#define WINDOWS_CODEPAGE
Definition: constants.h:24
#define ICONV_CONST
Definition: win32config.h:27
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
unsigned char uint8
Definition: types.h:28
iconv_t iconv_open(const char *tocode, const char *fromcode)
Definition: win_iconv.c:730
#define RDP_CF_TEXT
Definition: xclip.c:48
GLenum target
Definition: glext.h:7315
int iconv_close(iconv_t cd)
Definition: win_iconv.c:756
static void helper_cliprdr_send_response(RDPCLIENT *This, uint8 *data, uint32 length)
Definition: xclip.c:182

Referenced by xclip_handle_PropertyNotify(), and xclip_handle_SelectionNotify().