116 |
/* If this is a smaller number than the max-request-size of the display, |
/* If this is a smaller number than the max-request-size of the display, |
117 |
emacs will use INCR selection transfer when the selection is larger |
emacs will use INCR selection transfer when the selection is larger |
118 |
than this. The max-request-size is usually around 64k, so if you want |
than this. The max-request-size is usually around 64k, so if you want |
119 |
emacs to use incremental selection transfers when the selection is |
emacs to use incremental selection transfers when the selection is |
120 |
smaller than that, set this. I added this mostly for debugging the |
smaller than that, set this. I added this mostly for debugging the |
121 |
incremental transfer stuff, but it might improve server performance. */ |
incremental transfer stuff, but it might improve server performance. */ |
122 |
#define MAX_SELECTION_QUANTUM 0xFFFFFF |
#define MAX_SELECTION_QUANTUM 0xFFFFFF |
147 |
|
|
148 |
/* This is an alist whose CARs are selection-types (whose names are the same |
/* This is an alist whose CARs are selection-types (whose names are the same |
149 |
as the names of X Atoms) and whose CDRs are the names of Lisp functions to |
as the names of X Atoms) and whose CDRs are the names of Lisp functions to |
150 |
call to convert the given Emacs selection value to a string representing |
call to convert the given Emacs selection value to a string representing |
151 |
the given selection type. This is for Lisp-level extension of the emacs |
the given selection type. This is for Lisp-level extension of the emacs |
152 |
selection handling. */ |
selection handling. */ |
153 |
static Lisp_Object Vselection_converter_alist; |
static Lisp_Object Vselection_converter_alist; |
162 |
static Lisp_Object selection_data_to_lisp_data (); |
static Lisp_Object selection_data_to_lisp_data (); |
163 |
static Lisp_Object x_get_window_property_as_lisp_data (); |
static Lisp_Object x_get_window_property_as_lisp_data (); |
164 |
|
|
165 |
/* This converts a Lisp symbol to a server Atom, avoiding a server |
/* This converts a Lisp symbol to a server Atom, avoiding a server |
166 |
roundtrip whenever possible. */ |
roundtrip whenever possible. */ |
167 |
|
|
168 |
static Atom |
static Atom |
219 |
struct x_display_info *dpyinfo; |
struct x_display_info *dpyinfo; |
220 |
char *str; |
char *str; |
221 |
Lisp_Object val; |
Lisp_Object val; |
222 |
|
|
223 |
if (! atom) |
if (! atom) |
224 |
return Qnil; |
return Qnil; |
225 |
|
|
226 |
switch (atom) |
switch (atom) |
227 |
{ |
{ |
228 |
case XA_PRIMARY: |
case XA_PRIMARY: |
291 |
} |
} |
292 |
|
|
293 |
/* Do protocol to assert ourself as a selection owner. |
/* Do protocol to assert ourself as a selection owner. |
294 |
Update the Vselection_alist so that we can reply to later requests for |
Update the Vselection_alist so that we can reply to later requests for |
295 |
our selection. */ |
our selection. */ |
296 |
|
|
297 |
static void |
static void |
436 |
&& SYMBOLP (XCAR (value))) |
&& SYMBOLP (XCAR (value))) |
437 |
type = XCAR (value), |
type = XCAR (value), |
438 |
check = XCDR (value); |
check = XCDR (value); |
439 |
|
|
440 |
if (STRINGP (check) |
if (STRINGP (check) |
441 |
|| VECTORP (check) |
|| VECTORP (check) |
442 |
|| SYMBOLP (check) |
|| SYMBOLP (check) |
470 |
{ |
{ |
471 |
XSelectionEvent reply; |
XSelectionEvent reply; |
472 |
int count; |
int count; |
473 |
|
|
474 |
reply.type = SelectionNotify; |
reply.type = SelectionNotify; |
475 |
reply.display = SELECTION_EVENT_DISPLAY (event); |
reply.display = SELECTION_EVENT_DISPLAY (event); |
476 |
reply.requestor = SELECTION_EVENT_REQUESTOR (event); |
reply.requestor = SELECTION_EVENT_REQUESTOR (event); |
644 |
|
|
645 |
if (x_window_to_frame (dpyinfo, window)) /* #### debug */ |
if (x_window_to_frame (dpyinfo, window)) /* #### debug */ |
646 |
error ("Attempt to transfer an INCR to ourself!"); |
error ("Attempt to transfer an INCR to ourself!"); |
647 |
|
|
648 |
TRACE2 ("Start sending %d bytes incrementally (%s)", |
TRACE2 ("Start sending %d bytes incrementally (%s)", |
649 |
bytes_remaining, XGetAtomName (display, reply.property)); |
bytes_remaining, XGetAtomName (display, reply.property)); |
650 |
wait_object = expect_property_change (display, window, reply.property, |
wait_object = expect_property_change (display, window, reply.property, |
656 |
32, PropModeReplace, |
32, PropModeReplace, |
657 |
(unsigned char *) &bytes_remaining, 1); |
(unsigned char *) &bytes_remaining, 1); |
658 |
XSelectInput (display, window, PropertyChangeMask); |
XSelectInput (display, window, PropertyChangeMask); |
659 |
|
|
660 |
/* Tell 'em the INCR data is there... */ |
/* Tell 'em the INCR data is there... */ |
661 |
TRACE0 ("Send SelectionNotify event"); |
TRACE0 ("Send SelectionNotify event"); |
662 |
XSendEvent (display, window, False, 0L, (XEvent *) &reply); |
XSendEvent (display, window, False, 0L, (XEvent *) &reply); |
690 |
TRACE1 ("Sending increment of %d bytes", i); |
TRACE1 ("Sending increment of %d bytes", i); |
691 |
TRACE1 ("Set %s to increment data", |
TRACE1 ("Set %s to increment data", |
692 |
XGetAtomName (display, reply.property)); |
XGetAtomName (display, reply.property)); |
693 |
|
|
694 |
/* Append the next chunk of data to the property. */ |
/* Append the next chunk of data to the property. */ |
695 |
XChangeProperty (display, window, reply.property, type, format, |
XChangeProperty (display, window, reply.property, type, format, |
696 |
PropModeAppend, data, i / format_bytes); |
PropModeAppend, data, i / format_bytes); |
709 |
XGetAtomName (display, reply.property)); |
XGetAtomName (display, reply.property)); |
710 |
wait_for_property_change (wait_object); |
wait_for_property_change (wait_object); |
711 |
} |
} |
712 |
|
|
713 |
/* Now write a zero-length chunk to the property to tell the |
/* Now write a zero-length chunk to the property to tell the |
714 |
requester that we're done. */ |
requester that we're done. */ |
715 |
BLOCK_INPUT; |
BLOCK_INPUT; |
797 |
if (EQ (target_symbol, QMULTIPLE)) |
if (EQ (target_symbol, QMULTIPLE)) |
798 |
target_symbol = fetch_multiple_target (event); |
target_symbol = fetch_multiple_target (event); |
799 |
#endif |
#endif |
800 |
|
|
801 |
/* Convert lisp objects back into binary data */ |
/* Convert lisp objects back into binary data */ |
802 |
|
|
803 |
converted_selection |
converted_selection |
804 |
= x_get_local_selection (selection_symbol, target_symbol); |
= x_get_local_selection (selection_symbol, target_symbol); |
805 |
|
|
806 |
if (! NILP (converted_selection)) |
if (! NILP (converted_selection)) |
807 |
{ |
{ |
808 |
unsigned char *data; |
unsigned char *data; |
814 |
lisp_data_to_selection_data (SELECTION_EVENT_DISPLAY (event), |
lisp_data_to_selection_data (SELECTION_EVENT_DISPLAY (event), |
815 |
converted_selection, |
converted_selection, |
816 |
&data, &type, &size, &format, &nofree); |
&data, &type, &size, &format, &nofree); |
817 |
|
|
818 |
x_reply_selection_request (event, format, data, size, type); |
x_reply_selection_request (event, format, data, size, type); |
819 |
successful_p = Qt; |
successful_p = Qt; |
820 |
|
|
853 |
Display *display = SELECTION_EVENT_DISPLAY (event); |
Display *display = SELECTION_EVENT_DISPLAY (event); |
854 |
Atom selection = SELECTION_EVENT_SELECTION (event); |
Atom selection = SELECTION_EVENT_SELECTION (event); |
855 |
Time changed_owner_time = SELECTION_EVENT_TIME (event); |
Time changed_owner_time = SELECTION_EVENT_TIME (event); |
856 |
|
|
857 |
Lisp_Object selection_symbol, local_selection_data; |
Lisp_Object selection_symbol, local_selection_data; |
858 |
Time local_selection_time; |
Time local_selection_time; |
859 |
struct x_display_info *dpyinfo = x_display_info_for_display (display); |
struct x_display_info *dpyinfo = x_display_info_for_display (display); |
1139 |
xfree (rest); |
xfree (rest); |
1140 |
return; |
return; |
1141 |
} |
} |
1142 |
|
|
1143 |
prev = rest; |
prev = rest; |
1144 |
rest = rest->next; |
rest = rest->next; |
1145 |
} |
} |
1174 |
int size; |
int size; |
1175 |
if (CONSP (obj)) |
if (CONSP (obj)) |
1176 |
return Fcons (XCAR (obj), copy_multiple_data (XCDR (obj))); |
return Fcons (XCAR (obj), copy_multiple_data (XCDR (obj))); |
1177 |
|
|
1178 |
CHECK_VECTOR (obj, 0); |
CHECK_VECTOR (obj, 0); |
1179 |
vec = Fmake_vector (size = XVECTOR (obj)->size, Qnil); |
vec = Fmake_vector (size = XVECTOR (obj)->size, Qnil); |
1180 |
for (i = 0; i < size; i++) |
for (i = 0; i < size; i++) |
1227 |
type_atom = symbol_to_x_atom (dpyinfo, display, target_type); |
type_atom = symbol_to_x_atom (dpyinfo, display, target_type); |
1228 |
|
|
1229 |
BLOCK_INPUT; |
BLOCK_INPUT; |
1230 |
|
|
1231 |
count = x_catch_errors (display); |
count = x_catch_errors (display); |
1232 |
|
|
1233 |
TRACE2 ("Get selection %s, type %s", |
TRACE2 ("Get selection %s, type %s", |
1234 |
XGetAtomName (display, type_atom), |
XGetAtomName (display, type_atom), |
1235 |
XGetAtomName (display, target_property)); |
XGetAtomName (display, target_property)); |
1305 |
unsigned char *tmp_data = 0; |
unsigned char *tmp_data = 0; |
1306 |
int result; |
int result; |
1307 |
int buffer_size = SELECTION_QUANTUM (display); |
int buffer_size = SELECTION_QUANTUM (display); |
1308 |
|
|
1309 |
if (buffer_size > MAX_SELECTION_QUANTUM) |
if (buffer_size > MAX_SELECTION_QUANTUM) |
1310 |
buffer_size = MAX_SELECTION_QUANTUM; |
buffer_size = MAX_SELECTION_QUANTUM; |
1311 |
|
|
1312 |
BLOCK_INPUT; |
BLOCK_INPUT; |
1313 |
|
|
1314 |
/* First probe the thing to find out how big it is. */ |
/* First probe the thing to find out how big it is. */ |
1315 |
result = XGetWindowProperty (display, window, property, |
result = XGetWindowProperty (display, window, property, |
1316 |
0L, 0L, False, AnyPropertyType, |
0L, 0L, False, AnyPropertyType, |
1324 |
*bytes_ret = 0; |
*bytes_ret = 0; |
1325 |
return; |
return; |
1326 |
} |
} |
1327 |
|
|
1328 |
/* This was allocated by Xlib, so use XFree. */ |
/* This was allocated by Xlib, so use XFree. */ |
1329 |
XFree ((char *) tmp_data); |
XFree ((char *) tmp_data); |
1330 |
|
|
1331 |
if (*actual_type_ret == None || *actual_format_ret == 0) |
if (*actual_type_ret == None || *actual_format_ret == 0) |
1332 |
{ |
{ |
1333 |
UNBLOCK_INPUT; |
UNBLOCK_INPUT; |
1336 |
|
|
1337 |
total_size = bytes_remaining + 1; |
total_size = bytes_remaining + 1; |
1338 |
*data_ret = (unsigned char *) xmalloc (total_size); |
*data_ret = (unsigned char *) xmalloc (total_size); |
1339 |
|
|
1340 |
/* Now read, until we've gotten it all. */ |
/* Now read, until we've gotten it all. */ |
1341 |
while (bytes_remaining) |
while (bytes_remaining) |
1342 |
{ |
{ |
1363 |
*actual_size_ret *= *actual_format_ret / 8; |
*actual_size_ret *= *actual_format_ret / 8; |
1364 |
bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret); |
bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret); |
1365 |
offset += *actual_size_ret; |
offset += *actual_size_ret; |
1366 |
|
|
1367 |
/* This was allocated by Xlib, so use XFree. */ |
/* This was allocated by Xlib, so use XFree. */ |
1368 |
XFree ((char *) tmp_data); |
XFree ((char *) tmp_data); |
1369 |
} |
} |
1424 |
|
|
1425 |
TRACE0 (" Wait for property change"); |
TRACE0 (" Wait for property change"); |
1426 |
wait_for_property_change (wait_object); |
wait_for_property_change (wait_object); |
1427 |
|
|
1428 |
/* expect it again immediately, because x_get_window_property may |
/* expect it again immediately, because x_get_window_property may |
1429 |
.. no it won't, I don't get it. |
.. no it won't, I don't get it. |
1430 |
.. Ok, I get it now, the Xt code that implements INCR is broken. */ |
.. Ok, I get it now, the Xt code that implements INCR is broken. */ |
1462 |
*size_bytes_ret = offset + tmp_size_bytes; |
*size_bytes_ret = offset + tmp_size_bytes; |
1463 |
*data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret); |
*data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret); |
1464 |
} |
} |
1465 |
|
|
1466 |
bcopy (tmp_data, (*data_ret) + offset, tmp_size_bytes); |
bcopy (tmp_data, (*data_ret) + offset, tmp_size_bytes); |
1467 |
offset += tmp_size_bytes; |
offset += tmp_size_bytes; |
1468 |
|
|
1469 |
/* Use xfree, not XFree, because x_get_window_property |
/* Use xfree, not XFree, because x_get_window_property |
1470 |
calls xmalloc itself. */ |
calls xmalloc itself. */ |
1471 |
xfree (tmp_data); |
xfree (tmp_data); |
1519 |
selection_atom), |
selection_atom), |
1520 |
Qnil))); |
Qnil))); |
1521 |
} |
} |
1522 |
|
|
1523 |
if (actual_type == dpyinfo->Xatom_INCR) |
if (actual_type == dpyinfo->Xatom_INCR) |
1524 |
{ |
{ |
1525 |
/* That wasn't really the data, just the beginning. */ |
/* That wasn't really the data, just the beginning. */ |
1546 |
manner. */ |
manner. */ |
1547 |
val = selection_data_to_lisp_data (display, data, bytes, |
val = selection_data_to_lisp_data (display, data, bytes, |
1548 |
actual_type, actual_format); |
actual_type, actual_format); |
1549 |
|
|
1550 |
/* Use xfree, not XFree, because x_get_window_property |
/* Use xfree, not XFree, because x_get_window_property |
1551 |
calls xmalloc itself. */ |
calls xmalloc itself. */ |
1552 |
xfree ((char *) data); |
xfree ((char *) data); |
1852 |
Lisp_Object pair = XVECTOR (obj)->contents [i]; |
Lisp_Object pair = XVECTOR (obj)->contents [i]; |
1853 |
if (XVECTOR (pair)->size != 2) |
if (XVECTOR (pair)->size != 2) |
1854 |
Fsignal (Qerror, |
Fsignal (Qerror, |
1855 |
Fcons (build_string |
Fcons (build_string |
1856 |
("elements of the vector must be vectors of exactly two elements"), |
("elements of the vector must be vectors of exactly two elements"), |
1857 |
Fcons (pair, Qnil))); |
Fcons (pair, Qnil))); |
1858 |
|
|
1859 |
(*(Atom **) data_ret) [i * 2] |
(*(Atom **) data_ret) [i * 2] |
1860 |
= symbol_to_x_atom (dpyinfo, display, |
= symbol_to_x_atom (dpyinfo, display, |
1861 |
XVECTOR (pair)->contents [0]); |
XVECTOR (pair)->contents [0]); |
1868 |
Fcons (build_string |
Fcons (build_string |
1869 |
("all elements of the vector must be of the same type"), |
("all elements of the vector must be of the same type"), |
1870 |
Fcons (obj, Qnil))); |
Fcons (obj, Qnil))); |
1871 |
|
|
1872 |
} |
} |
1873 |
#endif |
#endif |
1874 |
else |
else |
2112 |
CHECK_SYMBOL (selection, 0); |
CHECK_SYMBOL (selection, 0); |
2113 |
if (EQ (selection, Qnil)) selection = QPRIMARY; |
if (EQ (selection, Qnil)) selection = QPRIMARY; |
2114 |
if (EQ (selection, Qt)) selection = QSECONDARY; |
if (EQ (selection, Qt)) selection = QSECONDARY; |
2115 |
|
|
2116 |
if (NILP (Fassq (selection, Vselection_alist))) |
if (NILP (Fassq (selection, Vselection_alist))) |
2117 |
return Qnil; |
return Qnil; |
2118 |
return Qt; |
return Qt; |
2219 |
&type, &format, &size, 0); |
&type, &format, &size, 0); |
2220 |
if (!data || !format) |
if (!data || !format) |
2221 |
return Qnil; |
return Qnil; |
2222 |
|
|
2223 |
if (format != 8 || type != XA_STRING) |
if (format != 8 || type != XA_STRING) |
2224 |
Fsignal (Qerror, |
Fsignal (Qerror, |
2225 |
Fcons (build_string ("cut buffer doesn't contain 8-bit data"), |
Fcons (build_string ("cut buffer doesn't contain 8-bit data"), |
2407 |
"Coding system for communicating with other X clients.\n\ |
"Coding system for communicating with other X clients.\n\ |
2408 |
When sending or receiving text via cut_buffer, selection, and clipboard,\n\ |
When sending or receiving text via cut_buffer, selection, and clipboard,\n\ |
2409 |
the text is encoded or decoded by this coding system.\n\ |
the text is encoded or decoded by this coding system.\n\ |
2410 |
The default value is `compound-text'."); |
The default value is `compound-text-with-extensions'."); |
2411 |
Vselection_coding_system = Qcompound_text_with_extensions; |
Vselection_coding_system = Qcompound_text_with_extensions; |
2412 |
|
|
2413 |
DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, |
DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, |