1 |
/* X Selection processing for Emacs. |
/* X Selection processing for Emacs. |
2 |
Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2001 |
Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2003 |
3 |
Free Software Foundation. |
Free Software Foundation. |
4 |
|
|
5 |
This file is part of GNU Emacs. |
This file is part of GNU Emacs. |
40 |
static Atom symbol_to_x_atom P_ ((struct x_display_info *, Display *, |
static Atom symbol_to_x_atom P_ ((struct x_display_info *, Display *, |
41 |
Lisp_Object)); |
Lisp_Object)); |
42 |
static void x_own_selection P_ ((Lisp_Object, Lisp_Object)); |
static void x_own_selection P_ ((Lisp_Object, Lisp_Object)); |
43 |
static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object)); |
static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object, int)); |
44 |
static void x_decline_selection_request P_ ((struct input_event *)); |
static void x_decline_selection_request P_ ((struct input_event *)); |
45 |
static Lisp_Object x_selection_request_lisp_error P_ ((Lisp_Object)); |
static Lisp_Object x_selection_request_lisp_error P_ ((Lisp_Object)); |
46 |
static Lisp_Object queue_selection_requests_unwind P_ ((Lisp_Object)); |
static Lisp_Object queue_selection_requests_unwind P_ ((Lisp_Object)); |
96 |
QATOM_PAIR; |
QATOM_PAIR; |
97 |
|
|
98 |
Lisp_Object QCOMPOUND_TEXT; /* This is a type of selection. */ |
Lisp_Object QCOMPOUND_TEXT; /* This is a type of selection. */ |
99 |
|
Lisp_Object QUTF8_STRING; /* This is a type of selection. */ |
100 |
|
|
101 |
Lisp_Object Qcompound_text_with_extensions; |
Lisp_Object Qcompound_text_with_extensions; |
102 |
|
|
183 |
if (EQ (sym, QTIMESTAMP)) return dpyinfo->Xatom_TIMESTAMP; |
if (EQ (sym, QTIMESTAMP)) return dpyinfo->Xatom_TIMESTAMP; |
184 |
if (EQ (sym, QTEXT)) return dpyinfo->Xatom_TEXT; |
if (EQ (sym, QTEXT)) return dpyinfo->Xatom_TEXT; |
185 |
if (EQ (sym, QCOMPOUND_TEXT)) return dpyinfo->Xatom_COMPOUND_TEXT; |
if (EQ (sym, QCOMPOUND_TEXT)) return dpyinfo->Xatom_COMPOUND_TEXT; |
186 |
|
if (EQ (sym, QUTF8_STRING)) return dpyinfo->Xatom_UTF8_STRING; |
187 |
if (EQ (sym, QDELETE)) return dpyinfo->Xatom_DELETE; |
if (EQ (sym, QDELETE)) return dpyinfo->Xatom_DELETE; |
188 |
if (EQ (sym, QMULTIPLE)) return dpyinfo->Xatom_MULTIPLE; |
if (EQ (sym, QMULTIPLE)) return dpyinfo->Xatom_MULTIPLE; |
189 |
if (EQ (sym, QINCR)) return dpyinfo->Xatom_INCR; |
if (EQ (sym, QINCR)) return dpyinfo->Xatom_INCR; |
202 |
#endif |
#endif |
203 |
if (!SYMBOLP (sym)) abort (); |
if (!SYMBOLP (sym)) abort (); |
204 |
|
|
205 |
TRACE1 (" XInternAtom %s", (char *) XSTRING (SYMBOL_NAME (sym))->data); |
TRACE1 (" XInternAtom %s", (char *) SDATA (SYMBOL_NAME (sym))); |
206 |
BLOCK_INPUT; |
BLOCK_INPUT; |
207 |
val = XInternAtom (display, (char *) XSTRING (SYMBOL_NAME (sym))->data, False); |
val = XInternAtom (display, (char *) SDATA (SYMBOL_NAME (sym)), False); |
208 |
UNBLOCK_INPUT; |
UNBLOCK_INPUT; |
209 |
return val; |
return val; |
210 |
} |
} |
266 |
return QTEXT; |
return QTEXT; |
267 |
if (atom == dpyinfo->Xatom_COMPOUND_TEXT) |
if (atom == dpyinfo->Xatom_COMPOUND_TEXT) |
268 |
return QCOMPOUND_TEXT; |
return QCOMPOUND_TEXT; |
269 |
|
if (atom == dpyinfo->Xatom_UTF8_STRING) |
270 |
|
return QUTF8_STRING; |
271 |
if (atom == dpyinfo->Xatom_DELETE) |
if (atom == dpyinfo->Xatom_DELETE) |
272 |
return QDELETE; |
return QDELETE; |
273 |
if (atom == dpyinfo->Xatom_MULTIPLE) |
if (atom == dpyinfo->Xatom_MULTIPLE) |
354 |
/* Given a selection-name and desired type, look up our local copy of |
/* Given a selection-name and desired type, look up our local copy of |
355 |
the selection value and convert it to the type. |
the selection value and convert it to the type. |
356 |
The value is nil or a string. |
The value is nil or a string. |
357 |
This function is used both for remote requests |
This function is used both for remote requests (LOCAL_REQUEST is zero) |
358 |
and for local x-get-selection-internal. |
and for local x-get-selection-internal (LOCAL_REQUEST is nonzero). |
359 |
|
|
360 |
This calls random Lisp code, and may signal or gc. */ |
This calls random Lisp code, and may signal or gc. */ |
361 |
|
|
362 |
static Lisp_Object |
static Lisp_Object |
363 |
x_get_local_selection (selection_symbol, target_type) |
x_get_local_selection (selection_symbol, target_type, local_request) |
364 |
Lisp_Object selection_symbol, target_type; |
Lisp_Object selection_symbol, target_type; |
365 |
|
int local_request; |
366 |
{ |
{ |
367 |
Lisp_Object local_value; |
Lisp_Object local_value; |
368 |
Lisp_Object handler_fn, value, type, check; |
Lisp_Object handler_fn, value, type, check; |
409 |
pair = XVECTOR (pairs)->contents [i]; |
pair = XVECTOR (pairs)->contents [i]; |
410 |
XVECTOR (pair)->contents [1] |
XVECTOR (pair)->contents [1] |
411 |
= x_get_local_selection (XVECTOR (pair)->contents [0], |
= x_get_local_selection (XVECTOR (pair)->contents [0], |
412 |
XVECTOR (pair)->contents [1]); |
XVECTOR (pair)->contents [1], |
413 |
|
local_request); |
414 |
} |
} |
415 |
return pairs; |
return pairs; |
416 |
} |
} |
420 |
/* Don't allow a quit within the converter. |
/* Don't allow a quit within the converter. |
421 |
When the user types C-g, he would be surprised |
When the user types C-g, he would be surprised |
422 |
if by luck it came during a converter. */ |
if by luck it came during a converter. */ |
423 |
count = specpdl_ptr - specpdl; |
count = SPECPDL_INDEX (); |
424 |
specbind (Qinhibit_quit, Qt); |
specbind (Qinhibit_quit, Qt); |
425 |
|
|
426 |
CHECK_SYMBOL (target_type); |
CHECK_SYMBOL (target_type); |
427 |
handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); |
handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); |
428 |
if (!NILP (handler_fn)) |
if (!NILP (handler_fn)) |
429 |
value = call3 (handler_fn, |
value = call3 (handler_fn, |
430 |
selection_symbol, target_type, |
selection_symbol, (local_request ? Qnil : target_type), |
431 |
XCAR (XCDR (local_value))); |
XCAR (XCDR (local_value))); |
432 |
else |
else |
433 |
value = Qnil; |
value = Qnil; |
729 |
TRACE0 ("Done sending incrementally"); |
TRACE0 ("Done sending incrementally"); |
730 |
} |
} |
731 |
|
|
732 |
|
/* rms, 2003-01-03: I think I have fixed this bug. */ |
733 |
/* The window we're communicating with may have been deleted |
/* The window we're communicating with may have been deleted |
734 |
in the meantime (that's a real situation from a bug report). |
in the meantime (that's a real situation from a bug report). |
735 |
In this case, there may be events in the event queue still |
In this case, there may be events in the event queue still |
793 |
} |
} |
794 |
|
|
795 |
x_selection_current_request = event; |
x_selection_current_request = event; |
796 |
count = BINDING_STACK_SIZE (); |
count = SPECPDL_INDEX (); |
797 |
selection_request_dpyinfo = dpyinfo; |
selection_request_dpyinfo = dpyinfo; |
798 |
record_unwind_protect (x_selection_request_lisp_error, Qnil); |
record_unwind_protect (x_selection_request_lisp_error, Qnil); |
799 |
|
|
808 |
/* Convert lisp objects back into binary data */ |
/* Convert lisp objects back into binary data */ |
809 |
|
|
810 |
converted_selection |
converted_selection |
811 |
= x_get_local_selection (selection_symbol, target_symbol); |
= x_get_local_selection (selection_symbol, target_symbol, 0); |
812 |
|
|
813 |
if (! NILP (converted_selection)) |
if (! NILP (converted_selection)) |
814 |
{ |
{ |
1081 |
struct prop_location *location; |
struct prop_location *location; |
1082 |
{ |
{ |
1083 |
int secs, usecs; |
int secs, usecs; |
1084 |
int count = specpdl_ptr - specpdl; |
int count = SPECPDL_INDEX (); |
1085 |
Lisp_Object tem; |
Lisp_Object tem; |
1086 |
|
|
1087 |
tem = Fcons (Qnil, Qnil); |
tem = Fcons (Qnil, Qnil); |
1279 |
if (NILP (XCAR (reading_selection_reply))) |
if (NILP (XCAR (reading_selection_reply))) |
1280 |
error ("Timed out waiting for reply from selection owner"); |
error ("Timed out waiting for reply from selection owner"); |
1281 |
if (EQ (XCAR (reading_selection_reply), Qlambda)) |
if (EQ (XCAR (reading_selection_reply), Qlambda)) |
1282 |
error ("No `%s' selection", XSTRING (SYMBOL_NAME (selection_symbol))->data); |
error ("No `%s' selection", SDATA (SYMBOL_NAME (selection_symbol))); |
1283 |
|
|
1284 |
/* Otherwise, the selection is waiting for us on the requested property. */ |
/* Otherwise, the selection is waiting for us on the requested property. */ |
1285 |
return |
return |
1653 |
coding.dst_multibyte = 1; |
coding.dst_multibyte = 1; |
1654 |
Vnext_selection_coding_system = Qnil; |
Vnext_selection_coding_system = Qnil; |
1655 |
coding.mode |= CODING_MODE_LAST_BLOCK; |
coding.mode |= CODING_MODE_LAST_BLOCK; |
1656 |
|
/* We explicitely disable composition handling because |
1657 |
|
selection data should not contain any composition |
1658 |
|
sequence. */ |
1659 |
|
coding.composing = COMPOSITION_DISABLED; |
1660 |
bufsize = decoding_buffer_size (&coding, size); |
bufsize = decoding_buffer_size (&coding, size); |
1661 |
buf = (unsigned char *) xmalloc (bufsize); |
buf = (unsigned char *) xmalloc (bufsize); |
1662 |
decode_coding (&coding, data, buf, size, bufsize); |
decode_coding (&coding, data, buf, size, bufsize); |
1669 |
str = run_pre_post_conversion_on_str (str, &coding, 0); |
str = run_pre_post_conversion_on_str (str, &coding, 0); |
1670 |
Vlast_coding_system_used = coding.symbol; |
Vlast_coding_system_used = coding.symbol; |
1671 |
} |
} |
1672 |
compose_chars_in_text (0, XSTRING (str)->size, str); |
compose_chars_in_text (0, SCHARS (str), str); |
1673 |
return str; |
return str; |
1674 |
} |
} |
1675 |
/* Convert a single atom to a Lisp_Symbol. Convert a set of atoms to |
/* Convert a single atom to a Lisp_Symbol. Convert a set of atoms to |
1695 |
If the number is > 16 bits, convert it to a cons of integers, |
If the number is > 16 bits, convert it to a cons of integers, |
1696 |
16 bits in each half. |
16 bits in each half. |
1697 |
*/ |
*/ |
1698 |
else if (format == 32 && size == sizeof (long)) |
else if (format == 32 && size == sizeof (int)) |
1699 |
return long_to_cons (((unsigned long *) data) [0]); |
return long_to_cons (((unsigned int *) data) [0]); |
1700 |
else if (format == 16 && size == sizeof (short)) |
else if (format == 16 && size == sizeof (short)) |
1701 |
return make_number ((int) (((unsigned short *) data) [0])); |
return make_number ((int) (((unsigned short *) data) [0])); |
1702 |
|
|
1721 |
Lisp_Object v = Fmake_vector (make_number (size / 4), make_number (0)); |
Lisp_Object v = Fmake_vector (make_number (size / 4), make_number (0)); |
1722 |
for (i = 0; i < size / 4; i++) |
for (i = 0; i < size / 4; i++) |
1723 |
{ |
{ |
1724 |
unsigned long j = ((unsigned long *) data) [i]; |
unsigned int j = ((unsigned int *) data) [i]; |
1725 |
Faset (v, make_number (i), long_to_cons (j)); |
Faset (v, make_number (i), long_to_cons (j)); |
1726 |
} |
} |
1727 |
return v; |
return v; |
1765 |
} |
} |
1766 |
else if (STRINGP (obj)) |
else if (STRINGP (obj)) |
1767 |
{ |
{ |
1768 |
/* Since we are now handling multilingual text, we must consider |
xassert (! STRING_MULTIBYTE (obj)); |
|
sending back compound text. */ |
|
|
int stringp; |
|
|
extern Lisp_Object Qcompound_text; |
|
|
|
|
|
if (NILP (Vnext_selection_coding_system)) |
|
|
Vnext_selection_coding_system = Vselection_coding_system; |
|
|
|
|
|
*format_ret = 8; |
|
|
/* If the requested type is STRING, we must encode the selected |
|
|
text as a string, even if the coding system set by the user |
|
|
is ctext or its derivatives. */ |
|
|
if (EQ (type, QSTRING) |
|
|
&& (EQ (Vnext_selection_coding_system, Qcompound_text) |
|
|
|| EQ (Vnext_selection_coding_system, |
|
|
Qcompound_text_with_extensions))) |
|
|
{ |
|
|
Lisp_Object unibyte_string; |
|
|
|
|
|
unibyte_string = string_make_unibyte (obj); |
|
|
*data_ret = XSTRING (unibyte_string)->data; |
|
|
*nofree_ret = 1; |
|
|
*size_ret = SBYTES (unibyte_string); |
|
|
} |
|
|
else |
|
|
{ |
|
|
*data_ret = x_encode_text (obj, Vnext_selection_coding_system, 1, |
|
|
(int *) size_ret, &stringp); |
|
|
*nofree_ret = (*data_ret == XSTRING (obj)->data); |
|
|
} |
|
1769 |
if (NILP (type)) |
if (NILP (type)) |
1770 |
type = (stringp ? QSTRING : QCOMPOUND_TEXT); |
type = QSTRING; |
1771 |
Vlast_coding_system_used = (*nofree_ret |
*format_ret = 8; |
1772 |
? Qraw_text |
*size_ret = SBYTES (obj); |
1773 |
: Vnext_selection_coding_system); |
*data_ret = SDATA (obj); |
1774 |
Vnext_selection_coding_system = Qnil; |
*nofree_ret = 1; |
1775 |
} |
} |
1776 |
else if (SYMBOLP (obj)) |
else if (SYMBOLP (obj)) |
1777 |
{ |
{ |
2003 |
#endif |
#endif |
2004 |
CHECK_SYMBOL (target_type); |
CHECK_SYMBOL (target_type); |
2005 |
|
|
2006 |
val = x_get_local_selection (selection_symbol, target_type); |
val = x_get_local_selection (selection_symbol, target_type, 1); |
2007 |
|
|
2008 |
if (NILP (val)) |
if (NILP (val)) |
2009 |
{ |
{ |
2255 |
CHECK_STRING (string); |
CHECK_STRING (string); |
2256 |
buffer_atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (sf), |
buffer_atom = symbol_to_x_atom (FRAME_X_DISPLAY_INFO (sf), |
2257 |
display, buffer); |
display, buffer); |
2258 |
data = (unsigned char *) XSTRING (string)->data; |
data = (unsigned char *) SDATA (string); |
2259 |
bytes = STRING_BYTES (XSTRING (string)); |
bytes = SBYTES (string); |
2260 |
bytes_remaining = bytes; |
bytes_remaining = bytes; |
2261 |
|
|
2262 |
if (! FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized) |
if (! FRAME_X_DISPLAY_INFO (sf)->cut_buffers_initialized) |
2404 |
DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, |
DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, |
2405 |
doc: /* Coding system for the next communication with other X clients. |
doc: /* Coding system for the next communication with other X clients. |
2406 |
Usually, `selection-coding-system' is used for communicating with |
Usually, `selection-coding-system' is used for communicating with |
2407 |
other X clients. But, if this variable is set, it is used for the |
other X clients. But, if this variable is set, it is used for the |
2408 |
next communication only. After the communication, this variable is |
next communication only. After the communication, this variable is |
2409 |
set to nil. */); |
set to nil. */); |
2410 |
Vnext_selection_coding_system = Qnil; |
Vnext_selection_coding_system = Qnil; |
2411 |
|
|
2424 |
QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP); |
QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP); |
2425 |
QTEXT = intern ("TEXT"); staticpro (&QTEXT); |
QTEXT = intern ("TEXT"); staticpro (&QTEXT); |
2426 |
QCOMPOUND_TEXT = intern ("COMPOUND_TEXT"); staticpro (&QCOMPOUND_TEXT); |
QCOMPOUND_TEXT = intern ("COMPOUND_TEXT"); staticpro (&QCOMPOUND_TEXT); |
2427 |
|
QUTF8_STRING = intern ("UTF8_STRING"); staticpro (&QUTF8_STRING); |
2428 |
QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP); |
QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP); |
2429 |
QDELETE = intern ("DELETE"); staticpro (&QDELETE); |
QDELETE = intern ("DELETE"); staticpro (&QDELETE); |
2430 |
QMULTIPLE = intern ("MULTIPLE"); staticpro (&QMULTIPLE); |
QMULTIPLE = intern ("MULTIPLE"); staticpro (&QMULTIPLE); |