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