comparison src/xselect.c @ 412:697ef44129c6 r21-2-14

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