1 /* X Selection processing for XEmacs
2 Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of XEmacs.
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
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
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. */
21 /* Synched up with: Not synched with FSF. */
23 /* Rewritten by jwz */
29 #include "console-x.h"
30 #include "objects-x.h"
37 int lisp_to_time (Lisp_Object, time_t *);
38 Lisp_Object time_to_lisp (time_t);
40 #ifdef LWLIB_USES_MOTIF
41 # define MOTIF_CLIPBOARDS
44 #ifdef MOTIF_CLIPBOARDS
45 # include <Xm/CutPaste.h>
46 static void hack_motif_clipboard_selection (Atom selection_atom,
47 Lisp_Object selection_value,
48 Time thyme, Display *display,
49 Window selecting_window,
53 #define CUT_BUFFER_SUPPORT
55 #ifdef CUT_BUFFER_SUPPORT
56 Lisp_Object QCUT_BUFFER0, QCUT_BUFFER1, QCUT_BUFFER2, QCUT_BUFFER3,
57 QCUT_BUFFER4, QCUT_BUFFER5, QCUT_BUFFER6, QCUT_BUFFER7;
60 Lisp_Object Vx_sent_selection_hooks;
62 /* If this is a smaller number than the max-request-size of the display,
63 emacs will use INCR selection transfer when the selection is larger
64 than this. The max-request-size is usually around 64k, so if you want
65 emacs to use incremental selection transfers when the selection is
66 smaller than that, set this. I added this mostly for debugging the
67 incremental transfer stuff, but it might improve server performance.
69 #define MAX_SELECTION_QUANTUM 0xFFFFFF
71 #define SELECTION_QUANTUM(dpy) ((XMaxRequestSize (dpy) << 2) - 100)
73 /* If the selection owner takes too long to reply to a selection request,
74 we give up on it. This is in seconds (0 = no timeout).
76 Fixnum x_selection_timeout;
78 /* Enable motif selection optimizations. */
79 int x_selection_strict_motif_ownership;
82 /* Utility functions */
84 static void lisp_data_to_selection_data (struct device *,
86 unsigned char **data_ret,
88 unsigned int *size_ret,
90 static Lisp_Object selection_data_to_lisp_data (struct device *,
95 static Lisp_Object x_get_window_property_as_lisp_data (Display *,
98 Lisp_Object target_type,
101 static int expect_property_change (Display *, Window, Atom prop, int state);
102 static void wait_for_property_change (long);
103 static void unexpect_property_change (int);
104 static int waiting_for_other_props_on_window (Display *, Window);
106 /* This converts a Lisp symbol to a server Atom, avoiding a server
107 roundtrip whenever possible.
110 symbol_to_x_atom (struct device *d, Lisp_Object sym, int only_if_exists)
112 Display *display = DEVICE_X_DISPLAY (d);
114 if (NILP (sym)) return XA_PRIMARY;
115 if (EQ (sym, Qt)) return XA_SECONDARY;
116 if (EQ (sym, QPRIMARY)) return XA_PRIMARY;
117 if (EQ (sym, QSECONDARY)) return XA_SECONDARY;
118 if (EQ (sym, QSTRING)) return XA_STRING;
119 if (EQ (sym, QINTEGER)) return XA_INTEGER;
120 if (EQ (sym, QATOM)) return XA_ATOM;
121 if (EQ (sym, QCLIPBOARD)) return DEVICE_XATOM_CLIPBOARD (d);
122 if (EQ (sym, QTIMESTAMP)) return DEVICE_XATOM_TIMESTAMP (d);
123 if (EQ (sym, QTEXT)) return DEVICE_XATOM_TEXT (d);
124 if (EQ (sym, QDELETE)) return DEVICE_XATOM_DELETE (d);
125 if (EQ (sym, QMULTIPLE)) return DEVICE_XATOM_MULTIPLE (d);
126 if (EQ (sym, QINCR)) return DEVICE_XATOM_INCR (d);
127 if (EQ (sym, QEMACS_TMP)) return DEVICE_XATOM_EMACS_TMP (d);
128 if (EQ (sym, QTARGETS)) return DEVICE_XATOM_TARGETS (d);
129 if (EQ (sym, QNULL)) return DEVICE_XATOM_NULL (d);
130 if (EQ (sym, QATOM_PAIR)) return DEVICE_XATOM_ATOM_PAIR (d);
131 if (EQ (sym, QCOMPOUND_TEXT)) return DEVICE_XATOM_COMPOUND_TEXT (d);
133 #ifdef CUT_BUFFER_SUPPORT
134 if (EQ (sym, QCUT_BUFFER0)) return XA_CUT_BUFFER0;
135 if (EQ (sym, QCUT_BUFFER1)) return XA_CUT_BUFFER1;
136 if (EQ (sym, QCUT_BUFFER2)) return XA_CUT_BUFFER2;
137 if (EQ (sym, QCUT_BUFFER3)) return XA_CUT_BUFFER3;
138 if (EQ (sym, QCUT_BUFFER4)) return XA_CUT_BUFFER4;
139 if (EQ (sym, QCUT_BUFFER5)) return XA_CUT_BUFFER5;
140 if (EQ (sym, QCUT_BUFFER6)) return XA_CUT_BUFFER6;
141 if (EQ (sym, QCUT_BUFFER7)) return XA_CUT_BUFFER7;
142 #endif /* CUT_BUFFER_SUPPORT */
146 LISP_STRING_TO_EXTERNAL (Fsymbol_name (sym), nameext, Qctext);
147 return XInternAtom (display, nameext, only_if_exists ? True : False);
152 /* This converts a server Atom to a Lisp symbol, avoiding server roundtrips
153 and calls to intern whenever possible.
156 x_atom_to_symbol (struct device *d, Atom atom)
158 Display *display = DEVICE_X_DISPLAY (d);
160 if (! atom) return Qnil;
161 if (atom == XA_PRIMARY) return QPRIMARY;
162 if (atom == XA_SECONDARY) return QSECONDARY;
163 if (atom == XA_STRING) return QSTRING;
164 if (atom == XA_INTEGER) return QINTEGER;
165 if (atom == XA_ATOM) return QATOM;
166 if (atom == DEVICE_XATOM_CLIPBOARD (d)) return QCLIPBOARD;
167 if (atom == DEVICE_XATOM_TIMESTAMP (d)) return QTIMESTAMP;
168 if (atom == DEVICE_XATOM_TEXT (d)) return QTEXT;
169 if (atom == DEVICE_XATOM_DELETE (d)) return QDELETE;
170 if (atom == DEVICE_XATOM_MULTIPLE (d)) return QMULTIPLE;
171 if (atom == DEVICE_XATOM_INCR (d)) return QINCR;
172 if (atom == DEVICE_XATOM_EMACS_TMP (d)) return QEMACS_TMP;
173 if (atom == DEVICE_XATOM_TARGETS (d)) return QTARGETS;
174 if (atom == DEVICE_XATOM_NULL (d)) return QNULL;
175 if (atom == DEVICE_XATOM_ATOM_PAIR (d)) return QATOM_PAIR;
176 if (atom == DEVICE_XATOM_COMPOUND_TEXT (d)) return QCOMPOUND_TEXT;
178 #ifdef CUT_BUFFER_SUPPORT
179 if (atom == XA_CUT_BUFFER0) return QCUT_BUFFER0;
180 if (atom == XA_CUT_BUFFER1) return QCUT_BUFFER1;
181 if (atom == XA_CUT_BUFFER2) return QCUT_BUFFER2;
182 if (atom == XA_CUT_BUFFER3) return QCUT_BUFFER3;
183 if (atom == XA_CUT_BUFFER4) return QCUT_BUFFER4;
184 if (atom == XA_CUT_BUFFER5) return QCUT_BUFFER5;
185 if (atom == XA_CUT_BUFFER6) return QCUT_BUFFER6;
186 if (atom == XA_CUT_BUFFER7) return QCUT_BUFFER7;
191 char *str = XGetAtomName (display, atom);
193 if (! str) return Qnil;
195 TO_INTERNAL_FORMAT (C_STRING, str,
196 C_STRING_ALLOCA, intstr,
199 return intern (intstr);
204 /* Do protocol to assert ourself as a selection owner.
207 x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
208 Lisp_Object how_to_add, Lisp_Object selection_type,
211 struct device *d = decode_x_device (Qnil);
212 Display *display = DEVICE_X_DISPLAY (d);
213 struct frame *sel_frame = selected_frame ();
214 Window selecting_window = XtWindow (FRAME_X_TEXT_WIDGET (sel_frame));
215 Lisp_Object selection_time;
216 /* Use the time of the last-read mouse or keyboard event.
217 For selection purposes, we use this as a sleazy way of knowing what the
218 current time is in server-time. This assumes that the most recently read
219 mouse or keyboard event has something to do with the assertion of the
220 selection, which is probably true.
222 Time thyme = DEVICE_X_MOUSE_TIMESTAMP (d);
225 CHECK_SYMBOL (selection_name);
226 selection_atom = symbol_to_x_atom (d, selection_name, 0);
228 XSetSelectionOwner (display, selection_atom, selecting_window, thyme);
230 /* We do NOT use time_to_lisp() here any more, like we used to.
231 That assumed equivalence of time_t and Time, which is not
232 necessarily the case (e.g. under OSF on the Alphas, where
233 Time is a 64-bit quantity and time_t is a 32-bit quantity).
235 Opaque pointers are the clean way to go here.
237 selection_time = make_opaque (&thyme, sizeof (thyme));
239 #ifdef MOTIF_CLIPBOARDS
240 hack_motif_clipboard_selection (selection_atom, selection_value,
241 thyme, display, selecting_window, owned_p);
243 return selection_time;
246 #ifdef MOTIF_CLIPBOARDS /* Bend over baby. Take it and like it. */
248 # ifdef MOTIF_INCREMENTAL_CLIPBOARDS_WORK
249 static void motif_clipboard_cb ();
253 hack_motif_clipboard_selection (Atom selection_atom,
254 Lisp_Object selection_value,
257 Window selecting_window,
260 struct device *d = get_device_from_display (display);
261 /* Those Motif wankers can't be bothered to follow the ICCCM, and do
262 their own non-Xlib non-Xt clipboard processing. So we have to do
263 this so that linked-in Motif widgets don't get themselves wedged.
265 if (selection_atom == DEVICE_XATOM_CLIPBOARD (d)
266 && STRINGP (selection_value)
268 /* If we already own the clipboard, don't own it again in the Motif
269 way. This might lose in some subtle way, since the timestamp won't
270 be current, but owning the selection on the Motif way does a
271 SHITLOAD of X protocol, and it makes killing text be incredibly
272 slow when using an X terminal. ARRRRGGGHHH!!!!
274 /* No, this is no good, because then Motif text fields don't bother
275 to look up the new value, and you can't Copy from a buffer, Paste
276 into a text field, then Copy something else from the buffer and
277 paste it into the text field -- it pastes the first thing again. */
279 /* Selectively re-enable this because for most users its
280 just too painful - especially over a remote link. */
281 || x_selection_strict_motif_ownership)
284 #ifdef MOTIF_INCREMENTAL_CLIPBOARDS_WORK
285 Widget widget = FRAME_X_TEXT_WIDGET (selected_frame());
288 #if XmVersion >= 1002
291 int dataid; /* 1.2 wants long, but 1.1.5 wants int... */
294 String encoding = "STRING";
295 const Bufbyte *data = XSTRING_DATA (selection_value);
296 Bytecount bytes = XSTRING_LENGTH (selection_value);
300 enum { ASCII, LATIN_1, WORLD } chartypes = ASCII;
301 const Bufbyte *ptr = data, *end = ptr + bytes;
302 /* Optimize for the common ASCII case */
305 if (BYTE_ASCII_P (*ptr))
311 if ((*ptr) == LEADING_BYTE_LATIN_ISO8859_1 ||
312 (*ptr) == LEADING_BYTE_CONTROL_1)
323 if (chartypes == LATIN_1)
324 TO_EXTERNAL_FORMAT (LISP_STRING, selection_value,
325 ALLOCA, (data, bytes),
327 else if (chartypes == WORLD)
329 TO_EXTERNAL_FORMAT (LISP_STRING, selection_value,
330 ALLOCA, (data, bytes),
332 encoding = "COMPOUND_TEXT";
337 fmh = XmStringCreateLtoR ("Clipboard", XmSTRING_DEFAULT_CHARSET);
338 while (ClipboardSuccess !=
339 XmClipboardStartCopy (display, selecting_window, fmh, thyme,
340 #ifdef MOTIF_INCREMENTAL_CLIPBOARDS_WORK
341 widget, motif_clipboard_cb,
348 while (ClipboardSuccess !=
349 XmClipboardCopy (display, selecting_window, itemid, encoding,
350 #ifdef MOTIF_INCREMENTAL_CLIPBOARDS_WORK
351 /* O'Reilly examples say size can be 0,
352 but this clearly is not the case. */
353 0, bytes, (int) selecting_window, /* private id */
354 #else /* !MOTIF_INCREMENTAL_CLIPBOARDS_WORK */
355 (XtPointer) data, bytes, 0,
356 #endif /* !MOTIF_INCREMENTAL_CLIPBOARDS_WORK */
359 while (ClipboardSuccess !=
360 XmClipboardEndCopy (display, selecting_window, itemid))
365 # ifdef MOTIF_INCREMENTAL_CLIPBOARDS_WORK
366 /* I tried to treat the clipboard like a real selection, and not send
367 the data until it was requested, but it looks like that just doesn't
368 work at all unless the selection owner and requestor are in different
369 processes. From reading the Motif source, it looks like they never
370 even considered having two widgets in the same application transfer
371 data between each other using "by-name" clipboard values. What a
375 motif_clipboard_cb (Widget widget, int *data_id, int *private_id, int *reason)
379 case XmCR_CLIPBOARD_DATA_REQUEST:
381 Display *dpy = XtDisplay (widget);
382 Window window = (Window) *private_id;
383 Lisp_Object selection = select_convert_out (QCLIPBOARD, Qnil, Qnil);
385 /* Whichever lazy git wrote this originally just called ABORT()
386 when anything didn't go their way... */
388 /* Try some other text types */
389 if (NILP (selection))
390 selection = select_convert_out (QCLIPBOARD, QSTRING, Qnil);
391 if (NILP (selection))
392 selection = select_convert_out (QCLIPBOARD, QTEXT, Qnil);
393 if (NILP (selection))
394 selection = select_convert_out (QCLIPBOARD, QCOMPOUND_TEXT, Qnil);
396 if (CONSP (selection) && SYMBOLP (XCAR (selection))
397 && (EQ (XCAR (selection), QSTRING)
398 || EQ (XCAR (selection), QTEXT)
399 || EQ (XCAR (selection), QCOMPOUND_TEXT)))
400 selection = XCDR (selection);
402 if (NILP (selection))
403 signal_error (Qselection_conversion_error,
404 build_string ("no selection"));
406 if (!STRINGP (selection))
407 signal_error (Qselection_conversion_error,
408 build_string ("couldn't convert selection to string"));
411 XmClipboardCopyByName (dpy, window, *data_id,
412 (char *) XSTRING_DATA (selection),
413 XSTRING_LENGTH (selection) + 1,
417 case XmCR_CLIPBOARD_DATA_DELETE:
419 /* don't need to free anything */
423 # endif /* MOTIF_INCREMENTAL_CLIPBOARDS_WORK */
424 #endif /* MOTIF_CLIPBOARDS */
429 /* Send a SelectionNotify event to the requestor with property=None, meaning
430 we were unable to do what they wanted.
433 x_decline_selection_request (XSelectionRequestEvent *event)
435 XSelectionEvent reply;
436 reply.type = SelectionNotify;
437 reply.display = event->display;
438 reply.requestor = event->requestor;
439 reply.selection = event->selection;
440 reply.time = event->time;
441 reply.target = event->target;
442 reply.property = None;
444 XSendEvent (reply.display, reply.requestor, False, 0L, (XEvent *) &reply);
445 XFlush (reply.display);
449 /* Used as an unwind-protect clause so that, if a selection-converter signals
450 an error, we tell the requestor that we were unable to do what they wanted
451 before we throw to top-level or go into the debugger or whatever.
454 x_selection_request_lisp_error (Lisp_Object closure)
456 XSelectionRequestEvent *event = (XSelectionRequestEvent *)
457 get_opaque_ptr (closure);
459 free_opaque_ptr (closure);
460 if (event->type == 0) /* we set this to mean "completed normally" */
462 x_decline_selection_request (event);
467 /* Convert our selection to the requested type, and put that data where the
468 requestor wants it. Then tell them whether we've succeeded.
471 x_reply_selection_request (XSelectionRequestEvent *event, int format,
472 unsigned char *data, int size, Atom type)
474 /* This function can GC */
475 XSelectionEvent reply;
476 Display *display = event->display;
477 struct device *d = get_device_from_display (display);
478 Window window = event->requestor;
480 int format_bytes = format/8;
481 int max_bytes = SELECTION_QUANTUM (display);
482 if (max_bytes > MAX_SELECTION_QUANTUM) max_bytes = MAX_SELECTION_QUANTUM;
484 reply.type = SelectionNotify;
485 reply.display = display;
486 reply.requestor = window;
487 reply.selection = event->selection;
488 reply.time = event->time;
489 reply.target = event->target;
490 reply.property = (event->property == None ? event->target : event->property);
492 /* #### XChangeProperty can generate BadAlloc, and we must handle it! */
494 /* Store the data on the requested property.
495 If the selection is large, only store the first N bytes of it.
497 bytes_remaining = size * format_bytes;
498 if (bytes_remaining <= max_bytes)
500 /* Send all the data at once, with minimal handshaking. */
502 stderr_out ("\nStoring all %d\n", bytes_remaining);
504 XChangeProperty (display, window, reply.property, type, format,
505 PropModeReplace, data, size);
506 /* At this point, the selection was successfully stored; ack it. */
507 XSendEvent (display, window, False, 0L, (XEvent *) &reply);
512 #ifndef HAVE_XTREGISTERDRAWABLE
513 invalid_operation("Copying that much data requires X11R6.", Qunbound);
515 /* Send an INCR selection. */
517 Widget widget = FRAME_X_TEXT_WIDGET (XFRAME(DEVICE_SELECTED_FRAME(d)));
519 if (x_window_to_frame (d, window)) /* #### debug */
520 error ("attempt to transfer an INCR to ourself!");
522 stderr_out ("\nINCR %d\n", bytes_remaining);
524 /* Tell Xt not to drop PropertyNotify events that arrive for the
525 target window, rather, pass them to us. This would be a hack, but
526 the Xt selection routines are broken for our purposes--we can't
527 pass them callbacks from Lisp, for example. Let's call it a
530 The call to wait_for_property_change means we can break out of that
531 function, switch to another frame on the same display (which will
532 be another Xt widget), select a huge amount of text, and have the
533 same (foreign) app ask for another incremental selection
534 transfer. Programming like X11 made sense, would mean that, in that
535 case, XtRegisterDrawable is called twice with different widgets.
537 Since the results of calling XtRegisterDrawable when the drawable
538 is already registered with another widget are undefined, we want to
539 avoid that--so, only call it when XtWindowToWidget returns NULL,
540 which it will only do with a valid Window if it's not already
542 if (NULL == XtWindowToWidget(display, window))
544 XtRegisterDrawable(display, (Drawable)window, widget);
547 prop_id = expect_property_change (display, window, reply.property,
550 XChangeProperty (display, window, reply.property, DEVICE_XATOM_INCR (d),
551 32, PropModeReplace, (unsigned char *)
552 &bytes_remaining, 1);
553 XSelectInput (display, window, PropertyChangeMask);
554 /* Tell 'em the INCR data is there... */
555 XSendEvent (display, window, False, 0L, (XEvent *) &reply);
558 /* First, wait for the requestor to ack by deleting the property.
559 This can run random lisp code (process handlers) or signal.
561 wait_for_property_change (prop_id);
563 while (bytes_remaining)
565 int i = ((bytes_remaining < max_bytes)
568 prop_id = expect_property_change (display, window, reply.property,
571 stderr_out (" INCR adding %d\n", i);
573 /* Append the next chunk of data to the property. */
574 XChangeProperty (display, window, reply.property, type, format,
575 PropModeAppend, data, i / format_bytes);
576 bytes_remaining -= i;
579 /* Now wait for the requestor to ack this chunk by deleting the
580 property. This can run random lisp code or signal.
582 wait_for_property_change (prop_id);
584 /* Now write a zero-length chunk to the property to tell the requestor
587 stderr_out (" INCR done\n");
589 if (! waiting_for_other_props_on_window (display, window))
591 XSelectInput (display, window, 0L);
592 XtUnregisterDrawable(display, (Drawable)window);
595 XChangeProperty (display, window, reply.property, type, format,
596 PropModeReplace, data, 0);
597 #endif /* HAVE_XTREGISTERDRAWABLE */
603 /* Called from the event-loop in response to a SelectionRequest event.
606 x_handle_selection_request (XSelectionRequestEvent *event)
608 /* This function can GC */
609 struct gcpro gcpro1, gcpro2;
610 Lisp_Object temp_obj;
611 Lisp_Object selection_symbol;
612 Lisp_Object target_symbol = Qnil;
613 Lisp_Object converted_selection = Qnil;
614 Time local_selection_time;
615 Lisp_Object successful_p = Qnil;
617 struct device *d = get_device_from_display (event->display);
619 GCPRO2 (converted_selection, target_symbol);
621 selection_symbol = x_atom_to_symbol (d, event->selection);
622 target_symbol = x_atom_to_symbol (d, event->target);
624 #if 0 /* #### MULTIPLE doesn't work yet */
625 if (EQ (target_symbol, QMULTIPLE))
626 target_symbol = fetch_multiple_target (event);
629 temp_obj = Fget_selection_timestamp (selection_symbol);
633 /* We don't appear to have the selection. */
634 x_decline_selection_request (event);
639 local_selection_time = * (Time *) XOPAQUE_DATA (temp_obj);
641 if (event->time != CurrentTime &&
642 local_selection_time > event->time)
644 /* Someone asked for the selection, and we have one, but not the one
645 they're looking for. */
646 x_decline_selection_request (event);
650 converted_selection = select_convert_out (selection_symbol,
651 target_symbol, Qnil);
653 /* #### Is this the right thing to do? I'm no X expert. -- ajh */
654 if (NILP (converted_selection))
656 /* We don't appear to have a selection in that data type. */
657 x_decline_selection_request (event);
661 count = specpdl_depth ();
662 record_unwind_protect (x_selection_request_lisp_error,
663 make_opaque_ptr (event));
670 lisp_data_to_selection_data (d, converted_selection,
671 &data, &type, &size, &format);
673 x_reply_selection_request (event, format, data, size, type);
675 /* Tell x_selection_request_lisp_error() it's cool. */
680 unbind_to (count, Qnil);
686 /* Let random lisp code notice that the selection has been asked for. */
688 Lisp_Object val = Vx_sent_selection_hooks;
689 if (!UNBOUNDP (val) && !NILP (val))
692 if (CONSP (val) && !EQ (XCAR (val), Qlambda))
693 for (rest = val; !NILP (rest); rest = Fcdr (rest))
694 call3 (Fcar (rest), selection_symbol, target_symbol, successful_p);
696 call3 (val, selection_symbol, target_symbol, successful_p);
702 /* Called from the event-loop in response to a SelectionClear event.
705 x_handle_selection_clear (XSelectionClearEvent *event)
707 Display *display = event->display;
708 struct device *d = get_device_from_display (display);
709 Atom selection = event->selection;
710 Time changed_owner_time = event->time;
712 Lisp_Object selection_symbol, local_selection_time_lisp;
713 Time local_selection_time;
715 selection_symbol = x_atom_to_symbol (d, selection);
717 local_selection_time_lisp = Fget_selection_timestamp (selection_symbol);
719 /* We don't own the selection, so that's fine. */
720 if (NILP (local_selection_time_lisp))
723 local_selection_time = * (Time *) XOPAQUE_DATA (local_selection_time_lisp);
725 /* This SelectionClear is for a selection that we no longer own, so we can
726 disregard it. (That is, we have reasserted the selection since this
727 request was generated.)
729 if (changed_owner_time != CurrentTime &&
730 local_selection_time > changed_owner_time)
733 handle_selection_clear (selection_symbol);
737 /* This stuff is so that INCR selections are reentrant (that is, so we can
738 be servicing multiple INCR selection requests simultaneously). I haven't
739 actually tested that yet.
742 static int prop_location_tick;
744 static struct prop_location {
750 struct prop_location *next;
751 } *for_whom_the_bell_tolls;
755 property_deleted_p (void *tick)
757 struct prop_location *rest = for_whom_the_bell_tolls;
759 if (rest->tick == (long) tick)
767 waiting_for_other_props_on_window (Display *display, Window window)
769 struct prop_location *rest = for_whom_the_bell_tolls;
771 if (rest->display == display && rest->window == window)
780 expect_property_change (Display *display, Window window,
781 Atom property, int state)
783 struct prop_location *pl = xnew (struct prop_location);
784 pl->tick = ++prop_location_tick;
785 pl->display = display;
787 pl->property = property;
788 pl->desired_state = state;
789 pl->next = for_whom_the_bell_tolls;
790 for_whom_the_bell_tolls = pl;
795 unexpect_property_change (int tick)
797 struct prop_location *prev = 0, *rest = for_whom_the_bell_tolls;
800 if (rest->tick == tick)
803 prev->next = rest->next;
805 for_whom_the_bell_tolls = rest->next;
815 wait_for_property_change (long tick)
817 /* This function can GC */
818 wait_delaying_user_input (property_deleted_p, (void *) tick);
822 /* Called from the event-loop in response to a PropertyNotify event.
825 x_handle_property_notify (XPropertyEvent *event)
827 struct prop_location *prev = 0, *rest = for_whom_the_bell_tolls;
830 if (rest->property == event->atom &&
831 rest->window == event->window &&
832 rest->display == event->display &&
833 rest->desired_state == event->state)
836 stderr_out ("Saw expected prop-%s on %s\n",
837 (event->state == PropertyDelete ? "delete" : "change"),
838 (char *) string_data (XSYMBOL (x_atom_to_symbol (get_device_from_display (event->display), event->atom))->name);
841 prev->next = rest->next;
843 for_whom_the_bell_tolls = rest->next;
851 stderr_out ("Saw UNexpected prop-%s on %s\n",
852 (event->state == PropertyDelete ? "delete" : "change"),
853 (char *) string_data (XSYMBOL (x_atom_to_symbol (get_device_from_display (event->display), event->atom))->name));
859 #if 0 /* #### MULTIPLE doesn't work yet */
862 fetch_multiple_target (XSelectionRequestEvent *event)
864 /* This function can GC */
865 Display *display = event->display;
866 Window window = event->requestor;
867 Atom target = event->target;
868 Atom selection_atom = event->selection;
873 x_get_window_property_as_lisp_data (display, window, target,
879 copy_multiple_data (Lisp_Object obj)
885 return Fcons (XCAR (obj), copy_multiple_data (XCDR (obj)));
888 len = XVECTOR_LENGTH (obj);
889 vec = make_vector (len, Qnil);
890 for (i = 0; i < len; i++)
892 Lisp_Object vec2 = XVECTOR_DATA (obj) [i];
894 if (XVECTOR_LENGTH (vec2) != 2)
895 signal_error (Qerror, list2 (build_string
896 ("vectors must be of length 2"),
898 XVECTOR_DATA (vec) [i] = make_vector (2, Qnil);
899 XVECTOR_DATA (XVECTOR_DATA (vec) [i]) [0] = XVECTOR_DATA (vec2) [0];
900 XVECTOR_DATA (XVECTOR_DATA (vec) [i]) [1] = XVECTOR_DATA (vec2) [1];
908 static Window reading_selection_reply;
909 static Atom reading_which_selection;
910 static int selection_reply_timed_out;
913 selection_reply_done (void *ignore)
915 return !reading_selection_reply;
918 static Lisp_Object Qx_selection_reply_timeout_internal;
920 DEFUN ("x-selection-reply-timeout-internal", Fx_selection_reply_timeout_internal,
925 selection_reply_timed_out = 1;
926 reading_selection_reply = 0;
931 /* Do protocol to read selection-data from the server.
932 Converts this to lisp data and returns it.
935 x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type)
937 /* This function can GC */
938 struct device *d = decode_x_device (Qnil);
939 Display *display = DEVICE_X_DISPLAY (d);
940 struct frame *sel_frame = selected_frame ();
941 Window requestor_window = XtWindow (FRAME_X_TEXT_WIDGET (sel_frame));
942 Time requestor_time = DEVICE_X_MOUSE_TIMESTAMP (d);
943 Atom target_property = DEVICE_XATOM_EMACS_TMP (d);
944 Atom selection_atom = symbol_to_x_atom (d, selection_symbol, 0);
946 Atom type_atom = symbol_to_x_atom (d, (CONSP (target_type) ?
947 XCAR (target_type) : target_type), 0);
949 XConvertSelection (display, selection_atom, type_atom, target_property,
950 requestor_window, requestor_time);
952 /* Block until the reply has been read. */
953 reading_selection_reply = requestor_window;
954 reading_which_selection = selection_atom;
955 selection_reply_timed_out = 0;
957 speccount = specpdl_depth ();
959 /* add a timeout handler */
960 if (x_selection_timeout > 0)
962 Lisp_Object id = Fadd_timeout (make_int (x_selection_timeout),
963 Qx_selection_reply_timeout_internal,
965 record_unwind_protect (Fdisable_timeout, id);
969 wait_delaying_user_input (selection_reply_done, 0);
971 if (selection_reply_timed_out)
972 error ("timed out waiting for reply from selection owner");
974 unbind_to (speccount, Qnil);
976 /* otherwise, the selection is waiting for us on the requested property. */
978 return select_convert_in (selection_symbol,
980 x_get_window_property_as_lisp_data(display,
989 x_get_window_property (Display *display, Window window, Atom property,
990 Extbyte **data_ret, int *bytes_ret,
991 Atom *actual_type_ret, int *actual_format_ret,
992 unsigned long *actual_size_ret, int delete_p)
995 unsigned long bytes_remaining;
997 unsigned char *tmp_data = 0;
999 int buffer_size = SELECTION_QUANTUM (display);
1000 if (buffer_size > MAX_SELECTION_QUANTUM) buffer_size = MAX_SELECTION_QUANTUM;
1002 /* First probe the thing to find out how big it is. */
1003 result = XGetWindowProperty (display, window, property,
1004 0, 0, False, AnyPropertyType,
1005 actual_type_ret, actual_format_ret,
1007 &bytes_remaining, &tmp_data);
1008 if (result != Success)
1014 XFree ((char *) tmp_data);
1016 if (*actual_type_ret == None || *actual_format_ret == 0)
1018 if (delete_p) XDeleteProperty (display, window, property);
1024 total_size = bytes_remaining + 1;
1025 *data_ret = (Extbyte *) xmalloc (total_size);
1027 /* Now read, until we've gotten it all. */
1028 while (bytes_remaining)
1031 int last = bytes_remaining;
1034 XGetWindowProperty (display, window, property,
1035 offset/4, buffer_size/4,
1036 (delete_p ? True : False),
1038 actual_type_ret, actual_format_ret,
1039 actual_size_ret, &bytes_remaining, &tmp_data);
1041 stderr_out ("<< read %d\n", last-bytes_remaining);
1043 /* If this doesn't return Success at this point, it means that
1044 some clod deleted the selection while we were in the midst of
1045 reading it. Deal with that, I guess....
1047 if (result != Success) break;
1048 *actual_size_ret *= *actual_format_ret / 8;
1049 memcpy ((*data_ret) + offset, tmp_data, *actual_size_ret);
1050 offset += *actual_size_ret;
1051 XFree ((char *) tmp_data);
1053 *bytes_ret = offset;
1058 receive_incremental_selection (Display *display, Window window, Atom property,
1059 /* this one is for error messages only */
1060 Lisp_Object target_type,
1061 unsigned int min_size_bytes,
1062 Extbyte **data_ret, int *size_bytes_ret,
1063 Atom *type_ret, int *format_ret,
1064 unsigned long *size_ret)
1066 /* This function can GC */
1069 *size_bytes_ret = min_size_bytes;
1070 *data_ret = (Extbyte *) xmalloc (*size_bytes_ret);
1072 stderr_out ("\nread INCR %d\n", min_size_bytes);
1074 /* At this point, we have read an INCR property, and deleted it (which
1075 is how we ack its receipt: the sending window will be selecting
1076 PropertyNotify events on our window to notice this).
1078 Now, we must loop, waiting for the sending window to put a value on
1079 that property, then reading the property, then deleting it to ack.
1080 We are done when the sender places a property of length 0.
1082 prop_id = expect_property_change (display, window, property,
1088 wait_for_property_change (prop_id);
1089 /* expect it again immediately, because x_get_window_property may
1090 .. no it won't, I don't get it.
1091 .. Ok, I get it now, the Xt code that implements INCR is broken.
1093 prop_id = expect_property_change (display, window, property,
1095 x_get_window_property (display, window, property,
1096 &tmp_data, &tmp_size_bytes,
1097 type_ret, format_ret, size_ret, 1);
1099 if (tmp_size_bytes == 0) /* we're done */
1102 stderr_out (" read INCR done\n");
1104 unexpect_property_change (prop_id);
1105 if (tmp_data) xfree (tmp_data);
1109 stderr_out (" read INCR %d\n", tmp_size_bytes);
1111 if (*size_bytes_ret < offset + tmp_size_bytes)
1114 stderr_out (" read INCR realloc %d -> %d\n",
1115 *size_bytes_ret, offset + tmp_size_bytes);
1117 *size_bytes_ret = offset + tmp_size_bytes;
1118 *data_ret = (Extbyte *) xrealloc (*data_ret, *size_bytes_ret);
1120 memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes);
1121 offset += tmp_size_bytes;
1128 x_get_window_property_as_lisp_data (Display *display,
1131 /* next two for error messages only */
1132 Lisp_Object target_type,
1133 Atom selection_atom)
1135 /* This function can GC */
1138 unsigned long actual_size;
1139 Extbyte *data = NULL;
1142 struct device *d = get_device_from_display (display);
1144 x_get_window_property (display, window, property, &data, &bytes,
1145 &actual_type, &actual_format, &actual_size, 1);
1148 if (XGetSelectionOwner (display, selection_atom))
1149 /* there is a selection owner */
1151 (Qselection_conversion_error,
1152 Fcons (build_string ("selection owner couldn't convert"),
1153 Fcons (x_atom_to_symbol (d, selection_atom),
1155 list2 (target_type, x_atom_to_symbol (d, actual_type)) :
1156 list1 (target_type))));
1158 signal_error (Qerror,
1159 list2 (build_string ("no selection"),
1160 x_atom_to_symbol (d, selection_atom)));
1163 if (actual_type == DEVICE_XATOM_INCR (d))
1165 /* Ok, that data wasn't *the* data, it was just the beginning. */
1167 unsigned int min_size_bytes = * ((unsigned int *) data);
1169 receive_incremental_selection (display, window, property, target_type,
1170 min_size_bytes, &data, &bytes,
1171 &actual_type, &actual_format,
1175 /* It's been read. Now convert it to a lisp object in some semi-rational
1177 val = selection_data_to_lisp_data (d, data, bytes,
1178 actual_type, actual_format);
1184 /* #### These are going to move into Lisp code(!) with the aid of
1185 some new functions I'm working on - ajh */
1187 /* These functions convert from the selection data read from the server into
1188 something that we can use from elisp, and vice versa.
1190 Type: Format: Size: Elisp Type:
1191 ----- ------- ----- -----------
1194 ATOM 32 > 1 Vector of Symbols
1196 * 16 > 1 Vector of Integers
1197 * 32 1 if <=16 bits: Integer
1198 if > 16 bits: Cons of top16, bot16
1199 * 32 > 1 Vector of the above
1201 When converting a Lisp number to C, it is assumed to be of format 16 if
1202 it is an integer, and of format 32 if it is a cons of two integers.
1204 When converting a vector of numbers from Elisp to C, it is assumed to be
1205 of format 16 if every element in the vector is an integer, and is assumed
1206 to be of format 32 if any element is a cons of two integers.
1208 When converting an object to C, it may be of the form (SYMBOL . <data>)
1209 where SYMBOL is what we should claim that the type is. Format and
1210 representation are as above.
1212 NOTE: Under Mule, when someone shoves us a string without a type, we
1213 set the type to 'COMPOUND_TEXT and automatically convert to Compound
1214 Text. If the string has a type, we assume that the user wants the
1215 data sent as-is so we just do "binary" conversion.
1220 selection_data_to_lisp_data (struct device *d,
1226 if (type == DEVICE_XATOM_NULL (d))
1229 /* Convert any 8-bit data to a string, for compactness. */
1230 else if (format == 8)
1231 return make_ext_string (data, size,
1232 type == DEVICE_XATOM_TEXT (d) ||
1233 type == DEVICE_XATOM_COMPOUND_TEXT (d)
1234 ? Qctext : Qbinary);
1236 /* Convert a single atom to a Lisp Symbol.
1237 Convert a set of atoms to a vector of symbols. */
1238 else if (type == XA_ATOM)
1240 if (size == sizeof (Atom))
1241 return x_atom_to_symbol (d, *((Atom *) data));
1245 int len = size / sizeof (Atom);
1246 Lisp_Object v = Fmake_vector (make_int (len), Qzero);
1247 for (i = 0; i < len; i++)
1248 Faset (v, make_int (i), x_atom_to_symbol (d, ((Atom *) data) [i]));
1253 /* Convert a single 16 or small 32 bit number to a Lisp Int.
1254 If the number is > 16 bits, convert it to a cons of integers,
1255 16 bits in each half.
1257 else if (format == 32 && size == sizeof (long))
1258 return word_to_lisp (((unsigned long *) data) [0]);
1259 else if (format == 16 && size == sizeof (short))
1260 return make_int ((int) (((unsigned short *) data) [0]));
1262 /* Convert any other kind of data to a vector of numbers, represented
1263 as above (as an integer, or a cons of two 16 bit integers).
1265 #### Perhaps we should return the actual type to lisp as well.
1267 (x-get-selection-internal 'PRIMARY 'LINE_NUMBER)
1270 and perhaps it should be
1272 (x-get-selection-internal 'PRIMARY 'LINE_NUMBER)
1275 Right now the fact that the return type was SPAN is discarded before
1276 lisp code gets to see it.
1278 else if (format == 16)
1281 Lisp_Object v = make_vector (size / 4, Qzero);
1282 for (i = 0; i < (int) size / 4; i++)
1284 int j = (int) ((unsigned short *) data) [i];
1285 Faset (v, make_int (i), make_int (j));
1292 Lisp_Object v = make_vector (size / 4, Qzero);
1293 for (i = 0; i < (int) size / 4; i++)
1295 unsigned long j = ((unsigned long *) data) [i];
1296 Faset (v, make_int (i), word_to_lisp (j));
1304 lisp_data_to_selection_data (struct device *d,
1306 unsigned char **data_ret,
1308 unsigned int *size_ret,
1311 Lisp_Object type = Qnil;
1313 if (CONSP (obj) && SYMBOLP (XCAR (obj)))
1317 if (CONSP (obj) && NILP (XCDR (obj)))
1321 if (EQ (obj, QNULL) || (EQ (type, QNULL)))
1322 { /* This is not the same as declining */
1328 else if (STRINGP (obj))
1330 const Extbyte *extval;
1333 TO_EXTERNAL_FORMAT (LISP_STRING, obj,
1334 ALLOCA, (extval, extvallen),
1335 (NILP (type) ? Qctext : Qbinary));
1337 *size_ret = extvallen;
1338 *data_ret = (unsigned char *) xmalloc (*size_ret);
1339 memcpy (*data_ret, extval, *size_ret);
1341 if (NILP (type)) type = QCOMPOUND_TEXT;
1343 if (NILP (type)) type = QSTRING;
1346 else if (CHARP (obj))
1348 Bufbyte buf[MAX_EMCHAR_LEN];
1350 const Extbyte *extval;
1354 len = set_charptr_emchar (buf, XCHAR (obj));
1355 TO_EXTERNAL_FORMAT (DATA, (buf, len),
1356 ALLOCA, (extval, extvallen),
1358 *size_ret = extvallen;
1359 *data_ret = (unsigned char *) xmalloc (*size_ret);
1360 memcpy (*data_ret, extval, *size_ret);
1362 if (NILP (type)) type = QCOMPOUND_TEXT;
1364 if (NILP (type)) type = QSTRING;
1367 else if (SYMBOLP (obj))
1371 *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1);
1372 (*data_ret) [sizeof (Atom)] = 0;
1373 (*(Atom **) data_ret) [0] = symbol_to_x_atom (d, obj, 0);
1374 if (NILP (type)) type = QATOM;
1376 else if (INTP (obj) &&
1377 XINT (obj) <= 0x7FFF &&
1378 XINT (obj) >= -0x8000)
1382 *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
1383 (*data_ret) [sizeof (short)] = 0;
1384 (*(short **) data_ret) [0] = (short) XINT (obj);
1385 if (NILP (type)) type = QINTEGER;
1387 else if (INTP (obj) || CONSP (obj))
1391 *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
1392 (*data_ret) [sizeof (long)] = 0;
1393 (*(unsigned long **) data_ret) [0] = lisp_to_word (obj);
1394 if (NILP (type)) type = QINTEGER;
1396 else if (VECTORP (obj))
1398 /* Lisp Vectors may represent a set of ATOMs;
1399 a set of 16 or 32 bit INTEGERs;
1400 or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...]
1404 if (SYMBOLP (XVECTOR_DATA (obj) [0]))
1405 /* This vector is an ATOM set */
1407 if (NILP (type)) type = QATOM;
1408 *size_ret = XVECTOR_LENGTH (obj);
1410 *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom));
1411 for (i = 0; i < (int) (*size_ret); i++)
1412 if (SYMBOLP (XVECTOR_DATA (obj) [i]))
1413 (*(Atom **) data_ret) [i] =
1414 symbol_to_x_atom (d, XVECTOR_DATA (obj) [i], 0);
1416 signal_error (Qerror, /* Qselection_error */
1418 ("all elements of the vector must be of the same type"),
1421 #if 0 /* #### MULTIPLE doesn't work yet */
1422 else if (VECTORP (XVECTOR_DATA (obj) [0]))
1423 /* This vector is an ATOM_PAIR set */
1425 if (NILP (type)) type = QATOM_PAIR;
1426 *size_ret = XVECTOR_LENGTH (obj);
1428 *data_ret = (unsigned char *)
1429 xmalloc ((*size_ret) * sizeof (Atom) * 2);
1430 for (i = 0; i < *size_ret; i++)
1431 if (VECTORP (XVECTOR_DATA (obj) [i]))
1433 Lisp_Object pair = XVECTOR_DATA (obj) [i];
1434 if (XVECTOR_LENGTH (pair) != 2)
1435 signal_error (Qerror,
1437 ("elements of the vector must be vectors of exactly two elements"),
1440 (*(Atom **) data_ret) [i * 2] =
1441 symbol_to_x_atom (d, XVECTOR_DATA (pair) [0], 0);
1442 (*(Atom **) data_ret) [(i * 2) + 1] =
1443 symbol_to_x_atom (d, XVECTOR_DATA (pair) [1], 0);
1446 signal_error (Qerror,
1448 ("all elements of the vector must be of the same type"),
1453 /* This vector is an INTEGER set, or something like it */
1455 *size_ret = XVECTOR_LENGTH (obj);
1456 if (NILP (type)) type = QINTEGER;
1458 for (i = 0; i < (int) (*size_ret); i++)
1459 if (CONSP (XVECTOR_DATA (obj) [i]))
1461 else if (!INTP (XVECTOR_DATA (obj) [i]))
1462 signal_error (Qerror, /* Qselection_error */
1464 ("all elements of the vector must be integers or conses of integers"),
1467 *data_ret = (unsigned char *) xmalloc (*size_ret * (*format_ret/8));
1468 for (i = 0; i < (int) (*size_ret); i++)
1469 if (*format_ret == 32)
1470 (*((unsigned long **) data_ret)) [i] =
1471 lisp_to_word (XVECTOR_DATA (obj) [i]);
1473 (*((unsigned short **) data_ret)) [i] =
1474 (unsigned short) lisp_to_word (XVECTOR_DATA (obj) [i]);
1478 signal_error (Qerror, /* Qselection_error */
1479 list2 (build_string ("unrecognized selection data"),
1482 *type_ret = symbol_to_x_atom (d, type, 0);
1487 /* Called from the event loop to handle SelectionNotify events.
1488 I don't think this needs to be reentrant.
1491 x_handle_selection_notify (XSelectionEvent *event)
1493 if (! reading_selection_reply)
1494 message ("received an unexpected SelectionNotify event");
1495 else if (event->requestor != reading_selection_reply)
1496 message ("received a SelectionNotify event for the wrong window");
1497 else if (event->selection != reading_which_selection)
1498 message ("received the wrong selection type in SelectionNotify!");
1500 reading_selection_reply = 0; /* we're done now. */
1504 x_disown_selection (Lisp_Object selection, Lisp_Object timeval)
1506 struct device *d = decode_x_device (Qnil);
1507 Display *display = DEVICE_X_DISPLAY (d);
1509 Atom selection_atom;
1511 CHECK_SYMBOL (selection);
1513 timestamp = DEVICE_X_MOUSE_TIMESTAMP (d);
1516 /* #### This is bogus. See the comment above about problems
1517 on OSF/1 and DEC Alphas. Yet another reason why it sucks
1518 to have the implementation (i.e. cons of two 16-bit
1519 integers) exposed. */
1521 lisp_to_time (timeval, &the_time);
1522 timestamp = (Time) the_time;
1525 selection_atom = symbol_to_x_atom (d, selection, 0);
1527 XSetSelectionOwner (display, selection_atom, None, timestamp);
1531 x_selection_exists_p (Lisp_Object selection,
1532 Lisp_Object selection_type)
1534 struct device *d = decode_x_device (Qnil);
1535 Display *dpy = DEVICE_X_DISPLAY (d);
1536 return XGetSelectionOwner (dpy, symbol_to_x_atom (d, selection, 0)) != None ?
1541 #ifdef CUT_BUFFER_SUPPORT
1543 static int cut_buffers_initialized; /* Whether we're sure they all exist */
1545 /* Ensure that all 8 cut buffers exist. ICCCM says we gotta... */
1547 initialize_cut_buffers (Display *display, Window window)
1549 static unsigned const char * const data = (unsigned const char *) "";
1550 #define FROB(atom) XChangeProperty (display, window, atom, XA_STRING, 8, \
1551 PropModeAppend, data, 0)
1552 FROB (XA_CUT_BUFFER0);
1553 FROB (XA_CUT_BUFFER1);
1554 FROB (XA_CUT_BUFFER2);
1555 FROB (XA_CUT_BUFFER3);
1556 FROB (XA_CUT_BUFFER4);
1557 FROB (XA_CUT_BUFFER5);
1558 FROB (XA_CUT_BUFFER6);
1559 FROB (XA_CUT_BUFFER7);
1561 cut_buffers_initialized = 1;
1564 #define CHECK_CUTBUFFER(symbol) do { \
1565 CHECK_SYMBOL (symbol); \
1566 if (! (EQ (symbol, QCUT_BUFFER0) || \
1567 EQ (symbol, QCUT_BUFFER1) || \
1568 EQ (symbol, QCUT_BUFFER2) || \
1569 EQ (symbol, QCUT_BUFFER3) || \
1570 EQ (symbol, QCUT_BUFFER4) || \
1571 EQ (symbol, QCUT_BUFFER5) || \
1572 EQ (symbol, QCUT_BUFFER6) || \
1573 EQ (symbol, QCUT_BUFFER7))) \
1574 signal_simple_error ("Doesn't name a cutbuffer", symbol); \
1577 DEFUN ("x-get-cutbuffer-internal", Fx_get_cutbuffer_internal, 1, 1, 0, /*
1578 Return the value of the named CUTBUFFER (typically CUT_BUFFER0).
1582 struct device *d = decode_x_device (Qnil);
1583 Display *display = DEVICE_X_DISPLAY (d);
1584 Window window = RootWindow (display, 0); /* Cutbuffers are on frame 0 */
1585 Atom cut_buffer_atom;
1593 CHECK_CUTBUFFER (cutbuffer);
1594 cut_buffer_atom = symbol_to_x_atom (d, cutbuffer, 0);
1596 x_get_window_property (display, window, cut_buffer_atom, &data, &bytes,
1597 &type, &format, &size, 0);
1598 if (!data) return Qnil;
1600 if (format != 8 || type != XA_STRING)
1601 signal_simple_error_2 ("Cut buffer doesn't contain 8-bit STRING data",
1602 x_atom_to_symbol (d, type),
1605 /* We cheat - if the string contains an ESC character, that's
1606 technically not allowed in a STRING, so we assume it's
1607 COMPOUND_TEXT that we stored there ourselves earlier,
1608 in x-store-cutbuffer-internal */
1610 make_ext_string (data, bytes,
1611 memchr (data, 0x1b, bytes) ?
1619 DEFUN ("x-store-cutbuffer-internal", Fx_store_cutbuffer_internal, 2, 2, 0, /*
1620 Set the value of the named CUTBUFFER (typically CUT_BUFFER0) to STRING.
1622 (cutbuffer, string))
1624 struct device *d = decode_x_device (Qnil);
1625 Display *display = DEVICE_X_DISPLAY (d);
1626 Window window = RootWindow (display, 0); /* Cutbuffers are on frame 0 */
1627 Atom cut_buffer_atom;
1628 const Bufbyte *data = XSTRING_DATA (string);
1629 Bytecount bytes = XSTRING_LENGTH (string);
1630 Bytecount bytes_remaining;
1631 int max_bytes = SELECTION_QUANTUM (display);
1633 const Bufbyte *ptr, *end;
1634 enum { ASCII, LATIN_1, WORLD } chartypes = ASCII;
1637 if (max_bytes > MAX_SELECTION_QUANTUM)
1638 max_bytes = MAX_SELECTION_QUANTUM;
1640 CHECK_CUTBUFFER (cutbuffer);
1641 CHECK_STRING (string);
1642 cut_buffer_atom = symbol_to_x_atom (d, cutbuffer, 0);
1644 if (! cut_buffers_initialized)
1645 initialize_cut_buffers (display, window);
1647 /* We use the STRING encoding (Latin-1 only) if we can, else COMPOUND_TEXT.
1648 We cheat and use type = `STRING' even when using COMPOUND_TEXT.
1649 The ICCCM requires that this be so, and other clients assume it,
1650 as we do ourselves in initialize_cut_buffers. */
1653 /* Optimize for the common ASCII case */
1654 for (ptr = data, end = ptr + bytes; ptr <= end; )
1656 if (BYTE_ASCII_P (*ptr))
1665 chartypes = LATIN_1;
1670 if ((*ptr) == LEADING_BYTE_LATIN_ISO8859_1 ||
1671 (*ptr) == LEADING_BYTE_CONTROL_1)
1673 chartypes = LATIN_1;
1683 if (chartypes == LATIN_1)
1684 TO_EXTERNAL_FORMAT (LISP_STRING, string,
1685 ALLOCA, (data, bytes),
1687 else if (chartypes == WORLD)
1688 TO_EXTERNAL_FORMAT (LISP_STRING, string,
1689 ALLOCA, (data, bytes),
1693 bytes_remaining = bytes;
1695 while (bytes_remaining)
1697 int chunk = bytes_remaining < max_bytes ? bytes_remaining : max_bytes;
1698 XChangeProperty (display, window, cut_buffer_atom, XA_STRING, 8,
1699 (bytes_remaining == bytes
1700 ? PropModeReplace : PropModeAppend),
1703 bytes_remaining -= chunk;
1709 DEFUN ("x-rotate-cutbuffers-internal", Fx_rotate_cutbuffers_internal, 1, 1, 0, /*
1710 Rotate the values of the cutbuffers by the given number of steps;
1711 positive means move values forward, negative means backward.
1715 struct device *d = decode_x_device (Qnil);
1716 Display *display = DEVICE_X_DISPLAY (d);
1717 Window window = RootWindow (display, 0); /* Cutbuffers are on frame 0 */
1723 if (! cut_buffers_initialized)
1724 initialize_cut_buffers (display, window);
1725 props[0] = XA_CUT_BUFFER0;
1726 props[1] = XA_CUT_BUFFER1;
1727 props[2] = XA_CUT_BUFFER2;
1728 props[3] = XA_CUT_BUFFER3;
1729 props[4] = XA_CUT_BUFFER4;
1730 props[5] = XA_CUT_BUFFER5;
1731 props[6] = XA_CUT_BUFFER6;
1732 props[7] = XA_CUT_BUFFER7;
1733 XRotateWindowProperties (display, window, props, 8, XINT (n));
1737 #endif /* CUT_BUFFER_SUPPORT */
1741 /************************************************************************/
1742 /* initialization */
1743 /************************************************************************/
1746 syms_of_select_x (void)
1749 #ifdef CUT_BUFFER_SUPPORT
1750 DEFSUBR (Fx_get_cutbuffer_internal);
1751 DEFSUBR (Fx_store_cutbuffer_internal);
1752 DEFSUBR (Fx_rotate_cutbuffers_internal);
1753 #endif /* CUT_BUFFER_SUPPORT */
1755 /* Unfortunately, timeout handlers must be lisp functions. */
1756 defsymbol (&Qx_selection_reply_timeout_internal,
1757 "x-selection-reply-timeout-internal");
1758 DEFSUBR (Fx_selection_reply_timeout_internal);
1760 #ifdef CUT_BUFFER_SUPPORT
1761 defsymbol (&QCUT_BUFFER0, "CUT_BUFFER0");
1762 defsymbol (&QCUT_BUFFER1, "CUT_BUFFER1");
1763 defsymbol (&QCUT_BUFFER2, "CUT_BUFFER2");
1764 defsymbol (&QCUT_BUFFER3, "CUT_BUFFER3");
1765 defsymbol (&QCUT_BUFFER4, "CUT_BUFFER4");
1766 defsymbol (&QCUT_BUFFER5, "CUT_BUFFER5");
1767 defsymbol (&QCUT_BUFFER6, "CUT_BUFFER6");
1768 defsymbol (&QCUT_BUFFER7, "CUT_BUFFER7");
1769 #endif /* CUT_BUFFER_SUPPORT */
1773 console_type_create_select_x (void)
1775 CONSOLE_HAS_METHOD (x, own_selection);
1776 CONSOLE_HAS_METHOD (x, disown_selection);
1777 CONSOLE_HAS_METHOD (x, get_foreign_selection);
1778 CONSOLE_HAS_METHOD (x, selection_exists_p);
1782 reinit_vars_of_select_x (void)
1784 reading_selection_reply = 0;
1785 reading_which_selection = 0;
1786 selection_reply_timed_out = 0;
1787 for_whom_the_bell_tolls = 0;
1788 prop_location_tick = 0;
1792 vars_of_select_x (void)
1794 reinit_vars_of_select_x ();
1796 #ifdef CUT_BUFFER_SUPPORT
1797 cut_buffers_initialized = 0;
1798 Fprovide (intern ("cut-buffer"));
1801 DEFVAR_LISP ("x-sent-selection-hooks", &Vx_sent_selection_hooks /*
1802 A function or functions to be called after we have responded to some
1803 other client's request for the value of a selection that we own. The
1804 function(s) will be called with four arguments:
1805 - the name of the selection (typically PRIMARY, SECONDARY, or CLIPBOARD);
1806 - the name of the selection-type which we were requested to convert the
1807 selection into before sending (for example, STRING or LENGTH);
1808 - and whether we successfully transmitted the selection.
1809 We might have failed (and declined the request) for any number of reasons,
1810 including being asked for a selection that we no longer own, or being asked
1811 to convert into a type that we don't know about or that is inappropriate.
1812 This hook doesn't let you change the behavior of emacs's selection replies,
1813 it merely informs you that they have happened.
1815 Vx_sent_selection_hooks = Qunbound;
1817 DEFVAR_INT ("x-selection-timeout", &x_selection_timeout /*
1818 If the selection owner doesn't reply in this many seconds, we give up.
1819 A value of 0 means wait as long as necessary. This is initialized from the
1820 \"*selectionTimeout\" resource (which is expressed in milliseconds).
1822 x_selection_timeout = 0;
1824 DEFVAR_BOOL ("x-selection-strict-motif-ownership", &x_selection_strict_motif_ownership /*
1825 *If nil and XEmacs already owns the clipboard, don't own it again in the
1826 Motif way. Owning the selection on the Motif way does a huge amount of
1827 X protocol, and it makes killing text incredibly slow when using an
1828 X terminal. However, when enabled Motif text fields don't bother to look up
1829 the new value, and you can't Copy from a buffer, Paste into a text
1830 field, then Copy something else from the buffer and paste it into the
1831 text field; it pastes the first thing again.
1833 x_selection_strict_motif_ownership = 1;
1837 Xatoms_of_select_x (struct device *d)
1839 Display *D = DEVICE_X_DISPLAY (d);
1841 /* Non-predefined atoms that we might end up using a lot */
1842 DEVICE_XATOM_CLIPBOARD (d) = XInternAtom (D, "CLIPBOARD", False);
1843 DEVICE_XATOM_TIMESTAMP (d) = XInternAtom (D, "TIMESTAMP", False);
1844 DEVICE_XATOM_TEXT (d) = XInternAtom (D, "TEXT", False);
1845 DEVICE_XATOM_DELETE (d) = XInternAtom (D, "DELETE", False);
1846 DEVICE_XATOM_MULTIPLE (d) = XInternAtom (D, "MULTIPLE", False);
1847 DEVICE_XATOM_INCR (d) = XInternAtom (D, "INCR", False);
1848 DEVICE_XATOM_TARGETS (d) = XInternAtom (D, "TARGETS", False);
1849 DEVICE_XATOM_NULL (d) = XInternAtom (D, "NULL", False);
1850 DEVICE_XATOM_ATOM_PAIR (d) = XInternAtom (D, "ATOM_PAIR", False);
1851 DEVICE_XATOM_COMPOUND_TEXT (d) = XInternAtom (D, "COMPOUND_TEXT", False);
1853 /* #### I don't like the looks of this... what is it for? - ajh */
1854 DEVICE_XATOM_EMACS_TMP (d) = XInternAtom (D, "_EMACS_TMP_", False);