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