(x_set_frame_parameters, x_get_arg, x_window, Fx_create_frame,
[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{
703e0710 1580 check_x ();
ede4db72
RS
1581 CHECK_SYMBOL (selection_name, 0);
1582 if (NILP (selection_value)) error ("selection-value may not be nil.");
1583 x_own_selection (selection_name, selection_value);
1584 return selection_value;
1585}
1586
1587
1588/* Request the selection value from the owner. If we are the owner,
1589 simply return our selection value. If we are not the owner, this
1590 will block until all of the data has arrived. */
1591
1592DEFUN ("x-get-selection-internal",
1593 Fx_get_selection_internal, Sx_get_selection_internal, 2, 2, 0,
1594 "Return text selected from some X window.\n\
1595SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
1596\(Those are literal upper-case symbol names, since that's what X expects.)\n\
a87ed99c 1597TYPE is the type of data desired, typically `STRING'.")
ede4db72
RS
1598 (selection_symbol, target_type)
1599 Lisp_Object selection_symbol, target_type;
1600{
1601 Lisp_Object val = Qnil;
1602 struct gcpro gcpro1, gcpro2;
1603 GCPRO2 (target_type, val); /* we store newly consed data into these */
703e0710 1604 check_x ();
ede4db72
RS
1605 CHECK_SYMBOL (selection_symbol, 0);
1606
1607#if 0 /* #### MULTIPLE doesn't work yet */
1608 if (CONSP (target_type)
1609 && XCONS (target_type)->car == QMULTIPLE)
1610 {
1611 CHECK_VECTOR (XCONS (target_type)->cdr, 0);
1612 /* So we don't destructively modify this... */
1613 target_type = copy_multiple_data (target_type);
1614 }
1615 else
1616#endif
1617 CHECK_SYMBOL (target_type, 0);
1618
1619 val = x_get_local_selection (selection_symbol, target_type);
1620
1621 if (NILP (val))
1622 {
1623 val = x_get_foreign_selection (selection_symbol, target_type);
1624 goto DONE;
1625 }
1626
1627 if (CONSP (val)
1628 && SYMBOLP (XCONS (val)->car))
1629 {
1630 val = XCONS (val)->cdr;
1631 if (CONSP (val) && NILP (XCONS (val)->cdr))
1632 val = XCONS (val)->car;
1633 }
1634 val = clean_local_selection_data (val);
1635 DONE:
1636 UNGCPRO;
1637 return val;
1638}
1639
1640DEFUN ("x-disown-selection-internal",
1641 Fx_disown_selection_internal, Sx_disown_selection_internal, 1, 2, 0,
a87ed99c
RS
1642 "If we own the selection SELECTION, disown it.\n\
1643Disowning it means there is no such selection.")
ede4db72
RS
1644 (selection, time)
1645 Lisp_Object selection;
1646 Lisp_Object time;
1647{
1648 Display *display = x_current_display;
1649 Time timestamp;
1650 Atom selection_atom;
1651 XSelectionClearEvent event;
1652
703e0710 1653 check_x ();
ede4db72
RS
1654 CHECK_SYMBOL (selection, 0);
1655 if (NILP (time))
7da64e5c 1656 timestamp = last_event_timestamp;
ede4db72
RS
1657 else
1658 timestamp = cons_to_long (time);
1659
1660 if (NILP (assq_no_quit (selection, Vselection_alist)))
1661 return Qnil; /* Don't disown the selection when we're not the owner. */
1662
1663 selection_atom = symbol_to_x_atom (display, selection);
1664
1665 BLOCK_INPUT;
1666 XSetSelectionOwner (display, selection_atom, None, timestamp);
1667 UNBLOCK_INPUT;
1668
eb8c3be9 1669 /* It doesn't seem to be guaranteed that a SelectionClear event will be
ede4db72
RS
1670 generated for a window which owns the selection when that window sets
1671 the selection owner to None. The NCD server does, the MIT Sun4 server
1672 doesn't. So we synthesize one; this means we might get two, but
1673 that's ok, because the second one won't have any effect. */
8d47f8c4
RS
1674 SELECTION_EVENT_DISPLAY (&event) = display;
1675 SELECTION_EVENT_SELECTION (&event) = selection_atom;
1676 SELECTION_EVENT_TIME (&event) = timestamp;
ede4db72
RS
1677 x_handle_selection_clear (&event);
1678
1679 return Qt;
1680}
1681
a87ed99c
RS
1682/* Get rid of all the selections in buffer BUFFER.
1683 This is used when we kill a buffer. */
1684
1685void
1686x_disown_buffer_selections (buffer)
1687 Lisp_Object buffer;
1688{
1689 Lisp_Object tail;
1690 struct buffer *buf = XBUFFER (buffer);
1691
1692 for (tail = Vselection_alist; CONSP (tail); tail = XCONS (tail)->cdr)
1693 {
1694 Lisp_Object elt, value;
1695 elt = XCONS (tail)->car;
1696 value = XCONS (elt)->cdr;
1697 if (CONSP (value) && MARKERP (XCONS (value)->car)
1698 && XMARKER (XCONS (value)->car)->buffer == buf)
1699 Fx_disown_selection_internal (XCONS (elt)->car, Qnil);
1700 }
1701}
ede4db72
RS
1702
1703DEFUN ("x-selection-owner-p", Fx_selection_owner_p, Sx_selection_owner_p,
1704 0, 1, 0,
a87ed99c 1705 "Whether the current Emacs process owns the given X Selection.\n\
ede4db72
RS
1706The arg should be the name of the selection in question, typically one of\n\
1707the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
1708\(Those are literal upper-case symbol names, since that's what X expects.)\n\
1709For convenience, the symbol nil is the same as `PRIMARY',\n\
1710and t is the same as `SECONDARY'.)")
1711 (selection)
1712 Lisp_Object selection;
1713{
703e0710 1714 check_x ();
ede4db72
RS
1715 CHECK_SYMBOL (selection, 0);
1716 if (EQ (selection, Qnil)) selection = QPRIMARY;
1717 if (EQ (selection, Qt)) selection = QSECONDARY;
1718
1719 if (NILP (Fassq (selection, Vselection_alist)))
1720 return Qnil;
1721 return Qt;
1722}
1723
1724DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
1725 0, 1, 0,
1726 "Whether there is an owner for the given X Selection.\n\
1727The arg should be the name of the selection in question, typically one of\n\
1728the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
1729\(Those are literal upper-case symbol names, since that's what X expects.)\n\
1730For convenience, the symbol nil is the same as `PRIMARY',\n\
1731and t is the same as `SECONDARY'.)")
1732 (selection)
1733 Lisp_Object selection;
1734{
1735 Window owner;
356ba514 1736 Atom atom;
ede4db72 1737 Display *dpy = x_current_display;
703e0710 1738 check_x ();
ede4db72
RS
1739 CHECK_SYMBOL (selection, 0);
1740 if (!NILP (Fx_selection_owner_p (selection)))
1741 return Qt;
356ba514
RS
1742 if (EQ (selection, Qnil)) selection = QPRIMARY;
1743 if (EQ (selection, Qt)) selection = QSECONDARY;
1744 atom = symbol_to_x_atom (dpy, selection);
1745 if (atom == 0)
1746 return Qnil;
ede4db72 1747 BLOCK_INPUT;
356ba514 1748 owner = XGetSelectionOwner (dpy, atom);
ede4db72
RS
1749 UNBLOCK_INPUT;
1750 return (owner ? Qt : Qnil);
1751}
1752
1753\f
1754#ifdef CUT_BUFFER_SUPPORT
1755
1756static int cut_buffers_initialized; /* Whether we're sure they all exist */
1757
1758/* Ensure that all 8 cut buffers exist. ICCCM says we gotta... */
1759static void
1760initialize_cut_buffers (display, window)
1761 Display *display;
1762 Window window;
1763{
1764 unsigned char *data = (unsigned char *) "";
1765 BLOCK_INPUT;
1766#define FROB(atom) XChangeProperty (display, window, atom, XA_STRING, 8, \
1767 PropModeAppend, data, 0)
1768 FROB (XA_CUT_BUFFER0);
1769 FROB (XA_CUT_BUFFER1);
1770 FROB (XA_CUT_BUFFER2);
1771 FROB (XA_CUT_BUFFER3);
1772 FROB (XA_CUT_BUFFER4);
1773 FROB (XA_CUT_BUFFER5);
1774 FROB (XA_CUT_BUFFER6);
1775 FROB (XA_CUT_BUFFER7);
1776#undef FROB
1777 UNBLOCK_INPUT;
1778 cut_buffers_initialized = 1;
1779}
1780
1781
a87ed99c 1782#define CHECK_CUT_BUFFER(symbol,n) \
ede4db72
RS
1783 { CHECK_SYMBOL ((symbol), (n)); \
1784 if (!EQ((symbol), QCUT_BUFFER0) && !EQ((symbol), QCUT_BUFFER1) \
1785 && !EQ((symbol), QCUT_BUFFER2) && !EQ((symbol), QCUT_BUFFER3) \
1786 && !EQ((symbol), QCUT_BUFFER4) && !EQ((symbol), QCUT_BUFFER5) \
1787 && !EQ((symbol), QCUT_BUFFER6) && !EQ((symbol), QCUT_BUFFER7)) \
1788 Fsignal (Qerror, \
a87ed99c 1789 Fcons (build_string ("doesn't name a cut buffer"), \
ede4db72
RS
1790 Fcons ((symbol), Qnil))); \
1791 }
1792
a87ed99c
RS
1793DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
1794 Sx_get_cut_buffer_internal, 1, 1, 0,
1795 "Returns the value of the named cut buffer (typically CUT_BUFFER0).")
ede4db72
RS
1796 (buffer)
1797 Lisp_Object buffer;
1798{
1799 Display *display = x_current_display;
a87ed99c 1800 Window window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
ede4db72
RS
1801 Atom buffer_atom;
1802 unsigned char *data;
1803 int bytes;
1804 Atom type;
1805 int format;
1806 unsigned long size;
1807 Lisp_Object ret;
1808
703e0710 1809 check_x ();
a87ed99c 1810 CHECK_CUT_BUFFER (buffer, 0);
ede4db72
RS
1811 buffer_atom = symbol_to_x_atom (display, buffer);
1812
1813 x_get_window_property (display, window, buffer_atom, &data, &bytes,
1814 &type, &format, &size, 0);
1815 if (!data) return Qnil;
1816
1817 if (format != 8 || type != XA_STRING)
1818 Fsignal (Qerror,
1819 Fcons (build_string ("cut buffer doesn't contain 8-bit data"),
1820 Fcons (x_atom_to_symbol (display, type),
1821 Fcons (make_number (format), Qnil))));
1822
1823 ret = (bytes ? make_string ((char *) data, bytes) : Qnil);
1824 xfree (data);
1825 return ret;
1826}
1827
1828
a87ed99c
RS
1829DEFUN ("x-store-cut-buffer-internal", Fx_store_cut_buffer_internal,
1830 Sx_store_cut_buffer_internal, 2, 2, 0,
1831 "Sets the value of the named cut buffer (typically CUT_BUFFER0).")
ede4db72
RS
1832 (buffer, string)
1833 Lisp_Object buffer, string;
1834{
1835 Display *display = x_current_display;
a87ed99c 1836 Window window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
ede4db72
RS
1837 Atom buffer_atom;
1838 unsigned char *data;
1839 int bytes;
1840 int bytes_remaining;
1841 int max_bytes = SELECTION_QUANTUM (display);
1842 if (max_bytes > MAX_SELECTION_QUANTUM) max_bytes = MAX_SELECTION_QUANTUM;
1843
703e0710 1844 check_x ();
a87ed99c 1845 CHECK_CUT_BUFFER (buffer, 0);
ede4db72
RS
1846 CHECK_STRING (string, 0);
1847 buffer_atom = symbol_to_x_atom (display, buffer);
1848 data = (unsigned char *) XSTRING (string)->data;
1849 bytes = XSTRING (string)->size;
1850 bytes_remaining = bytes;
1851
1852 if (! cut_buffers_initialized) initialize_cut_buffers (display, window);
1853
1854 BLOCK_INPUT;
10608c8c
RS
1855
1856 /* Don't mess up with an empty value. */
1857 if (!bytes_remaining)
1858 XChangeProperty (display, window, buffer_atom, XA_STRING, 8,
1859 PropModeReplace, data, 0);
1860
ede4db72
RS
1861 while (bytes_remaining)
1862 {
1863 int chunk = (bytes_remaining < max_bytes
1864 ? bytes_remaining : max_bytes);
1865 XChangeProperty (display, window, buffer_atom, XA_STRING, 8,
1866 (bytes_remaining == bytes
1867 ? PropModeReplace
1868 : PropModeAppend),
1869 data, chunk);
1870 data += chunk;
1871 bytes_remaining -= chunk;
1872 }
1873 UNBLOCK_INPUT;
1874 return string;
1875}
1876
1877
a87ed99c
RS
1878DEFUN ("x-rotate-cut-buffers-internal", Fx_rotate_cut_buffers_internal,
1879 Sx_rotate_cut_buffers_internal, 1, 1, 0,
1880 "Rotate the values of the cut buffers by the given number of steps;\n\
ede4db72
RS
1881positive means move values forward, negative means backward.")
1882 (n)
1883 Lisp_Object n;
1884{
1885 Display *display = x_current_display;
a87ed99c 1886 Window window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
ede4db72
RS
1887 Atom props [8];
1888
703e0710 1889 check_x ();
7da64e5c 1890 CHECK_NUMBER (n, 0);
ede4db72
RS
1891 if (XINT (n) == 0) return n;
1892 if (! cut_buffers_initialized) initialize_cut_buffers (display, window);
1893 props[0] = XA_CUT_BUFFER0;
1894 props[1] = XA_CUT_BUFFER1;
1895 props[2] = XA_CUT_BUFFER2;
1896 props[3] = XA_CUT_BUFFER3;
1897 props[4] = XA_CUT_BUFFER4;
1898 props[5] = XA_CUT_BUFFER5;
1899 props[6] = XA_CUT_BUFFER6;
1900 props[7] = XA_CUT_BUFFER7;
1901 BLOCK_INPUT;
1902 XRotateWindowProperties (display, window, props, 8, XINT (n));
1903 UNBLOCK_INPUT;
1904 return n;
1905}
1906
1907#endif
1908\f
7da64e5c
RS
1909void
1910Xatoms_of_xselect ()
ede4db72
RS
1911{
1912#define ATOM(x) XInternAtom (x_current_display, (x), False)
1913
1914 BLOCK_INPUT;
1915 /* Non-predefined atoms that we might end up using a lot */
1916 Xatom_CLIPBOARD = ATOM ("CLIPBOARD");
1917 Xatom_TIMESTAMP = ATOM ("TIMESTAMP");
1918 Xatom_TEXT = ATOM ("TEXT");
1919 Xatom_DELETE = ATOM ("DELETE");
1920 Xatom_MULTIPLE = ATOM ("MULTIPLE");
1921 Xatom_INCR = ATOM ("INCR");
1922 Xatom_EMACS_TMP = ATOM ("_EMACS_TMP_");
1923 Xatom_TARGETS = ATOM ("TARGETS");
1924 Xatom_NULL = ATOM ("NULL");
1925 Xatom_ATOM_PAIR = ATOM ("ATOM_PAIR");
1926 UNBLOCK_INPUT;
1927}
1928
1929void
1930syms_of_xselect ()
1931{
ede4db72
RS
1932 defsubr (&Sx_get_selection_internal);
1933 defsubr (&Sx_own_selection_internal);
1934 defsubr (&Sx_disown_selection_internal);
1935 defsubr (&Sx_selection_owner_p);
1936 defsubr (&Sx_selection_exists_p);
1937
1938#ifdef CUT_BUFFER_SUPPORT
a87ed99c
RS
1939 defsubr (&Sx_get_cut_buffer_internal);
1940 defsubr (&Sx_store_cut_buffer_internal);
1941 defsubr (&Sx_rotate_cut_buffers_internal);
ede4db72
RS
1942 cut_buffers_initialized = 0;
1943#endif
1944
1945 reading_selection_reply = Fcons (Qnil, Qnil);
1946 staticpro (&reading_selection_reply);
1947 reading_selection_window = 0;
1948 reading_which_selection = 0;
1949
1950 property_change_wait_list = 0;
2f65feb6 1951 prop_location_identifier = 0;
ede4db72
RS
1952 property_change_reply = Fcons (Qnil, Qnil);
1953 staticpro (&property_change_reply);
1954
1955 Vselection_alist = Qnil;
1956 staticpro (&Vselection_alist);
1957
1958 DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist,
1959 "An alist associating X Windows selection-types with functions.\n\
1960These functions are called to convert the selection, with three args:\n\
1961the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
1962a desired type to which the selection should be converted;\n\
1963and the local selection value (whatever was given to `x-own-selection').\n\
1964\n\
1965The function should return the value to send to the X server\n\
1966\(typically a string). A return value of nil\n\
1967means that the conversion could not be done.\n\
1968A return value which is the symbol `NULL'\n\
1969means that a side-effect was executed,\n\
1970and there is no meaningful selection value.");
1971 Vselection_converter_alist = Qnil;
1972
1973 DEFVAR_LISP ("x-lost-selection-hooks", &Vx_lost_selection_hooks,
1974 "A list of functions to be called when Emacs loses an X selection.\n\
1975\(This happens when some other X client makes its own selection\n\
1976or when a Lisp program explicitly clears the selection.)\n\
1977The functions are called with one argument, the selection type\n\
1978\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.)");
1979 Vx_lost_selection_hooks = Qnil;
1980
1981 DEFVAR_LISP ("x-sent-selection-hooks", &Vx_sent_selection_hooks,
1982 "A list of functions to be called when Emacs answers a selection request.\n\
1983The functions are called with four arguments:\n\
1984 - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
1985 - the selection-type which Emacs was asked to convert the\n\
1986 selection into before sending (for example, `STRING' or `LENGTH');\n\
1987 - a flag indicating success or failure for responding to the request.\n\
1988We might have failed (and declined the request) for any number of reasons,\n\
1989including being asked for a selection that we no longer own, or being asked\n\
1990to convert into a type that we don't know about or that is inappropriate.\n\
1991This hook doesn't let you change the behavior of Emacs's selection replies,\n\
1992it merely informs you that they have happened.");
1993 Vx_sent_selection_hooks = Qnil;
1994
1995 DEFVAR_INT ("x-selection-timeout", &x_selection_timeout,
80da0190
RS
1996 "Number of milliseconds to wait for a selection reply.\n\
1997If the selection owner doens't reply in this time, we give up.\n\
ede4db72 1998A value of 0 means wait as long as necessary. This is initialized from the\n\
80da0190 1999\"*selectionTimeout\" resource.");
ede4db72
RS
2000 x_selection_timeout = 0;
2001
2002 QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY);
2003 QSECONDARY = intern ("SECONDARY"); staticpro (&QSECONDARY);
2004 QSTRING = intern ("STRING"); staticpro (&QSTRING);
2005 QINTEGER = intern ("INTEGER"); staticpro (&QINTEGER);
2006 QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
2007 QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP);
2008 QTEXT = intern ("TEXT"); staticpro (&QTEXT);
2009 QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP);
2010 QDELETE = intern ("DELETE"); staticpro (&QDELETE);
2011 QMULTIPLE = intern ("MULTIPLE"); staticpro (&QMULTIPLE);
2012 QINCR = intern ("INCR"); staticpro (&QINCR);
2013 QEMACS_TMP = intern ("_EMACS_TMP_"); staticpro (&QEMACS_TMP);
2014 QTARGETS = intern ("TARGETS"); staticpro (&QTARGETS);
2015 QATOM = intern ("ATOM"); staticpro (&QATOM);
2016 QATOM_PAIR = intern ("ATOM_PAIR"); staticpro (&QATOM_PAIR);
2017 QNULL = intern ("NULL"); staticpro (&QNULL);
2018
2019#ifdef CUT_BUFFER_SUPPORT
2020 QCUT_BUFFER0 = intern ("CUT_BUFFER0"); staticpro (&QCUT_BUFFER0);
2021 QCUT_BUFFER1 = intern ("CUT_BUFFER1"); staticpro (&QCUT_BUFFER1);
2022 QCUT_BUFFER2 = intern ("CUT_BUFFER2"); staticpro (&QCUT_BUFFER2);
2023 QCUT_BUFFER3 = intern ("CUT_BUFFER3"); staticpro (&QCUT_BUFFER3);
2024 QCUT_BUFFER4 = intern ("CUT_BUFFER4"); staticpro (&QCUT_BUFFER4);
2025 QCUT_BUFFER5 = intern ("CUT_BUFFER5"); staticpro (&QCUT_BUFFER5);
2026 QCUT_BUFFER6 = intern ("CUT_BUFFER6"); staticpro (&QCUT_BUFFER6);
2027 QCUT_BUFFER7 = intern ("CUT_BUFFER7"); staticpro (&QCUT_BUFFER7);
2028#endif
2029
2030}