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