comparison src/xselect.c @ 0:376386a54a3c r19-14

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