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