summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2016-01-13 12:19:13 +0100
committerPierre Ossman <ossman@cendio.se>2016-02-05 10:35:42 +0100
commitee04c6dd550b9198c37c78c14d41e52c29d7c5a7 (patch)
treee93380cc8fd95ae215bfa6e5015705721bcc3c48 /unix
parent419091c40550903b23612ddb95eab128936e8467 (diff)
downloadtigervnc-ee04c6dd550b9198c37c78c14d41e52c29d7c5a7.tar.gz
tigervnc-ee04c6dd550b9198c37c78c14d41e52c29d7c5a7.zip
Support UTF8_STRING selection target type
The protocol still only supports 8859-1 though, so we need to convert things to and from UTF-8.
Diffstat (limited to 'unix')
-rw-r--r--unix/xserver/hw/vnc/vncSelection.c95
1 files changed, 93 insertions, 2 deletions
diff --git a/unix/xserver/hw/vnc/vncSelection.c b/unix/xserver/hw/vnc/vncSelection.c
index 6faff1ee..cea8ecf2 100644
--- a/unix/xserver/hw/vnc/vncSelection.c
+++ b/unix/xserver/hw/vnc/vncSelection.c
@@ -42,7 +42,7 @@
#define LOG_DEBUG(...) vncLogDebug(LOG_NAME, __VA_ARGS__)
static Atom xaPRIMARY, xaCLIPBOARD;
-static Atom xaTARGETS, xaTIMESTAMP, xaSTRING, xaTEXT;
+static Atom xaTARGETS, xaTIMESTAMP, xaSTRING, xaTEXT, xaUTF8_STRING;
static WindowPtr pWindow;
static Window wid;
@@ -69,6 +69,7 @@ void vncSelectionInit(void)
xaTIMESTAMP = MakeAtom("TIMESTAMP", 9, TRUE);
xaSTRING = MakeAtom("STRING", 6, TRUE);
xaTEXT = MakeAtom("TEXT", 4, TRUE);
+ xaUTF8_STRING = MakeAtom("UTF8_STRING", 11, TRUE);
/* There are no hooks for when these are internal windows, so
* override the relevant handlers. */
@@ -223,7 +224,8 @@ static int vncConvertSelection(ClientPtr client, Atom selection,
/* FIXME: MULTIPLE target */
if (target == xaTARGETS) {
- Atom targets[] = { xaTARGETS, xaTIMESTAMP, xaSTRING, xaTEXT };
+ Atom targets[] = { xaTARGETS, xaTIMESTAMP,
+ xaSTRING, xaTEXT, xaUTF8_STRING };
rc = ChangeWindowProperty(pWin, realProperty, XA_ATOM, 32,
PropModeReplace,
@@ -244,6 +246,41 @@ static int vncConvertSelection(ClientPtr client, Atom selection,
clientCutText, TRUE);
if (rc != Success)
return rc;
+ } else if (target == xaUTF8_STRING) {
+ unsigned char* buffer;
+ unsigned char* out;
+ size_t len;
+
+ const unsigned char* in;
+ size_t in_len;
+
+ buffer = malloc(clientCutTextLen*2);
+ if (buffer == NULL)
+ return BadAlloc;
+
+ out = buffer;
+ len = 0;
+ in = clientCutText;
+ in_len = clientCutTextLen;
+ while (in_len > 0) {
+ if (*in & 0x80) {
+ *out++ = 0xc0 | (*in >> 6);
+ *out++ = 0x80 | (*in & 0x3f);
+ len += 2;
+ in++;
+ in_len--;
+ } else {
+ *out++ = *in++;
+ len++;
+ in_len--;
+ }
+ }
+
+ rc = ChangeWindowProperty(pWin, realProperty, xaUTF8_STRING, 8,
+ PropModeReplace, len, buffer, TRUE);
+ free(buffer);
+ if (rc != Success)
+ return rc;
} else {
return BadMatch;
}
@@ -372,6 +409,8 @@ static void vncHandleSelection(Atom selection, Atom target,
if (vncHasAtom(xaSTRING, (const Atom*)prop->data, prop->size))
vncSelectionRequest(selection, xaSTRING);
+ else if (vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size))
+ vncSelectionRequest(selection, xaUTF8_STRING);
} else if (target == xaSTRING) {
if (prop->format != 8)
return;
@@ -379,6 +418,58 @@ static void vncHandleSelection(Atom selection, Atom target,
return;
vncServerCutText(prop->data, prop->size);
+ } else if (target == xaUTF8_STRING) {
+ unsigned char* buffer;
+ unsigned char* out;
+ size_t len;
+
+ const unsigned char* in;
+ size_t in_len;
+
+ if (prop->format != 8)
+ return;
+ if (prop->type != xaUTF8_STRING)
+ return;
+
+ buffer = malloc(prop->size);
+ if (buffer == NULL)
+ return;
+
+ out = buffer;
+ len = 0;
+ in = prop->data;
+ in_len = prop->size;
+ while (in_len > 0) {
+ if ((*in & 0x80) == 0x00) {
+ *out++ = *in++;
+ len++;
+ in_len--;
+ } else if ((*in & 0xe0) == 0xc0) {
+ unsigned ucs;
+ ucs = (*in++ & 0x1f) << 6;
+ in_len--;
+ if (in_len > 0) {
+ ucs |= (*in++ & 0x3f);
+ in_len--;
+ }
+ if (ucs <= 0xff)
+ *out++ = ucs;
+ else
+ *out++ = '?';
+ len++;
+ } else {
+ *out++ = '?';
+ len++;
+ do {
+ in++;
+ in_len--;
+ } while ((in_len > 0) && ((*in & 0xc0) == 0x80));
+ }
+ }
+
+ vncServerCutText((const char*)buffer, len);
+
+ free(buffer);
}
}