Initial revision
[chise/xemacs-chise.git.1] / src / select-gtk.c
1 /* GTK 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 /* Authorship:
24
25    Written by Kevin Gallo for FSF Emacs.
26    Rewritten for mswindows by Jonathan Harris, December 1997 for 21.0.
27    Rewritten for GTK by William Perry, April 2000 for 21.1
28  */
29
30
31 #include <config.h>
32 #include "lisp.h"
33 #include "events.h"
34 #include "buffer.h"
35 #include "device.h"
36 #include "console-gtk.h"
37 #include "select.h"
38 #include "opaque.h"
39 #include "frame.h"
40
41 static Lisp_Object Vretrieved_selection;
42 static gboolean waiting_for_selection;
43 Lisp_Object Vgtk_sent_selection_hooks;
44
45 static Lisp_Object atom_to_symbol (struct device *d, GdkAtom atom);
46 static GdkAtom symbol_to_gtk_atom (struct device *d, Lisp_Object sym, int only_if_exists);
47
48 static void lisp_data_to_selection_data (struct device *,
49                                          Lisp_Object obj,
50                                          unsigned char **data_ret,
51                                          GdkAtom *type_ret,
52                                          unsigned int *size_ret,
53                                          int *format_ret);
54 static Lisp_Object selection_data_to_lisp_data (struct device *,
55                                                 Extbyte *data,
56                                                 size_t size,
57                                                 GdkAtom type,
58                                                 int format);
59
60 /* Set the selection data to GDK_NONE and NULL data, meaning we were
61 ** unable to do what they wanted.
62 */
63 static void
64 gtk_decline_selection_request (GtkSelectionData *data)
65 {
66   gtk_selection_data_set (data, GDK_NONE, 0, NULL, 0);
67 }
68
69 /* Used as an unwind-protect clause so that, if a selection-converter signals
70    an error, we tell the requestor that we were unable to do what they wanted
71    before we throw to top-level or go into the debugger or whatever.
72  */
73 struct _selection_closure
74 {
75   GtkSelectionData *data;
76   gboolean successful;
77 };
78
79 static Lisp_Object
80 gtk_selection_request_lisp_error (Lisp_Object closure)
81 {
82   struct _selection_closure *cl = (struct _selection_closure *)
83     get_opaque_ptr (closure);
84
85   free_opaque_ptr (closure);
86   if (cl->successful == TRUE)
87     return Qnil;
88   gtk_decline_selection_request (cl->data);
89   return Qnil;
90 }
91
92 /* This provides the current selection to a requester.
93 **
94 ** This is connected to the selection_get() signal of the application
95 ** shell in device-gtk.c:gtk_init_device().
96 **
97 ** This is radically different than the old selection code (21.1.x),
98 ** but has been modeled after the X code, and appears to work.
99 **
100 ** WMP Feb 12 2001
101 */
102 void
103 emacs_gtk_selection_handle (GtkWidget *widget,
104                             GtkSelectionData *selection_data,
105                             guint info,
106                             guint time_stamp,
107                             gpointer data)
108 {
109   /* This function can GC */
110   struct gcpro gcpro1, gcpro2;
111   Lisp_Object temp_obj;
112   Lisp_Object selection_symbol;
113   Lisp_Object target_symbol = Qnil;
114   Lisp_Object converted_selection = Qnil;
115   guint32 local_selection_time;
116   Lisp_Object successful_p = Qnil;
117   int count;
118   struct device *d = decode_gtk_device (Qnil);
119   struct _selection_closure *cl = NULL;
120
121   GCPRO2 (converted_selection, target_symbol);
122
123   selection_symbol = atom_to_symbol (d, selection_data->selection);
124   target_symbol = atom_to_symbol (d, selection_data->target);
125
126 #if 0 /* #### MULTIPLE doesn't work yet */
127   if (EQ (target_symbol, QMULTIPLE))
128     target_symbol = fetch_multiple_target (selection_data);
129 #endif
130
131   temp_obj = Fget_selection_timestamp (selection_symbol);
132
133   if (NILP (temp_obj))
134     {
135       /* We don't appear to have the selection. */
136       gtk_decline_selection_request (selection_data);
137
138       goto DONE_LABEL;
139     }
140
141   local_selection_time = * (guint32 *) XOPAQUE_DATA (temp_obj);
142
143   if (time_stamp != GDK_CURRENT_TIME &&
144       local_selection_time > time_stamp)
145     {
146       /* Someone asked for the selection, and we have one, but not the one
147          they're looking for. */
148       gtk_decline_selection_request (selection_data);
149       goto DONE_LABEL;
150     }
151
152   converted_selection = select_convert_out (selection_symbol,
153                                             target_symbol, Qnil);
154
155   /* #### Is this the right thing to do? I'm no X expert. -- ajh */
156   if (NILP (converted_selection))
157     {
158       /* We don't appear to have a selection in that data type. */
159       gtk_decline_selection_request (selection_data);
160       goto DONE_LABEL;
161     }
162
163   count = specpdl_depth ();
164
165   cl = (struct _selection_closure *) xmalloc (sizeof (*cl));
166   cl->data = selection_data;
167   cl->successful = FALSE;
168
169   record_unwind_protect (gtk_selection_request_lisp_error,
170                          make_opaque_ptr (cl));
171
172   {
173     unsigned char *data;
174     unsigned int size;
175     int format;
176     GdkAtom type;
177     lisp_data_to_selection_data (d, converted_selection,
178                                  &data, &type, &size, &format);
179
180     gtk_selection_data_set (selection_data, type, format, data, size);
181     successful_p = Qt;
182     /* Tell x_selection_request_lisp_error() it's cool. */
183     cl->successful = TRUE;
184     xfree (data);
185   }
186
187   unbind_to (count, Qnil);
188
189  DONE_LABEL:
190
191   if (cl) xfree (cl);
192
193   UNGCPRO;
194
195   /* Let random lisp code notice that the selection has been asked for. */
196   {
197     Lisp_Object val = Vgtk_sent_selection_hooks;
198     if (!UNBOUNDP (val) && !NILP (val))
199       {
200         Lisp_Object rest;
201         if (CONSP (val) && !EQ (XCAR (val), Qlambda))
202           for (rest = val; !NILP (rest); rest = Fcdr (rest))
203             call3 (Fcar (rest), selection_symbol, target_symbol, successful_p);
204         else
205           call3 (val, selection_symbol, target_symbol, successful_p);
206       }
207   }
208 }
209
210
211 \f
212 static GtkWidget *reading_selection_reply;
213 static GdkAtom reading_which_selection;
214 static int selection_reply_timed_out;
215
216 /* Gets the current selection owned by another application */
217 void
218 emacs_gtk_selection_received (GtkWidget *widget,
219                               GtkSelectionData *selection_data,
220                               gpointer user_data)
221 {
222   waiting_for_selection = FALSE;
223   Vretrieved_selection = Qnil;
224
225   reading_selection_reply = NULL;
226
227   signal_fake_event ();
228
229   if (selection_data->length < 0)
230     {
231       return;
232     }
233
234   Vretrieved_selection =
235     selection_data_to_lisp_data (NULL,
236                                  selection_data->data,
237                                  selection_data->length,
238                                  selection_data->type,
239                                  selection_data->format);
240 }
241
242 static int
243 selection_reply_done (void *ignore)
244 {
245   return !reading_selection_reply;
246 }
247
248 /* Do protocol to read selection-data from the server.
249    Converts this to lisp data and returns it.
250  */
251 static Lisp_Object
252 gtk_get_foreign_selection (Lisp_Object selection_symbol,
253                            Lisp_Object target_type)
254 {
255   /* This function can GC */
256   struct device *d = decode_gtk_device (Qnil);
257   GtkWidget *requestor = DEVICE_GTK_APP_SHELL (d);
258   guint32 requestor_time = DEVICE_GTK_MOUSE_TIMESTAMP (d);
259   GdkAtom selection_atom = symbol_to_gtk_atom (d, selection_symbol, 0);
260   int speccount;
261   GdkAtom type_atom = symbol_to_gtk_atom (d, (CONSP (target_type) ?
262                                               XCAR (target_type) : target_type), 0);
263
264   gtk_selection_convert (requestor, selection_atom, type_atom,
265                          requestor_time);
266
267   signal_fake_event ();
268
269   /* Block until the reply has been read. */
270   reading_selection_reply = requestor;
271   reading_which_selection = selection_atom;
272   selection_reply_timed_out = 0;
273
274   speccount = specpdl_depth ();
275
276 #if 0
277   /* add a timeout handler */
278   if (gtk_selection_timeout > 0)
279     {
280       Lisp_Object id = Fadd_timeout (make_int (x_selection_timeout),
281                                      Qx_selection_reply_timeout_internal,
282                                      Qnil, Qnil);
283       record_unwind_protect (Fdisable_timeout, id);
284     }
285 #endif
286
287   /* This is ^Gable */
288   wait_delaying_user_input (selection_reply_done, 0);
289
290   if (selection_reply_timed_out)
291     error ("timed out waiting for reply from selection owner");
292
293   unbind_to (speccount, Qnil);
294
295   /* otherwise, the selection is waiting for us on the requested property. */
296   return select_convert_in (selection_symbol,
297                             target_type,
298                             Vretrieved_selection);
299 }
300
301
302 #if 0
303 static void
304 gtk_get_window_property (struct device *d, GtkWidget *window, GdkAtom property,
305                          Extbyte **data_ret, int *bytes_ret,
306                          GdkAtom *actual_type_ret, int *actual_format_ret,
307                          unsigned long *actual_size_ret, int delete_p)
308 {
309   size_t total_size;
310   unsigned long bytes_remaining;
311   int offset = 0;
312   unsigned char *tmp_data = 0;
313   int result;
314   int buffer_size = SELECTION_QUANTUM (display);
315   if (buffer_size > MAX_SELECTION_QUANTUM) buffer_size = MAX_SELECTION_QUANTUM;
316
317   /* First probe the thing to find out how big it is. */
318   result = XGetWindowProperty (display, window, property,
319                                0, 0, False, AnyPropertyType,
320                                actual_type_ret, actual_format_ret,
321                                actual_size_ret,
322                                &bytes_remaining, &tmp_data);
323   if (result != Success)
324     {
325       *data_ret = 0;
326       *bytes_ret = 0;
327       return;
328     }
329   XFree ((char *) tmp_data);
330
331   if (*actual_type_ret == None || *actual_format_ret == 0)
332     {
333       if (delete_p) XDeleteProperty (display, window, property);
334       *data_ret = 0;
335       *bytes_ret = 0;
336       return;
337     }
338
339   total_size = bytes_remaining + 1;
340   *data_ret = (Extbyte *) xmalloc (total_size);
341
342   /* Now read, until we've gotten it all. */
343   while (bytes_remaining)
344     {
345 #if 0
346       int last = bytes_remaining;
347 #endif
348       result =
349         XGetWindowProperty (display, window, property,
350                             offset/4, buffer_size/4,
351                             (delete_p ? True : False),
352                             AnyPropertyType,
353                             actual_type_ret, actual_format_ret,
354                             actual_size_ret, &bytes_remaining, &tmp_data);
355 #if 0
356       stderr_out ("<< read %d\n", last-bytes_remaining);
357 #endif
358       /* If this doesn't return Success at this point, it means that
359          some clod deleted the selection while we were in the midst of
360          reading it.  Deal with that, I guess....
361        */
362       if (result != Success) break;
363       *actual_size_ret *= *actual_format_ret / 8;
364       memcpy ((*data_ret) + offset, tmp_data, *actual_size_ret);
365       offset += *actual_size_ret;
366       XFree ((char *) tmp_data);
367     }
368   *bytes_ret = offset;
369 }
370
371
372 static void
373 receive_incremental_selection (Display *display, Window window, Atom property,
374                                /* this one is for error messages only */
375                                Lisp_Object target_type,
376                                unsigned int min_size_bytes,
377                                Extbyte **data_ret, int *size_bytes_ret,
378                                Atom *type_ret, int *format_ret,
379                                unsigned long *size_ret)
380 {
381   /* This function can GC */
382   int offset = 0;
383   int prop_id;
384   *size_bytes_ret = min_size_bytes;
385   *data_ret = (Extbyte *) xmalloc (*size_bytes_ret);
386 #if 0
387   stderr_out ("\nread INCR %d\n", min_size_bytes);
388 #endif
389   /* At this point, we have read an INCR property, and deleted it (which
390      is how we ack its receipt: the sending window will be selecting
391      PropertyNotify events on our window to notice this).
392
393      Now, we must loop, waiting for the sending window to put a value on
394      that property, then reading the property, then deleting it to ack.
395      We are done when the sender places a property of length 0.
396    */
397   prop_id = expect_property_change (display, window, property,
398                                     PropertyNewValue);
399   while (1)
400     {
401       Extbyte *tmp_data;
402       int tmp_size_bytes;
403       wait_for_property_change (prop_id);
404       /* expect it again immediately, because x_get_window_property may
405          .. no it won't, I don't get it.
406          .. Ok, I get it now, the Xt code that implements INCR is broken.
407        */
408       prop_id = expect_property_change (display, window, property,
409                                         PropertyNewValue);
410       x_get_window_property (display, window, property,
411                              &tmp_data, &tmp_size_bytes,
412                              type_ret, format_ret, size_ret, 1);
413
414       if (tmp_size_bytes == 0) /* we're done */
415         {
416 #if 0
417           stderr_out ("  read INCR done\n");
418 #endif
419           unexpect_property_change (prop_id);
420           if (tmp_data) xfree (tmp_data);
421           break;
422         }
423 #if 0
424       stderr_out ("  read INCR %d\n", tmp_size_bytes);
425 #endif
426       if (*size_bytes_ret < offset + tmp_size_bytes)
427         {
428 #if 0
429           stderr_out ("  read INCR realloc %d -> %d\n",
430                    *size_bytes_ret, offset + tmp_size_bytes);
431 #endif
432           *size_bytes_ret = offset + tmp_size_bytes;
433           *data_ret = (Extbyte *) xrealloc (*data_ret, *size_bytes_ret);
434         }
435       memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes);
436       offset += tmp_size_bytes;
437       xfree (tmp_data);
438     }
439 }
440
441
442 static Lisp_Object
443 gtk_get_window_property_as_lisp_data (struct device *d,
444                                       GtkWidget *window,
445                                       GdkAtom property,
446                                       /* next two for error messages only */
447                                       Lisp_Object target_type,
448                                       GdkAtom selection_atom)
449 {
450   /* This function can GC */
451   Atom actual_type;
452   int actual_format;
453   unsigned long actual_size;
454   Extbyte *data = NULL;
455   int bytes = 0;
456   Lisp_Object val;
457   struct device *d = get_device_from_display (display);
458
459   x_get_window_property (display, window, property, &data, &bytes,
460                          &actual_type, &actual_format, &actual_size, 1);
461   if (! data)
462     {
463       if (XGetSelectionOwner (display, selection_atom))
464         /* there is a selection owner */
465         signal_error
466           (Qselection_conversion_error,
467            Fcons (build_string ("selection owner couldn't convert"),
468                   Fcons (x_atom_to_symbol (d, selection_atom),
469                          actual_type ?
470                          list2 (target_type, x_atom_to_symbol (d, actual_type)) :
471                          list1 (target_type))));
472       else
473         signal_error (Qerror,
474                       list2 (build_string ("no selection"),
475                              x_atom_to_symbol (d, selection_atom)));
476     }
477
478   if (actual_type == DEVICE_XATOM_INCR (d))
479     {
480       /* Ok, that data wasn't *the* data, it was just the beginning. */
481
482       unsigned int min_size_bytes = * ((unsigned int *) data);
483       xfree (data);
484       receive_incremental_selection (display, window, property, target_type,
485                                      min_size_bytes, &data, &bytes,
486                                      &actual_type, &actual_format,
487                                      &actual_size);
488     }
489
490   /* It's been read.  Now convert it to a lisp object in some semi-rational
491      manner. */
492   val = selection_data_to_lisp_data (d, data, bytes,
493                                      actual_type, actual_format);
494
495   xfree (data);
496   return val;
497 }
498 #endif
499
500 \f
501 static GdkAtom
502 symbol_to_gtk_atom (struct device *d, Lisp_Object sym, int only_if_exists)
503 {
504   if (NILP (sym))               return GDK_SELECTION_PRIMARY;
505   if (EQ (sym, Qt))             return GDK_SELECTION_SECONDARY;
506   if (EQ (sym, QPRIMARY))       return GDK_SELECTION_PRIMARY;
507   if (EQ (sym, QSECONDARY))     return GDK_SELECTION_SECONDARY;
508
509   {
510     const char *nameext;
511     LISP_STRING_TO_EXTERNAL (Fsymbol_name (sym), nameext, Qctext);
512     return gdk_atom_intern (nameext, only_if_exists ? TRUE : FALSE);
513   }
514 }
515
516 static Lisp_Object
517 atom_to_symbol (struct device *d, GdkAtom atom)
518 {
519   if (atom == GDK_SELECTION_PRIMARY) return (QPRIMARY);
520   if (atom == GDK_SELECTION_SECONDARY) return (QSECONDARY);
521
522   {
523     char *intstr;
524     char *str = gdk_atom_name (atom);
525
526     if (! str) return Qnil;
527
528     TO_INTERNAL_FORMAT (C_STRING, str,
529                         C_STRING_ALLOCA, intstr,
530                         Qctext);
531     g_free (str);
532     return intern (intstr);
533   }
534 }
535
536 /* #### These are going to move into Lisp code(!) with the aid of
537         some new functions I'm working on - ajh */
538
539 /* These functions convert from the selection data read from the server into
540    something that we can use from elisp, and vice versa.
541
542         Type:   Format: Size:           Elisp Type:
543         -----   ------- -----           -----------
544         *       8       *               String
545         ATOM    32      1               Symbol
546         ATOM    32      > 1             Vector of Symbols
547         *       16      1               Integer
548         *       16      > 1             Vector of Integers
549         *       32      1               if <=16 bits: Integer
550                                         if > 16 bits: Cons of top16, bot16
551         *       32      > 1             Vector of the above
552
553    When converting a Lisp number to C, it is assumed to be of format 16 if
554    it is an integer, and of format 32 if it is a cons of two integers.
555
556    When converting a vector of numbers from Elisp to C, it is assumed to be
557    of format 16 if every element in the vector is an integer, and is assumed
558    to be of format 32 if any element is a cons of two integers.
559
560    When converting an object to C, it may be of the form (SYMBOL . <data>)
561    where SYMBOL is what we should claim that the type is.  Format and
562    representation are as above.
563
564    NOTE: Under Mule, when someone shoves us a string without a type, we
565    set the type to 'COMPOUND_TEXT and automatically convert to Compound
566    Text.  If the string has a type, we assume that the user wants the
567    data sent as-is so we just do "binary" conversion.
568  */
569
570
571 static Lisp_Object
572 selection_data_to_lisp_data (struct device *d,
573                              Extbyte *data,
574                              size_t size,
575                              GdkAtom type,
576                              int format)
577 {
578   if (type == gdk_atom_intern ("NULL", 0))
579     return QNULL;
580
581   /* Convert any 8-bit data to a string, for compactness. */
582   else if (format == 8)
583     return make_ext_string (data, size,
584                             ((type == gdk_atom_intern ("TEXT", FALSE)) ||
585                              (type == gdk_atom_intern ("COMPOUND_TEXT", FALSE)))
586                             ? Qctext : Qbinary);
587
588   /* Convert a single atom to a Lisp Symbol.
589      Convert a set of atoms to a vector of symbols. */
590   else if (type == gdk_atom_intern ("ATOM", FALSE))
591     {
592       if (size == sizeof (GdkAtom))
593         return atom_to_symbol (d, *((GdkAtom *) data));
594       else
595         {
596           int i;
597           int len = size / sizeof (GdkAtom);
598           Lisp_Object v = Fmake_vector (make_int (len), Qzero);
599           for (i = 0; i < len; i++)
600             Faset (v, make_int (i), atom_to_symbol (d, ((GdkAtom *) data) [i]));
601           return v;
602         }
603     }
604
605   /* Convert a single 16 or small 32 bit number to a Lisp Int.
606      If the number is > 16 bits, convert it to a cons of integers,
607      16 bits in each half.
608    */
609   else if (format == 32 && size == sizeof (long))
610     return word_to_lisp (((unsigned long *) data) [0]);
611   else if (format == 16 && size == sizeof (short))
612     return make_int ((int) (((unsigned short *) data) [0]));
613
614   /* Convert any other kind of data to a vector of numbers, represented
615      as above (as an integer, or a cons of two 16 bit integers).
616
617      #### Perhaps we should return the actual type to lisp as well.
618
619         (x-get-selection-internal 'PRIMARY 'LINE_NUMBER)
620         ==> [4 4]
621
622      and perhaps it should be
623
624         (x-get-selection-internal 'PRIMARY 'LINE_NUMBER)
625         ==> (SPAN . [4 4])
626
627      Right now the fact that the return type was SPAN is discarded before
628      lisp code gets to see it.
629    */
630   else if (format == 16)
631     {
632       int i;
633       Lisp_Object v = make_vector (size / 4, Qzero);
634       for (i = 0; i < (int) size / 4; i++)
635         {
636           int j = (int) ((unsigned short *) data) [i];
637           Faset (v, make_int (i), make_int (j));
638         }
639       return v;
640     }
641   else
642     {
643       int i;
644       Lisp_Object v = make_vector (size / 4, Qzero);
645       for (i = 0; i < (int) size / 4; i++)
646         {
647           unsigned long j = ((unsigned long *) data) [i];
648           Faset (v, make_int (i), word_to_lisp (j));
649         }
650       return v;
651     }
652 }
653
654
655 static void
656 lisp_data_to_selection_data (struct device *d,
657                              Lisp_Object obj,
658                              unsigned char **data_ret,
659                              GdkAtom *type_ret,
660                              unsigned int *size_ret,
661                              int *format_ret)
662 {
663   Lisp_Object type = Qnil;
664
665   if (CONSP (obj) && SYMBOLP (XCAR (obj)))
666     {
667       type = XCAR (obj);
668       obj = XCDR (obj);
669       if (CONSP (obj) && NILP (XCDR (obj)))
670         obj = XCAR (obj);
671     }
672
673   if (EQ (obj, QNULL) || (EQ (type, QNULL)))
674     {                           /* This is not the same as declining */
675       *format_ret = 32;
676       *size_ret = 0;
677       *data_ret = 0;
678       type = QNULL;
679     }
680   else if (STRINGP (obj))
681     {
682       const Extbyte *extval;
683       Extcount extvallen;
684
685       TO_EXTERNAL_FORMAT (LISP_STRING, obj,
686                           ALLOCA, (extval, extvallen),
687                           (NILP (type) ? Qctext : Qbinary));
688       *format_ret = 8;
689       *size_ret = extvallen;
690       *data_ret = (unsigned char *) xmalloc (*size_ret);
691       memcpy (*data_ret, extval, *size_ret);
692 #ifdef MULE
693       if (NILP (type)) type = QCOMPOUND_TEXT;
694 #else
695       if (NILP (type)) type = QSTRING;
696 #endif
697     }
698   else if (CHARP (obj))
699     {
700       Bufbyte buf[MAX_EMCHAR_LEN];
701       Bytecount len;
702       const Extbyte *extval;
703       Extcount extvallen;
704
705       *format_ret = 8;
706       len = set_charptr_emchar (buf, XCHAR (obj));
707       TO_EXTERNAL_FORMAT (DATA, (buf, len),
708                           ALLOCA, (extval, extvallen),
709                           Qctext);
710       *size_ret = extvallen;
711       *data_ret = (unsigned char *) xmalloc (*size_ret);
712       memcpy (*data_ret, extval, *size_ret);
713 #ifdef MULE
714       if (NILP (type)) type = QCOMPOUND_TEXT;
715 #else
716       if (NILP (type)) type = QSTRING;
717 #endif
718     }
719   else if (SYMBOLP (obj))
720     {
721       *format_ret = 32;
722       *size_ret = 1;
723       *data_ret = (unsigned char *) xmalloc (sizeof (GdkAtom) + 1);
724       (*data_ret) [sizeof (GdkAtom)] = 0;
725       (*(GdkAtom **) data_ret) [0] = symbol_to_gtk_atom (d, obj, 0);
726       if (NILP (type)) type = QATOM;
727     }
728   else if (INTP (obj) &&
729            XINT (obj) <= 0x7FFF &&
730            XINT (obj) >= -0x8000)
731     {
732       *format_ret = 16;
733       *size_ret = 1;
734       *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
735       (*data_ret) [sizeof (short)] = 0;
736       (*(short **) data_ret) [0] = (short) XINT (obj);
737       if (NILP (type)) type = QINTEGER;
738     }
739   else if (INTP (obj) || CONSP (obj))
740     {
741       *format_ret = 32;
742       *size_ret = 1;
743       *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
744       (*data_ret) [sizeof (long)] = 0;
745       (*(unsigned long **) data_ret) [0] = lisp_to_word (obj);
746       if (NILP (type)) type = QINTEGER;
747     }
748   else if (VECTORP (obj))
749     {
750       /* Lisp Vectors may represent a set of ATOMs;
751          a set of 16 or 32 bit INTEGERs;
752          or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...]
753        */
754       int i;
755
756       if (SYMBOLP (XVECTOR_DATA (obj) [0]))
757         /* This vector is an ATOM set */
758         {
759           if (NILP (type)) type = QATOM;
760           *size_ret = XVECTOR_LENGTH (obj);
761           *format_ret = 32;
762           *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (GdkAtom));
763           for (i = 0; i < (int) (*size_ret); i++)
764             if (SYMBOLP (XVECTOR_DATA (obj) [i]))
765               (*(GdkAtom **) data_ret) [i] =
766                 symbol_to_gtk_atom (d, XVECTOR_DATA (obj) [i], 0);
767             else
768               signal_error (Qerror, /* Qselection_error */
769                             list2 (build_string
770                    ("all elements of the vector must be of the same type"),
771                                    obj));
772         }
773 #if 0 /* #### MULTIPLE doesn't work yet */
774       else if (VECTORP (XVECTOR_DATA (obj) [0]))
775         /* This vector is an ATOM_PAIR set */
776         {
777           if (NILP (type)) type = QATOM_PAIR;
778           *size_ret = XVECTOR_LENGTH (obj);
779           *format_ret = 32;
780           *data_ret = (unsigned char *)
781             xmalloc ((*size_ret) * sizeof (Atom) * 2);
782           for (i = 0; i < *size_ret; i++)
783             if (VECTORP (XVECTOR_DATA (obj) [i]))
784               {
785                 Lisp_Object pair = XVECTOR_DATA (obj) [i];
786                 if (XVECTOR_LENGTH (pair) != 2)
787                   signal_error (Qerror,
788                                 list2 (build_string
789        ("elements of the vector must be vectors of exactly two elements"),
790                                   pair));
791
792                 (*(GdkAtom **) data_ret) [i * 2] =
793                   symbol_to_gtk_atom (d, XVECTOR_DATA (pair) [0], 0);
794                 (*(GdkAtom **) data_ret) [(i * 2) + 1] =
795                   symbol_to_gtk_atom (d, XVECTOR_DATA (pair) [1], 0);
796               }
797             else
798               signal_error (Qerror,
799                             list2 (build_string
800                    ("all elements of the vector must be of the same type"),
801                                    obj));
802         }
803 #endif
804       else
805         /* This vector is an INTEGER set, or something like it */
806         {
807           *size_ret = XVECTOR_LENGTH (obj);
808           if (NILP (type)) type = QINTEGER;
809           *format_ret = 16;
810           for (i = 0; i < (int) (*size_ret); i++)
811             if (CONSP (XVECTOR_DATA (obj) [i]))
812               *format_ret = 32;
813             else if (!INTP (XVECTOR_DATA (obj) [i]))
814               signal_error (Qerror, /* Qselection_error */
815                             list2 (build_string
816         ("all elements of the vector must be integers or conses of integers"),
817                                    obj));
818
819           *data_ret = (unsigned char *) xmalloc (*size_ret * (*format_ret/8));
820           for (i = 0; i < (int) (*size_ret); i++)
821             if (*format_ret == 32)
822               (*((unsigned long **) data_ret)) [i] =
823                 lisp_to_word (XVECTOR_DATA (obj) [i]);
824             else
825               (*((unsigned short **) data_ret)) [i] =
826                 (unsigned short) lisp_to_word (XVECTOR_DATA (obj) [i]);
827         }
828     }
829   else
830     signal_error (Qerror, /* Qselection_error */
831                   list2 (build_string ("unrecognized selection data"),
832                          obj));
833
834   *type_ret = symbol_to_gtk_atom (d, type, 0);
835 }
836
837 \f
838
839 static Lisp_Object
840 gtk_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
841                    Lisp_Object how_to_add, Lisp_Object selection_type)
842 {
843   struct device *d = decode_gtk_device (Qnil);
844   GtkWidget *selecting_window = GTK_WIDGET (DEVICE_GTK_APP_SHELL (d));
845   Lisp_Object selection_time;
846   /* Use the time of the last-read mouse or keyboard event.
847      For selection purposes, we use this as a sleazy way of knowing what the
848      current time is in server-time.  This assumes that the most recently read
849      mouse or keyboard event has something to do with the assertion of the
850      selection, which is probably true.
851      */
852   guint32 thyme = DEVICE_GTK_MOUSE_TIMESTAMP (d);
853   GdkAtom selection_atom;
854
855   CHECK_SYMBOL (selection_name);
856   selection_atom = symbol_to_gtk_atom (d, selection_name, 0);
857
858   gtk_selection_owner_set (selecting_window,
859                            selection_atom,
860                            thyme);
861
862   /* We do NOT use time_to_lisp() here any more, like we used to.
863      That assumed equivalence of time_t and Time, which is not
864      necessarily the case (e.g. under OSF on the Alphas, where
865      Time is a 64-bit quantity and time_t is a 32-bit quantity).
866
867      Opaque pointers are the clean way to go here.
868   */
869   selection_time = make_opaque (&thyme, sizeof (thyme));
870
871   return selection_time;
872 }
873
874 static void
875 gtk_disown_selection (Lisp_Object selection, Lisp_Object timeval)
876 {
877   struct device *d = decode_gtk_device (Qnil);
878   GdkAtom selection_atom;
879   guint32 timestamp;
880
881   CHECK_SYMBOL (selection);
882   selection_atom = symbol_to_gtk_atom (d, selection, 0);
883
884   if (NILP (timeval))
885     timestamp = DEVICE_GTK_MOUSE_TIMESTAMP (d);
886   else
887     {
888       time_t the_time;
889       lisp_to_time (timeval, &the_time);
890       timestamp = (guint32) the_time;
891     }
892
893   gtk_selection_owner_set (NULL, selection_atom, timestamp);
894 }
895
896 static Lisp_Object
897 gtk_selection_exists_p (Lisp_Object selection,
898                         Lisp_Object selection_type)
899 {
900   struct device *d = decode_gtk_device (Qnil);
901   
902   return (gdk_selection_owner_get (symbol_to_gtk_atom (d, selection, 0)) ? Qt : Qnil);
903 }
904
905
906  \f
907 /************************************************************************/
908 /*                            initialization                            */
909 /************************************************************************/
910
911 void
912 syms_of_select_gtk (void)
913 {
914 }
915
916 void
917 console_type_create_select_gtk (void)
918 {
919   CONSOLE_HAS_METHOD (gtk, own_selection);
920   CONSOLE_HAS_METHOD (gtk, disown_selection);
921   CONSOLE_HAS_METHOD (gtk, selection_exists_p);
922   CONSOLE_HAS_METHOD (gtk, get_foreign_selection);
923 }
924
925 void
926 vars_of_select_gtk (void)
927 {
928   staticpro (&Vretrieved_selection);
929   Vretrieved_selection = Qnil;
930
931   DEFVAR_LISP ("gtk-sent-selection-hooks", &Vgtk_sent_selection_hooks /*
932 A function or functions to be called after we have responded to some
933 other client's request for the value of a selection that we own.  The
934 function(s) will be called with four arguments:
935   - the name of the selection (typically PRIMARY, SECONDARY, or CLIPBOARD);
936   - the name of the selection-type which we were requested to convert the
937     selection into before sending (for example, STRING or LENGTH);
938   - and whether we successfully transmitted the selection.
939 We might have failed (and declined the request) for any number of reasons,
940 including being asked for a selection that we no longer own, or being asked
941 to convert into a type that we don't know about or that is inappropriate.
942 This hook doesn't let you change the behavior of emacs's selection replies,
943 it merely informs you that they have happened.
944 */ );
945   Vgtk_sent_selection_hooks = Qunbound;
946 }