GTK eradication -- the build chain.
[sxemacs] / src / ui / Gtk / event-gtk.c
1 /* The event_stream interface for X11 with gtk, and/or tty frames.
2    Copyright (C) 1991-5, 1997 Free Software Foundation, Inc.
3    Copyright (C) 1995 Sun Microsystems, Inc.
4    Copyright (C) 1996 Ben Wing.
5    Copyright (C) 2000 William Perry.
6
7 This file is part of SXEmacs
8
9 SXEmacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 SXEmacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
21
22
23 /* This file is heavily based upon event-Xt.c */
24
25 /* Synched up with: Not in FSF. */
26
27 #include <config.h>
28 #include "lisp.h"
29
30 #include "console-gtk.h"
31
32 #include "mem/blocktype.h"
33 #include "buffer.h"
34 #include "commands.h"
35 #include "ui/console.h"
36 #include "ui/TTY/console-tty.h"
37 #include "events/events.h"
38 #include "ui/frame.h"
39 #include "objects-gtk.h"
40 #include "process.h"
41 #include "ui/redisplay.h"
42 #include "elhash.h"
43
44 #include "gtk-xemacs.h"
45
46 #include "systime.h"
47 #include "sysproc.h"            /* for MAXDESC */
48
49 #ifdef FILE_CODING
50 #include "lstream.h"
51 #include "mule/file-coding.h"
52 #endif
53
54 #include <gdk/gdkkeysyms.h>
55
56 #ifdef HAVE_DRAGNDROP
57 #include "dragdrop.h"
58 #endif
59
60 #ifdef HAVE_MENUBARS
61 # include "ui/menubar.h"
62 #endif
63
64 #if defined (HAVE_OFFIX_DND)
65 #include "X11/offix.h"
66 #endif
67
68 #include "events/events-mod.h"
69
70 #include <gdk/gdkx.h>
71
72 static struct event_stream *gtk_event_stream;
73
74 /* Do we accept events sent by other clients? */
75 int gtk_allow_sendevents;
76
77 static int process_events_occurred;
78 static int tty_events_occurred;
79
80 /* Mask of bits indicating the descriptors that we wait for input on */
81 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
82
83 static Lisp_Object gtk_keysym_to_emacs_keysym();
84 void debug_process_finalization(struct Lisp_Process *p);
85 gboolean emacs_gtk_event_handler(GtkWidget * wid /* unused */ ,
86                                  GdkEvent * event,
87                                  gpointer closure /* unused */ );
88
89 static int last_quit_check_signal_tick_count;
90
91 Lisp_Object Qkey_mapping;
92 Lisp_Object Qsans_modifiers;
93
94 void enqueue_gtk_dispatch_event(Lisp_Object event);
95
96 /*
97  * Identify if the keysym is a modifier.  This implementation mirrors x.org's
98  * IsModifierKey(), but for GDK keysyms.
99  */
100 #ifdef GDK_ISO_Lock
101 #define IS_MODIFIER_KEY(keysym)                                         \
102         ((((keysym) >= GDK_Shift_L) && ((keysym) <= GDK_Hyper_R))       \
103          || (((keysym) >= GDK_ISO_Lock) &&                              \
104              ((keysym) <= GDK_ISO_Last_Group_Lock))                     \
105          || ((keysym) == GDK_Mode_switch)                               \
106          || ((keysym) == GDK_Num_Lock))
107 #else
108 #define IS_MODIFIER_KEY(keysym)                                         \
109         ((((keysym) >= GDK_Shift_L) && ((keysym) <= GDK_Hyper_R))       \
110          || ((keysym) == GDK_Mode_switch)                               \
111          || ((keysym) == GDK_Num_Lock))
112 #endif
113
114 \f
115 /************************************************************************/
116 /*                           magic-event handling                       */
117 /************************************************************************/
118 static void handle_focus_event_1(struct frame *f, int in_p)
119 {
120         /* We don't want to handle the focus change now, because we might
121            be in an accept-process-output, sleep-for, or sit-for.  So
122            we enqueue it.
123
124            Actually, we half handle it: we handle it as far as changing the
125            box cursor for redisplay, but we don't call any hooks or do any
126            select-frame stuff until after the sit-for.
127          */
128
129         if (in_p) {
130                 GTK_WIDGET_SET_FLAGS(FRAME_GTK_TEXT_WIDGET(f), GTK_HAS_FOCUS);
131         } else {
132                 GTK_WIDGET_UNSET_FLAGS(FRAME_GTK_TEXT_WIDGET(f), GTK_HAS_FOCUS);
133         }
134         gtk_widget_grab_focus(FRAME_GTK_TEXT_WIDGET(f));
135         gtk_widget_draw_focus(FRAME_GTK_TEXT_WIDGET(f));
136
137         {
138                 Lisp_Object frm;
139                 Lisp_Object conser;
140                 struct gcpro gcpro1;
141
142                 XSETFRAME(frm, f);
143                 conser = Fcons(frm, Fcons(FRAME_DEVICE(f), in_p ? Qt : Qnil));
144                 GCPRO1(conser);
145
146                 emacs_handle_focus_change_preliminary(conser);
147                 enqueue_magic_eval_event(emacs_handle_focus_change_final,
148                                          conser);
149                 UNGCPRO;
150         }
151 }
152
153 /* both GDK_MAP and GDK_VISIBILITY_NOTIFY can cause this
154    JV is_visible has the same semantics as f->visible*/
155 static void change_frame_visibility(struct frame *f, int is_visible)
156 {
157         Lisp_Object frame;
158
159         XSETFRAME(frame, f);
160
161         if (!FRAME_VISIBLE_P(f) && is_visible) {
162                 FRAME_VISIBLE_P(f) = is_visible;
163                 /* This improves the double flicker when uniconifying a frame
164                    some.  A lot of it is not showing a buffer which has changed
165                    while the frame was iconified.  To fix it further requires
166                    the good 'ol double redisplay structure. */
167                 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
168                 va_run_hook_with_args(Qmap_frame_hook, 1, frame);
169         } else if (FRAME_VISIBLE_P(f) && !is_visible) {
170                 FRAME_VISIBLE_P(f) = 0;
171                 va_run_hook_with_args(Qunmap_frame_hook, 1, frame);
172         } else if (FRAME_VISIBLE_P(f) * is_visible < 0) {
173                 FRAME_VISIBLE_P(f) = -FRAME_VISIBLE_P(f);
174                 if (FRAME_REPAINT_P(f))
175                         MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
176                 va_run_hook_with_args(Qmap_frame_hook, 1, frame);
177         }
178 }
179
180 static void handle_map_event(struct frame *f, GdkEvent * event)
181 {
182         Lisp_Object frame;
183
184         XSETFRAME(frame, f);
185         if (event->any.type == GDK_MAP) {
186                 FRAME_GTK_TOTALLY_VISIBLE_P(f) = 1;
187                 change_frame_visibility(f, 1);
188         } else {
189                 FRAME_GTK_TOTALLY_VISIBLE_P(f) = 0;
190                 change_frame_visibility(f, 0);
191                 /* Calling Fframe_iconified_p is the only way we have to
192                    correctly update FRAME_ICONIFIED_P */
193                 Fframe_iconified_p(frame);
194         }
195 }
196
197 static void handle_client_message(struct frame *f, GdkEvent * event)
198 {
199         Lisp_Object frame;
200
201         XSETFRAME(frame, f);
202
203         /* The event-Xt code used to handle WM_DELETE_WINDOW here, but we
204            handle that directly in frame-gtk.c */
205
206         if (event->client.message_type == gdk_atom_intern("WM_PROTOCOLS", 0) &&
207             (GdkAtom) event->client.data.l[0] ==
208             gdk_atom_intern("WM_TAKE_FOCUS", 0)) {
209                 handle_focus_event_1(f, 1);
210         }
211 }
212
213 static void emacs_gtk_handle_magic_event(struct Lisp_Event *emacs_event)
214 {
215         /* This function can GC */
216         GdkEvent *event = &emacs_event->event.magic.underlying_gdk_event;
217         struct frame *f = XFRAME(EVENT_CHANNEL(emacs_event));
218
219         if (!FRAME_LIVE_P(f))
220                 return;
221
222         switch (event->any.type) {
223         case GDK_CLIENT_EVENT:
224                 handle_client_message(f, event);
225                 break;
226
227         case GDK_FOCUS_CHANGE:
228                 handle_focus_event_1(f, event->focus_change.in);
229                 break;
230
231         case GDK_MAP:
232         case GDK_UNMAP:
233                 handle_map_event(f, event);
234                 break;
235
236         case GDK_ENTER_NOTIFY:
237                 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
238                         Lisp_Object frame;
239
240                         XSETFRAME(frame, f);
241                         /* FRAME_X_MOUSE_P (f) = 1; */
242                         va_run_hook_with_args(Qmouse_enter_frame_hook, 1,
243                                               frame);
244                 }
245                 break;
246
247         case GDK_LEAVE_NOTIFY:
248                 if (event->crossing.detail != GDK_NOTIFY_INFERIOR) {
249                         Lisp_Object frame;
250
251                         XSETFRAME(frame, f);
252                         /* FRAME_X_MOUSE_P (f) = 0; */
253                         va_run_hook_with_args(Qmouse_leave_frame_hook, 1,
254                                               frame);
255                 }
256                 break;
257
258         case GDK_VISIBILITY_NOTIFY:     /* window visiblity has changed */
259                 if (event->visibility.window ==
260                     GET_GTK_WIDGET_WINDOW(FRAME_GTK_SHELL_WIDGET(f))) {
261                         FRAME_GTK_TOTALLY_VISIBLE_P(f) =
262                             (event->visibility.state ==
263                              GDK_VISIBILITY_UNOBSCURED);
264                         /* Note that the fvwm pager only sends VisibilityNotify when
265                            changing pages. Is this all we need to do ? JV */
266                         /* Nope.  We must at least trigger a redisplay here.
267                            Since this case seems similar to MapNotify, I've
268                            factored out some code to change_frame_visibility().
269                            This triggers the necessary redisplay and runs
270                            (un)map-frame-hook.  - dkindred@cs.cmu.edu */
271                         /* Changed it again to support the tristate visibility flag */
272                         change_frame_visibility(f, (event->visibility.state
273                                                     !=
274                                                     GDK_VISIBILITY_FULLY_OBSCURED)
275                                                 ? 1 : -1);
276                 }
277                 break;
278
279         default:
280                 break;
281         }
282 }
283
284 /************************************************************************/
285 /*                 Gtk to Emacs event conversion                        */
286 /************************************************************************/
287
288 static int keysym_obeys_caps_lock_p(guint sym, struct device *d)
289 {
290         struct gtk_device *gd = DEVICE_GTK_DATA(d);
291         /* Eeeeevil hack.  Don't apply Caps_Lock to things that aren't alphabetic
292            characters, where "alphabetic" means something more than simply A-Z.
293            That is, if Caps_Lock is down, typing ESC doesn't produce Shift-ESC.
294            But if shift-lock is down, then it does. */
295         if (gd->lock_interpretation == GDK_Shift_Lock)
296                 return 1;
297
298         return
299             ((sym >= GDK_A) && (sym <= GDK_Z)) ||
300             ((sym >= GDK_a) && (sym <= GDK_z)) ||
301             ((sym >= GDK_Agrave) && (sym <= GDK_Odiaeresis)) ||
302             ((sym >= GDK_agrave) && (sym <= GDK_odiaeresis)) ||
303             ((sym >= GDK_Ooblique) && (sym <= GDK_Thorn)) ||
304             ((sym >= GDK_oslash) && (sym <= GDK_thorn));
305 }
306
307 static void set_last_server_timestamp(struct device *d, GdkEvent * gdk_event)
308 {
309         guint32 t;
310         switch (gdk_event->type) {
311         case GDK_KEY_PRESS:
312         case GDK_KEY_RELEASE:
313                 t = gdk_event->key.time;
314                 break;
315         case GDK_BUTTON_PRESS:
316         case GDK_2BUTTON_PRESS:
317         case GDK_3BUTTON_PRESS:
318         case GDK_BUTTON_RELEASE:
319                 t = gdk_event->button.time;
320                 break;
321         case GDK_ENTER_NOTIFY:
322         case GDK_LEAVE_NOTIFY:
323                 t = gdk_event->crossing.time;
324                 break;
325         case GDK_MOTION_NOTIFY:
326                 t = gdk_event->motion.time;
327                 break;
328         case GDK_PROPERTY_NOTIFY:
329                 t = gdk_event->property.time;
330                 break;
331         case GDK_SELECTION_CLEAR:
332         case GDK_SELECTION_REQUEST:
333         case GDK_SELECTION_NOTIFY:
334                 t = gdk_event->selection.time;
335                 break;
336         default:
337                 return;
338         }
339         DEVICE_GTK_LAST_SERVER_TIMESTAMP(d) = t;
340 }
341
342 static Lisp_Object gtk_keysym_to_emacs_keysym(guint keysym, int simple_p)
343 {
344         char *name;
345         if (keysym >= GDK_exclam && keysym <= GDK_asciitilde)
346                 /* We must assume that the X keysym numbers for the ASCII graphic
347                    characters are the same as their ASCII codes.  */
348                 return make_char(keysym);
349
350         switch (keysym) {
351                 /* These would be handled correctly by the default case, but by
352                    special-casing them here we don't garbage a string or call
353                    intern().  */
354         case GDK_BackSpace:
355                 return QKbackspace;
356         case GDK_Tab:
357                 return QKtab;
358         case GDK_Linefeed:
359                 return QKlinefeed;
360         case GDK_Return:
361                 return QKreturn;
362         case GDK_Escape:
363                 return QKescape;
364         case GDK_space:
365                 return QKspace;
366         case GDK_Delete:
367                 return QKdelete;
368         case 0:
369                 return Qnil;
370         default:
371                 if (simple_p)
372                         return Qnil;
373                 /* !!#### not Mule-ized */
374                 name = gdk_keyval_name(keysym);
375                 if (!name || !name[0])
376                         /* This happens if there is a mismatch between the Xlib of
377                            SXEmacs and the Xlib of the X server...
378
379                            Let's hard-code in some knowledge of common keysyms introduced
380                            in recent X11 releases.  Snarfed from X11/keysymdef.h
381
382                            Probably we should add some stuff here for X11R6. */
383                         switch (keysym) {
384                         case 0xFF95:
385                                 return KEYSYM("kp-home");
386                         case 0xFF96:
387                                 return KEYSYM("kp-left");
388                         case 0xFF97:
389                                 return KEYSYM("kp-up");
390                         case 0xFF98:
391                                 return KEYSYM("kp-right");
392                         case 0xFF99:
393                                 return KEYSYM("kp-down");
394                         case 0xFF9A:
395                                 return KEYSYM("kp-prior");
396                         case 0xFF9B:
397                                 return KEYSYM("kp-next");
398                         case 0xFF9C:
399                                 return KEYSYM("kp-end");
400                         case 0xFF9D:
401                                 return KEYSYM("kp-begin");
402                         case 0xFF9E:
403                                 return KEYSYM("kp-insert");
404                         case 0xFF9F:
405                                 return KEYSYM("kp-delete");
406
407                         case 0x1005FF10:
408                                 return KEYSYM("SunF36");        /* labeled F11 */
409                         case 0x1005FF11:
410                                 return KEYSYM("SunF37");        /* labeled F12 */
411                         default:
412                                 {
413                                         char buf[64];
414                                         int sz = snprintf(buf, sizeof(buf),
415                                                           "unknown-keysym-0x%X",
416                                                           (int)keysym);
417                                         assert(sz >= 0 && sz < sizeof(buf));
418                                         return KEYSYM(buf);
419                                 }
420                         }
421                 /* If it's got a one-character name, that's good enough. */
422                 if (!name[1])
423                         return make_char(name[0]);
424
425                 /* If it's in the "Keyboard" character set, downcase it.
426                    The case of those keysyms is too totally random for us to
427                    force anyone to remember them.
428                    The case of the other character sets is significant, however.
429                  */
430                 if ((((unsigned int)keysym) & (~0x1FF)) ==
431                     ((unsigned int)0xFE00)) {
432                         char buf[255];
433                         char *s1, *s2;
434                         for (s1 = name, s2 = buf; *s1; s1++, s2++) {
435                                 if (*s1 == '_') {
436                                         *s2 = '-';
437                                 } else {
438                                         *s2 = tolower(*(unsigned char *)s1);
439                                 }
440                         }
441                         *s2 = 0;
442                         return KEYSYM(buf);
443                 }
444                 return KEYSYM(name);
445         }
446 }
447
448 static Lisp_Object
449 gtk_to_emacs_keysym(struct device *d, GdkEventKey * event, int simple_p)
450      /* simple_p means don't try too hard (ASCII only) */
451 {
452         if (event->length != 1) {
453 #ifdef FILE_CODING
454                 /* Generate multiple emacs events */
455                 Emchar ch;
456                 Lisp_Object instream, fb_instream;
457                 Lstream *istr;
458                 struct gcpro gcpro1, gcpro2;
459
460                 fb_instream =
461                     make_fixed_buffer_input_stream((unsigned char *)event->
462                                                    string, event->length);
463
464                 /* ### Use Fget_coding_system (Vcomposed_input_coding_system) */
465                 instream =
466                     make_decoding_input_stream(XLSTREAM(fb_instream),
467                                                Fget_coding_system(Qundecided));
468
469                 istr = XLSTREAM(instream);
470
471                 GCPRO2(instream, fb_instream);
472                 while ((ch = Lstream_get_emchar(istr)) != EOF) {
473                         Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
474                         struct Lisp_Event *ev = XEVENT(emacs_event);
475                         ev->channel = DEVICE_CONSOLE(d);
476                         ev->event_type = key_press_event;
477                         ev->timestamp = event->time;
478                         ev->event.key.modifiers = 0;
479                         ev->event.key.keysym = make_char(ch);
480                         enqueue_gtk_dispatch_event(emacs_event);
481                 }
482                 Lstream_close(istr);
483                 UNGCPRO;
484                 Lstream_delete(istr);
485                 Lstream_delete(XLSTREAM(fb_instream));
486 #else
487                 int i;
488                 for (i = 0; i < event->length; i++) {
489                         Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
490                         struct Lisp_Event *ev = XEVENT(emacs_event);
491                         ev->channel = DEVICE_CONSOLE(d);
492                         ev->event_type = key_press_event;
493                         ev->timestamp = event->time;
494                         ev->event.key.modifiers = 0;
495                         ev->event.key.keysym = make_char(event->string[i]);
496                         enqueue_gtk_dispatch_event(emacs_event);
497                 }
498 #endif
499                 if (IS_MODIFIER_KEY(event->keyval)
500                     || (event->keyval == GDK_Mode_switch))
501                         return (Qnil);
502                 return (gtk_keysym_to_emacs_keysym(event->keyval, simple_p));
503         } else {
504                 if (IS_MODIFIER_KEY(event->keyval)
505                     || (event->keyval == GDK_Mode_switch))
506                         return (Qnil);
507                 return (gtk_keysym_to_emacs_keysym(event->keyval, simple_p));
508         }
509 }
510 \f
511 /************************************************************************/
512 /*                              timeout events                          */
513 /************************************************************************/
514
515 static int timeout_id_tick;
516
517 struct GTK_timeout {
518         int id;
519         guint timeout_id;
520         struct GTK_timeout *next;
521 } *pending_timeouts, *completed_timeouts;
522
523 struct GTK_timeout_blocktype {
524         Blocktype_declare(struct GTK_timeout);
525 } *the_GTK_timeout_blocktype;
526
527 /* called by the gtk main loop */
528 static gint gtk_timeout_callback(gpointer closure)
529 {
530         struct GTK_timeout *timeout = (struct GTK_timeout *)closure;
531         struct GTK_timeout *t2 = pending_timeouts;
532
533         /* Remove this one from the list of pending timeouts */
534         if (t2 == timeout)
535                 pending_timeouts = pending_timeouts->next;
536         else {
537                 while (t2->next && t2->next != timeout)
538                         t2 = t2->next;
539                 assert(t2->next);
540                 t2->next = t2->next->next;
541         }
542         /* Add this one to the list of completed timeouts */
543         timeout->next = completed_timeouts;
544         completed_timeouts = timeout;
545         return (FALSE);
546 }
547
548 static int emacs_gtk_add_timeout(EMACS_TIME thyme)
549 {
550         struct GTK_timeout *timeout =
551             Blocktype_alloc(the_GTK_timeout_blocktype);
552         EMACS_TIME current_time;
553         int milliseconds;
554
555         timeout->id = timeout_id_tick++;
556         timeout->next = pending_timeouts;
557         pending_timeouts = timeout;
558         EMACS_GET_TIME(current_time);
559         EMACS_SUB_TIME(thyme, thyme, current_time);
560         milliseconds = EMACS_SECS(thyme) * 1000 + EMACS_USECS(thyme) / 1000;
561         if (milliseconds < 1)
562                 milliseconds = 1;
563         timeout->timeout_id = gtk_timeout_add(milliseconds,
564                                               gtk_timeout_callback,
565                                               (gpointer) timeout);
566         return timeout->id;
567 }
568
569 static void emacs_gtk_remove_timeout(int id)
570 {
571         struct GTK_timeout *timeout, *t2;
572
573         timeout = NULL;
574
575         /* Find the timeout on the list of pending ones, if it's still there. */
576         if (pending_timeouts) {
577                 if (id == pending_timeouts->id) {
578                         timeout = pending_timeouts;
579                         pending_timeouts = pending_timeouts->next;
580                 } else {
581                         t2 = pending_timeouts;
582                         while (t2->next && t2->next->id != id)
583                                 t2 = t2->next;
584                         if (t2->next) { /*found it */
585                                 timeout = t2->next;
586                                 t2->next = t2->next->next;
587                         }
588                 }
589                 /* if it was pending, we have removed it from the list */
590                 if (timeout)
591                         gtk_timeout_remove(timeout->timeout_id);
592         }
593
594         /* It could be that the call back was already called but we didn't convert
595            into an Emacs event yet */
596         if (!timeout && completed_timeouts) {
597                 /* Code duplication! */
598                 if (id == completed_timeouts->id) {
599                         timeout = completed_timeouts;
600                         completed_timeouts = completed_timeouts->next;
601                 } else {
602                         t2 = completed_timeouts;
603                         while (t2->next && t2->next->id != id)
604                                 t2 = t2->next;
605                         if (t2->next) { /*found it */
606                                 timeout = t2->next;
607                                 t2->next = t2->next->next;
608                         }
609                 }
610         }
611
612         /* If we found the thing on the lists of timeouts,
613            and removed it, deallocate
614          */
615         if (timeout)
616                 Blocktype_free(the_GTK_timeout_blocktype, timeout);
617 }
618
619 static void gtk_timeout_to_emacs_event(struct Lisp_Event *emacs_event)
620 {
621         struct GTK_timeout *timeout = completed_timeouts;
622         assert(timeout);
623         completed_timeouts = completed_timeouts->next;
624         emacs_event->event_type = timeout_event;
625         /* timeout events have nil as channel */
626         emacs_event->timestamp = 0;     /* #### wrong!! */
627         emacs_event->event.timeout.interval_id = timeout->id;
628         Blocktype_free(the_GTK_timeout_blocktype, timeout);
629 }
630 \f
631 /************************************************************************/
632 /*                      process and tty events                          */
633 /************************************************************************/
634
635 struct what_is_ready_closure {
636         int fd;
637         Lisp_Object what;
638         gint id;
639 };
640
641 static Lisp_Object *filedesc_with_input;
642 static struct what_is_ready_closure **filedesc_to_what_closure;
643
644 static void init_what_input_once(void)
645 {
646         int i;
647
648         filedesc_with_input = xnew_array(Lisp_Object, MAXDESC);
649         filedesc_to_what_closure =
650             xnew_array(struct what_is_ready_closure *, MAXDESC);
651
652         for (i = 0; i < MAXDESC; i++) {
653                 filedesc_to_what_closure[i] = 0;
654                 filedesc_with_input[i] = Qnil;
655         }
656
657         process_events_occurred = 0;
658         tty_events_occurred = 0;
659 }
660
661 static void mark_what_as_being_ready(struct what_is_ready_closure *closure)
662 {
663         if (NILP(filedesc_with_input[closure->fd])) {
664                 SELECT_TYPE temp_mask;
665                 FD_ZERO(&temp_mask);
666                 FD_SET(closure->fd, &temp_mask);
667                 /* Check to make sure there's *really* input available.
668                    Sometimes things seem to get confused and this gets called
669                    for the tty fd when there's really only input available
670                    on some process's fd.  (It will subsequently get called
671                    for that process's fd, so returning without setting any
672                    flags will take care of it.)  To see the problem, uncomment
673                    the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS
674                    down to 25, do sh -c 'sxemacs -nw -q -f shell 2>/tmp/log'
675                    and press return repeatedly.  (Seen under AIX & Linux.)
676                    -dkindred@cs.cmu.edu */
677                 if (!poll_fds_for_input(temp_mask)) {
678 #if 0
679                         stderr_out
680                             ("mark_what_as_being_ready: no input available (fd=%d)\n",
681                              closure->fd);
682 #endif
683                         return;
684                 }
685                 filedesc_with_input[closure->fd] = closure->what;
686                 if (PROCESSP(closure->what)) {
687                         /* Don't increment this if the current process is already marked
688                          *  as having input. */
689                         process_events_occurred++;
690                 } else {
691                         tty_events_occurred++;
692                 }
693         }
694 }
695
696 static void
697 gtk_what_callback(gpointer closure, gint source, GdkInputCondition why)
698 {
699         /* If closure is 0, then we got a fake event from a signal handler.
700            The only purpose of this is to make XtAppProcessEvent() stop
701            blocking. */
702         if (closure)
703                 mark_what_as_being_ready((struct what_is_ready_closure *)
704                                          closure);
705         else {
706                 fake_event_occurred++;
707                 drain_signal_event_pipe();
708         }
709 }
710
711 static void select_filedesc(int fd, Lisp_Object what)
712 {
713         struct what_is_ready_closure *closure;
714
715         /* If somebody is trying to select something that's already selected
716            for, then something went wrong.  The generic routines ought to
717            detect this and error before here. */
718         assert(!filedesc_to_what_closure[fd]);
719
720         closure = xnew(struct what_is_ready_closure);
721         closure->fd = fd;
722         closure->what = what;
723         closure->id = gdk_input_add(fd, GDK_INPUT_READ,
724                                     (GdkInputFunction) gtk_what_callback,
725                                     closure);
726         filedesc_to_what_closure[fd] = closure;
727 }
728
729 static void unselect_filedesc(int fd)
730 {
731         struct what_is_ready_closure *closure = filedesc_to_what_closure[fd];
732
733         assert(closure);
734         if (!NILP(filedesc_with_input[fd])) {
735                 /* We are unselecting this process before we have drained the rest of
736                    the input from it, probably from status_notify() in the command loop.
737                    This can happen like so:
738
739                    - We are waiting in XtAppNextEvent()
740                    - Process generates output
741                    - Process is marked as being ready
742                    - Process dies, SIGCHLD gets generated before we return (!?)
743                    It could happen I guess.
744                    - sigchld_handler() marks process as dead
745                    - Somehow we end up getting a new KeyPress event on the queue
746                    at the same time (I'm really so sure how that happens but I'm
747                    not sure it can't either so let's assume it can...).
748                    - Key events have priority so we return that instead of the proc.
749                    - Before dispatching the lisp key event we call status_notify()
750                    - Which deselects the process that SIGCHLD marked as dead.
751
752                    Thus we never remove it from _with_input and turn it into a lisp
753                    event, so we need to do it here.  But this does not mean that we're
754                    throwing away the last block of output - status_notify() has already
755                    taken care of running the proc filter or whatever.
756                  */
757                 filedesc_with_input[fd] = Qnil;
758                 if (PROCESSP(closure->what)) {
759                         assert(process_events_occurred > 0);
760                         process_events_occurred--;
761                 } else {
762                         assert(tty_events_occurred > 0);
763                         tty_events_occurred--;
764                 }
765         }
766         gdk_input_remove(closure->id);
767         xfree(closure);
768         filedesc_to_what_closure[fd] = 0;
769 }
770
771 static void emacs_gtk_select_process(struct Lisp_Process *p)
772 {
773         Lisp_Object process;
774         int infd = event_stream_unixoid_select_process(p);
775
776         XSETPROCESS(process, p);
777         select_filedesc(infd, process);
778 }
779
780 static void emacs_gtk_unselect_process(struct Lisp_Process *p)
781 {
782         int infd = event_stream_unixoid_unselect_process(p);
783
784         unselect_filedesc(infd);
785 }
786
787 static USID
788 emacs_gtk_create_stream_pair(void *inhandle, void *outhandle,
789                              Lisp_Object * instream, Lisp_Object * outstream,
790                              int flags)
791 {
792         USID u = event_stream_unixoid_create_stream_pair
793             (inhandle, outhandle, instream, outstream, flags);
794         if (u != USID_ERROR)
795                 u = USID_DONTHASH;
796         return u;
797 }
798
799 static USID
800 emacs_gtk_delete_stream_pair(Lisp_Object instream, Lisp_Object outstream)
801 {
802         event_stream_unixoid_delete_stream_pair(instream, outstream);
803         return USID_DONTHASH;
804 }
805
806 /* This is called from GC when a process object is about to be freed.
807    If we've still got pointers to it in this file, we're gonna lose hard.
808  */
809 void debug_process_finalization(struct Lisp_Process *p)
810 {
811 #if 0                           /* #### */
812         int i;
813         Lisp_Object instr, outstr;
814
815         get_process_streams(p, &instr, &outstr);
816         /* if it still has fds, then it hasn't been killed yet. */
817         assert(NILP(instr));
818         assert(NILP(outstr));
819         /* Better not still be in the "with input" table; we know it's got no fds. */
820         for (i = 0; i < MAXDESC; i++) {
821                 Lisp_Object process = filedesc_fds_with_input[i];
822                 assert(!PROCESSP(process) || XPROCESS(process) != p);
823         }
824 #endif
825 }
826
827 static void gtk_process_to_emacs_event(struct Lisp_Event *emacs_event)
828 {
829         int i;
830         Lisp_Object process;
831
832         assert(process_events_occurred > 0);
833         for (i = 0; i < MAXDESC; i++) {
834                 process = filedesc_with_input[i];
835                 if (PROCESSP(process))
836                         break;
837         }
838         assert(i < MAXDESC);
839         filedesc_with_input[i] = Qnil;
840         process_events_occurred--;
841         /* process events have nil as channel */
842         emacs_event->event_type = process_event;
843         emacs_event->timestamp = 0;     /* #### */
844         emacs_event->event.process.process = process;
845 }
846
847 static void emacs_gtk_select_console(struct console *con)
848 {
849         Lisp_Object console;
850         int infd;
851
852         if (CONSOLE_GTK_P(con))
853                 return;         /* Gtk consoles are automatically selected for when we initialize them */
854         infd = event_stream_unixoid_select_console(con);
855         XSETCONSOLE(console, con);
856         select_filedesc(infd, console);
857 }
858
859 static void emacs_gtk_unselect_console(struct console *con)
860 {
861         Lisp_Object console;
862         int infd;
863
864         if (CONSOLE_GTK_P(con))
865                 return;         /* X consoles are automatically selected for when we initialize them */
866         infd = event_stream_unixoid_unselect_console(con);
867         XSETCONSOLE(console, con);
868         unselect_filedesc(infd);
869 }
870
871 /* read an event from a tty, if one is available.  Returns non-zero
872    if an event was available.  Note that when this function is
873    called, there should always be a tty marked as ready for input.
874    However, the input condition might actually be EOF, so there
875    may not really be any input available. (In this case,
876    read_event_from_tty_or_stream_desc() will arrange for the TTY device
877    to be deleted.) */
878
879 static int gtk_tty_to_emacs_event(struct Lisp_Event *emacs_event)
880 {
881         int i;
882
883         assert(tty_events_occurred > 0);
884         for (i = 0; i < MAXDESC; i++) {
885                 Lisp_Object console = filedesc_with_input[i];
886                 if (CONSOLEP(console)) {
887                         assert(tty_events_occurred > 0);
888                         tty_events_occurred--;
889                         filedesc_with_input[i] = Qnil;
890                         if (read_event_from_tty_or_stream_desc
891                             (emacs_event, XCONSOLE(console), i))
892                                 return 1;
893                 }
894         }
895
896         return 0;
897 }
898 \f
899 /************************************************************************/
900 /*                      Drag 'n Drop handling                           */
901 /************************************************************************/
902 #ifdef HAVE_DRAGNDROP
903 #define TARGET_URI_LIST   0x00
904 #define TARGET_TEXT_PLAIN 0x01
905 #define TARGET_FILE_NAME  0x02
906 #define TARGET_NETSCAPE   0x03
907
908 static GdkAtom preferred_targets[10];
909
910 void
911 dragndrop_data_received(GtkWidget * widget,
912                         GdkDragContext * context,
913                         gint x,
914                         gint y, GtkSelectionData * data, guint info, guint time)
915 {
916         Lisp_Object event = Fmake_event(Qnil, Qnil);
917         struct device *d = gtk_any_window_to_device(widget->window);
918         struct frame *f = gtk_any_widget_or_parent_to_frame(d, widget);
919         struct Lisp_Event *ev = XEVENT(event);
920         Lisp_Object l_type = Qnil, l_data = Qnil;
921         Lisp_Object l_dndlist = Qnil, l_item = Qnil;
922         struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
923
924         GCPRO4(l_type, l_data, l_dndlist, l_item);
925
926         ev->event_type = misc_user_event;
927         ev->timestamp = time;
928
929         XSETFRAME(ev->channel, f);
930
931         ev->event.misc.x = x;
932         ev->event.misc.y = y;
933
934         if (data->type == preferred_targets[TARGET_URI_LIST]) {
935                 /* newline-separated list of URLs */
936                 int start, end;
937                 const char *string_data = (char *)data->data;
938
939                 l_type = Qdragdrop_URL;
940
941                 for (start = 0, end = 0; string_data && string_data[end]; end++) {
942                         if ((string_data[end] == '\r')
943                             && (string_data[end + 1] == '\n')) {
944                                 l_item =
945                                     make_string(&string_data[start],
946                                                 end - start);
947                                 l_dndlist = Fcons(l_item, l_dndlist);
948                                 ++end;
949                                 start = ++end;
950                         }
951                 }
952         } else if (data->type == preferred_targets[TARGET_TEXT_PLAIN]) {
953                 /* Arbitrary string */
954                 l_type = Qdragdrop_MIME;
955                 l_dndlist = list1(list3(list1(build_string("text/plain")),
956                                         build_string("8_bit"),
957                                         make_ext_string(data->data,
958                                                         strlen((char *)data->
959                                                                data), Qctext)));
960         } else if (data->type == preferred_targets[TARGET_FILE_NAME]) {
961                 /* Random filename */
962                 char *hurl = dnd_url_hexify_string(data->data, "file:");
963
964                 l_dndlist = list1(make_string((Bufbyte *) hurl, strlen(hurl)));
965                 l_type = Qdragdrop_URL;
966
967                 xfree(hurl);
968         } else if (data->type == preferred_targets[TARGET_NETSCAPE]) {
969                 /* Single URL */
970                 l_dndlist = list1(make_string((Extbyte *) data->data,
971                                               strlen((char *)data->data)));
972                 l_type = Qdragdrop_URL;
973         } else {
974                 /* Unknown type - what to do?
975                    We just pass it up to lisp - we already have a mime type.
976                  */
977                 l_type = Qdragdrop_MIME;
978                 l_dndlist =
979                     list1(list3
980                           (list1(build_string(gdk_atom_name(data->type))),
981                            build_string("8bit"),
982                            make_ext_string((Extbyte *) data->data, data->length,
983                                            Qbinary)));
984         }
985
986         ev->event.misc.function = Qdragdrop_drop_dispatch;
987         ev->event.misc.object = Fcons(l_type, l_dndlist);
988
989         UNGCPRO;
990
991         gtk_drag_finish(context, TRUE, FALSE, time);
992         enqueue_gtk_dispatch_event(event);
993 }
994
995 gboolean
996 dragndrop_dropped(GtkWidget * widget,
997                   GdkDragContext * drag_context,
998                   gint x, gint y, guint time, gpointer user_data)
999 {
1000         /* Netscape drops things like:
1001            STRING
1002            _SGI_ICON
1003            _SGI_ICON_TYPE
1004            SGI_FILE
1005            FILE_NAME
1006            _NETSCAPE_URL
1007
1008            gmc drops things like
1009            application/x-mc-desktop-icon
1010            text/uri-list
1011            text/plain
1012            _NETSCAPE_URL
1013
1014            We prefer:
1015            text/uri-list
1016            text/plain
1017            FILE_NAME
1018            _NETSCAPE_URL
1019            first one
1020          */
1021         GdkAtom found = 0;
1022         GList *list = drag_context->targets;
1023
1024         int i;
1025
1026         if (!preferred_targets[0]) {
1027                 preferred_targets[TARGET_URI_LIST] =
1028                     gdk_atom_intern("text/uri-list", FALSE);
1029                 preferred_targets[TARGET_TEXT_PLAIN] =
1030                     gdk_atom_intern("text/plain", FALSE);
1031                 preferred_targets[TARGET_FILE_NAME] =
1032                     gdk_atom_intern("FILE_NAME", FALSE);
1033                 preferred_targets[TARGET_NETSCAPE] =
1034                     gdk_atom_intern("_NETSCAPE_URL", FALSE);
1035         }
1036 #if 0
1037         stderr_out("Drop info available in the following formats: \n");
1038         while (list) {
1039                 stderr_out("\t%s\n", gdk_atom_name((GdkAtom) list->data));
1040                 list = list->next;
1041         }
1042         list = drag_context->targets;
1043 #endif
1044
1045         while (list && !found) {
1046                 for (i = 0; preferred_targets[i] && !found; i++) {
1047                         if ((GdkAtom) list->data == preferred_targets[i]) {
1048                                 found = (GdkAtom) list->data;
1049                         }
1050                 }
1051                 list = list->next;
1052         }
1053
1054         if (!found) {
1055                 found = (GdkAtom) drag_context->targets->data;
1056         }
1057
1058         gtk_drag_get_data(GTK_WIDGET(user_data), drag_context, found, time);
1059         return (TRUE);
1060 }
1061 #endif                          /* HAVE_DRAGNDROP */
1062 \f
1063 /************************************************************************/
1064 /*                      get the next event from gtk                     */
1065 /************************************************************************/
1066
1067 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
1068
1069 void enqueue_gtk_dispatch_event(Lisp_Object event)
1070 {
1071         enqueue_event(event, &dispatch_event_queue, &dispatch_event_queue_tail);
1072 }
1073
1074 static Lisp_Object dequeue_gtk_dispatch_event(void)
1075 {
1076         return dequeue_event(&dispatch_event_queue, &dispatch_event_queue_tail);
1077 }
1078
1079 /* This business exists because menu events "happen" when
1080    menubar_selection_callback() is called from somewhere deep
1081    within XtAppProcessEvent in emacs_Xt_next_event().  The
1082    callback needs to terminate the modal loop in that function
1083    or else it will continue waiting until another event is
1084    received.
1085
1086    Same business applies to scrollbar events. */
1087
1088 void
1089 signal_special_gtk_user_event(Lisp_Object channel, Lisp_Object function,
1090                               Lisp_Object object)
1091 {
1092         Lisp_Object event = Fmake_event(Qnil, Qnil);
1093
1094         XEVENT(event)->event_type = misc_user_event;
1095         XEVENT(event)->channel = channel;
1096         XEVENT(event)->event.eval.function = function;
1097         XEVENT(event)->event.eval.object = object;
1098
1099         enqueue_gtk_dispatch_event(event);
1100 }
1101
1102 static void emacs_gtk_next_event(struct Lisp_Event *emacs_event)
1103 {
1104       we_didnt_get_an_event:
1105
1106         while (NILP(dispatch_event_queue) &&
1107                !completed_timeouts &&
1108                !fake_event_occurred &&
1109                !process_events_occurred && !tty_events_occurred) {
1110                 gtk_main_iteration();
1111         }
1112
1113         if (!NILP(dispatch_event_queue)) {
1114                 Lisp_Object event, event2;
1115                 XSETEVENT(event2, emacs_event);
1116                 event = dequeue_gtk_dispatch_event();
1117                 Fcopy_event(event, event2);
1118                 Fdeallocate_event(event);
1119         } else if (tty_events_occurred) {
1120                 if (!gtk_tty_to_emacs_event(emacs_event))
1121                         goto we_didnt_get_an_event;
1122         } else if (completed_timeouts)
1123                 gtk_timeout_to_emacs_event(emacs_event);
1124         else if (fake_event_occurred) {
1125                 /* A dummy event, so that a cycle of the command loop will occur. */
1126                 fake_event_occurred = 0;
1127                 /* eval events have nil as channel */
1128                 emacs_event->event_type = eval_event;
1129                 emacs_event->event.eval.function = Qidentity;
1130                 emacs_event->event.eval.object = Qnil;
1131         } else                  /* if (process_events_occurred) */
1132                 gtk_process_to_emacs_event(emacs_event);
1133 }
1134
1135 int
1136 gtk_event_to_emacs_event(struct frame *frame, GdkEvent * gdk_event,
1137                          struct Lisp_Event *emacs_event)
1138 {
1139         struct device *d = NULL;
1140         struct gtk_device *gd = NULL;
1141         gboolean accept_any_window = FALSE;
1142
1143         if (!frame) {
1144                 frame = XFRAME(Fselected_frame(Vdefault_gtk_device));
1145                 accept_any_window = TRUE;
1146         }
1147
1148         d = XDEVICE(FRAME_DEVICE(frame));
1149         gd = DEVICE_GTK_DATA(d);
1150
1151         set_last_server_timestamp(d, gdk_event);
1152
1153         switch (gdk_event->type) {
1154                 /* SXEmacs handles double and triple clicking on its own, and if
1155                    we capture these events, it royally confuses the code in
1156                    ../lisp/mouse.el */
1157         case GDK_2BUTTON_PRESS:
1158         case GDK_3BUTTON_PRESS:
1159                 return (0);
1160
1161         case GDK_BUTTON_PRESS:
1162         case GDK_BUTTON_RELEASE:
1163                 /* We need to ignore button events outside our main window or
1164                    things get ugly.  The standard scrollbars in Gtk try to be
1165                    nice and pass the button press events up to the parent
1166                    widget.  This causes us no end of grief though.  Effects
1167                    range from setting point to the wrong place to selecting
1168                    new windows. */
1169                 {
1170                         GdkWindow *w = gdk_window_at_pointer(NULL, NULL);
1171
1172                         /* If you press mouse button and drag it around, and release
1173                            it outside the window, you will get a NULL GdkWindow at
1174                            pointer.  We need to forward these events on to SXEmacs so
1175                            that the mouse selection voodoo works.
1176                          */
1177                         if (w && (w != gdk_window_lookup(GDK_ROOT_WINDOW()))) {
1178                                 GdkEvent ev;
1179                                 GtkWidget *wid = NULL;
1180
1181                                 ev.any.window = w;
1182                                 wid = gtk_get_event_widget(&ev);
1183
1184                                 if (!GTK_IS_XEMACS(wid) && !accept_any_window) {
1185                                         return (0);
1186                                 }
1187                         }
1188                         if (!accept_any_window)
1189                                 gtk_widget_grab_focus(FRAME_GTK_TEXT_WIDGET
1190                                                       (frame));
1191                 }
1192                 /* Fall through */
1193         case GDK_KEY_PRESS:
1194                 {
1195                         unsigned int modifiers = 0;
1196                         int shift_p, lock_p;
1197                         gboolean key_event_p =
1198                             (gdk_event->type == GDK_KEY_PRESS);
1199                         unsigned int *state =
1200                             key_event_p ? &gdk_event->key.state : &gdk_event->
1201                             button.state;
1202
1203                         /* If this is a synthetic KeyPress or Button event, and the user
1204                            has expressed a disinterest in this security hole, then drop
1205                            it on the floor. */
1206                         /* #### BILL!!! Should this be a generic check for ANY synthetic
1207                            event? */
1208                         if ((gdk_event->any.send_event)
1209                             && !gtk_allow_sendevents)
1210                                 return 0;
1211
1212                         DEVICE_GTK_MOUSE_TIMESTAMP(d) =
1213                             DEVICE_GTK_GLOBAL_MOUSE_TIMESTAMP(d) =
1214                             key_event_p ? gdk_event->key.time : gdk_event->
1215                             button.time;
1216
1217                         if (*state & GDK_CONTROL_MASK)
1218                                 modifiers |= XEMACS_MOD_CONTROL;
1219                         if (*state & gd->MetaMask)
1220                                 modifiers |= XEMACS_MOD_META;
1221                         if (*state & gd->SuperMask)
1222                                 modifiers |= XEMACS_MOD_SUPER;
1223                         if (*state & gd->HyperMask)
1224                                 modifiers |= XEMACS_MOD_HYPER;
1225                         if (*state & gd->AltMask)
1226                                 modifiers |= XEMACS_MOD_ALT;
1227
1228                         {
1229                                 int numero_de_botao = -1;
1230
1231                                 if (!key_event_p)
1232                                         numero_de_botao =
1233                                             gdk_event->button.button;
1234
1235                                 /* the button gets noted either in the button or the modifiers
1236                                    field, but not both. */
1237                                 if (numero_de_botao != 1
1238                                     && (*state & GDK_BUTTON1_MASK))
1239                                         modifiers |= XEMACS_MOD_BUTTON1;
1240                                 if (numero_de_botao != 2
1241                                     && (*state & GDK_BUTTON2_MASK))
1242                                         modifiers |= XEMACS_MOD_BUTTON2;
1243                                 if (numero_de_botao != 3
1244                                     && (*state & GDK_BUTTON3_MASK))
1245                                         modifiers |= XEMACS_MOD_BUTTON3;
1246                                 if (numero_de_botao != 4
1247                                     && (*state & GDK_BUTTON4_MASK))
1248                                         modifiers |= XEMACS_MOD_BUTTON4;
1249                                 if (numero_de_botao != 5
1250                                     && (*state & GDK_BUTTON5_MASK))
1251                                         modifiers |= XEMACS_MOD_BUTTON5;
1252                         }
1253
1254                         /* Ignore the Caps_Lock key if:
1255                            - any other modifiers are down, so that Caps_Lock doesn't
1256                            turn C-x into C-X, which would suck.
1257                            - the event was a mouse event. */
1258                         if (modifiers || !key_event_p)
1259                                 *state &= (~GDK_LOCK_MASK);
1260
1261                         shift_p = *state & GDK_SHIFT_MASK;
1262                         lock_p = *state & GDK_LOCK_MASK;
1263
1264                         if (shift_p || lock_p)
1265                                 modifiers |= XEMACS_MOD_SHIFT;
1266
1267                         if (key_event_p) {
1268                                 GdkEventKey *key_event = &gdk_event->key;
1269                                 Lisp_Object keysym;
1270
1271 #ifdef HAVE_MENUBARS
1272                                 /* If the user wants see if the event is a menu bar accelerator.
1273                                    The process of checking absorbs the event and starts menu
1274                                    processing so send a null event into XEmacs to make sure it
1275                                    does nothing.
1276                                  */
1277                                 if (!NILP(Vmenu_accelerator_enabled)
1278                                     &&
1279                                     gtk_accel_groups_activate(GTK_OBJECT
1280                                                               (FRAME_GTK_SHELL_WIDGET
1281                                                                (frame)),
1282                                                               key_event->keyval,
1283                                                               *state)) {
1284                                         zero_event(emacs_event);
1285                                         return 1;
1286                                 }
1287 #endif
1288
1289                                 /* This used to compute the frame from the given X window and
1290                                    store it here, but we really don't care about the frame. */
1291                                 emacs_event->channel = DEVICE_CONSOLE(d);
1292
1293                                 /* Keysym mucking has already been done inside the
1294                                    GdkEventKey parsing */
1295                                 keysym = gtk_to_emacs_keysym(d, key_event, 0);
1296
1297                                 /* If the emacs keysym is nil, then that means that the X
1298                                    keysym was either a Modifier or NoSymbol, which
1299                                    probably means that we're in the midst of reading a
1300                                    Multi_key sequence, or a "dead" key prefix, or XIM
1301                                    input. Ignore it. */
1302                                 if (NILP(keysym))
1303                                         return 0;
1304
1305                                 /* More Caps_Lock garbage: Caps_Lock should *only* add the
1306                                    shift modifier to two-case keys (that is, A-Z and
1307                                    related characters). So at this point (after looking up
1308                                    the keysym) if the keysym isn't a dual-case alphabetic,
1309                                    and if the caps lock key was down but the shift key
1310                                    wasn't, then turn off the shift modifier.  Gag barf */
1311                                 /* #### type lossage: assuming equivalence of emacs and
1312                                    X keysyms */
1313                                 /* !!#### maybe fix for Mule */
1314                                 if (lock_p && !shift_p &&
1315                                     !(CHAR_OR_CHAR_INTP(keysym)
1316                                       && keysym_obeys_caps_lock_p
1317                                       ((guint) XCHAR_OR_CHAR_INT(keysym), d)))
1318                                         modifiers &= (~XEMACS_MOD_SHIFT);
1319
1320                                 /* If this key contains two distinct keysyms, that is,
1321                                    "shift" generates a different keysym than the
1322                                    non-shifted key, then don't apply the shift modifier
1323                                    bit: it's implicit.  Otherwise, if there would be no
1324                                    other way to tell the difference between the shifted
1325                                    and unshifted version of this key, apply the shift bit.
1326                                    Non-graphics, like Backspace and F1 get the shift bit
1327                                    in the modifiers slot.  Neither the characters "a",
1328                                    "A", "2", nor "@" normally have the shift bit set.
1329                                    However, "F1" normally does. */
1330                                 if (modifiers & XEMACS_MOD_SHIFT) {
1331                                         if (CHAR_OR_CHAR_INTP(keysym)) {
1332                                                 modifiers &= ~XEMACS_MOD_SHIFT;
1333                                         }
1334                                 }
1335
1336                                 emacs_event->event_type = key_press_event;
1337                                 emacs_event->timestamp = key_event->time;
1338                                 emacs_event->event.key.modifiers = modifiers;
1339                                 emacs_event->event.key.keysym = keysym;
1340                         } else {        /* Mouse press/release event */
1341
1342                                 GdkEventButton *button_event =
1343                                     &gdk_event->button;
1344                                 XSETFRAME(emacs_event->channel, frame);
1345
1346                                 emacs_event->event_type =
1347                                     (button_event->type ==
1348                                      GDK_BUTTON_RELEASE) ? button_release_event
1349                                     : button_press_event;
1350
1351                                 emacs_event->event.button.modifiers = modifiers;
1352                                 emacs_event->timestamp = button_event->time;
1353                                 emacs_event->event.button.button =
1354                                     button_event->button;
1355                                 emacs_event->event.button.x = button_event->x;
1356                                 emacs_event->event.button.y = button_event->y;
1357                         }
1358                 }
1359                 break;
1360         case GDK_KEY_RELEASE:
1361                 return 0;
1362                 break;
1363         case GDK_MOTION_NOTIFY:
1364                 {
1365                         GdkEventMotion *ev = &gdk_event->motion;
1366                         unsigned int modifiers = 0;
1367                         gint x, y;
1368                         GdkModifierType mask;
1369
1370                         /* We use MOTION_HINT_MASK, so we will get only one motion
1371                            event until the next time we call gdk_window_get_pointer or
1372                            the user clicks the mouse.  So call gdk_window_get_pointer
1373                            now (meaning that the event will be in sync with the server
1374                            just before Fnext_event() returns).  If the mouse is still
1375                            in motion, then the server will immediately generate
1376                            exactly one more motion event, which will be on the queue
1377                            waiting for us next time around. */
1378                         gdk_window_get_pointer(ev->window, &x, &y, &mask);
1379
1380                         DEVICE_GTK_MOUSE_TIMESTAMP(d) = ev->time;
1381
1382                         XSETFRAME(emacs_event->channel, frame);
1383                         emacs_event->event_type = pointer_motion_event;
1384                         emacs_event->timestamp = ev->time;
1385                         emacs_event->event.motion.x = x;
1386                         emacs_event->event.motion.y = y;
1387                         if (mask & GDK_SHIFT_MASK)
1388                                 modifiers |= XEMACS_MOD_SHIFT;
1389                         if (mask & GDK_CONTROL_MASK)
1390                                 modifiers |= XEMACS_MOD_CONTROL;
1391                         if (mask & gd->MetaMask)
1392                                 modifiers |= XEMACS_MOD_META;
1393                         if (mask & gd->SuperMask)
1394                                 modifiers |= XEMACS_MOD_SUPER;
1395                         if (mask & gd->HyperMask)
1396                                 modifiers |= XEMACS_MOD_HYPER;
1397                         if (mask & gd->AltMask)
1398                                 modifiers |= XEMACS_MOD_ALT;
1399                         if (mask & GDK_BUTTON1_MASK)
1400                                 modifiers |= XEMACS_MOD_BUTTON1;
1401                         if (mask & GDK_BUTTON2_MASK)
1402                                 modifiers |= XEMACS_MOD_BUTTON2;
1403                         if (mask & GDK_BUTTON3_MASK)
1404                                 modifiers |= XEMACS_MOD_BUTTON3;
1405                         if (mask & GDK_BUTTON4_MASK)
1406                                 modifiers |= XEMACS_MOD_BUTTON4;
1407                         if (mask & GDK_BUTTON5_MASK)
1408                                 modifiers |= XEMACS_MOD_BUTTON5;
1409
1410                         /* Currently ignores Shift_Lock but probably shouldn't
1411                            (but it definitely should ignore Caps_Lock). */
1412                         emacs_event->event.motion.modifiers = modifiers;
1413                 }
1414                 break;
1415
1416         default:                /* it's a magic event */
1417                 return (0);
1418                 break;
1419         }
1420         return 1;
1421 }
1422
1423 static const char *event_name(GdkEvent *);
1424
1425 static gboolean generic_event_handler(GtkWidget * widget, GdkEvent * event)
1426 {
1427         Lisp_Object emacs_event = Qnil;
1428         if (!GTK_IS_XEMACS(widget)) {
1429                 stderr_out("Got a %s event for a non-SXEmacs widget\n",
1430                            event_name(event));
1431                 return (FALSE);
1432         }
1433
1434         emacs_event = Fmake_event(Qnil, Qnil);
1435
1436         if (gtk_event_to_emacs_event
1437             (GTK_XEMACS_FRAME(widget), event, XEVENT(emacs_event))) {
1438                 enqueue_gtk_dispatch_event(emacs_event);
1439                 return (TRUE);
1440         } else {
1441                 Fdeallocate_event(emacs_event);
1442         }
1443         return (FALSE);
1444 }
1445
1446 gint emacs_gtk_key_event_handler(GtkWidget * widget, GdkEventKey * event)
1447 {
1448         return (generic_event_handler(widget, (GdkEvent *) event));
1449 }
1450
1451 gint emacs_gtk_button_event_handler(GtkWidget * widget, GdkEventButton * event)
1452 {
1453         return (generic_event_handler(widget, (GdkEvent *) event));
1454 }
1455
1456 gint emacs_gtk_motion_event_handler(GtkWidget * widget, GdkEventMotion * event)
1457 {
1458         return (generic_event_handler(widget, (GdkEvent *) event));
1459 }
1460
1461 gboolean emacs_shell_event_handler(GtkWidget * wid /* unused */ ,
1462                                    GdkEvent * event, gpointer closure)
1463 {
1464         struct frame *frame = (struct frame *)closure;
1465         Lisp_Object lisp_event = Fmake_event(Qnil, Qnil);
1466         struct Lisp_Event *emacs_event = XEVENT(lisp_event);
1467         GdkEvent *gdk_event_copy =
1468             &emacs_event->event.magic.underlying_gdk_event;
1469         struct device *d = XDEVICE(FRAME_DEVICE(frame));
1470         gboolean ignore_p = FALSE;
1471
1472         set_last_server_timestamp(d, event);
1473
1474 #define FROB(event_member) gdk_event_copy->event_member = event->event_member
1475
1476         switch (event->type) {
1477         case GDK_SELECTION_REQUEST:
1478         case GDK_SELECTION_CLEAR:
1479         case GDK_SELECTION_NOTIFY:
1480                 FROB(selection);
1481                 break;
1482         case GDK_PROPERTY_NOTIFY:
1483                 FROB(property);
1484                 break;
1485         case GDK_CLIENT_EVENT:
1486                 FROB(client);
1487                 break;
1488         case GDK_MAP:
1489         case GDK_UNMAP:
1490                 FROB(any);
1491                 break;
1492         case GDK_CONFIGURE:
1493                 FROB(configure);
1494                 break;
1495         case GDK_ENTER_NOTIFY:
1496         case GDK_LEAVE_NOTIFY:
1497                 FROB(crossing);
1498                 break;
1499         case GDK_FOCUS_CHANGE:
1500                 FROB(focus_change);
1501                 break;
1502         case GDK_VISIBILITY_NOTIFY:
1503                 FROB(visibility);
1504                 break;
1505         default:
1506                 ignore_p = TRUE;
1507                 /* Hrmm... do we really want to swallow all the other events as magic? */
1508                 *gdk_event_copy = *event;
1509                 break;
1510         }
1511 #undef FROB
1512
1513         emacs_event->event_type = magic_event;
1514         XSETFRAME(emacs_event->channel, frame);
1515
1516         if (ignore_p) {
1517                 stderr_out("Ignoring event... (%s)\n", event_name(event));
1518                 Fdeallocate_event(lisp_event);
1519                 return (FALSE);
1520         } else {
1521                 enqueue_gtk_dispatch_event(lisp_event);
1522                 return (TRUE);
1523         }
1524 }
1525 \f
1526 /************************************************************************/
1527 /*                      input pending / C-g checking                    */
1528 /************************************************************************/
1529 static void gtk_check_for_quit_char(struct device *d);
1530
1531 static void check_for_tty_quit_char(struct device *d)
1532 {
1533         SELECT_TYPE temp_mask;
1534         int infd = DEVICE_INFD(d);
1535         struct console *con = XCONSOLE(DEVICE_CONSOLE(d));
1536         Emchar quit_char = CONSOLE_QUIT_CHAR(con);
1537
1538         FD_ZERO(&temp_mask);
1539         FD_SET(infd, &temp_mask);
1540
1541         while (1) {
1542                 Lisp_Object event;
1543                 Emchar the_char;
1544
1545                 if (!poll_fds_for_input(temp_mask))
1546                         return;
1547
1548                 event = Fmake_event(Qnil, Qnil);
1549                 if (!read_event_from_tty_or_stream_desc
1550                     (XEVENT(event), con, infd))
1551                         /* EOF, or something ... */
1552                         return;
1553                 /* #### bogus.  quit-char should be allowed to be any sort
1554                    of event. */
1555                 the_char = event_to_character(XEVENT(event), 1, 0, 0);
1556                 if (the_char >= 0 && the_char == quit_char) {
1557                         Vquit_flag = Qt;
1558                         /* do not queue the C-g.  See above. */
1559                         return;
1560                 }
1561
1562                 /* queue the read event to be read for real later. */
1563                 enqueue_gtk_dispatch_event(event);
1564         }
1565 }
1566
1567 static void emacs_gtk_quit_p(void)
1568 {
1569         Lisp_Object devcons, concons;
1570
1571         CONSOLE_LOOP(concons) {
1572                 struct console *con = XCONSOLE(XCAR(concons));
1573                 if (!con->input_enabled)
1574                         continue;
1575
1576                 CONSOLE_DEVICE_LOOP(devcons, con) {
1577                         struct device *d;
1578                         d = XDEVICE(XCAR(devcons));
1579
1580                         if (DEVICE_GTK_P(d))
1581                                 /* emacs may be exiting */
1582                                 gtk_check_for_quit_char(d);
1583                         else if (DEVICE_TTY_P(d))
1584                                 check_for_tty_quit_char(d);
1585                 }
1586         }
1587 }
1588
1589 #include <gdk/gdkx.h>
1590
1591 static void drain_gtk_queue(void)
1592 {
1593         /* We can't just spin through here and wait for GTKs idea of the
1594            event queue to get empty, or the queue never gets drained.  The
1595            situation is as follows.  A process event gets signalled, we put
1596            it on the queue, then we go into Fnext_event(), which calls
1597            drain_gtk_queue().  But gtk_events_pending() will always return
1598            TRUE if there are file-descriptor (aka our process) events
1599            pending.  Using GDK_events_pending() only shows us windowing
1600            system events.
1601          */
1602         if (GDK_DISPLAY())
1603                 while (gdk_events_pending())
1604                         gtk_main_iteration();
1605 }
1606
1607 static int emacs_gtk_event_pending_p(int user_p)
1608 {
1609         Lisp_Object event;
1610         int tick_count_val;
1611
1612         /* If `user_p' is false, then this function returns whether there are any
1613            X, timeout, or fd events pending (that is, whether emacs_gtk_next_event()
1614            would return immediately without blocking).
1615
1616            if `user_p' is true, then this function returns whether there are any
1617            *user generated* events available (that is, whether there are keyboard
1618            or mouse-click events ready to be read).  This also implies that
1619            emacs_Xt_next_event() would not block.
1620
1621            In a non-SIGIO world, this also checks whether the user has typed ^G,
1622            since this is a convenient place to do so.  We don't need to do this
1623            in a SIGIO world, since input causes an interrupt.
1624          */
1625
1626         /* This function used to simply check whether there were any X
1627            events (or if user_p was 1, it iterated over all the pending
1628            X events using XCheckIfEvent(), looking for keystrokes and
1629            button events).  That worked in the old cheesoid event loop,
1630            which didn't go through XtAppDispatchEvent(), but it doesn't
1631            work any more -- X events may not result in anything.  For
1632            example, a button press in a blank part of the menubar appears
1633            as an X event but will not result in any Emacs events (a
1634            button press that activates the menubar results in an Emacs
1635            event through the stop_next_event mechanism).
1636
1637            The only accurate way of determining whether these X events
1638            translate into Emacs events is to go ahead and dispatch them
1639            until there's something on the dispatch queue. */
1640
1641         /* See if there are any user events already on the queue. */
1642         EVENT_CHAIN_LOOP(event, dispatch_event_queue)
1643             if (!user_p || command_event_p(event))
1644                 return 1;
1645
1646         /* See if there's any TTY input available.
1647          */
1648         if (poll_fds_for_input(tty_only_mask))
1649                 return 1;
1650
1651         if (!user_p) {
1652                 /* If not user_p and there are any timer or file-desc events
1653                    pending, we know there will be an event so we're through. */
1654 /*      XtInputMask pending_value; */
1655
1656                 /* Note that formerly we just checked the value of XtAppPending()
1657                    to determine if there was file-desc input.  This doesn't
1658                    work any more with the signal_event_pipe; XtAppPending()
1659                    will says "yes" in this case but there isn't really any
1660                    input.  Another way of fixing this problem is for the
1661                    signal_event_pipe to generate actual input in the form
1662                    of an identity eval event or something. (#### maybe this
1663                    actually happens?) */
1664
1665                 if (poll_fds_for_input(process_only_mask))
1666                         return 1;
1667
1668                 /* #### Is there any way to do this in Gtk?  I don't think there
1669                    is a 'peek' for events */
1670 #if 0
1671                 pending_value = XtAppPending(Xt_app_con);
1672
1673                 if (pending_value & XtIMTimer)
1674                         return 1;
1675 #endif
1676         }
1677
1678         /* XtAppPending() can be super-slow, esp. over a network connection.
1679            Quantify results have indicated that in some cases the
1680            call to detect_input_pending() completely dominates the
1681            running time of redisplay().  Fortunately, in a SIGIO world
1682            we can more quickly determine whether there are any X events:
1683            if an event has happened since the last time we checked, then
1684            a SIGIO will have happened.  On a machine with broken SIGIO,
1685            we'll still be in an OK state -- the sigio_happened flag
1686            will get set at least once a second, so we'll be no more than
1687            one second behind reality. (In general it's OK if we
1688            erroneously report no input pending when input is actually
1689            pending() -- preemption is just a bit less efficient, that's
1690            all.  It's bad bad bad if you err the other way -- you've
1691            promised that `next-event' won't block but it actually will,
1692            and some action might get delayed until the next time you
1693            hit a key.)
1694          */
1695
1696         /* quit_check_signal_tick_count is volatile so try to avoid race conditions
1697            by using a temporary variable */
1698         tick_count_val = quit_check_signal_tick_count;
1699         if (last_quit_check_signal_tick_count != tick_count_val) {
1700                 last_quit_check_signal_tick_count = tick_count_val;
1701
1702                 /* We need to drain the entire queue now -- if we only
1703                    drain part of it, we may later on end up with events
1704                    actually pending but detect_input_pending() returning
1705                    false because there wasn't another SIGIO. */
1706
1707                 drain_gtk_queue();
1708
1709                 EVENT_CHAIN_LOOP(event, dispatch_event_queue)
1710                     if (!user_p || command_event_p(event))
1711                         return 1;
1712         }
1713
1714         return 0;
1715 }
1716 \f
1717 /************************************************************************/
1718 /*                            initialization                            */
1719 /************************************************************************/
1720
1721 void syms_of_event_gtk(void)
1722 {
1723         defsymbol(&Qkey_mapping, "key-mapping");
1724         defsymbol(&Qsans_modifiers, "sans-modifiers");
1725 }
1726
1727 void reinit_vars_of_event_gtk(void)
1728 {
1729         gtk_event_stream = xnew(struct event_stream);
1730         gtk_event_stream->event_pending_p = emacs_gtk_event_pending_p;
1731         gtk_event_stream->next_event_cb = emacs_gtk_next_event;
1732         gtk_event_stream->handle_magic_event_cb = emacs_gtk_handle_magic_event;
1733         gtk_event_stream->add_timeout_cb = emacs_gtk_add_timeout;
1734         gtk_event_stream->remove_timeout_cb = emacs_gtk_remove_timeout;
1735         gtk_event_stream->select_console_cb = emacs_gtk_select_console;
1736         gtk_event_stream->unselect_console_cb = emacs_gtk_unselect_console;
1737         gtk_event_stream->select_process_cb = emacs_gtk_select_process;
1738         gtk_event_stream->unselect_process_cb = emacs_gtk_unselect_process;
1739         gtk_event_stream->quit_p_cb = emacs_gtk_quit_p;
1740         gtk_event_stream->create_stream_pair_cb = emacs_gtk_create_stream_pair;
1741         gtk_event_stream->delete_stream_pair_cb = emacs_gtk_delete_stream_pair;
1742
1743         the_GTK_timeout_blocktype = Blocktype_new(struct GTK_timeout_blocktype);
1744
1745         /* this function only makes safe calls */
1746         init_what_input_once();
1747 }
1748
1749 void vars_of_event_gtk(void)
1750 {
1751         reinit_vars_of_event_gtk();
1752
1753         dispatch_event_queue = Qnil;
1754         staticpro(&dispatch_event_queue);
1755         dispatch_event_queue_tail = Qnil;
1756         staticpro(&dispatch_event_queue_tail);
1757
1758         DEFVAR_BOOL("gtk-allow-sendevents", &gtk_allow_sendevents       /*
1759 *Non-nil means to allow synthetic events.  Nil means they are ignored.
1760 Beware: allowing emacs to process SendEvents opens a big security hole.
1761                                                                          */ );
1762         gtk_allow_sendevents = 0;
1763
1764         last_quit_check_signal_tick_count = 0;
1765 }
1766
1767 void init_event_gtk_late(void)
1768 {                               /* called when already initialized */
1769         timeout_id_tick = 1;
1770         pending_timeouts = 0;
1771         completed_timeouts = 0;
1772
1773         event_stream = gtk_event_stream;
1774
1775 #if 0
1776         /* Shut GDK the hell up */
1777         gdk_error_trap_push();
1778 #endif
1779
1780         gdk_input_add(signal_event_pipe[0], GDK_INPUT_READ,
1781                       (GdkInputFunction) gtk_what_callback, NULL);
1782 }
1783
1784 /* Bogus utility routines */
1785 static const char *event_name(GdkEvent * ev)
1786 {
1787         return (gtk_event_name(ev->any.type));
1788 }
1789
1790 /* This is down at the bottom of the file so I can avoid polluting the
1791    generic code with this X specific CRAP! */
1792
1793 #include <gdk/gdkx.h>
1794 #include <X11/keysym.h>
1795 /* #### BILL!!! Fix this please! */
1796 \f
1797 /************************************************************************/
1798 /*                            keymap handling                           */
1799 /************************************************************************/
1800
1801 /* X bogusly doesn't define the interpretations of any bits besides
1802    ModControl, ModShift, and ModLock; so the Interclient Communication
1803    Conventions Manual says that we have to bend over backwards to figure
1804    out what the other modifier bits mean.  According to ICCCM:
1805
1806    - Any keycode which is assigned ModControl is a "control" key.
1807
1808    - Any modifier bit which is assigned to a keycode which generates Meta_L
1809      or Meta_R is the modifier bit meaning "meta".  Likewise for Super, Hyper,
1810      etc.
1811
1812    - Any keypress event which contains ModControl in its state should be
1813      interpreted as a "control" character.
1814
1815    - Any keypress event which contains a modifier bit in its state which is
1816      generated by a keycode whose corresponding keysym is Meta_L or Meta_R
1817      should be interpreted as a "meta" character.  Likewise for Super, Hyper,
1818      etc.
1819
1820    - It is illegal for a keysym to be associated with more than one modifier
1821      bit.
1822
1823    This means that the only thing that emacs can reasonably interpret as a
1824    "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
1825    one of the modifier bits Mod1-Mod5.
1826
1827    Unfortunately, many keyboards don't have Meta keys in their default
1828    configuration.  So, if there are no Meta keys, but there are "Alt" keys,
1829    emacs will interpret Alt as Meta.  If there are both Meta and Alt keys,
1830    then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
1831    mean "Symbol," but that just confused the hell out of way too many people).
1832
1833    This works with the default configurations of the 19 keyboard-types I've
1834    checked.
1835
1836    Emacs detects keyboard configurations which violate the above rules, and
1837    prints an error message on the standard-error-output.  (Perhaps it should
1838    use a pop-up-window instead.)
1839  */
1840
1841 static void gtk_reset_key_mapping(struct device *d)
1842 {
1843         Display *display = GDK_DISPLAY();
1844         struct gtk_device *xd = DEVICE_GTK_DATA(d);
1845         XModifierKeymap *map = (XModifierKeymap *) xd->x_keysym_map;
1846         KeySym *keysym, *keysym_end;
1847         Lisp_Object hashtable;
1848         int key_code_count, keysyms_per_code;
1849
1850         if (map)
1851                 XFree((char *)map);
1852         XDisplayKeycodes(display,
1853                          &xd->x_keysym_map_min_code,
1854                          &xd->x_keysym_map_max_code);
1855         key_code_count =
1856             xd->x_keysym_map_max_code - xd->x_keysym_map_min_code + 1;
1857         map = (XModifierKeymap *)
1858             XGetKeyboardMapping(display, xd->x_keysym_map_min_code,
1859                                 key_code_count,
1860                                 &xd->x_keysym_map_keysyms_per_code);
1861
1862         xd->x_keysym_map = (void *)map;
1863         hashtable = xd->x_keysym_map_hashtable;
1864         if (HASH_TABLEP(hashtable)) {
1865                 Fclrhash(hashtable);
1866         } else {
1867                 xd->x_keysym_map_hashtable = hashtable =
1868                     make_lisp_hash_table(128, HASH_TABLE_NON_WEAK,
1869                                          HASH_TABLE_EQUAL);
1870         }
1871
1872         for (keysym = (KeySym *) map,
1873              keysyms_per_code = xd->x_keysym_map_keysyms_per_code,
1874              keysym_end = keysym + (key_code_count * keysyms_per_code);
1875              keysym < keysym_end; keysym += keysyms_per_code) {
1876                 int j;
1877
1878                 if (keysym[0] == NoSymbol)
1879                         continue;
1880
1881                 {
1882                         char *name = XKeysymToString(keysym[0]);
1883                         Lisp_Object sym =
1884                             gtk_keysym_to_emacs_keysym(keysym[0], 0);
1885                         if (name) {
1886                                 Fputhash(build_string(name), Qsans_modifiers,
1887                                          hashtable);
1888                                 Fputhash(sym, Qsans_modifiers, hashtable);
1889                         }
1890                 }
1891
1892                 for (j = 1; j < keysyms_per_code; j++) {
1893                         if (keysym[j] != keysym[0] && keysym[j] != NoSymbol) {
1894                                 char *name = XKeysymToString(keysym[j]);
1895                                 Lisp_Object sym =
1896                                     gtk_keysym_to_emacs_keysym(keysym[j], 0);
1897                                 if (name
1898                                     && NILP(Fgethash(sym, hashtable, Qnil))) {
1899                                         Fputhash(build_string(name), Qt,
1900                                                  hashtable);
1901                                         Fputhash(sym, Qt, hashtable);
1902                                 }
1903                         }
1904                 }
1905         }
1906 }
1907
1908 static const char *index_to_name(int indice)
1909 {
1910         switch (indice) {
1911         case ShiftMapIndex:
1912                 return "ModShift";
1913         case LockMapIndex:
1914                 return "ModLock";
1915         case ControlMapIndex:
1916                 return "ModControl";
1917         case Mod1MapIndex:
1918                 return "Mod1";
1919         case Mod2MapIndex:
1920                 return "Mod2";
1921         case Mod3MapIndex:
1922                 return "Mod3";
1923         case Mod4MapIndex:
1924                 return "Mod4";
1925         case Mod5MapIndex:
1926                 return "Mod5";
1927         default:
1928                 return "???";
1929         }
1930 }
1931
1932 /* Boy, I really wish C had local functions... */
1933 struct c_doesnt_have_closures { /* #### not yet used */
1934         int warned_about_overlapping_modifiers;
1935         int warned_about_predefined_modifiers;
1936         int warned_about_duplicate_modifiers;
1937         int meta_bit;
1938         int hyper_bit;
1939         int super_bit;
1940         int alt_bit;
1941         int mode_bit;
1942 };
1943
1944 static void gtk_reset_modifier_mapping(struct device *d)
1945 {
1946         Display *display = GDK_DISPLAY();
1947         struct gtk_device *xd = DEVICE_GTK_DATA(d);
1948         int modifier_index, modifier_key, column, mkpm;
1949         int warned_about_overlapping_modifiers = 0;
1950         /*  int warned_about_predefined_modifiers  = 0; */
1951         /* int warned_about_duplicate_modifiers   = 0; */
1952         int meta_bit = 0;
1953         int hyper_bit = 0;
1954         int super_bit = 0;
1955         int alt_bit = 0;
1956         int mode_bit = 0;
1957         XModifierKeymap *map = (XModifierKeymap *) xd->x_modifier_keymap;
1958
1959         xd->lock_interpretation = 0;
1960
1961         if (map)
1962                 XFreeModifiermap(map);
1963
1964         gtk_reset_key_mapping(d);
1965
1966         xd->x_modifier_keymap = map = XGetModifierMapping(display);
1967
1968         /* Boy, I really wish C had local functions...
1969          */
1970
1971         /* The call to warn_when_safe must be on the same line as the string or
1972            make-msgfile won't pick it up properly (the newline doesn't confuse
1973            it, but the backslash does). */
1974
1975 #define store_modifier(name,old)                                           \
1976     old = modifier_index;
1977
1978         mkpm = map->max_keypermod;
1979         for (modifier_index = 0; modifier_index < 8; modifier_index++)
1980                 for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
1981                         KeySym last_sym = 0;
1982                         for (column = 0; column < 4; column += 2) {
1983                                 KeyCode code =
1984                                     map->modifiermap[modifier_index * mkpm +
1985                                                      modifier_key];
1986                                 KeySym sym =
1987                                     (code ?
1988                                      XKeycodeToKeysym(display, code,
1989                                                       column) : 0);
1990                                 if (sym == last_sym)
1991                                         continue;
1992                                 last_sym = sym;
1993                                 switch (sym) {
1994                                 case XK_Mode_switch:
1995                                         store_modifier("Mode_switch", mode_bit);
1996                                         break;
1997                                 case XK_Meta_L:
1998                                         store_modifier("Meta_L", meta_bit);
1999                                         break;
2000                                 case XK_Meta_R:
2001                                         store_modifier("Meta_R", meta_bit);
2002                                         break;
2003                                 case XK_Super_L:
2004                                         store_modifier("Super_L", super_bit);
2005                                         break;
2006                                 case XK_Super_R:
2007                                         store_modifier("Super_R", super_bit);
2008                                         break;
2009                                 case XK_Hyper_L:
2010                                         store_modifier("Hyper_L", hyper_bit);
2011                                         break;
2012                                 case XK_Hyper_R:
2013                                         store_modifier("Hyper_R", hyper_bit);
2014                                         break;
2015                                 case XK_Alt_L:
2016                                         store_modifier("Alt_L", alt_bit);
2017                                         break;
2018                                 case XK_Alt_R:
2019                                         store_modifier("Alt_R", alt_bit);
2020                                         break;
2021 #if 0
2022                                 case XK_Control_L:
2023                                         check_modifier("Control_L",
2024                                                        ControlMask);
2025                                         break;
2026                                 case XK_Control_R:
2027                                         check_modifier("Control_R",
2028                                                        ControlMask);
2029                                         break;
2030                                 case XK_Shift_L:
2031                                         check_modifier("Shift_L", ShiftMask);
2032                                         break;
2033                                 case XK_Shift_R:
2034                                         check_modifier("Shift_R", ShiftMask);
2035                                         break;
2036 #endif
2037                                 case XK_Shift_Lock:     /* check_modifier ("Shift_Lock", LockMask); */
2038                                         xd->lock_interpretation = XK_Shift_Lock;
2039                                         break;
2040                                 case XK_Caps_Lock:      /* check_modifier ("Caps_Lock", LockMask); */
2041                                         xd->lock_interpretation = XK_Caps_Lock;
2042                                         break;
2043
2044                                         /* It probably doesn't make any sense for a modifier bit to be
2045                                            assigned to a key that is not one of the above, but OpenWindows
2046                                            assigns modifier bits to a couple of random function keys for
2047                                            no reason that I can discern, so printing a warning here would
2048                                            be annoying. */
2049                                 }
2050                         }
2051                 }
2052 #undef store_modifier
2053 #undef check_modifier
2054 #undef modwarn
2055 #undef modbarf
2056
2057         /* If there was no Meta key, then try using the Alt key instead.
2058            If there is both a Meta key and an Alt key, then the Alt key
2059            is not disturbed and remains an Alt key. */
2060         if (!meta_bit && alt_bit)
2061                 meta_bit = alt_bit, alt_bit = 0;
2062
2063         /* mode_bit overrides everything, since it's processed down inside of
2064            XLookupString() instead of by us.  If Meta and Mode_switch both
2065            generate the same modifier bit (which is an error), then we don't
2066            interpret that bit as Meta, because we can't make XLookupString()
2067            not interpret it as Mode_switch; and interpreting it as both would
2068            be totally wrong. */
2069         if (mode_bit) {
2070                 const char *warn = 0;
2071                 if (mode_bit == meta_bit)
2072                         warn = "Meta", meta_bit = 0;
2073                 else if (mode_bit == hyper_bit)
2074                         warn = "Hyper", hyper_bit = 0;
2075                 else if (mode_bit == super_bit)
2076                         warn = "Super", super_bit = 0;
2077                 else if (mode_bit == alt_bit)
2078                         warn = "Alt", alt_bit = 0;
2079                 if (warn) {
2080                         warn_when_safe
2081                             (Qkey_mapping, Qwarning,
2082                              "SXEmacs:  %s is being used for both Mode_switch and %s.",
2083                              index_to_name(mode_bit), warn),
2084                             warned_about_overlapping_modifiers = 1;
2085                 }
2086         }
2087 #undef index_to_name
2088
2089         xd->MetaMask = (meta_bit ? (1 << meta_bit) : 0);
2090         xd->HyperMask = (hyper_bit ? (1 << hyper_bit) : 0);
2091         xd->SuperMask = (super_bit ? (1 << super_bit) : 0);
2092         xd->AltMask = (alt_bit ? (1 << alt_bit) : 0);
2093         xd->ModeMask = (mode_bit ? (1 << mode_bit) : 0);        /* unused */
2094
2095 }
2096
2097 void gtk_init_modifier_mapping(struct device *d)
2098 {
2099         struct gtk_device *gd = DEVICE_GTK_DATA(d);
2100         gd->x_keysym_map_hashtable = Qnil;
2101         gd->x_keysym_map = NULL;
2102         gd->x_modifier_keymap = NULL;
2103         gtk_reset_modifier_mapping(d);
2104 }
2105
2106 #if 0
2107 static int gtk_key_is_modifier_p(KeyCode keycode, struct device *d)
2108 {
2109         struct gtk_device *xd = DEVICE_GTK_DATA(d);
2110         KeySym *syms;
2111         KeySym *map = (KeySym *) xd->x_keysym_map;
2112         int i;
2113
2114         if (keycode < xd->x_keysym_map_min_code ||
2115             keycode > xd->x_keysym_map_max_code)
2116                 return 0;
2117
2118         syms = &map[(keycode - xd->x_keysym_map_min_code) *
2119                     xd->x_keysym_map_keysyms_per_code];
2120         for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
2121                 if (IsModifierKey(syms[i]) || syms[i] == XK_Mode_switch)        /* why doesn't IsModifierKey count this? */
2122                         return 1;
2123         return 0;
2124 }
2125 #endif
2126
2127 struct _quit_predicate_closure {
2128         struct device *device;
2129         Bool *critical;
2130 };
2131
2132 static Bool
2133 quit_char_predicate(Display * display, XEvent * event, XPointer data)
2134 {
2135         struct _quit_predicate_closure *cl =
2136             (struct _quit_predicate_closure *)data;
2137         struct device *d = cl->device;
2138         struct frame *f = NULL;
2139         struct gtk_device *gd = DEVICE_GTK_DATA(d);
2140         char c, quit_char;
2141         Bool *critical = cl->critical;
2142         Lisp_Object keysym;
2143         GdkWindow *window = gdk_window_lookup(event->xany.window);
2144         guint32 keycode = 0;
2145         GdkEventKey gdk_event;
2146
2147         if (window)
2148                 f = gtk_any_window_to_frame(d, window);
2149
2150         if (critical)
2151                 *critical = False;
2152
2153         if ((event->type != KeyPress) ||
2154             (!window) ||
2155             (!f) ||
2156             (event->xkey.state
2157              & (gd->MetaMask | gd->HyperMask | gd->SuperMask | gd->AltMask))) {
2158                 return 0;
2159         }
2160
2161         {
2162                 char dummy[256];
2163                 XLookupString(&(event->xkey), dummy, 200, (KeySym *) & keycode,
2164                               0);
2165         }
2166
2167         memset(&gdk_event, 0, sizeof(gdk_event));
2168         gdk_event.type = GDK_KEY_PRESS;
2169         gdk_event.window = window;
2170         gdk_event.keyval = keycode;
2171         gdk_event.state = event->xkey.state;
2172
2173         /* This duplicates some code that exists elsewhere, but it's relatively
2174            fast and doesn't cons. */
2175         keysym = gtk_to_emacs_keysym(d, &gdk_event, 1);
2176         if (NILP(keysym))
2177                 return 0;
2178         if (CHAR_OR_CHAR_INTP(keysym))
2179                 c = XCHAR_OR_CHAR_INT(keysym);
2180         /* Highly doubtful that these are the quit character, but... */
2181         else if (EQ(keysym, QKbackspace))
2182                 c = '\b';
2183         else if (EQ(keysym, QKtab))
2184                 c = '\t';
2185         else if (EQ(keysym, QKlinefeed))
2186                 c = '\n';
2187         else if (EQ(keysym, QKreturn))
2188                 c = '\r';
2189         else if (EQ(keysym, QKescape))
2190                 c = 27;
2191         else if (EQ(keysym, QKspace))
2192                 c = ' ';
2193         else if (EQ(keysym, QKdelete))
2194                 c = 127;
2195         else
2196                 return 0;
2197
2198         if (event->xkey.state & gd->MetaMask)
2199                 c |= 0x80;
2200         if ((event->xkey.state & ControlMask) && !(c >= 'A' && c <= 'Z'))
2201                 c &= 0x1F;      /* unshifted control characters */
2202         quit_char = CONSOLE_QUIT_CHAR(XCONSOLE(DEVICE_CONSOLE(d)));
2203
2204         if (c == quit_char)
2205                 return True;
2206         /* If we've got Control-Shift-G instead of Control-G, that means
2207            we have a critical_quit.  Caps_Lock is its own modifier, so it
2208            won't cause ^G to act differently than before. */
2209         if (event->xkey.state & ControlMask)
2210                 c &= 0x1F;
2211         if (c == quit_char) {
2212                 if (critical)
2213                         *critical = True;
2214                 return True;
2215         }
2216         return False;
2217 }
2218
2219 static void gtk_check_for_quit_char(struct device *d)
2220 {
2221         XEvent event;
2222         int queued;
2223         Bool critical_quit = False;
2224         struct _quit_predicate_closure closure;
2225
2226         XEventsQueued(GDK_DISPLAY(), QueuedAfterReading);
2227
2228         closure.device = d;
2229         closure.critical = &critical_quit;
2230
2231         queued =
2232             XCheckIfEvent(GDK_DISPLAY(), &event, quit_char_predicate,
2233                           (char *)&closure);
2234
2235         if (queued) {
2236                 Vquit_flag = (critical_quit ? Qcritical : Qt);
2237         }
2238 }