(wait_for_termination): Fix sigpause in POSIX_SIGNALS case.
[bpt/emacs.git] / src / xselect.c
CommitLineData
ede4db72 1/* X Selection processing for emacs
c6c5df7f 2 Copyright (C) 1993 Free Software Foundation.
ede4db72
RS
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
c6c5df7f
JB
20/* x_handle_selection_notify
21x_reply_selection_request
22XFree
23x_selection_timeout initial value */
24
ede4db72
RS
25/* Rewritten by jwz */
26
27#include "config.h"
28#include "lisp.h"
7da64e5c
RS
29#if 0
30#include <stdio.h> /* termhooks.h needs this */
31#include "termhooks.h"
32#endif
ede4db72 33#include "xterm.h" /* for all of the X includes */
7da64e5c
RS
34#include "dispextern.h" /* frame.h seems to want this */
35#include "frame.h" /* Need this to get the X window of selected_frame */
9ac0d9e0 36#include "blockinput.h"
7da64e5c
RS
37
38#define xfree free
ede4db72
RS
39
40#define CUT_BUFFER_SUPPORT
41
42static Atom Xatom_CLIPBOARD, Xatom_TIMESTAMP, Xatom_TEXT, Xatom_DELETE,
43 Xatom_MULTIPLE, Xatom_INCR, Xatom_EMACS_TMP, Xatom_TARGETS, Xatom_NULL,
44 Xatom_ATOM_PAIR;
45
46Lisp_Object QPRIMARY, QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
47 QTEXT, QDELETE, QMULTIPLE, QINCR, QEMACS_TMP, QTARGETS, QATOM, QNULL,
48 QATOM_PAIR;
49
50#ifdef CUT_BUFFER_SUPPORT
51Lisp_Object QCUT_BUFFER0, QCUT_BUFFER1, QCUT_BUFFER2, QCUT_BUFFER3,
52 QCUT_BUFFER4, QCUT_BUFFER5, QCUT_BUFFER6, QCUT_BUFFER7;
53#endif
54
55Lisp_Object Vx_lost_selection_hooks;
56Lisp_Object Vx_sent_selection_hooks;
57
58/* If this is a smaller number than the max-request-size of the display,
59 emacs will use INCR selection transfer when the selection is larger
60 than this. The max-request-size is usually around 64k, so if you want
61 emacs to use incremental selection transfers when the selection is
62 smaller than that, set this. I added this mostly for debugging the
63 incremental transfer stuff, but it might improve server performance.
64 */
65#define MAX_SELECTION_QUANTUM 0xFFFFFF
66
c3498e64
JB
67#ifdef HAVE_X11R4
68#define SELECTION_QUANTUM(dpy) ((XMaxRequestSize(dpy) << 2) - 100)
69#else
70#define SELECTION_QUANTUM(dpy) (((dpy)->max_request_size << 2) - 100)
71#endif
ede4db72 72
7da64e5c
RS
73/* The timestamp of the last input event Emacs received from the X server. */
74unsigned long last_event_timestamp;
ede4db72
RS
75
76/* This is an association list whose elements are of the form
77 ( selection-name selection-value selection-timestamp )
78 selection-name is a lisp symbol, whose name is the name of an X Atom.
79 selection-value is the value that emacs owns for that selection.
80 It may be any kind of Lisp object.
81 selection-timestamp is the time at which emacs began owning this selection,
82 as a cons of two 16-bit numbers (making a 32 bit time.)
83 If there is an entry in this alist, then it can be assumed that emacs owns
84 that selection.
85 The only (eq) parts of this list that are visible from Lisp are the
86 selection-values.
87 */
88Lisp_Object Vselection_alist;
89
90/* This is an alist whose CARs are selection-types (whose names are the same
91 as the names of X Atoms) and whose CDRs are the names of Lisp functions to
92 call to convert the given Emacs selection value to a string representing
93 the given selection type. This is for Lisp-level extension of the emacs
94 selection handling.
95 */
96Lisp_Object Vselection_converter_alist;
97
98/* If the selection owner takes too long to reply to a selection request,
99 we give up on it. This is in seconds (0 = no timeout.)
100 */
101int x_selection_timeout;
102
103\f
104/* Utility functions */
105
106static void lisp_data_to_selection_data ();
107static Lisp_Object selection_data_to_lisp_data ();
108static Lisp_Object x_get_window_property_as_lisp_data ();
109
110static int expect_property_change ();
111static void wait_for_property_change ();
112static void unexpect_property_change ();
113static int waiting_for_other_props_on_window ();
114
115/* This converts a Lisp symbol to a server Atom, avoiding a server
116 roundtrip whenever possible. */
117
118static Atom
119symbol_to_x_atom (display, sym)
120 Display *display;
121 Lisp_Object sym;
122{
123 Atom val;
124 if (NILP (sym)) return 0;
125 if (EQ (sym, QPRIMARY)) return XA_PRIMARY;
126 if (EQ (sym, QSECONDARY)) return XA_SECONDARY;
127 if (EQ (sym, QSTRING)) return XA_STRING;
128 if (EQ (sym, QINTEGER)) return XA_INTEGER;
129 if (EQ (sym, QATOM)) return XA_ATOM;
130 if (EQ (sym, QCLIPBOARD)) return Xatom_CLIPBOARD;
131 if (EQ (sym, QTIMESTAMP)) return Xatom_TIMESTAMP;
132 if (EQ (sym, QTEXT)) return Xatom_TEXT;
133 if (EQ (sym, QDELETE)) return Xatom_DELETE;
134 if (EQ (sym, QMULTIPLE)) return Xatom_MULTIPLE;
135 if (EQ (sym, QINCR)) return Xatom_INCR;
136 if (EQ (sym, QEMACS_TMP)) return Xatom_EMACS_TMP;
137 if (EQ (sym, QTARGETS)) return Xatom_TARGETS;
138 if (EQ (sym, QNULL)) return Xatom_NULL;
139#ifdef CUT_BUFFER_SUPPORT
140 if (EQ (sym, QCUT_BUFFER0)) return XA_CUT_BUFFER0;
141 if (EQ (sym, QCUT_BUFFER1)) return XA_CUT_BUFFER1;
142 if (EQ (sym, QCUT_BUFFER2)) return XA_CUT_BUFFER2;
143 if (EQ (sym, QCUT_BUFFER3)) return XA_CUT_BUFFER3;
144 if (EQ (sym, QCUT_BUFFER4)) return XA_CUT_BUFFER4;
145 if (EQ (sym, QCUT_BUFFER5)) return XA_CUT_BUFFER5;
146 if (EQ (sym, QCUT_BUFFER6)) return XA_CUT_BUFFER6;
147 if (EQ (sym, QCUT_BUFFER7)) return XA_CUT_BUFFER7;
148#endif
149 if (!SYMBOLP (sym)) abort ();
150
151#if 0
152 fprintf (stderr, " XInternAtom %s\n", (char *) XSYMBOL (sym)->name->data);
153#endif
154 BLOCK_INPUT;
155 val = XInternAtom (display, (char *) XSYMBOL (sym)->name->data, False);
156 UNBLOCK_INPUT;
157 return val;
158}
159
160
161/* This converts a server Atom to a Lisp symbol, avoiding server roundtrips
162 and calls to intern whenever possible. */
163
164static Lisp_Object
165x_atom_to_symbol (display, atom)
166 Display *display;
167 Atom atom;
168{
169 char *str;
170 Lisp_Object val;
171 if (! atom) return Qnil;
7da64e5c
RS
172 switch (atom)
173 {
174 case XA_PRIMARY:
175 return QPRIMARY;
176 case XA_SECONDARY:
177 return QSECONDARY;
178 case XA_STRING:
179 return QSTRING;
180 case XA_INTEGER:
181 return QINTEGER;
182 case XA_ATOM:
183 return QATOM;
ede4db72 184#ifdef CUT_BUFFER_SUPPORT
7da64e5c
RS
185 case XA_CUT_BUFFER0:
186 return QCUT_BUFFER0;
187 case XA_CUT_BUFFER1:
188 return QCUT_BUFFER1;
189 case XA_CUT_BUFFER2:
190 return QCUT_BUFFER2;
191 case XA_CUT_BUFFER3:
192 return QCUT_BUFFER3;
193 case XA_CUT_BUFFER4:
194 return QCUT_BUFFER4;
195 case XA_CUT_BUFFER5:
196 return QCUT_BUFFER5;
197 case XA_CUT_BUFFER6:
198 return QCUT_BUFFER6;
199 case XA_CUT_BUFFER7:
200 return QCUT_BUFFER7;
ede4db72 201#endif
7da64e5c
RS
202 }
203
204 if (atom == Xatom_CLIPBOARD)
205 return QCLIPBOARD;
206 if (atom == Xatom_TIMESTAMP)
207 return QTIMESTAMP;
208 if (atom == Xatom_TEXT)
209 return QTEXT;
210 if (atom == Xatom_DELETE)
211 return QDELETE;
212 if (atom == Xatom_MULTIPLE)
213 return QMULTIPLE;
214 if (atom == Xatom_INCR)
215 return QINCR;
216 if (atom == Xatom_EMACS_TMP)
217 return QEMACS_TMP;
218 if (atom == Xatom_TARGETS)
219 return QTARGETS;
220 if (atom == Xatom_NULL)
221 return QNULL;
ede4db72
RS
222
223 BLOCK_INPUT;
224 str = XGetAtomName (display, atom);
225 UNBLOCK_INPUT;
226#if 0
227 fprintf (stderr, " XGetAtomName --> %s\n", str);
228#endif
229 if (! str) return Qnil;
230 val = intern (str);
231 BLOCK_INPUT;
232 XFree (str);
233 UNBLOCK_INPUT;
234 return val;
235}
8a89415e 236\f
ede4db72
RS
237/* Do protocol to assert ourself as a selection owner.
238 Update the Vselection_alist so that we can reply to later requests for
239 our selection. */
240
241static void
242x_own_selection (selection_name, selection_value)
243 Lisp_Object selection_name, selection_value;
244{
245 Display *display = x_current_display;
246#ifdef X_TOOLKIT
247 Window selecting_window = XtWindow (selected_screen->display.x->edit_widget);
248#else
249 Window selecting_window = FRAME_X_WINDOW (selected_frame);
250#endif
7da64e5c 251 Time time = last_event_timestamp;
ede4db72
RS
252 Atom selection_atom;
253
254 CHECK_SYMBOL (selection_name, 0);
255 selection_atom = symbol_to_x_atom (display, selection_name);
256
257 BLOCK_INPUT;
258 XSetSelectionOwner (display, selection_atom, selecting_window, time);
259 UNBLOCK_INPUT;
260
261 /* Now update the local cache */
262 {
263 Lisp_Object selection_time;
264 Lisp_Object selection_data;
265 Lisp_Object prev_value;
266
267 selection_time = long_to_cons ((unsigned long) time);
268 selection_data = Fcons (selection_name,
269 Fcons (selection_value,
270 Fcons (selection_time, Qnil)));
271 prev_value = assq_no_quit (selection_name, Vselection_alist);
272
273 Vselection_alist = Fcons (selection_data, Vselection_alist);
274
275 /* If we already owned the selection, remove the old selection data.
276 Perhaps we should destructively modify it instead.
277 Don't use Fdelq as that may QUIT. */
278 if (!NILP (prev_value))
279 {
280 Lisp_Object rest; /* we know it's not the CAR, so it's easy. */
281 for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
282 if (EQ (prev_value, Fcar (XCONS (rest)->cdr)))
283 {
284 XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
285 break;
286 }
287 }
288 }
289}
290\f
291/* Given a selection-name and desired type, look up our local copy of
292 the selection value and convert it to the type.
293 The value is nil or a string.
294 This function is used both for remote requests
7da64e5c 295 and for local x-get-selection-internal.
ede4db72
RS
296
297 This calls random Lisp code, and may signal or gc. */
298
299static Lisp_Object
300x_get_local_selection (selection_symbol, target_type)
301 Lisp_Object selection_symbol, target_type;
302{
303 Lisp_Object local_value;
304 Lisp_Object handler_fn, value, type, check;
305 int count;
306
307 local_value = assq_no_quit (selection_symbol, Vselection_alist);
308
309 if (NILP (local_value)) return Qnil;
310
311 /* TIMESTAMP and MULTIPLE are special cases 'cause that's easiest. */
312 if (EQ (target_type, QTIMESTAMP))
313 {
314 handler_fn = Qnil;
315 value = XCONS (XCONS (XCONS (local_value)->cdr)->cdr)->car;
316 }
317#if 0
318 else if (EQ (target_type, QDELETE))
319 {
320 handler_fn = Qnil;
321 Fx_disown_selection_internal
322 (selection_symbol,
323 XCONS (XCONS (XCONS (local_value)->cdr)->cdr)->car);
324 value = QNULL;
325 }
326#endif
327
328#if 0 /* #### MULTIPLE doesn't work yet */
329 else if (CONSP (target_type)
330 && XCONS (target_type)->car == QMULTIPLE)
331 {
332 Lisp_Object pairs = XCONS (target_type)->cdr;
333 int size = XVECTOR (pairs)->size;
334 int i;
335 /* If the target is MULTIPLE, then target_type looks like
336 (MULTIPLE . [[SELECTION1 TARGET1] [SELECTION2 TARGET2] ... ])
337 We modify the second element of each pair in the vector and
338 return it as [[SELECTION1 <value1>] [SELECTION2 <value2>] ... ]
339 */
340 for (i = 0; i < size; i++)
341 {
342 Lisp_Object pair = XVECTOR (pairs)->contents [i];
343 XVECTOR (pair)->contents [1]
344 = x_get_local_selection (XVECTOR (pair)->contents [0],
345 XVECTOR (pair)->contents [1]);
346 }
347 return pairs;
348 }
349#endif
350 else
351 {
352 /* Don't allow a quit within the converter.
353 When the user types C-g, he would be surprised
354 if by luck it came during a converter. */
355 count = specpdl_ptr - specpdl;
356 specbind (Qinhibit_quit, Qt);
357
358 CHECK_SYMBOL (target_type, 0);
359 handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist));
1eb4d468
RS
360 if (!NILP (handler_fn))
361 value = call3 (handler_fn,
362 selection_symbol, target_type,
363 XCONS (XCONS (local_value)->cdr)->car);
364 else
365 value = Qnil;
ede4db72
RS
366 unbind_to (count, Qnil);
367 }
368
369 /* Make sure this value is of a type that we could transmit
370 to another X client. */
a87ed99c 371
ede4db72
RS
372 check = value;
373 if (CONSP (value)
374 && SYMBOLP (XCONS (value)->car))
375 type = XCONS (value)->car,
376 check = XCONS (value)->cdr;
377
378 if (STRINGP (check)
379 || VECTORP (check)
380 || SYMBOLP (check)
7da64e5c 381 || INTEGERP (check)
ede4db72
RS
382 || NILP (value))
383 return value;
a87ed99c 384 /* Check for a value that cons_to_long could handle. */
ede4db72 385 else if (CONSP (check)
7da64e5c
RS
386 && INTEGERP (XCONS (check)->car)
387 && (INTEGERP (XCONS (check)->cdr)
ede4db72
RS
388 ||
389 (CONSP (XCONS (check)->cdr)
7da64e5c 390 && INTEGERP (XCONS (XCONS (check)->cdr)->car)
ede4db72
RS
391 && NILP (XCONS (XCONS (check)->cdr)->cdr))))
392 return value;
393 else
394 return
395 Fsignal (Qerror,
a87ed99c 396 Fcons (build_string ("invalid data returned by selection-conversion function"),
ede4db72
RS
397 Fcons (handler_fn, Fcons (value, Qnil))));
398}
399\f
400/* Subroutines of x_reply_selection_request. */
401
402/* Send a SelectionNotify event to the requestor with property=None,
403 meaning we were unable to do what they wanted. */
404
405static void
406x_decline_selection_request (event)
407 struct input_event *event;
408{
409 XSelectionEvent reply;
410 reply.type = SelectionNotify;
411 reply.display = SELECTION_EVENT_DISPLAY (event);
412 reply.requestor = SELECTION_EVENT_REQUESTOR (event);
413 reply.selection = SELECTION_EVENT_SELECTION (event);
414 reply.time = SELECTION_EVENT_TIME (event);
415 reply.target = SELECTION_EVENT_TARGET (event);
416 reply.property = None;
417
418 BLOCK_INPUT;
419 (void) XSendEvent (reply.display, reply.requestor, False, 0L,
420 (XEvent *) &reply);
421 UNBLOCK_INPUT;
422}
423
424/* This is the selection request currently being processed.
425 It is set to zero when the request is fully processed. */
426static struct input_event *x_selection_current_request;
427
428/* Used as an unwind-protect clause so that, if a selection-converter signals
429 an error, we tell the requestor that we were unable to do what they wanted
430 before we throw to top-level or go into the debugger or whatever. */
431
432static Lisp_Object
433x_selection_request_lisp_error (ignore)
434 Lisp_Object ignore;
435{
436 if (x_selection_current_request != 0)
437 x_decline_selection_request (x_selection_current_request);
438 return Qnil;
439}
440\f
441/* Send the reply to a selection request event EVENT.
442 TYPE is the type of selection data requested.
443 DATA and SIZE describe the data to send, already converted.
444 FORMAT is the unit-size (in bits) of the data to be transmitted. */
445
446static void
447x_reply_selection_request (event, format, data, size, type)
448 struct input_event *event;
449 int format, size;
450 unsigned char *data;
451 Atom type;
452{
453 XSelectionEvent reply;
454 Display *display = SELECTION_EVENT_DISPLAY (event);
455 Window window = SELECTION_EVENT_REQUESTOR (event);
456 int bytes_remaining;
457 int format_bytes = format/8;
458 int max_bytes = SELECTION_QUANTUM (display);
459
460 if (max_bytes > MAX_SELECTION_QUANTUM)
461 max_bytes = MAX_SELECTION_QUANTUM;
462
463 reply.type = SelectionNotify;
464 reply.display = display;
465 reply.requestor = window;
466 reply.selection = SELECTION_EVENT_SELECTION (event);
467 reply.time = SELECTION_EVENT_TIME (event);
468 reply.target = SELECTION_EVENT_TARGET (event);
469 reply.property = SELECTION_EVENT_PROPERTY (event);
470 if (reply.property == None)
471 reply.property = reply.target;
472
473 /* #### XChangeProperty can generate BadAlloc, and we must handle it! */
474
475 BLOCK_INPUT;
476 /* Store the data on the requested property.
477 If the selection is large, only store the first N bytes of it.
478 */
479 bytes_remaining = size * format_bytes;
480 if (bytes_remaining <= max_bytes)
481 {
482 /* Send all the data at once, with minimal handshaking. */
483#if 0
484 fprintf (stderr,"\nStoring all %d\n", bytes_remaining);
485#endif
486 XChangeProperty (display, window, reply.property, type, format,
487 PropModeReplace, data, size);
488 /* At this point, the selection was successfully stored; ack it. */
489 (void) XSendEvent (display, window, False, 0L, (XEvent *) &reply);
490 }
491 else
492 {
493 /* Send an INCR selection. */
494 int prop_id;
495
7da64e5c 496 if (x_window_to_frame (window)) /* #### debug */
ede4db72
RS
497 error ("attempt to transfer an INCR to ourself!");
498#if 0
499 fprintf (stderr, "\nINCR %d\n", bytes_remaining);
500#endif
501 prop_id = expect_property_change (display, window, reply.property,
502 PropertyDelete);
503
504 XChangeProperty (display, window, reply.property, Xatom_INCR,
505 32, PropModeReplace, (unsigned char *)
506 &bytes_remaining, 1);
507 XSelectInput (display, window, PropertyChangeMask);
508 /* Tell 'em the INCR data is there... */
509 (void) XSendEvent (display, window, False, 0L, (XEvent *) &reply);
510
511 /* First, wait for the requestor to ack by deleting the property.
512 This can run random lisp code (process handlers) or signal. */
513 wait_for_property_change (prop_id);
514
515 while (bytes_remaining)
516 {
517 int i = ((bytes_remaining < max_bytes)
518 ? bytes_remaining
519 : max_bytes);
520 prop_id = expect_property_change (display, window, reply.property,
521 PropertyDelete);
522#if 0
523 fprintf (stderr," INCR adding %d\n", i);
524#endif
525 /* Append the next chunk of data to the property. */
526 XChangeProperty (display, window, reply.property, type, format,
527 PropModeAppend, data, i / format_bytes);
528 bytes_remaining -= i;
529 data += i;
530
531 /* Now wait for the requestor to ack this chunk by deleting the
532 property. This can run random lisp code or signal.
533 */
534 wait_for_property_change (prop_id);
535 }
536 /* Now write a zero-length chunk to the property to tell the requestor
537 that we're done. */
538#if 0
539 fprintf (stderr," INCR done\n");
540#endif
541 if (! waiting_for_other_props_on_window (display, window))
542 XSelectInput (display, window, 0L);
543
544 XChangeProperty (display, window, reply.property, type, format,
545 PropModeReplace, data, 0);
546 }
cf2d699c 547 XFlushQueue ();
ede4db72
RS
548 UNBLOCK_INPUT;
549}
550\f
551/* Handle a SelectionRequest event EVENT.
552 This is called from keyboard.c when such an event is found in the queue. */
553
554void
555x_handle_selection_request (event)
556 struct input_event *event;
557{
558 struct gcpro gcpro1, gcpro2, gcpro3;
559 XSelectionEvent reply;
560 Lisp_Object local_selection_data = Qnil;
561 Lisp_Object selection_symbol;
562 Lisp_Object target_symbol = Qnil;
563 Lisp_Object converted_selection = Qnil;
564 Time local_selection_time;
565 Lisp_Object successful_p = Qnil;
566 int count;
567
568 GCPRO3 (local_selection_data, converted_selection, target_symbol);
569
570 reply.type = SelectionNotify; /* Construct the reply event */
571 reply.display = SELECTION_EVENT_DISPLAY (event);
572 reply.requestor = SELECTION_EVENT_REQUESTOR (event);
573 reply.selection = SELECTION_EVENT_SELECTION (event);
574 reply.time = SELECTION_EVENT_TIME (event);
575 reply.target = SELECTION_EVENT_TARGET (event);
576 reply.property = SELECTION_EVENT_PROPERTY (event);
577 if (reply.property == None)
578 reply.property = reply.target;
579
580 selection_symbol = x_atom_to_symbol (reply.display,
581 SELECTION_EVENT_SELECTION (event));
582
583 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
584
585#if 0
586# define CDR(x) (XCONS (x)->cdr)
587# define CAR(x) (XCONS (x)->car)
588 /* This list isn't user-visible, so it can't "go bad." */
589 if (!CONSP (local_selection_data)) abort ();
590 if (!CONSP (CDR (local_selection_data))) abort ();
591 if (!CONSP (CDR (CDR (local_selection_data)))) abort ();
592 if (!NILP (CDR (CDR (CDR (local_selection_data))))) abort ();
593 if (!CONSP (CAR (CDR (CDR (local_selection_data))))) abort ();
7da64e5c
RS
594 if (!INTEGERP (CAR (CAR (CDR (CDR (local_selection_data)))))) abort ();
595 if (!INTEGERP (CDR (CAR (CDR (CDR (local_selection_data)))))) abort ();
ede4db72
RS
596# undef CAR
597# undef CDR
598#endif
599
600 if (NILP (local_selection_data))
601 {
602 /* Someone asked for the selection, but we don't have it any more.
603 */
604 x_decline_selection_request (event);
605 goto DONE;
606 }
607
608 local_selection_time = (Time)
609 cons_to_long (XCONS (XCONS (XCONS (local_selection_data)->cdr)->cdr)->car);
610
611 if (SELECTION_EVENT_TIME (event) != CurrentTime
7da64e5c 612 && local_selection_time > SELECTION_EVENT_TIME (event))
ede4db72
RS
613 {
614 /* Someone asked for the selection, and we have one, but not the one
615 they're looking for.
616 */
617 x_decline_selection_request (event);
618 goto DONE;
619 }
620
621 count = specpdl_ptr - specpdl;
622 x_selection_current_request = event;
623 record_unwind_protect (x_selection_request_lisp_error, Qnil);
624
625 target_symbol = x_atom_to_symbol (reply.display,
626 SELECTION_EVENT_TARGET (event));
627
628#if 0 /* #### MULTIPLE doesn't work yet */
629 if (EQ (target_symbol, QMULTIPLE))
630 target_symbol = fetch_multiple_target (event);
631#endif
632
633 /* Convert lisp objects back into binary data */
634
635 converted_selection
636 = x_get_local_selection (selection_symbol, target_symbol);
637
638 if (! NILP (converted_selection))
639 {
640 unsigned char *data;
641 unsigned int size;
642 int format;
643 Atom type;
644 lisp_data_to_selection_data (reply.display, converted_selection,
645 &data, &type, &size, &format);
646
647 x_reply_selection_request (event, format, data, size, type);
648 successful_p = Qt;
649
650 /* Indicate we have successfully processed this event. */
7da64e5c 651 x_selection_current_request = 0;
ede4db72
RS
652
653 xfree (data);
654 }
655 unbind_to (count, Qnil);
656
657 DONE:
658
659 UNGCPRO;
660
661 /* Let random lisp code notice that the selection has been asked for. */
662 {
663 Lisp_Object rest = Vx_sent_selection_hooks;
664 if (!EQ (rest, Qunbound))
665 for (; CONSP (rest); rest = Fcdr (rest))
666 call3 (Fcar (rest), selection_symbol, target_symbol, successful_p);
667 }
668}
669\f
670/* Handle a SelectionClear event EVENT, which indicates that some other
671 client cleared out our previously asserted selection.
672 This is called from keyboard.c when such an event is found in the queue. */
673
674void
675x_handle_selection_clear (event)
676 struct input_event *event;
677{
678 Display *display = SELECTION_EVENT_DISPLAY (event);
679 Atom selection = SELECTION_EVENT_SELECTION (event);
680 Time changed_owner_time = SELECTION_EVENT_TIME (event);
681
682 Lisp_Object selection_symbol, local_selection_data;
683 Time local_selection_time;
684
685 selection_symbol = x_atom_to_symbol (display, selection);
686
687 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
688
689 /* Well, we already believe that we don't own it, so that's just fine. */
690 if (NILP (local_selection_data)) return;
691
692 local_selection_time = (Time)
693 cons_to_long (XCONS (XCONS (XCONS (local_selection_data)->cdr)->cdr)->car);
694
695 /* This SelectionClear is for a selection that we no longer own, so we can
696 disregard it. (That is, we have reasserted the selection since this
697 request was generated.) */
698
699 if (changed_owner_time != CurrentTime
700 && local_selection_time > changed_owner_time)
701 return;
702
703 /* Otherwise, we're really honest and truly being told to drop it.
704 Don't use Fdelq as that may QUIT;. */
705
706 if (EQ (local_selection_data, Fcar (Vselection_alist)))
707 Vselection_alist = Fcdr (Vselection_alist);
708 else
709 {
710 Lisp_Object rest;
711 for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
712 if (EQ (local_selection_data, Fcar (XCONS (rest)->cdr)))
713 {
714 XCONS (rest)->cdr = Fcdr (XCONS (rest)->cdr);
715 break;
716 }
717 }
718
719 /* Let random lisp code notice that the selection has been stolen. */
720
721 {
722 Lisp_Object rest = Vx_lost_selection_hooks;
723 if (!EQ (rest, Qunbound))
724 for (; CONSP (rest); rest = Fcdr (rest))
725 call1 (Fcar (rest), selection_symbol);
726 }
727}
728
729\f
730/* This stuff is so that INCR selections are reentrant (that is, so we can
731 be servicing multiple INCR selection requests simultaneously.) I haven't
732 actually tested that yet. */
733
734static int prop_location_tick;
735
736static Lisp_Object property_change_reply;
737static int property_change_reply_tick;
738
739/* Keep a list of the property changes that are awaited. */
740
741struct prop_location
742{
743 int tick;
744 Display *display;
745 Window window;
746 Atom property;
747 int desired_state;
748 struct prop_location *next;
749};
750
751static struct prop_location *property_change_wait_list;
752
753static int
754property_deleted_p (tick)
755 void *tick;
756{
757 struct prop_location *rest = property_change_wait_list;
758 while (rest)
759 if (rest->tick == (int) tick)
760 return 0;
761 else
762 rest = rest->next;
763 return 1;
764}
765
766/* Nonzero if any properties for DISPLAY and WINDOW
767 are on the list of what we are waiting for. */
768
769static int
770waiting_for_other_props_on_window (display, window)
771 Display *display;
772 Window window;
773{
774 struct prop_location *rest = property_change_wait_list;
775 while (rest)
776 if (rest->display == display && rest->window == window)
777 return 1;
778 else
779 rest = rest->next;
780 return 0;
781}
782
783/* Add an entry to the list of property changes we are waiting for.
784 DISPLAY, WINDOW, PROPERTY, STATE describe what we will wait for.
785 The return value is a number that uniquely identifies
786 this awaited property change. */
787
788static int
789expect_property_change (display, window, property, state)
790 Display *display;
791 Window window;
792 Lisp_Object property;
793 int state;
794{
795 struct prop_location *pl
796 = (struct prop_location *) xmalloc (sizeof (struct prop_location));
797 pl->tick = ++prop_location_tick;
798 pl->display = display;
799 pl->window = window;
800 pl->property = property;
801 pl->desired_state = state;
802 pl->next = property_change_wait_list;
803 property_change_wait_list = pl;
804 return pl->tick;
805}
806
807/* Delete an entry from the list of property changes we are waiting for.
808 TICK is the number that uniquely identifies the entry. */
809
810static void
811unexpect_property_change (tick)
812 int tick;
813{
814 struct prop_location *prev = 0, *rest = property_change_wait_list;
815 while (rest)
816 {
817 if (rest->tick == tick)
818 {
819 if (prev)
820 prev->next = rest->next;
821 else
822 property_change_wait_list = rest->next;
823 xfree (rest);
824 return;
825 }
826 prev = rest;
827 rest = rest->next;
828 }
829}
830
831/* Actually wait for a property change.
832 TICK should be the value that expect_property_change returned. */
833
834static void
835wait_for_property_change (tick)
836{
837 XCONS (property_change_reply)->car = Qnil;
838 property_change_reply_tick = tick;
839 wait_reading_process_input (0, 0, property_change_reply, 0);
840}
841
842/* Called from XTread_socket in response to a PropertyNotify event. */
843
844void
845x_handle_property_notify (event)
846 XPropertyEvent *event;
847{
848 struct prop_location *prev = 0, *rest = property_change_wait_list;
849 while (rest)
850 {
851 if (rest->property == event->atom
852 && rest->window == event->window
853 && rest->display == event->display
854 && rest->desired_state == event->state)
855 {
856#if 0
857 fprintf (stderr, "Saw expected prop-%s on %s\n",
858 (event->state == PropertyDelete ? "delete" : "change"),
859 (char *) XSYMBOL (x_atom_to_symbol (event->display,
860 event->atom))
861 ->name->data);
862#endif
863
864 /* If this is the one wait_for_property_change is waiting for,
865 tell it to wake up. */
866 if (rest->tick == property_change_reply_tick)
867 XCONS (property_change_reply)->car = Qt;
868
869 if (prev)
870 prev->next = rest->next;
871 else
872 property_change_wait_list = rest->next;
873 xfree (rest);
874 return;
875 }
876 prev = rest;
877 rest = rest->next;
878 }
879#if 0
880 fprintf (stderr, "Saw UNexpected prop-%s on %s\n",
881 (event->state == PropertyDelete ? "delete" : "change"),
882 (char *) XSYMBOL (x_atom_to_symbol (event->display, event->atom))
883 ->name->data);
884#endif
885}
886
887
888\f
889#if 0 /* #### MULTIPLE doesn't work yet */
890
891static Lisp_Object
892fetch_multiple_target (event)
893 XSelectionRequestEvent *event;
894{
895 Display *display = event->display;
896 Window window = event->requestor;
897 Atom target = event->target;
898 Atom selection_atom = event->selection;
899 int result;
900
901 return
902 Fcons (QMULTIPLE,
903 x_get_window_property_as_lisp_data (display, window, target,
904 QMULTIPLE, selection_atom));
905}
906
907static Lisp_Object
908copy_multiple_data (obj)
909 Lisp_Object obj;
910{
911 Lisp_Object vec;
912 int i;
913 int size;
914 if (CONSP (obj))
915 return Fcons (XCONS (obj)->car, copy_multiple_data (XCONS (obj)->cdr));
916
917 CHECK_VECTOR (obj, 0);
918 vec = Fmake_vector (size = XVECTOR (obj)->size, Qnil);
919 for (i = 0; i < size; i++)
920 {
921 Lisp_Object vec2 = XVECTOR (obj)->contents [i];
922 CHECK_VECTOR (vec2, 0);
923 if (XVECTOR (vec2)->size != 2)
924 /* ??? Confusing error message */
925 Fsignal (Qerror, Fcons (build_string ("vectors must be of length 2"),
926 Fcons (vec2, Qnil)));
927 XVECTOR (vec)->contents [i] = Fmake_vector (2, Qnil);
928 XVECTOR (XVECTOR (vec)->contents [i])->contents [0]
929 = XVECTOR (vec2)->contents [0];
930 XVECTOR (XVECTOR (vec)->contents [i])->contents [1]
931 = XVECTOR (vec2)->contents [1];
932 }
933 return vec;
934}
935
936#endif
937
938\f
939/* Variables for communication with x_handle_selection_notify. */
940static Atom reading_which_selection;
941static Lisp_Object reading_selection_reply;
942static Window reading_selection_window;
943
944/* Do protocol to read selection-data from the server.
945 Converts this to Lisp data and returns it. */
946
947static Lisp_Object
948x_get_foreign_selection (selection_symbol, target_type)
949 Lisp_Object selection_symbol, target_type;
950{
951 Display *display = x_current_display;
952#ifdef X_TOOLKIT
7da64e5c 953 Window requestor_window = XtWindow (selected_screen->display.x->edit_widget);
ede4db72 954#else
7da64e5c 955 Window requestor_window = FRAME_X_WINDOW (selected_frame);
ede4db72 956#endif
7da64e5c 957 Time requestor_time = last_event_timestamp;
ede4db72
RS
958 Atom target_property = Xatom_EMACS_TMP;
959 Atom selection_atom = symbol_to_x_atom (display, selection_symbol);
960 Atom type_atom;
961
962 if (CONSP (target_type))
963 type_atom = symbol_to_x_atom (display, XCONS (target_type)->car);
964 else
965 type_atom = symbol_to_x_atom (display, target_type);
966
967 BLOCK_INPUT;
968 XConvertSelection (display, selection_atom, type_atom, target_property,
969 requestor_window, requestor_time);
a87ed99c 970 XFlushQueue ();
ede4db72
RS
971
972 /* Prepare to block until the reply has been read. */
973 reading_selection_window = requestor_window;
974 reading_which_selection = selection_atom;
975 XCONS (reading_selection_reply)->car = Qnil;
976 UNBLOCK_INPUT;
977
978 /* This allows quits. */
979 wait_reading_process_input (x_selection_timeout, 0,
980 reading_selection_reply, 0);
981
982 if (NILP (XCONS (reading_selection_reply)->car))
983 error ("timed out waiting for reply from selection owner");
984
985 /* Otherwise, the selection is waiting for us on the requested property. */
986 return
987 x_get_window_property_as_lisp_data (display, requestor_window,
988 target_property, target_type,
989 selection_atom);
990}
991\f
992/* Subroutines of x_get_window_property_as_lisp_data */
993
994static void
995x_get_window_property (display, window, property, data_ret, bytes_ret,
996 actual_type_ret, actual_format_ret, actual_size_ret,
997 delete_p)
998 Display *display;
999 Window window;
1000 Atom property;
1001 unsigned char **data_ret;
1002 int *bytes_ret;
1003 Atom *actual_type_ret;
1004 int *actual_format_ret;
1005 unsigned long *actual_size_ret;
1006 int delete_p;
1007{
1008 int total_size;
1009 unsigned long bytes_remaining;
1010 int offset = 0;
1011 unsigned char *tmp_data = 0;
1012 int result;
1013 int buffer_size = SELECTION_QUANTUM (display);
1014 if (buffer_size > MAX_SELECTION_QUANTUM) buffer_size = MAX_SELECTION_QUANTUM;
1015
1016 BLOCK_INPUT;
1017 /* First probe the thing to find out how big it is. */
1018 result = XGetWindowProperty (display, window, property,
1019 0, 0, False, AnyPropertyType,
1020 actual_type_ret, actual_format_ret,
1021 actual_size_ret,
1022 &bytes_remaining, &tmp_data);
1023 UNBLOCK_INPUT;
1024 if (result != Success)
1025 {
1026 *data_ret = 0;
1027 *bytes_ret = 0;
1028 return;
1029 }
1030 BLOCK_INPUT;
1031 XFree ((char *) tmp_data);
1032 UNBLOCK_INPUT;
1033
1034 if (*actual_type_ret == None || *actual_format_ret == 0)
1035 {
1036 if (delete_p) XDeleteProperty (display, window, property);
1037 return;
1038 }
1039
1040 total_size = bytes_remaining + 1;
1041 *data_ret = (unsigned char *) xmalloc (total_size);
1042
1043 /* Now read, until weve gotten it all. */
1044 BLOCK_INPUT;
1045 while (bytes_remaining)
1046 {
1047#if 0
1048 int last = bytes_remaining;
1049#endif
1050 result
1051 = XGetWindowProperty (display, window, property,
1052 offset/4, buffer_size/4,
1053 (delete_p ? True : False),
1054 AnyPropertyType,
1055 actual_type_ret, actual_format_ret,
1056 actual_size_ret, &bytes_remaining, &tmp_data);
1057#if 0
1058 fprintf (stderr, "<< read %d\n", last-bytes_remaining);
1059#endif
1060 /* If this doesn't return Success at this point, it means that
1061 some clod deleted the selection while we were in the midst of
1062 reading it. Deal with that, I guess....
1063 */
1064 if (result != Success) break;
1065 *actual_size_ret *= *actual_format_ret / 8;
1066 bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret);
1067 offset += *actual_size_ret;
1068 XFree ((char *) tmp_data);
1069 }
1070 UNBLOCK_INPUT;
1071 *bytes_ret = offset;
1072}
1073\f
1074static void
1075receive_incremental_selection (display, window, property, target_type,
1076 min_size_bytes, data_ret, size_bytes_ret,
1077 type_ret, format_ret, size_ret)
1078 Display *display;
1079 Window window;
1080 Atom property;
1081 Lisp_Object target_type; /* for error messages only */
1082 unsigned int min_size_bytes;
1083 unsigned char **data_ret;
1084 int *size_bytes_ret;
1085 Atom *type_ret;
1086 unsigned long *size_ret;
1087 int *format_ret;
1088{
1089 int offset = 0;
1090 int prop_id;
1091 *size_bytes_ret = min_size_bytes;
1092 *data_ret = (unsigned char *) xmalloc (*size_bytes_ret);
1093#if 0
1094 fprintf (stderr, "\nread INCR %d\n", min_size_bytes);
1095#endif
1096 /* At this point, we have read an INCR property, and deleted it (which
1097 is how we ack its receipt: the sending window will be selecting
1098 PropertyNotify events on our window to notice this.)
1099
1100 Now, we must loop, waiting for the sending window to put a value on
1101 that property, then reading the property, then deleting it to ack.
1102 We are done when the sender places a property of length 0.
1103 */
1104 prop_id = expect_property_change (display, window, property,
1105 PropertyNewValue);
1106 while (1)
1107 {
1108 unsigned char *tmp_data;
1109 int tmp_size_bytes;
1110 wait_for_property_change (prop_id);
1111 /* expect it again immediately, because x_get_window_property may
1112 .. no it wont, I dont get it.
1113 .. Ok, I get it now, the Xt code that implements INCR is broken.
1114 */
1115 prop_id = expect_property_change (display, window, property,
1116 PropertyNewValue);
1117 x_get_window_property (display, window, property,
1118 &tmp_data, &tmp_size_bytes,
1119 type_ret, format_ret, size_ret, 1);
1120
1121 if (tmp_size_bytes == 0) /* we're done */
1122 {
1123#if 0
1124 fprintf (stderr, " read INCR done\n");
1125#endif
1126 unexpect_property_change (prop_id);
1127 if (tmp_data) xfree (tmp_data);
1128 break;
1129 }
1130#if 0
1131 fprintf (stderr, " read INCR %d\n", tmp_size_bytes);
1132#endif
1133 if (*size_bytes_ret < offset + tmp_size_bytes)
1134 {
1135#if 0
1136 fprintf (stderr, " read INCR realloc %d -> %d\n",
1137 *size_bytes_ret, offset + tmp_size_bytes);
1138#endif
1139 *size_bytes_ret = offset + tmp_size_bytes;
1140 *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret);
1141 }
1142 memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes);
1143 offset += tmp_size_bytes;
1144 xfree (tmp_data);
1145 }
1146}
1147\f
1148/* Once a requested selection is "ready" (we got a SelectionNotify event),
1149 fetch value from property PROPERTY of X window WINDOW on display DISPLAY.
1150 TARGET_TYPE and SELECTION_ATOM are used in error message if this fails. */
1151
1152static Lisp_Object
1153x_get_window_property_as_lisp_data (display, window, property, target_type,
1154 selection_atom)
1155 Display *display;
1156 Window window;
1157 Atom property;
1158 Lisp_Object target_type; /* for error messages only */
1159 Atom selection_atom; /* for error messages only */
1160{
1161 Atom actual_type;
1162 int actual_format;
1163 unsigned long actual_size;
1164 unsigned char *data = 0;
1165 int bytes = 0;
1166 Lisp_Object val;
1167
1168 x_get_window_property (display, window, property, &data, &bytes,
1169 &actual_type, &actual_format, &actual_size, 1);
1170 if (! data)
1171 {
1172 int there_is_a_selection_owner;
1173 BLOCK_INPUT;
1174 there_is_a_selection_owner
1175 = XGetSelectionOwner (display, selection_atom);
1176 UNBLOCK_INPUT;
1177 while (1) /* Note debugger can no longer return, so this is obsolete */
1178 Fsignal (Qerror,
1179 there_is_a_selection_owner ?
1180 Fcons (build_string ("selection owner couldn't convert"),
1181 actual_type
1182 ? Fcons (target_type,
1183 Fcons (x_atom_to_symbol (display, actual_type),
1184 Qnil))
1185 : Fcons (target_type, Qnil))
1186 : Fcons (build_string ("no selection"),
1187 Fcons (x_atom_to_symbol (display, selection_atom),
1188 Qnil)));
1189 }
1190
1191 if (actual_type == Xatom_INCR)
1192 {
1193 /* That wasn't really the data, just the beginning. */
1194
1195 unsigned int min_size_bytes = * ((unsigned int *) data);
1196 BLOCK_INPUT;
1197 XFree ((char *) data);
1198 UNBLOCK_INPUT;
1199 receive_incremental_selection (display, window, property, target_type,
1200 min_size_bytes, &data, &bytes,
1201 &actual_type, &actual_format,
1202 &actual_size);
1203 }
1204
1205 /* It's been read. Now convert it to a lisp object in some semi-rational
1206 manner. */
1207 val = selection_data_to_lisp_data (display, data, bytes,
1208 actual_type, actual_format);
1209
1210 xfree ((char *) data);
1211 return val;
1212}
1213\f
1214/* These functions convert from the selection data read from the server into
1215 something that we can use from Lisp, and vice versa.
1216
1217 Type: Format: Size: Lisp Type:
1218 ----- ------- ----- -----------
1219 * 8 * String
1220 ATOM 32 1 Symbol
1221 ATOM 32 > 1 Vector of Symbols
1222 * 16 1 Integer
1223 * 16 > 1 Vector of Integers
1224 * 32 1 if <=16 bits: Integer
1225 if > 16 bits: Cons of top16, bot16
1226 * 32 > 1 Vector of the above
1227
1228 When converting a Lisp number to C, it is assumed to be of format 16 if
1229 it is an integer, and of format 32 if it is a cons of two integers.
1230
1231 When converting a vector of numbers from Lisp to C, it is assumed to be
1232 of format 16 if every element in the vector is an integer, and is assumed
1233 to be of format 32 if any element is a cons of two integers.
1234
1235 When converting an object to C, it may be of the form (SYMBOL . <data>)
1236 where SYMBOL is what we should claim that the type is. Format and
1237 representation are as above. */
1238
1239
1240
1241static Lisp_Object
1242selection_data_to_lisp_data (display, data, size, type, format)
1243 Display *display;
1244 unsigned char *data;
1245 Atom type;
1246 int size, format;
1247{
1248
1249 if (type == Xatom_NULL)
1250 return QNULL;
1251
1252 /* Convert any 8-bit data to a string, for compactness. */
1253 else if (format == 8)
1254 return make_string ((char *) data, size);
1255
1256 /* Convert a single atom to a Lisp_Symbol. Convert a set of atoms to
1257 a vector of symbols.
1258 */
1259 else if (type == XA_ATOM)
1260 {
1261 int i;
1262 if (size == sizeof (Atom))
1263 return x_atom_to_symbol (display, *((Atom *) data));
1264 else
1265 {
1266 Lisp_Object v = Fmake_vector (size / sizeof (Atom), 0);
1267 for (i = 0; i < size / sizeof (Atom); i++)
1268 Faset (v, i, x_atom_to_symbol (display, ((Atom *) data) [i]));
1269 return v;
1270 }
1271 }
1272
1273 /* Convert a single 16 or small 32 bit number to a Lisp_Int.
1274 If the number is > 16 bits, convert it to a cons of integers,
1275 16 bits in each half.
1276 */
1277 else if (format == 32 && size == sizeof (long))
1278 return long_to_cons (((unsigned long *) data) [0]);
1279 else if (format == 16 && size == sizeof (short))
1280 return make_number ((int) (((unsigned short *) data) [0]));
1281
1282 /* Convert any other kind of data to a vector of numbers, represented
1283 as above (as an integer, or a cons of two 16 bit integers.)
1284 */
1285 else if (format == 16)
1286 {
1287 int i;
1288 Lisp_Object v = Fmake_vector (size / 4, 0);
1289 for (i = 0; i < size / 4; i++)
1290 {
1291 int j = (int) ((unsigned short *) data) [i];
1292 Faset (v, i, make_number (j));
1293 }
1294 return v;
1295 }
1296 else
1297 {
1298 int i;
1299 Lisp_Object v = Fmake_vector (size / 4, 0);
1300 for (i = 0; i < size / 4; i++)
1301 {
1302 unsigned long j = ((unsigned long *) data) [i];
1303 Faset (v, i, long_to_cons (j));
1304 }
1305 return v;
1306 }
1307}
1308
1309
1310static void
1311lisp_data_to_selection_data (display, obj,
1312 data_ret, type_ret, size_ret, format_ret)
1313 Display *display;
1314 Lisp_Object obj;
1315 unsigned char **data_ret;
1316 Atom *type_ret;
1317 unsigned int *size_ret;
1318 int *format_ret;
1319{
1320 Lisp_Object type = Qnil;
1321 if (CONSP (obj) && SYMBOLP (XCONS (obj)->car))
1322 {
1323 type = XCONS (obj)->car;
1324 obj = XCONS (obj)->cdr;
1325 if (CONSP (obj) && NILP (XCONS (obj)->cdr))
1326 obj = XCONS (obj)->car;
1327 }
1328
1329 if (EQ (obj, QNULL) || (EQ (type, QNULL)))
1330 { /* This is not the same as declining */
1331 *format_ret = 32;
1332 *size_ret = 0;
1333 *data_ret = 0;
1334 type = QNULL;
1335 }
1336 else if (STRINGP (obj))
1337 {
1338 *format_ret = 8;
1339 *size_ret = XSTRING (obj)->size;
1340 *data_ret = (unsigned char *) xmalloc (*size_ret);
1341 memcpy (*data_ret, (char *) XSTRING (obj)->data, *size_ret);
1342 if (NILP (type)) type = QSTRING;
1343 }
1344 else if (SYMBOLP (obj))
1345 {
1346 *format_ret = 32;
1347 *size_ret = 1;
1348 *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1);
1349 (*data_ret) [sizeof (Atom)] = 0;
1350 (*(Atom **) data_ret) [0] = symbol_to_x_atom (display, obj);
1351 if (NILP (type)) type = QATOM;
1352 }
7da64e5c 1353 else if (INTEGERP (obj)
ede4db72
RS
1354 && XINT (obj) < 0xFFFF
1355 && XINT (obj) > -0xFFFF)
1356 {
1357 *format_ret = 16;
1358 *size_ret = 1;
1359 *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
1360 (*data_ret) [sizeof (short)] = 0;
1361 (*(short **) data_ret) [0] = (short) XINT (obj);
1362 if (NILP (type)) type = QINTEGER;
1363 }
a87ed99c
RS
1364 else if (INTEGERP (obj)
1365 || (CONSP (obj) && INTEGERP (XCONS (obj)->car)
1366 && (INTEGERP (XCONS (obj)->cdr)
1367 || (CONSP (XCONS (obj)->cdr)
1368 && INTEGERP (XCONS (XCONS (obj)->cdr)->car)))))
ede4db72
RS
1369 {
1370 *format_ret = 32;
1371 *size_ret = 1;
1372 *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
1373 (*data_ret) [sizeof (long)] = 0;
1374 (*(unsigned long **) data_ret) [0] = cons_to_long (obj);
1375 if (NILP (type)) type = QINTEGER;
1376 }
1377 else if (VECTORP (obj))
1378 {
1379 /* Lisp_Vectors may represent a set of ATOMs;
1380 a set of 16 or 32 bit INTEGERs;
1381 or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...]
1382 */
1383 int i;
1384
1385 if (SYMBOLP (XVECTOR (obj)->contents [0]))
1386 /* This vector is an ATOM set */
1387 {
1388 if (NILP (type)) type = QATOM;
1389 *size_ret = XVECTOR (obj)->size;
1390 *format_ret = 32;
1391 *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom));
1392 for (i = 0; i < *size_ret; i++)
1393 if (SYMBOLP (XVECTOR (obj)->contents [i]))
1394 (*(Atom **) data_ret) [i]
1395 = symbol_to_x_atom (display, XVECTOR (obj)->contents [i]);
1396 else
1397 Fsignal (Qerror, /* Qselection_error */
1398 Fcons (build_string
1399 ("all elements of selection vector must have same type"),
1400 Fcons (obj, Qnil)));
1401 }
1402#if 0 /* #### MULTIPLE doesn't work yet */
1403 else if (VECTORP (XVECTOR (obj)->contents [0]))
1404 /* This vector is an ATOM_PAIR set */
1405 {
1406 if (NILP (type)) type = QATOM_PAIR;
1407 *size_ret = XVECTOR (obj)->size;
1408 *format_ret = 32;
1409 *data_ret = (unsigned char *)
1410 xmalloc ((*size_ret) * sizeof (Atom) * 2);
1411 for (i = 0; i < *size_ret; i++)
1412 if (VECTORP (XVECTOR (obj)->contents [i]))
1413 {
1414 Lisp_Object pair = XVECTOR (obj)->contents [i];
1415 if (XVECTOR (pair)->size != 2)
1416 Fsignal (Qerror,
1417 Fcons (build_string
1418 ("elements of the vector must be vectors of exactly two elements"),
1419 Fcons (pair, Qnil)));
1420
1421 (*(Atom **) data_ret) [i * 2]
1422 = symbol_to_x_atom (display, XVECTOR (pair)->contents [0]);
1423 (*(Atom **) data_ret) [(i * 2) + 1]
1424 = symbol_to_x_atom (display, XVECTOR (pair)->contents [1]);
1425 }
1426 else
1427 Fsignal (Qerror,
1428 Fcons (build_string
1429 ("all elements of the vector must be of the same type"),
1430 Fcons (obj, Qnil)));
1431
1432 }
1433#endif
1434 else
1435 /* This vector is an INTEGER set, or something like it */
1436 {
1437 *size_ret = XVECTOR (obj)->size;
1438 if (NILP (type)) type = QINTEGER;
1439 *format_ret = 16;
1440 for (i = 0; i < *size_ret; i++)
1441 if (CONSP (XVECTOR (obj)->contents [i]))
1442 *format_ret = 32;
7da64e5c 1443 else if (!INTEGERP (XVECTOR (obj)->contents [i]))
ede4db72
RS
1444 Fsignal (Qerror, /* Qselection_error */
1445 Fcons (build_string
1446 ("elements of selection vector must be integers or conses of integers"),
1447 Fcons (obj, Qnil)));
1448
1449 *data_ret = (unsigned char *) xmalloc (*size_ret * (*format_ret/8));
1450 for (i = 0; i < *size_ret; i++)
1451 if (*format_ret == 32)
1452 (*((unsigned long **) data_ret)) [i]
1453 = cons_to_long (XVECTOR (obj)->contents [i]);
1454 else
1455 (*((unsigned short **) data_ret)) [i]
1456 = (unsigned short) cons_to_long (XVECTOR (obj)->contents [i]);
1457 }
1458 }
1459 else
1460 Fsignal (Qerror, /* Qselection_error */
1461 Fcons (build_string ("unrecognised selection data"),
1462 Fcons (obj, Qnil)));
1463
1464 *type_ret = symbol_to_x_atom (display, type);
1465}
1466
1467static Lisp_Object
1468clean_local_selection_data (obj)
1469 Lisp_Object obj;
1470{
1471 if (CONSP (obj)
7da64e5c 1472 && INTEGERP (XCONS (obj)->car)
ede4db72 1473 && CONSP (XCONS (obj)->cdr)
7da64e5c 1474 && INTEGERP (XCONS (XCONS (obj)->cdr)->car)
ede4db72
RS
1475 && NILP (XCONS (XCONS (obj)->cdr)->cdr))
1476 obj = Fcons (XCONS (obj)->car, XCONS (obj)->cdr);
1477
1478 if (CONSP (obj)
7da64e5c
RS
1479 && INTEGERP (XCONS (obj)->car)
1480 && INTEGERP (XCONS (obj)->cdr))
ede4db72
RS
1481 {
1482 if (XINT (XCONS (obj)->car) == 0)
1483 return XCONS (obj)->cdr;
1484 if (XINT (XCONS (obj)->car) == -1)
1485 return make_number (- XINT (XCONS (obj)->cdr));
1486 }
1487 if (VECTORP (obj))
1488 {
1489 int i;
1490 int size = XVECTOR (obj)->size;
1491 Lisp_Object copy;
1492 if (size == 1)
1493 return clean_local_selection_data (XVECTOR (obj)->contents [0]);
1494 copy = Fmake_vector (size, Qnil);
1495 for (i = 0; i < size; i++)
1496 XVECTOR (copy)->contents [i]
1497 = clean_local_selection_data (XVECTOR (obj)->contents [i]);
1498 return copy;
1499 }
1500 return obj;
1501}
1502\f
1503/* Called from XTread_socket to handle SelectionNotify events.
1504 If it's the selection we are waiting for, stop waiting. */
1505
1506void
1507x_handle_selection_notify (event)
1508 XSelectionEvent *event;
1509{
1510 if (event->requestor != reading_selection_window)
1511 return;
1512 if (event->selection != reading_which_selection)
1513 return;
1514
1515 XCONS (reading_selection_reply)->car = Qt;
1516}
1517
1518\f
1519DEFUN ("x-own-selection-internal",
1520 Fx_own_selection_internal, Sx_own_selection_internal,
1521 2, 2, 0,
1522 "Assert an X selection of the given TYPE with the given VALUE.\n\
1523TYPE is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
1524\(Those are literal upper-case symbol names, since that's what X expects.)\n\
1525VALUE is typically a string, or a cons of two markers, but may be\n\
a87ed99c 1526anything that the functions on `selection-converter-alist' know about.")
ede4db72
RS
1527 (selection_name, selection_value)
1528 Lisp_Object selection_name, selection_value;
1529{
1530 CHECK_SYMBOL (selection_name, 0);
1531 if (NILP (selection_value)) error ("selection-value may not be nil.");
1532 x_own_selection (selection_name, selection_value);
1533 return selection_value;
1534}
1535
1536
1537/* Request the selection value from the owner. If we are the owner,
1538 simply return our selection value. If we are not the owner, this
1539 will block until all of the data has arrived. */
1540
1541DEFUN ("x-get-selection-internal",
1542 Fx_get_selection_internal, Sx_get_selection_internal, 2, 2, 0,
1543 "Return text selected from some X window.\n\
1544SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
1545\(Those are literal upper-case symbol names, since that's what X expects.)\n\
a87ed99c 1546TYPE is the type of data desired, typically `STRING'.")
ede4db72
RS
1547 (selection_symbol, target_type)
1548 Lisp_Object selection_symbol, target_type;
1549{
1550 Lisp_Object val = Qnil;
1551 struct gcpro gcpro1, gcpro2;
1552 GCPRO2 (target_type, val); /* we store newly consed data into these */
1553 CHECK_SYMBOL (selection_symbol, 0);
1554
1555#if 0 /* #### MULTIPLE doesn't work yet */
1556 if (CONSP (target_type)
1557 && XCONS (target_type)->car == QMULTIPLE)
1558 {
1559 CHECK_VECTOR (XCONS (target_type)->cdr, 0);
1560 /* So we don't destructively modify this... */
1561 target_type = copy_multiple_data (target_type);
1562 }
1563 else
1564#endif
1565 CHECK_SYMBOL (target_type, 0);
1566
1567 val = x_get_local_selection (selection_symbol, target_type);
1568
1569 if (NILP (val))
1570 {
1571 val = x_get_foreign_selection (selection_symbol, target_type);
1572 goto DONE;
1573 }
1574
1575 if (CONSP (val)
1576 && SYMBOLP (XCONS (val)->car))
1577 {
1578 val = XCONS (val)->cdr;
1579 if (CONSP (val) && NILP (XCONS (val)->cdr))
1580 val = XCONS (val)->car;
1581 }
1582 val = clean_local_selection_data (val);
1583 DONE:
1584 UNGCPRO;
1585 return val;
1586}
1587
1588DEFUN ("x-disown-selection-internal",
1589 Fx_disown_selection_internal, Sx_disown_selection_internal, 1, 2, 0,
a87ed99c
RS
1590 "If we own the selection SELECTION, disown it.\n\
1591Disowning it means there is no such selection.")
ede4db72
RS
1592 (selection, time)
1593 Lisp_Object selection;
1594 Lisp_Object time;
1595{
1596 Display *display = x_current_display;
1597 Time timestamp;
1598 Atom selection_atom;
1599 XSelectionClearEvent event;
1600
1601 CHECK_SYMBOL (selection, 0);
1602 if (NILP (time))
7da64e5c 1603 timestamp = last_event_timestamp;
ede4db72
RS
1604 else
1605 timestamp = cons_to_long (time);
1606
1607 if (NILP (assq_no_quit (selection, Vselection_alist)))
1608 return Qnil; /* Don't disown the selection when we're not the owner. */
1609
1610 selection_atom = symbol_to_x_atom (display, selection);
1611
1612 BLOCK_INPUT;
1613 XSetSelectionOwner (display, selection_atom, None, timestamp);
1614 UNBLOCK_INPUT;
1615
1616 /* It doesn't seem to be guarenteed that a SelectionClear event will be
1617 generated for a window which owns the selection when that window sets
1618 the selection owner to None. The NCD server does, the MIT Sun4 server
1619 doesn't. So we synthesize one; this means we might get two, but
1620 that's ok, because the second one won't have any effect. */
1621 event.display = display;
1622 event.selection = selection_atom;
1623 event.time = timestamp;
1624 x_handle_selection_clear (&event);
1625
1626 return Qt;
1627}
1628
a87ed99c
RS
1629/* Get rid of all the selections in buffer BUFFER.
1630 This is used when we kill a buffer. */
1631
1632void
1633x_disown_buffer_selections (buffer)
1634 Lisp_Object buffer;
1635{
1636 Lisp_Object tail;
1637 struct buffer *buf = XBUFFER (buffer);
1638
1639 for (tail = Vselection_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1640 {
1641 Lisp_Object elt, value;
1642 elt = XCONS (tail)->car;
1643 value = XCONS (elt)->cdr;
1644 if (CONSP (value) && MARKERP (XCONS (value)->car)
1645 && XMARKER (XCONS (value)->car)->buffer == buf)
1646 Fx_disown_selection_internal (XCONS (elt)->car, Qnil);
1647 }
1648}
ede4db72
RS
1649
1650DEFUN ("x-selection-owner-p", Fx_selection_owner_p, Sx_selection_owner_p,
1651 0, 1, 0,
a87ed99c 1652 "Whether the current Emacs process owns the given X Selection.\n\
ede4db72
RS
1653The arg should be the name of the selection in question, typically one of\n\
1654the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
1655\(Those are literal upper-case symbol names, since that's what X expects.)\n\
1656For convenience, the symbol nil is the same as `PRIMARY',\n\
1657and t is the same as `SECONDARY'.)")
1658 (selection)
1659 Lisp_Object selection;
1660{
1661 CHECK_SYMBOL (selection, 0);
1662 if (EQ (selection, Qnil)) selection = QPRIMARY;
1663 if (EQ (selection, Qt)) selection = QSECONDARY;
1664
1665 if (NILP (Fassq (selection, Vselection_alist)))
1666 return Qnil;
1667 return Qt;
1668}
1669
1670DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
1671 0, 1, 0,
1672 "Whether there is an owner for the given X Selection.\n\
1673The arg should be the name of the selection in question, typically one of\n\
1674the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
1675\(Those are literal upper-case symbol names, since that's what X expects.)\n\
1676For convenience, the symbol nil is the same as `PRIMARY',\n\
1677and t is the same as `SECONDARY'.)")
1678 (selection)
1679 Lisp_Object selection;
1680{
1681 Window owner;
356ba514 1682 Atom atom;
ede4db72
RS
1683 Display *dpy = x_current_display;
1684 CHECK_SYMBOL (selection, 0);
1685 if (!NILP (Fx_selection_owner_p (selection)))
1686 return Qt;
356ba514
RS
1687 if (EQ (selection, Qnil)) selection = QPRIMARY;
1688 if (EQ (selection, Qt)) selection = QSECONDARY;
1689 atom = symbol_to_x_atom (dpy, selection);
1690 if (atom == 0)
1691 return Qnil;
ede4db72 1692 BLOCK_INPUT;
356ba514 1693 owner = XGetSelectionOwner (dpy, atom);
ede4db72
RS
1694 UNBLOCK_INPUT;
1695 return (owner ? Qt : Qnil);
1696}
1697
1698\f
1699#ifdef CUT_BUFFER_SUPPORT
1700
1701static int cut_buffers_initialized; /* Whether we're sure they all exist */
1702
1703/* Ensure that all 8 cut buffers exist. ICCCM says we gotta... */
1704static void
1705initialize_cut_buffers (display, window)
1706 Display *display;
1707 Window window;
1708{
1709 unsigned char *data = (unsigned char *) "";
1710 BLOCK_INPUT;
1711#define FROB(atom) XChangeProperty (display, window, atom, XA_STRING, 8, \
1712 PropModeAppend, data, 0)
1713 FROB (XA_CUT_BUFFER0);
1714 FROB (XA_CUT_BUFFER1);
1715 FROB (XA_CUT_BUFFER2);
1716 FROB (XA_CUT_BUFFER3);
1717 FROB (XA_CUT_BUFFER4);
1718 FROB (XA_CUT_BUFFER5);
1719 FROB (XA_CUT_BUFFER6);
1720 FROB (XA_CUT_BUFFER7);
1721#undef FROB
1722 UNBLOCK_INPUT;
1723 cut_buffers_initialized = 1;
1724}
1725
1726
a87ed99c 1727#define CHECK_CUT_BUFFER(symbol,n) \
ede4db72
RS
1728 { CHECK_SYMBOL ((symbol), (n)); \
1729 if (!EQ((symbol), QCUT_BUFFER0) && !EQ((symbol), QCUT_BUFFER1) \
1730 && !EQ((symbol), QCUT_BUFFER2) && !EQ((symbol), QCUT_BUFFER3) \
1731 && !EQ((symbol), QCUT_BUFFER4) && !EQ((symbol), QCUT_BUFFER5) \
1732 && !EQ((symbol), QCUT_BUFFER6) && !EQ((symbol), QCUT_BUFFER7)) \
1733 Fsignal (Qerror, \
a87ed99c 1734 Fcons (build_string ("doesn't name a cut buffer"), \
ede4db72
RS
1735 Fcons ((symbol), Qnil))); \
1736 }
1737
a87ed99c
RS
1738DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
1739 Sx_get_cut_buffer_internal, 1, 1, 0,
1740 "Returns the value of the named cut buffer (typically CUT_BUFFER0).")
ede4db72
RS
1741 (buffer)
1742 Lisp_Object buffer;
1743{
1744 Display *display = x_current_display;
a87ed99c 1745 Window window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
ede4db72
RS
1746 Atom buffer_atom;
1747 unsigned char *data;
1748 int bytes;
1749 Atom type;
1750 int format;
1751 unsigned long size;
1752 Lisp_Object ret;
1753
a87ed99c 1754 CHECK_CUT_BUFFER (buffer, 0);
ede4db72
RS
1755 buffer_atom = symbol_to_x_atom (display, buffer);
1756
1757 x_get_window_property (display, window, buffer_atom, &data, &bytes,
1758 &type, &format, &size, 0);
1759 if (!data) return Qnil;
1760
1761 if (format != 8 || type != XA_STRING)
1762 Fsignal (Qerror,
1763 Fcons (build_string ("cut buffer doesn't contain 8-bit data"),
1764 Fcons (x_atom_to_symbol (display, type),
1765 Fcons (make_number (format), Qnil))));
1766
1767 ret = (bytes ? make_string ((char *) data, bytes) : Qnil);
1768 xfree (data);
1769 return ret;
1770}
1771
1772
a87ed99c
RS
1773DEFUN ("x-store-cut-buffer-internal", Fx_store_cut_buffer_internal,
1774 Sx_store_cut_buffer_internal, 2, 2, 0,
1775 "Sets the value of the named cut buffer (typically CUT_BUFFER0).")
ede4db72
RS
1776 (buffer, string)
1777 Lisp_Object buffer, string;
1778{
1779 Display *display = x_current_display;
a87ed99c 1780 Window window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
ede4db72
RS
1781 Atom buffer_atom;
1782 unsigned char *data;
1783 int bytes;
1784 int bytes_remaining;
1785 int max_bytes = SELECTION_QUANTUM (display);
1786 if (max_bytes > MAX_SELECTION_QUANTUM) max_bytes = MAX_SELECTION_QUANTUM;
1787
a87ed99c 1788 CHECK_CUT_BUFFER (buffer, 0);
ede4db72
RS
1789 CHECK_STRING (string, 0);
1790 buffer_atom = symbol_to_x_atom (display, buffer);
1791 data = (unsigned char *) XSTRING (string)->data;
1792 bytes = XSTRING (string)->size;
1793 bytes_remaining = bytes;
1794
1795 if (! cut_buffers_initialized) initialize_cut_buffers (display, window);
1796
1797 BLOCK_INPUT;
1798 while (bytes_remaining)
1799 {
1800 int chunk = (bytes_remaining < max_bytes
1801 ? bytes_remaining : max_bytes);
1802 XChangeProperty (display, window, buffer_atom, XA_STRING, 8,
1803 (bytes_remaining == bytes
1804 ? PropModeReplace
1805 : PropModeAppend),
1806 data, chunk);
1807 data += chunk;
1808 bytes_remaining -= chunk;
1809 }
1810 UNBLOCK_INPUT;
1811 return string;
1812}
1813
1814
a87ed99c
RS
1815DEFUN ("x-rotate-cut-buffers-internal", Fx_rotate_cut_buffers_internal,
1816 Sx_rotate_cut_buffers_internal, 1, 1, 0,
1817 "Rotate the values of the cut buffers by the given number of steps;\n\
ede4db72
RS
1818positive means move values forward, negative means backward.")
1819 (n)
1820 Lisp_Object n;
1821{
1822 Display *display = x_current_display;
a87ed99c 1823 Window window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
ede4db72
RS
1824 Atom props [8];
1825
7da64e5c 1826 CHECK_NUMBER (n, 0);
ede4db72
RS
1827 if (XINT (n) == 0) return n;
1828 if (! cut_buffers_initialized) initialize_cut_buffers (display, window);
1829 props[0] = XA_CUT_BUFFER0;
1830 props[1] = XA_CUT_BUFFER1;
1831 props[2] = XA_CUT_BUFFER2;
1832 props[3] = XA_CUT_BUFFER3;
1833 props[4] = XA_CUT_BUFFER4;
1834 props[5] = XA_CUT_BUFFER5;
1835 props[6] = XA_CUT_BUFFER6;
1836 props[7] = XA_CUT_BUFFER7;
1837 BLOCK_INPUT;
1838 XRotateWindowProperties (display, window, props, 8, XINT (n));
1839 UNBLOCK_INPUT;
1840 return n;
1841}
1842
1843#endif
1844\f
7da64e5c
RS
1845void
1846Xatoms_of_xselect ()
ede4db72
RS
1847{
1848#define ATOM(x) XInternAtom (x_current_display, (x), False)
1849
1850 BLOCK_INPUT;
1851 /* Non-predefined atoms that we might end up using a lot */
1852 Xatom_CLIPBOARD = ATOM ("CLIPBOARD");
1853 Xatom_TIMESTAMP = ATOM ("TIMESTAMP");
1854 Xatom_TEXT = ATOM ("TEXT");
1855 Xatom_DELETE = ATOM ("DELETE");
1856 Xatom_MULTIPLE = ATOM ("MULTIPLE");
1857 Xatom_INCR = ATOM ("INCR");
1858 Xatom_EMACS_TMP = ATOM ("_EMACS_TMP_");
1859 Xatom_TARGETS = ATOM ("TARGETS");
1860 Xatom_NULL = ATOM ("NULL");
1861 Xatom_ATOM_PAIR = ATOM ("ATOM_PAIR");
1862 UNBLOCK_INPUT;
1863}
1864
1865void
1866syms_of_xselect ()
1867{
ede4db72
RS
1868 defsubr (&Sx_get_selection_internal);
1869 defsubr (&Sx_own_selection_internal);
1870 defsubr (&Sx_disown_selection_internal);
1871 defsubr (&Sx_selection_owner_p);
1872 defsubr (&Sx_selection_exists_p);
1873
1874#ifdef CUT_BUFFER_SUPPORT
a87ed99c
RS
1875 defsubr (&Sx_get_cut_buffer_internal);
1876 defsubr (&Sx_store_cut_buffer_internal);
1877 defsubr (&Sx_rotate_cut_buffers_internal);
ede4db72
RS
1878 cut_buffers_initialized = 0;
1879#endif
1880
1881 reading_selection_reply = Fcons (Qnil, Qnil);
1882 staticpro (&reading_selection_reply);
1883 reading_selection_window = 0;
1884 reading_which_selection = 0;
1885
1886 property_change_wait_list = 0;
1887 prop_location_tick = 0;
1888 property_change_reply = Fcons (Qnil, Qnil);
1889 staticpro (&property_change_reply);
1890
1891 Vselection_alist = Qnil;
1892 staticpro (&Vselection_alist);
1893
1894 DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist,
1895 "An alist associating X Windows selection-types with functions.\n\
1896These functions are called to convert the selection, with three args:\n\
1897the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
1898a desired type to which the selection should be converted;\n\
1899and the local selection value (whatever was given to `x-own-selection').\n\
1900\n\
1901The function should return the value to send to the X server\n\
1902\(typically a string). A return value of nil\n\
1903means that the conversion could not be done.\n\
1904A return value which is the symbol `NULL'\n\
1905means that a side-effect was executed,\n\
1906and there is no meaningful selection value.");
1907 Vselection_converter_alist = Qnil;
1908
1909 DEFVAR_LISP ("x-lost-selection-hooks", &Vx_lost_selection_hooks,
1910 "A list of functions to be called when Emacs loses an X selection.\n\
1911\(This happens when some other X client makes its own selection\n\
1912or when a Lisp program explicitly clears the selection.)\n\
1913The functions are called with one argument, the selection type\n\
1914\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.)");
1915 Vx_lost_selection_hooks = Qnil;
1916
1917 DEFVAR_LISP ("x-sent-selection-hooks", &Vx_sent_selection_hooks,
1918 "A list of functions to be called when Emacs answers a selection request.\n\
1919The functions are called with four arguments:\n\
1920 - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
1921 - the selection-type which Emacs was asked to convert the\n\
1922 selection into before sending (for example, `STRING' or `LENGTH');\n\
1923 - a flag indicating success or failure for responding to the request.\n\
1924We might have failed (and declined the request) for any number of reasons,\n\
1925including being asked for a selection that we no longer own, or being asked\n\
1926to convert into a type that we don't know about or that is inappropriate.\n\
1927This hook doesn't let you change the behavior of Emacs's selection replies,\n\
1928it merely informs you that they have happened.");
1929 Vx_sent_selection_hooks = Qnil;
1930
1931 DEFVAR_INT ("x-selection-timeout", &x_selection_timeout,
1932 "Number of seconds to wait for a selection reply from another X client.\n\
1933If the selection owner doens't reply in this many seconds, we give up.\n\
1934A value of 0 means wait as long as necessary. This is initialized from the\n\
1935\"*selectionTimeout\" resource (which is expressed in milliseconds).");
1936 x_selection_timeout = 0;
1937
1938 QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY);
1939 QSECONDARY = intern ("SECONDARY"); staticpro (&QSECONDARY);
1940 QSTRING = intern ("STRING"); staticpro (&QSTRING);
1941 QINTEGER = intern ("INTEGER"); staticpro (&QINTEGER);
1942 QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
1943 QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP);
1944 QTEXT = intern ("TEXT"); staticpro (&QTEXT);
1945 QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP);
1946 QDELETE = intern ("DELETE"); staticpro (&QDELETE);
1947 QMULTIPLE = intern ("MULTIPLE"); staticpro (&QMULTIPLE);
1948 QINCR = intern ("INCR"); staticpro (&QINCR);
1949 QEMACS_TMP = intern ("_EMACS_TMP_"); staticpro (&QEMACS_TMP);
1950 QTARGETS = intern ("TARGETS"); staticpro (&QTARGETS);
1951 QATOM = intern ("ATOM"); staticpro (&QATOM);
1952 QATOM_PAIR = intern ("ATOM_PAIR"); staticpro (&QATOM_PAIR);
1953 QNULL = intern ("NULL"); staticpro (&QNULL);
1954
1955#ifdef CUT_BUFFER_SUPPORT
1956 QCUT_BUFFER0 = intern ("CUT_BUFFER0"); staticpro (&QCUT_BUFFER0);
1957 QCUT_BUFFER1 = intern ("CUT_BUFFER1"); staticpro (&QCUT_BUFFER1);
1958 QCUT_BUFFER2 = intern ("CUT_BUFFER2"); staticpro (&QCUT_BUFFER2);
1959 QCUT_BUFFER3 = intern ("CUT_BUFFER3"); staticpro (&QCUT_BUFFER3);
1960 QCUT_BUFFER4 = intern ("CUT_BUFFER4"); staticpro (&QCUT_BUFFER4);
1961 QCUT_BUFFER5 = intern ("CUT_BUFFER5"); staticpro (&QCUT_BUFFER5);
1962 QCUT_BUFFER6 = intern ("CUT_BUFFER6"); staticpro (&QCUT_BUFFER6);
1963 QCUT_BUFFER7 = intern ("CUT_BUFFER7"); staticpro (&QCUT_BUFFER7);
1964#endif
1965
1966}