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