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