}
}
+
+static Atom xa_targets, xa_timestamp, xa_text, xa_compound_text;
+
+/*
+ * Set the required variable atoms at start-up to avoid errors later.
+ */
+static void set_atoms(void)
+{
+ xa_targets = XInternAtom(DPY, "TARGETS", False);
+ xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False);
+ xa_text = XInternAtom(DPY, "TEXT", False);
+ xa_compound_text = XInternAtom(DPY, "COMPOUND_TEXT", False);
+}
+
+
+static Atom request_target = 0;
+
/*
* Send a message to request that the PRIMARY buffer be sent here.
*/
-static void paste_x11_request(const Time time)
+static void paste_x11_request(Atom target, const Time time)
{
+ /*
+ * It's from some sample programs on the web.
+ * What does it mean? -- XXX
+ */
+ Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
+
/* Check the owner. */
- if (XGetSelectionOwner(Metadpy->dpy, XA_PRIMARY) == None)
+ if (XGetSelectionOwner(DPY, XA_PRIMARY) == None)
{
/* No selection. */
/* bell("No selection found."); */
return;
}
- /* Request the event as a STRING. */
- XConvertSelection(DPY, XA_PRIMARY, XA_STRING, XA_STRING, WIN, time);
+ request_target = target;
+
+ /* Request the event */
+ XConvertSelection(DPY, XA_PRIMARY, target, property, WIN, time);
+}
+
+
+/*
+ * Add the contents of the PRIMARY buffer to the input queue.
+ *
+ * Hack - This doesn't use the "time" of the event, and so accepts anything a
+ * client tries to send it.
+ */
+static void paste_x11_accept(const XSelectionEvent *ptr)
+{
+ unsigned long left;
+ const long offset = 0;
+ const long length = 32000;
+ XTextProperty xtextproperty;
+ errr err = 0;
+
+ /*
+ * It's from some sample programs on the web.
+ * What does it mean? -- XXX
+ */
+ Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
+
+
+ /* Failure. */
+ if (ptr->property == None)
+ {
+ if (request_target == xa_compound_text)
+ {
+ /* Re-request as STRING */
+ paste_x11_request(XA_STRING, ptr->time);
+ }
+ else
+ {
+ request_target = 0;
+ plog("Paste failure (remote client could not send).");
+ }
+ return;
+ }
+
+ if (ptr->selection != XA_PRIMARY)
+ {
+ plog("Paste failure (remote client did not send primary selection).");
+ return;
+ }
+
+ if (ptr->target != request_target)
+ {
+ plog("Paste failure (selection in unknown format).");
+ return;
+ }
+
+ /* Get text */
+ if (XGetWindowProperty(Metadpy->dpy, Infowin->win, property, offset,
+ length, TRUE, request_target,
+ &xtextproperty.encoding,
+ &xtextproperty.format,
+ &xtextproperty.nitems,
+ &left,
+ &xtextproperty.value)
+ != Success)
+ {
+ /* Failure */
+ return;
+ }
+
+ if (request_target == xa_compound_text)
+ {
+ char **list;
+ int count;
+
+ XmbTextPropertyToTextList(DPY, &xtextproperty, &list, &count);
+
+ if (list)
+ {
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ /* Paste the text. */
+ err = type_string(list[i], 0);
+
+ if (err) break;
+ }
+
+ /* Free the string */
+ XFreeStringList(list);
+ }
+ }
+ else /* if (request_target == XA_STRING) */
+ {
+ /* Paste the text. */
+ err = type_string((char *)xtextproperty.value, xtextproperty.nitems);
+ }
+
+ /* Free the data pasted. */
+ XFree(xtextproperty.value);
+
+ /* No room. */
+ if (err)
+ {
+ plog("Paste failure (too much text selected).");
+ }
}
+
/*
* Add a character to a string in preparation for sending it to another
* client as a STRING.
* receiving this format (although the standard specifies a restricted set).
* Strings do not have a colour.
*/
-static int add_char_string(char *buf, byte a, char c)
-{
- (void)a;
-
- *buf = c;
- return 1;
-}
-
-static bool paste_x11_send_text(XSelectionRequestEvent *rq, int (*add)(char *, byte, char))
+static bool paste_x11_send_text(XSelectionRequestEvent *rq)
{
char buf[1024];
+ char *list[1000];
co_ord max, min;
- int x,y,l;
+ int x,y,l,n;
byte a;
char c;
/* Too old, or incorrect call. */
- if (rq->time < s_ptr->time || !add) return FALSE;
+ if (rq->time < s_ptr->time) return FALSE;
/* Work out which way around to paste. */
sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
/* Delete the old value of the property. */
XDeleteProperty(DPY, rq->requestor, rq->property);
- for (y = 0; y < Term->hgt; y++)
+ for (n = 0, y = 0; y < Term->hgt; y++)
{
+#ifdef JP
+ int kanji = 0;
+#endif
if (y < min.y) continue;
if (y > max.y) break;
- for (x = l = 0; x < Term->wid; x++)
+ for (l = 0, x = 0; x < Term->wid; x++)
{
+#ifdef JP
+ if (x > max.x) break;
+
+ /* Find the character. */
+ Term_what(x, y, &a, &c);
+
+ if (1 == kanji) kanji = 2;
+ else if (iskanji(c)) kanji = 1;
+ else kanji = 0;
+
if (x < min.x) continue;
+
+ /*
+ * A single kanji character was divided in two...
+ * Delete the garbage.
+ */
+ if ((2 == kanji && x == min.x) ||
+ (1 == kanji && x == max.x))
+ c = ' ';
+#else
if (x > max.x) break;
+ if (x < min.x) continue;
/* Find the character. */
Term_what(x, y, &a, &c);
+#endif
/* Add it. */
- l += (*add)(buf+l, a, c);
+ buf[l] = c;
+ l++;
}
-#if 0
- /* Terminate all but the last line in an appropriate way. */
- if (y != max.y) l += (*add)(buf+l, TERM_WHITE, '\n');
-#else
- /* Terminate all line unless single line message. */
- if (min.y != max.y) l += (*add)(buf+l, TERM_WHITE, '\n');
-#endif
+ /* Ignore trailing spaces */
+ while (buf[l-1] == ' ') l--;
- /* Send the (non-empty) string. */
- XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8,
- PropModeAppend, (byte*)buf, l);
+ /* Terminate all line unless it's single line. */
+ if (min.y != max.y)
+ {
+ buf[l] = '\n';
+ l++;
+ }
+
+ /* End of string */
+ buf[l] = '\0';
+
+ list[n++] = (char *)string_make(buf);
}
- return TRUE;
-}
-static Atom xa_targets, xa_timestamp;
+ /* End of the list */
+ list[n] = NULL;
-/*
- * Set the required variable atoms at start-up to avoid errors later.
- */
-static void set_atoms(void)
-{
- xa_targets = XInternAtom(DPY, "TARGETS", False);
- xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False);
+
+ if (rq->target == XA_STRING)
+ {
+ for (n = 0; list[n]; n++)
+ {
+ /* Send the (non-empty) string. */
+ XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8,
+ PropModeAppend, (unsigned char *)list[n], strlen(list[n]));
+ }
+ }
+
+ else if (rq->target == xa_text ||
+ rq->target == xa_compound_text)
+ {
+ XTextProperty text_prop;
+ XICCEncodingStyle style;
+
+ if (rq->target == xa_text)
+ style = XStdICCTextStyle;
+ else /* if (rq->target == xa_compound_text) */
+ style = XCompoundTextStyle;
+
+ if (Success ==
+ XmbTextListToTextProperty(DPY, list, n, style, &text_prop))
+ {
+ /* Send the compound text */
+ XChangeProperty(DPY,
+ rq->requestor,
+ rq->property,
+ text_prop.encoding,
+ text_prop.format,
+ PropModeAppend,
+ text_prop.value,
+ text_prop.nitems);
+
+ /* Free the data. */
+ XFree(text_prop.value);
+ }
+ }
+
+ /* Free the list of strings */
+ for (n = 0; list[n]; n++)
+ {
+ string_free(list[n]);
+ }
+
+ return TRUE;
}
/*
* Note that this currently rejects MULTIPLE targets.
*/
- if (rq->target == XA_STRING)
+ if (rq->target == XA_STRING ||
+ rq->target == xa_text ||
+ rq->target == xa_compound_text)
{
- if (!paste_x11_send_text(rq, add_char_string))
+ if (!paste_x11_send_text(rq))
ptr->property = None;
}
else if (rq->target == xa_targets)
{
- Atom target_list[2];
+ Atom target_list[4];
target_list[0] = XA_STRING;
- target_list[1] = xa_targets;
+ target_list[1] = xa_text;
+ target_list[2] = xa_compound_text;
+ target_list[3] = xa_targets;
XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
(8 * sizeof(target_list[0])), PropModeReplace,
(unsigned char *)target_list,
XSendEvent(DPY, rq->requestor, FALSE, NoEventMask, &event);
}
-/*
- * Add the contents of the PRIMARY buffer to the input queue.
- *
- * Hack - This doesn't use the "time" of the event, and so accepts anything a
- * client tries to send it.
- */
-static void paste_x11_accept(const XSelectionEvent *ptr)
-{
- unsigned long offset, left;
-
- /* Failure. */
- if (ptr->property == None)
- {
- /* bell("Paste failure (remote client could not send)."); */
- return;
- }
-
- if (ptr->selection != XA_PRIMARY)
- {
- /* bell("Paste failure (remote client did not send primary selection)."); */
- return;
- }
-
- if (ptr->target != XA_STRING)
- {
- /* bell("Paste failure (selection in unknown format)."); */
- return;
- }
-
- for (offset = 0; ; offset += left)
- {
- errr err;
-
- /* A pointer for the pasted information. */
- unsigned char *data;
-
- Atom type;
- int fmt;
- unsigned long nitems;
-
- /* Set data to the string, and catch errors. */
- if (XGetWindowProperty(Metadpy->dpy, Infowin->win, XA_STRING, offset,
- 32767, TRUE, XA_STRING, &type, &fmt, &nitems, &left, &data)
- != Success) break;
-
- /* Paste the text. */
- err = type_string((char*)data, nitems);
-
- /* Free the data pasted. */
- XFree(data);
-
- /* No room. */
- if (err == PARSE_ERROR_OUT_OF_MEMORY)
- {
- /* bell("Paste failure (too much text selected)."); */
- break;
- }
- /* Paranoia? - strange errors. */
- else if (err)
- {
- break;
- }
-
- /* Pasted everything. */
- if (!left) return;
- }
-
- /* An error has occurred, so free the last bit of data before returning. */
- XFree(data);
-}
/*
* Handle various events conditional on presses of a mouse button.
if (press && button == 1) copy_x11_start(x, y);
if (!press && button == 1) copy_x11_end(time);
- if (!press && button == 2) paste_x11_request(time);
+ if (!press && button == 2) paste_x11_request(xa_compound_text, time);
}