import -ko -b 1.1.3 XEmacs XEmacs-21_2 r21-2-35
[chise/xemacs-chise.git.1] / src / event-Xt.c
1 /* The event_stream interface for X11 with Xt, 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
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Synched up with: Not in FSF. */
24
25 #include <config.h>
26 #include "lisp.h"
27
28 #include "console-x.h"
29 #include "../lwlib/lwlib.h"
30 #include "EmacsFrame.h"
31
32 #include "blocktype.h"
33 #include "buffer.h"
34 #include "console.h"
35 #include "console-tty.h"
36 #include "events.h"
37 #include "frame.h"
38 #include "objects-x.h"
39 #include "process.h"
40 #include "redisplay.h"
41 #include "elhash.h"
42
43 #include "systime.h"
44 #include "sysproc.h" /* for MAXDESC */
45
46 #include "xintrinsicp.h"        /* CoreP.h needs this */
47 #include <X11/CoreP.h>          /* Numerous places access the fields of
48                                    a core widget directly.  We could
49                                    use XtGetValues(), but ... */
50 #include <X11/ShellP.h>
51
52 #ifdef HAVE_XIM
53 #ifdef XIM_MOTIF
54 #include <Xm/Xm.h>
55 #endif
56 #include "lstream.h"
57 #include "file-coding.h"
58 #endif
59
60 #ifdef HAVE_DRAGNDROP
61 #include "dragdrop.h"
62 #endif
63
64 #if defined (HAVE_OFFIX_DND)
65 #include "offix.h"
66 #endif
67
68 #include "events-mod.h"
69
70 static void handle_focus_event_1 (struct frame *f, int in_p);
71
72 static struct event_stream *Xt_event_stream;
73
74 /* With the new event model, all events go through XtDispatchEvent()
75    and are picked up by an event handler that is added to each frame
76    widget. (This is how it's supposed to be.) In the old method,
77    Emacs sucks out events directly from XtNextEvent() and only
78    dispatches the events that it doesn't need to deal with.  This
79    old way has lots of corresponding junk that is no longer
80    necessary: lwlib extensions, synthetic XAnyEvents, unnecessary
81    magic events, etc. */
82
83 /* The one and only one application context that Emacs uses. */
84 XtAppContext Xt_app_con;
85
86 /* Do we accept events sent by other clients? */
87 int x_allow_sendevents;
88
89 #ifdef DEBUG_XEMACS
90 int x_debug_events;
91 #endif
92
93 static int process_events_occurred;
94 static int tty_events_occurred;
95
96 /* Mask of bits indicating the descriptors that we wait for input on */
97 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
98
99 static const String x_fallback_resources[] =
100 {
101   /* This file is automatically generated from the app-defaults file
102      in ../etc/Emacs.ad.  These resources are consulted only if no
103      app-defaults file is found at all.
104    */
105 #include <Emacs.ad.h>
106   0
107 };
108
109 static Lisp_Object x_keysym_to_emacs_keysym (KeySym keysym, int simple_p);
110 void emacs_Xt_mapping_action (Widget w, XEvent *event);
111 void debug_process_finalization (Lisp_Process *p);
112 void emacs_Xt_event_handler (Widget wid, XtPointer closure, XEvent *event,
113                              Boolean *continue_to_dispatch);
114
115 static int last_quit_check_signal_tick_count;
116
117 Lisp_Object Qkey_mapping;
118 Lisp_Object Qsans_modifiers;
119
120 \f
121 /************************************************************************/
122 /*                            keymap handling                           */
123 /************************************************************************/
124
125 /* X bogusly doesn't define the interpretations of any bits besides
126    ModControl, ModShift, and ModLock; so the Interclient Communication
127    Conventions Manual says that we have to bend over backwards to figure
128    out what the other modifier bits mean.  According to ICCCM:
129
130    - Any keycode which is assigned ModControl is a "control" key.
131
132    - Any modifier bit which is assigned to a keycode which generates Meta_L
133      or Meta_R is the modifier bit meaning "meta".  Likewise for Super, Hyper,
134      etc.
135
136    - Any keypress event which contains ModControl in its state should be
137      interpreted as a "control" character.
138
139    - Any keypress event which contains a modifier bit in its state which is
140      generated by a keycode whose corresponding keysym is Meta_L or Meta_R
141      should be interpreted as a "meta" character.  Likewise for Super, Hyper,
142      etc.
143
144    - It is illegal for a keysym to be associated with more than one modifier
145      bit.
146
147    This means that the only thing that emacs can reasonably interpret as a
148    "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
149    one of the modifier bits Mod1-Mod5.
150
151    Unfortunately, many keyboards don't have Meta keys in their default
152    configuration.  So, if there are no Meta keys, but there are "Alt" keys,
153    emacs will interpret Alt as Meta.  If there are both Meta and Alt keys,
154    then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
155    mean "Symbol," but that just confused the hell out of way too many people).
156
157    This works with the default configurations of the 19 keyboard-types I've
158    checked.
159
160    Emacs detects keyboard configurations which violate the above rules, and
161    prints an error message on the standard-error-output.  (Perhaps it should
162    use a pop-up-window instead.)
163  */
164
165 /* For every key on the keyboard that has a known character correspondence,
166    we define the ascii-character property of the keysym, and make the
167    default binding for the key be self-insert-command.
168
169    The following magic is basically intimate knowledge of X11/keysymdef.h.
170    The keysym mappings defined by X11 are based on the iso8859 standards,
171    except for Cyrillic and Greek.
172
173    In a non-Mule world, a user can still have a multi-lingual editor, by doing
174    (set-face-font "...-iso8859-2" (current-buffer))
175    for all their Latin-2 buffers, etc.  */
176
177 static Lisp_Object
178 x_keysym_to_character (KeySym keysym)
179 {
180 #ifdef MULE
181   Lisp_Object charset = Qzero;
182 #define USE_CHARSET(var,cs) \
183   ((var) = CHARSET_BY_LEADING_BYTE (LEADING_BYTE_##cs))
184 #else
185 #define USE_CHARSET(var,lb)
186 #endif /* MULE */
187   int code = 0;
188
189   if ((keysym & 0xff) < 0xa0)
190     return Qnil;
191
192   switch (keysym >> 8)
193     {
194     case 0: /* ASCII + Latin1 */
195       USE_CHARSET (charset, LATIN_ISO8859_1);
196       code = keysym & 0x7f;
197       break;
198     case 1: /* Latin2 */
199       USE_CHARSET (charset, LATIN_ISO8859_2);
200       code = keysym & 0x7f;
201       break;
202     case 2: /* Latin3 */
203       USE_CHARSET (charset, LATIN_ISO8859_3);
204       code = keysym & 0x7f;
205       break;
206     case 3: /* Latin4 */
207       USE_CHARSET (charset, LATIN_ISO8859_4);
208       code = keysym & 0x7f;
209       break;
210     case 4: /* Katakana */
211       USE_CHARSET (charset, KATAKANA_JISX0201);
212       if ((keysym & 0xff) > 0xa0)
213         code = keysym & 0x7f;
214       break;
215     case 5: /* Arabic */
216       USE_CHARSET (charset, ARABIC_ISO8859_6);
217       code = keysym & 0x7f;
218       break;
219     case 6: /* Cyrillic */
220       {
221         static unsigned char const cyrillic[] = /* 0x20 - 0x7f */
222         {0x00, 0x72, 0x73, 0x71, 0x74, 0x75, 0x76, 0x77,
223          0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x00, 0x7e, 0x7f,
224          0x70, 0x22, 0x23, 0x21, 0x24, 0x25, 0x26, 0x27,
225          0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x00, 0x2e, 0x2f,
226          0x6e, 0x50, 0x51, 0x66, 0x54, 0x55, 0x64, 0x53,
227          0x65, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
228          0x5f, 0x6f, 0x60, 0x61, 0x62, 0x63, 0x56, 0x52,
229          0x6c, 0x6b, 0x57, 0x68, 0x6d, 0x69, 0x67, 0x6a,
230          0x4e, 0x30, 0x31, 0x46, 0x34, 0x35, 0x44, 0x33,
231          0x45, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
232          0x3f, 0x4f, 0x40, 0x41, 0x42, 0x43, 0x36, 0x32,
233          0x4c, 0x4b, 0x37, 0x48, 0x4d, 0x49, 0x47, 0x4a};
234         USE_CHARSET (charset, CYRILLIC_ISO8859_5);
235         code = cyrillic[(keysym & 0x7f) - 0x20];
236         break;
237       }
238     case 7: /* Greek */
239       {
240         static unsigned char const greek[] = /* 0x20 - 0x7f */
241         {0x00, 0x36, 0x38, 0x39, 0x3a, 0x5a, 0x00, 0x3c,
242          0x3e, 0x5b, 0x00, 0x3f, 0x00, 0x00, 0x35, 0x2f,
243          0x00, 0x5c, 0x5d, 0x5e, 0x5f, 0x7a, 0x40, 0x7c,
244          0x7d, 0x7b, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00,
245          0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
246          0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
247          0x50, 0x51, 0x53, 0x00, 0x54, 0x55, 0x56, 0x57,
248          0x58, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249          0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
250          0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
251          0x70, 0x71, 0x73, 0x72, 0x74, 0x75, 0x76, 0x77,
252          0x78, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
253         USE_CHARSET (charset, GREEK_ISO8859_7);
254         code = greek[(keysym & 0x7f) - 0x20];
255         break;
256       }
257     case 8: /* Technical */
258       break;
259     case 9: /* Special */
260       break;
261     case 10: /* Publishing */
262       break;
263     case 11: /* APL */
264       break;
265     case 12: /* Hebrew */
266       USE_CHARSET (charset, HEBREW_ISO8859_8);
267       code = keysym & 0x7f;
268       break;
269     case 13: /* Thai */
270       /* #### This needs to deal with character composition. */
271       USE_CHARSET (charset, THAI_TIS620);
272       code = keysym & 0x7f;
273       break;
274     case 14: /* Korean Hangul */
275       break;
276     case 19: /* Latin 9 - ISO8859-15 - unsupported charset. */
277       break;
278     case 32: /* Currency */
279       break;
280     default:
281       break;
282     }
283
284   if (code == 0)
285     return Qnil;
286
287 #ifdef MULE
288   return make_char (MAKE_CHAR (charset, code, 0));
289 #else
290   return make_char (code + 0x80);
291 #endif
292 }
293
294 /* #### The way that keysym correspondence to characters should work:
295    - a Lisp_Event should contain a keysym AND a character slot.
296    - keybindings are tried with the keysym.  If no binding can be found,
297    and there is a corresponding character, call self-insert-command.
298
299    #### Nuke x-iso8859-1.el.
300    #### Nuke the Qascii_character property.
301    #### Nuke Vcharacter_set_property.
302 */
303 static void
304 maybe_define_x_key_as_self_inserting_character (KeySym keysym, Lisp_Object symbol)
305 {
306   Lisp_Object character = x_keysym_to_character (keysym);
307
308   if (CHARP (character))
309     {
310       extern Lisp_Object Vcurrent_global_map;
311       extern Lisp_Object Qascii_character;
312       Fput (symbol, Qascii_character, character);
313       if (NILP (Flookup_key (Vcurrent_global_map, symbol, Qnil)))
314         Fdefine_key (Vcurrent_global_map, symbol, Qself_insert_command);
315     }
316 }
317
318 static void
319 x_has_keysym (KeySym keysym, Lisp_Object hash_table, int with_modifiers)
320 {
321   KeySym upper_lower[2];
322   int j;
323
324   if (keysym < 0x80) /* Optimize for ASCII keysyms */
325     return;
326
327   /* If you execute:
328      xmodmap -e 'keysym NN = scaron'
329      and then press (Shift scaron), X11 will return the different
330      keysym `Scaron', but  `xmodmap -pke'  might not even mention `Scaron'.
331      So we "register" both `scaron' and `Scaron'. */
332 #ifdef HAVE_XCONVERTCASE
333   XConvertCase (keysym, &upper_lower[0], &upper_lower[1]);
334 #else
335   upper_lower[0] = upper_lower[1] = keysym;
336 #endif
337
338   for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++)
339     {
340       char *name;
341       keysym = upper_lower[j];
342
343       name = XKeysymToString (keysym);
344       if (name)
345         {
346           /* X guarantees NAME to be in the Host Portable Character Encoding */
347           Lisp_Object sym = x_keysym_to_emacs_keysym (keysym, 0);
348           Lisp_Object new_value = with_modifiers ? Qt : Qsans_modifiers;
349           Lisp_Object old_value = Fgethash (sym, hash_table, Qnil);
350
351           if (! EQ (old_value, new_value)
352               && ! (EQ (old_value, Qsans_modifiers) &&
353                     EQ (new_value, Qt)))
354             {
355               maybe_define_x_key_as_self_inserting_character (keysym, sym);
356               Fputhash (build_ext_string (name, Qbinary), new_value, hash_table);
357               Fputhash (sym, new_value, hash_table);
358             }
359         }
360     }
361 }
362
363 static void
364 x_reset_key_mapping (struct device *d)
365 {
366   Display *display = DEVICE_X_DISPLAY (d);
367   struct x_device *xd = DEVICE_X_DATA (d);
368   KeySym *keysym, *keysym_end;
369   Lisp_Object hash_table;
370   int key_code_count, keysyms_per_code;
371
372   if (xd->x_keysym_map)
373     XFree ((char *) xd->x_keysym_map);
374   XDisplayKeycodes (display,
375                     &xd->x_keysym_map_min_code,
376                     &xd->x_keysym_map_max_code);
377   key_code_count = xd->x_keysym_map_max_code - xd->x_keysym_map_min_code + 1;
378   xd->x_keysym_map =
379     XGetKeyboardMapping (display, xd->x_keysym_map_min_code, key_code_count,
380                          &xd->x_keysym_map_keysyms_per_code);
381
382   hash_table = xd->x_keysym_map_hash_table;
383   if (HASH_TABLEP (hash_table))
384     Fclrhash (hash_table);
385   else
386     xd->x_keysym_map_hash_table = hash_table =
387       make_lisp_hash_table (128, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
388
389   for (keysym = xd->x_keysym_map,
390          keysyms_per_code = xd->x_keysym_map_keysyms_per_code,
391          keysym_end = keysym + (key_code_count * keysyms_per_code);
392        keysym < keysym_end;
393        keysym += keysyms_per_code)
394     {
395       int j;
396
397       if (keysym[0] == NoSymbol)
398         continue;
399
400       x_has_keysym (keysym[0], hash_table, 0);
401
402       for (j = 1; j < keysyms_per_code; j++)
403         {
404           if (keysym[j] != keysym[0] &&
405               keysym[j] != NoSymbol)
406             x_has_keysym (keysym[j], hash_table, 1);
407         }
408     }
409 }
410
411 static const char *
412 index_to_name (int indice)
413 {
414   switch (indice)
415     {
416     case ShiftMapIndex:   return "ModShift";
417     case LockMapIndex:    return "ModLock";
418     case ControlMapIndex: return "ModControl";
419     case Mod1MapIndex:    return "Mod1";
420     case Mod2MapIndex:    return "Mod2";
421     case Mod3MapIndex:    return "Mod3";
422     case Mod4MapIndex:    return "Mod4";
423     case Mod5MapIndex:    return "Mod5";
424     default:              return "???";
425     }
426 }
427
428 /* Boy, I really wish C had local functions... */
429 struct c_doesnt_have_closures   /* #### not yet used */
430 {
431   int warned_about_overlapping_modifiers;
432   int warned_about_predefined_modifiers;
433   int warned_about_duplicate_modifiers;
434   int meta_bit;
435   int hyper_bit;
436   int super_bit;
437   int alt_bit;
438   int mode_bit;
439 };
440
441 static void
442 x_reset_modifier_mapping (struct device *d)
443 {
444   Display *display = DEVICE_X_DISPLAY (d);
445   struct x_device *xd = DEVICE_X_DATA (d);
446   int modifier_index, modifier_key, column, mkpm;
447   int warned_about_overlapping_modifiers = 0;
448   int warned_about_predefined_modifiers  = 0;
449   int warned_about_duplicate_modifiers   = 0;
450   int meta_bit  = 0;
451   int hyper_bit = 0;
452   int super_bit = 0;
453   int alt_bit   = 0;
454   int mode_bit  = 0;
455
456   xd->lock_interpretation = 0;
457
458   if (xd->x_modifier_keymap)
459     XFreeModifiermap (xd->x_modifier_keymap);
460
461   x_reset_key_mapping (d);
462
463   xd->x_modifier_keymap = XGetModifierMapping (display);
464
465   /* Boy, I really wish C had local functions...
466    */
467
468   /* The call to warn_when_safe must be on the same line as the string or
469      make-msgfile won't pick it up properly (the newline doesn't confuse
470      it, but the backslash does). */
471
472 #define modwarn(name,old,other)                                         \
473   warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates %s, which is generated by %s.", \
474                   name, code, index_to_name (old), other),              \
475   warned_about_overlapping_modifiers = 1
476
477 #define modbarf(name,other)                                                 \
478   warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates %s, which is nonsensical.", \
479                   name, code, other),                                       \
480   warned_about_predefined_modifiers = 1
481
482 #define check_modifier(name,mask)                                             \
483   if ((1<<modifier_index) != mask)                                            \
484     warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates %s, which is nonsensical.", \
485                     name, code, index_to_name (modifier_index)),              \
486     warned_about_predefined_modifiers = 1
487
488 #define store_modifier(name,old)                                           \
489   if (old && old != modifier_index)                                        \
490     warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates both %s and %s, which is nonsensical.",\
491                     name, code, index_to_name (old),                       \
492                     index_to_name (modifier_index)),                       \
493     warned_about_duplicate_modifiers = 1;                                  \
494   if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift");          \
495   else if (modifier_index == LockMapIndex) modbarf (name,"ModLock");       \
496   else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
497   else if (sym == XK_Mode_switch)                                          \
498     mode_bit = modifier_index; /* Mode_switch is special, see below... */  \
499   else if (modifier_index == meta_bit && old != meta_bit)                  \
500     modwarn (name, meta_bit, "Meta");                                      \
501   else if (modifier_index == super_bit && old != super_bit)                \
502     modwarn (name, super_bit, "Super");                                    \
503   else if (modifier_index == hyper_bit && old != hyper_bit)                \
504     modwarn (name, hyper_bit, "Hyper");                                    \
505   else if (modifier_index == alt_bit && old != alt_bit)                    \
506     modwarn (name, alt_bit, "Alt");                                        \
507   else                                                                     \
508     old = modifier_index;
509
510   mkpm = xd->x_modifier_keymap->max_keypermod;
511   for (modifier_index = 0; modifier_index < 8; modifier_index++)
512     for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
513       KeySym last_sym = 0;
514       for (column = 0; column < 4; column += 2) {
515         KeyCode code = xd->x_modifier_keymap->modifiermap[modifier_index * mkpm
516                                                           + modifier_key];
517         KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0);
518         if (sym == last_sym) continue;
519         last_sym = sym;
520         switch (sym) {
521         case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break;
522         case XK_Meta_L:     store_modifier ("Meta_L", meta_bit); break;
523         case XK_Meta_R:     store_modifier ("Meta_R", meta_bit); break;
524         case XK_Super_L:    store_modifier ("Super_L", super_bit); break;
525         case XK_Super_R:    store_modifier ("Super_R", super_bit); break;
526         case XK_Hyper_L:    store_modifier ("Hyper_L", hyper_bit); break;
527         case XK_Hyper_R:    store_modifier ("Hyper_R", hyper_bit); break;
528         case XK_Alt_L:      store_modifier ("Alt_L", alt_bit); break;
529         case XK_Alt_R:      store_modifier ("Alt_R", alt_bit); break;
530         case XK_Control_L:  check_modifier ("Control_L", ControlMask); break;
531         case XK_Control_R:  check_modifier ("Control_R", ControlMask); break;
532         case XK_Shift_L:    check_modifier ("Shift_L", ShiftMask); break;
533         case XK_Shift_R:    check_modifier ("Shift_R", ShiftMask); break;
534         case XK_Shift_Lock: check_modifier ("Shift_Lock", LockMask);
535           xd->lock_interpretation = XK_Shift_Lock; break;
536         case XK_Caps_Lock:  check_modifier ("Caps_Lock", LockMask);
537           xd->lock_interpretation = XK_Caps_Lock; break;
538
539         /* It probably doesn't make any sense for a modifier bit to be
540            assigned to a key that is not one of the above, but OpenWindows
541            assigns modifier bits to a couple of random function keys for
542            no reason that I can discern, so printing a warning here would
543            be annoying. */
544         }
545       }
546     }
547 #undef store_modifier
548 #undef check_modifier
549 #undef modwarn
550 #undef modbarf
551
552   /* If there was no Meta key, then try using the Alt key instead.
553      If there is both a Meta key and an Alt key, then the Alt key
554      is not disturbed and remains an Alt key. */
555   if (! meta_bit && alt_bit)
556     meta_bit = alt_bit, alt_bit = 0;
557
558   /* mode_bit overrides everything, since it's processed down inside of
559      XLookupString() instead of by us.  If Meta and Mode_switch both
560      generate the same modifier bit (which is an error), then we don't
561      interpret that bit as Meta, because we can't make XLookupString()
562      not interpret it as Mode_switch; and interpreting it as both would
563      be totally wrong. */
564   if (mode_bit)
565     {
566       const char *warn = 0;
567       if      (mode_bit == meta_bit)  warn = "Meta",  meta_bit  = 0;
568       else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
569       else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
570       else if (mode_bit == alt_bit)   warn = "Alt",   alt_bit   = 0;
571       if (warn)
572         {
573           warn_when_safe
574             (Qkey_mapping, Qwarning,
575              "XEmacs:  %s is being used for both Mode_switch and %s.",
576              index_to_name (mode_bit), warn),
577             warned_about_overlapping_modifiers = 1;
578         }
579     }
580 #undef index_to_name
581
582   xd->MetaMask   = (meta_bit   ? (1 << meta_bit)  : 0);
583   xd->HyperMask  = (hyper_bit  ? (1 << hyper_bit) : 0);
584   xd->SuperMask  = (super_bit  ? (1 << super_bit) : 0);
585   xd->AltMask    = (alt_bit    ? (1 << alt_bit)   : 0);
586   xd->ModeMask   = (mode_bit   ? (1 << mode_bit)  : 0); /* unused */
587
588
589   if (warned_about_overlapping_modifiers)
590     warn_when_safe (Qkey_mapping, Qwarning, "\n"
591 "       Two distinct modifier keys (such as Meta and Hyper) cannot generate\n"
592 "       the same modifier bit, because Emacs won't be able to tell which\n"
593 "       modifier was actually held down when some other key is pressed.  It\n"
594 "       won't be able to tell Meta-x and Hyper-x apart, for example.  Change\n"
595 "       one of these keys to use some other modifier bit.  If you intend for\n"
596 "       these keys to have the same behavior, then change them to have the\n"
597 "       same keysym as well as the same modifier bit.");
598
599   if (warned_about_predefined_modifiers)
600     warn_when_safe (Qkey_mapping, Qwarning, "\n"
601 "       The semantics of the modifier bits ModShift, ModLock, and ModControl\n"
602 "       are predefined.  It does not make sense to assign ModControl to any\n"
603 "       keysym other than Control_L or Control_R, or to assign any modifier\n"
604 "       bits to the \"control\" keysyms other than ModControl.  You can't\n"
605 "       turn a \"control\" key into a \"meta\" key (or vice versa) by simply\n"
606 "       assigning the key a different modifier bit.  You must also make that\n"
607 "       key generate an appropriate keysym (Control_L, Meta_L, etc).");
608
609   /* No need to say anything more for warned_about_duplicate_modifiers. */
610
611   if (warned_about_overlapping_modifiers || warned_about_predefined_modifiers)
612     warn_when_safe (Qkey_mapping, Qwarning, "\n"
613 "       The meanings of the modifier bits Mod1 through Mod5 are determined\n"
614 "       by the keysyms used to control those bits.  Mod1 does NOT always\n"
615 "       mean Meta, although some non-ICCCM-compliant programs assume that.");
616 }
617
618 void
619 x_init_modifier_mapping (struct device *d)
620 {
621   struct x_device *xd = DEVICE_X_DATA (d);
622   xd->x_keysym_map_hash_table = Qnil;
623   xd->x_keysym_map = NULL;
624   xd->x_modifier_keymap = NULL;
625   x_reset_modifier_mapping (d);
626 }
627
628 static int
629 x_key_is_modifier_p (KeyCode keycode, struct device *d)
630 {
631   struct x_device *xd = DEVICE_X_DATA (d);
632   KeySym *syms;
633   int i;
634
635   if (keycode < xd->x_keysym_map_min_code ||
636       keycode > xd->x_keysym_map_max_code)
637     return 0;
638
639   syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) *
640                            xd->x_keysym_map_keysyms_per_code];
641   for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
642     if (IsModifierKey (syms [i]) ||
643         syms [i] == XK_Mode_switch) /* why doesn't IsModifierKey count this? */
644       return 1;
645   return 0;
646 }
647
648 /* key-handling code is always ugly.  It just ends up working out
649    that way.
650
651    Here are some pointers:
652
653    -- DOWN_MASK indicates which modifiers should be treated as "down"
654       when the corresponding upstroke happens.  It gets reset for
655       a particular modifier when that modifier goes up, and reset
656       for all modifiers when a non-modifier key is pressed.  Example:
657
658       I press Control-A-Shift and then release Control-A-Shift.
659       I want the Shift key to be sticky but not the Control key.
660
661    -- LAST_DOWNKEY and RELEASE_TIME are used to keep track of
662       auto-repeat -- see below.
663
664    -- If a modifier key is sticky, I can unstick it by pressing
665       the modifier key again. */
666
667 static void
668 x_handle_sticky_modifiers (XEvent *ev, struct device *d)
669 {
670   struct x_device *xd;
671   KeyCode keycode;
672   int type;
673
674   if (!modifier_keys_are_sticky) /* Optimize for non-sticky modifiers */
675     return;
676
677   xd = DEVICE_X_DATA (d);
678   keycode = ev->xkey.keycode;
679   type = ev->type;
680
681   if (keycode < xd->x_keysym_map_min_code ||
682       keycode > xd->x_keysym_map_max_code)
683     return;
684
685   if (! ((type == KeyPress || type == KeyRelease) &&
686          x_key_is_modifier_p (keycode, d)))
687     { /* Not a modifier key */
688       Bool key_event_p = (type == KeyPress || type == KeyRelease);
689
690       if (type == KeyPress && !xd->last_downkey)
691         xd->last_downkey = keycode;
692       else if (type == ButtonPress ||
693                (type == KeyPress && xd->last_downkey &&
694                 (keycode != xd->last_downkey ||
695                  ev->xkey.time != xd->release_time)))
696         {
697           xd->need_to_add_mask = 0;
698           xd->last_downkey = 0;
699         }
700       if (type == KeyPress)
701         xd->release_time = 0;
702       if (type == KeyPress || type == ButtonPress)
703         xd->down_mask = 0;
704
705       if (key_event_p)
706         ev->xkey.state    |= xd->need_to_add_mask;
707       else
708         ev->xbutton.state |= xd->need_to_add_mask;
709
710       if (type == KeyRelease && keycode == xd->last_downkey)
711         /* If I hold press-and-release the Control key and then press
712            and hold down the right arrow, I want it to auto-repeat
713            Control-Right.  On the other hand, if I do the same but
714            manually press the Right arrow a bunch of times, I want
715            to see one Control-Right and then a bunch of Rights.
716            This means that we need to distinguish between an
717            auto-repeated key and a key pressed and released a bunch
718            of times.
719
720            Naturally, the designers of the X spec didn't see fit
721            to provide an obvious way to distinguish these cases.
722            So we assume that if the release and the next press
723            occur at the same time, the key was actually auto-
724            repeated.  Under Open-Windows, at least, this works. */
725         xd->release_time = key_event_p ? ev->xkey.time : ev->xbutton.time;
726     }
727   else                          /* Modifier key pressed */
728     {
729       int i;
730       KeySym *syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) *
731                                         xd->x_keysym_map_keysyms_per_code];
732
733       /* If a non-modifier key was pressed in the middle of a bunch
734          of modifiers, then it unsticks all the modifiers that were
735          previously pressed.  We cannot unstick the modifiers until
736          now because we want to check for auto-repeat of the
737          non-modifier key. */
738
739       if (xd->last_downkey)
740         {
741           xd->last_downkey = 0;
742           xd->need_to_add_mask = 0;
743         }
744
745 #define FROB(mask)                              \
746 do {                                            \
747   if (type == KeyPress)                         \
748     {                                           \
749       /* If modifier key is already sticky,     \
750          then unstick it.  Note that we do      \
751          not test down_mask to deal with the    \
752          unlikely but possible case that the    \
753          modifier key auto-repeats. */          \
754       if (xd->need_to_add_mask & mask)          \
755         {                                       \
756           xd->need_to_add_mask &= ~mask;        \
757           xd->down_mask &= ~mask;               \
758         }                                       \
759       else                                      \
760         xd->down_mask |= mask;                  \
761     }                                           \
762   else                                          \
763     {                                           \
764       if (xd->down_mask & mask)                 \
765         {                                       \
766           xd->down_mask &= ~mask;               \
767           xd->need_to_add_mask |= mask;         \
768         }                                       \
769     }                                           \
770 } while (0)
771
772       for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
773         switch (syms[i])
774           {
775           case XK_Control_L: case XK_Control_R: FROB (ControlMask);   break;
776           case XK_Shift_L:   case XK_Shift_R:   FROB (ShiftMask);     break;
777           case XK_Meta_L:    case XK_Meta_R:    FROB (xd->MetaMask);  break;
778           case XK_Super_L:   case XK_Super_R:   FROB (xd->SuperMask); break;
779           case XK_Hyper_L:   case XK_Hyper_R:   FROB (xd->HyperMask); break;
780           case XK_Alt_L:     case XK_Alt_R:     FROB (xd->AltMask);   break;
781           }
782     }
783 #undef FROB
784 }
785
786 static void
787 clear_sticky_modifiers (struct device *d)
788 {
789   struct x_device *xd = DEVICE_X_DATA (d);
790
791   xd->need_to_add_mask = 0;
792   xd->last_downkey     = 0;
793   xd->release_time     = 0;
794   xd->down_mask        = 0;
795 }
796
797 static int
798 keysym_obeys_caps_lock_p (KeySym sym, struct device *d)
799 {
800   struct x_device *xd = DEVICE_X_DATA (d);
801   /* Eeeeevil hack.  Don't apply Caps_Lock to things that aren't alphabetic
802      characters, where "alphabetic" means something more than simply A-Z.
803      That is, if Caps_Lock is down, typing ESC doesn't produce Shift-ESC.
804      But if shift-lock is down, then it does. */
805   if (xd->lock_interpretation == XK_Shift_Lock)
806     return 1;
807
808   return
809     ((sym >= XK_A)        && (sym <= XK_Z))          ||
810     ((sym >= XK_a)        && (sym <= XK_z))          ||
811     ((sym >= XK_Agrave)   && (sym <= XK_Odiaeresis)) ||
812     ((sym >= XK_agrave)   && (sym <= XK_odiaeresis)) ||
813     ((sym >= XK_Ooblique) && (sym <= XK_Thorn))      ||
814     ((sym >= XK_oslash)   && (sym <= XK_thorn));
815 }
816
817 /* called from EmacsFrame.c (actually from Xt itself) when a
818    MappingNotify event is received.  In its infinite wisdom, Xt
819    decided that Xt event handlers never get MappingNotify events.
820    O'Reilly Xt Programming Manual 9.1.2 says:
821
822    MappingNotify is automatically handled by Xt, so it isn't passed
823    to event handlers and you don't need to worry about it.
824
825    Of course, we DO worry about it, so we need a special translation. */
826 void
827 emacs_Xt_mapping_action (Widget w, XEvent* event)
828 {
829   struct device *d = get_device_from_display (event->xany.display);
830
831   if (DEVICE_X_BEING_DELETED (d))
832     return;
833 #if 0
834   /* nyet.  Now this is handled by Xt. */
835   XRefreshKeyboardMapping (&event->xmapping);
836 #endif
837   /* xmodmap generates about a billion MappingKeyboard events, followed
838      by a single MappingModifier event, so it might be worthwhile to
839      take extra MappingKeyboard events out of the queue before requesting
840      the current keymap from the server. */
841   switch (event->xmapping.request)
842     {
843     case MappingKeyboard:  x_reset_key_mapping      (d); break;
844     case MappingModifier:  x_reset_modifier_mapping (d); break;
845     case MappingPointer:   /* Do something here? */      break;
846     default: abort();
847     }
848 }
849
850 \f
851 /************************************************************************/
852 /*                  X to Emacs event conversion                         */
853 /************************************************************************/
854
855 static Lisp_Object
856 x_keysym_to_emacs_keysym (KeySym keysym, int simple_p)
857 {
858   char *name;
859   if (keysym >= XK_exclam && keysym <= XK_asciitilde)
860     /* We must assume that the X keysym numbers for the ASCII graphic
861        characters are the same as their ASCII codes.  */
862     return make_char (keysym);
863
864   switch (keysym)
865     {
866       /* These would be handled correctly by the default case, but by
867          special-casing them here we don't garbage a string or call
868          intern().  */
869     case XK_BackSpace:  return QKbackspace;
870     case XK_Tab:        return QKtab;
871     case XK_Linefeed:   return QKlinefeed;
872     case XK_Return:     return QKreturn;
873     case XK_Escape:     return QKescape;
874     case XK_space:      return QKspace;
875     case XK_Delete:     return QKdelete;
876     case 0:             return Qnil;
877     default:
878       if (simple_p) return Qnil;
879       /* !!#### not Mule-ized */
880       name = XKeysymToString (keysym);
881       if (!name || !name[0])
882         /* This happens if there is a mismatch between the Xlib of
883            XEmacs and the Xlib of the X server...
884
885            Let's hard-code in some knowledge of common keysyms introduced
886            in recent X11 releases.  Snarfed from X11/keysymdef.h
887
888            Probably we should add some stuff here for X11R6. */
889         switch (keysym)
890           {
891           case 0xFF95: return KEYSYM ("kp-home");
892           case 0xFF96: return KEYSYM ("kp-left");
893           case 0xFF97: return KEYSYM ("kp-up");
894           case 0xFF98: return KEYSYM ("kp-right");
895           case 0xFF99: return KEYSYM ("kp-down");
896           case 0xFF9A: return KEYSYM ("kp-prior");
897           case 0xFF9B: return KEYSYM ("kp-next");
898           case 0xFF9C: return KEYSYM ("kp-end");
899           case 0xFF9D: return KEYSYM ("kp-begin");
900           case 0xFF9E: return KEYSYM ("kp-insert");
901           case 0xFF9F: return KEYSYM ("kp-delete");
902
903           case 0x1005FF10: return KEYSYM ("SunF36"); /* labeled F11 */
904           case 0x1005FF11: return KEYSYM ("SunF37"); /* labeled F12 */
905           default:
906             {
907               char buf [64];
908               sprintf (buf, "unknown-keysym-0x%X", (int) keysym);
909               return KEYSYM (buf);
910             }
911           }
912       /* If it's got a one-character name, that's good enough. */
913       if (!name[1])
914         return make_char (name[0]);
915
916       /* If it's in the "Keyboard" character set, downcase it.
917          The case of those keysyms is too totally random for us to
918          force anyone to remember them.
919          The case of the other character sets is significant, however.
920          */
921       if ((((unsigned int) keysym) & (~0x1FF)) == ((unsigned int) 0xFE00))
922         {
923           char buf [255];
924           char *s1, *s2;
925           for (s1 = name, s2 = buf; *s1; s1++, s2++) {
926             if (*s1 == '_') {
927               *s2 = '-';
928             } else {
929               *s2 = tolower (* (unsigned char *) s1);
930             }
931           }
932           *s2 = 0;
933           return KEYSYM (buf);
934         }
935       return KEYSYM (name);
936     }
937 }
938
939 static Lisp_Object
940 x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p)
941      /* simple_p means don't try too hard (ASCII only) */
942 {
943   KeySym keysym = 0;
944
945 #ifdef HAVE_XIM
946   int len;
947   char buffer[64];
948   char *bufptr = buffer;
949   int   bufsiz = sizeof (buffer);
950   Status status;
951 #ifdef XIM_XLIB
952   XIC xic = FRAME_X_XIC (x_any_window_to_frame
953                          (get_device_from_display (event->display),
954                           event->window));
955 #endif /* XIM_XLIB */
956 #endif /* HAVE_XIM */
957
958   /* We use XLookupString if we're not using XIM, or are using
959      XIM_XLIB but input context creation failed. */
960 #if ! (defined (HAVE_XIM) && defined (XIM_MOTIF))
961 #if defined (HAVE_XIM) && defined (XIM_XLIB)
962      if (!xic)
963 #endif /* XIM_XLIB */
964     {
965       /* Apparently it's necessary to specify a dummy here (rather
966          than passing in 0) to avoid crashes on German IRIX */
967       char dummy[256];
968       XLookupString (event, dummy, 200, &keysym, 0);
969       return (IsModifierKey (keysym) || keysym == XK_Mode_switch )
970         ? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p);
971     }
972 #endif /* ! XIM_MOTIF */
973
974 #ifdef HAVE_XIM
975  Lookup_String: /* Come-From XBufferOverflow */
976 #ifdef XIM_MOTIF
977   len = XmImMbLookupString (XtWindowToWidget (event->display, event->window),
978                             event, bufptr, bufsiz, &keysym, &status);
979 #else /* XIM_XLIB */
980   if (xic)
981     len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status);
982 #endif /* HAVE_XIM */
983
984 #ifdef DEBUG_XEMACS
985   if (x_debug_events > 0)
986     {
987       stderr_out ("   status=");
988 #define print_status_when(S) if (status == S) stderr_out (#S)
989       print_status_when (XLookupKeySym);
990       print_status_when (XLookupBoth);
991       print_status_when (XLookupChars);
992       print_status_when (XLookupNone);
993       print_status_when (XBufferOverflow);
994
995       if (status == XLookupKeySym || status == XLookupBoth)
996         stderr_out (" keysym=%s",  XKeysymToString (keysym));
997       if (status == XLookupChars  || status == XLookupBoth)
998         {
999           if (len != 1)
1000             {
1001               int j;
1002               stderr_out (" chars=\"");
1003               for (j=0; j<len; j++)
1004                 stderr_out ("%c", bufptr[j]);
1005               stderr_out ("\"");
1006             }
1007           else if (bufptr[0] <= 32 || bufptr[0] >= 127)
1008             stderr_out (" char=0x%x", bufptr[0]);
1009           else
1010             stderr_out (" char=%c", bufptr[0]);
1011         }
1012       stderr_out ("\n");
1013     }
1014 #endif /* DEBUG_XEMACS */
1015
1016   switch (status)
1017     {
1018     case XLookupKeySym:
1019     case XLookupBoth:
1020       return (IsModifierKey (keysym) || keysym == XK_Mode_switch )
1021         ? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p);
1022
1023     case XLookupChars:
1024       {
1025         /* Generate multiple emacs events */
1026         struct device *d = get_device_from_display (event->display);
1027         Emchar ch;
1028         Lisp_Object instream, fb_instream;
1029         Lstream *istr;
1030         struct gcpro gcpro1, gcpro2;
1031
1032         fb_instream = make_fixed_buffer_input_stream (bufptr, len);
1033
1034         /* #### Use Fget_coding_system (Vcomposed_input_coding_system) */
1035         instream =
1036           make_decoding_input_stream (XLSTREAM (fb_instream),
1037                                       Fget_coding_system (Qundecided));
1038
1039         istr = XLSTREAM (instream);
1040
1041         GCPRO2 (instream, fb_instream);
1042         while ((ch = Lstream_get_emchar (istr)) != EOF)
1043           {
1044             Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
1045             Lisp_Event *ev          = XEVENT (emacs_event);
1046             ev->channel             = DEVICE_CONSOLE (d);
1047             ev->event_type          = key_press_event;
1048             ev->timestamp           = event->time;
1049             ev->event.key.modifiers = 0;
1050             ev->event.key.keysym    = make_char (ch);
1051             enqueue_Xt_dispatch_event (emacs_event);
1052           }
1053         Lstream_close (istr);
1054         UNGCPRO;
1055         Lstream_delete (istr);
1056         Lstream_delete (XLSTREAM (fb_instream));
1057         return Qnil;
1058       }
1059     case XLookupNone: return Qnil;
1060     case XBufferOverflow:
1061       bufptr = (char *) alloca (len+1);
1062       bufsiz = len+1;
1063       goto Lookup_String;
1064     }
1065   return Qnil; /* not reached */
1066 #endif /* HAVE_XIM */
1067 }
1068
1069 static void
1070 set_last_server_timestamp (struct device *d, XEvent *x_event)
1071 {
1072   Time t;
1073   switch (x_event->type)
1074     {
1075     case KeyPress:
1076     case KeyRelease:       t = x_event->xkey.time;              break;
1077     case ButtonPress:
1078     case ButtonRelease:    t = x_event->xbutton.time;           break;
1079     case EnterNotify:
1080     case LeaveNotify:      t = x_event->xcrossing.time;         break;
1081     case MotionNotify:     t = x_event->xmotion.time;           break;
1082     case PropertyNotify:   t = x_event->xproperty.time;         break;
1083     case SelectionClear:   t = x_event->xselectionclear.time;   break;
1084     case SelectionRequest: t = x_event->xselectionrequest.time; break;
1085     case SelectionNotify:  t = x_event->xselection.time;        break;
1086     default: return;
1087     }
1088   DEVICE_X_LAST_SERVER_TIMESTAMP (d) = t;
1089 }
1090
1091 static int
1092 x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
1093 {
1094   Display *display    = x_event->xany.display;
1095   struct device *d    = get_device_from_display (display);
1096   struct x_device *xd = DEVICE_X_DATA (d);
1097
1098   if (DEVICE_X_BEING_DELETED (d))
1099      /* #### Uh, is this 0 correct? */
1100      return 0;
1101
1102   set_last_server_timestamp (d, x_event);
1103
1104   switch (x_event->type)
1105     {
1106     case KeyRelease:
1107       x_handle_sticky_modifiers (x_event, d);
1108       return 0;
1109
1110     case KeyPress:
1111     case ButtonPress:
1112     case ButtonRelease:
1113       {
1114         int modifiers = 0;
1115         int shift_p, lock_p;
1116         Bool key_event_p = (x_event->type == KeyPress);
1117         unsigned int *state =
1118           key_event_p ? &x_event->xkey.state : &x_event->xbutton.state;
1119
1120         /* If this is a synthetic KeyPress or Button event, and the user
1121            has expressed a disinterest in this security hole, then drop
1122            it on the floor. */
1123         if ((key_event_p
1124              ? x_event->xkey.send_event
1125              : x_event->xbutton.send_event)
1126 #ifdef EXTERNAL_WIDGET
1127             /* ben: events get sent to an ExternalShell using XSendEvent.
1128                This is not a perfect solution. */
1129             && !FRAME_X_EXTERNAL_WINDOW_P
1130             (x_any_window_to_frame (d, x_event->xany.window))
1131 #endif
1132             && !x_allow_sendevents)
1133           return 0;
1134
1135         DEVICE_X_MOUSE_TIMESTAMP (d) =
1136           DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d) =
1137           key_event_p ? x_event->xkey.time : x_event->xbutton.time;
1138
1139         x_handle_sticky_modifiers (x_event, d);
1140
1141         if (*state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
1142         if (*state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
1143         if (*state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
1144         if (*state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
1145         if (*state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
1146
1147         /* Ignore the Caps_Lock key if:
1148            - any other modifiers are down, so that Caps_Lock doesn't
1149              turn C-x into C-X, which would suck.
1150            - the event was a mouse event. */
1151         if (modifiers || ! key_event_p)
1152           *state &= (~LockMask);
1153
1154         shift_p = *state & ShiftMask;
1155         lock_p  = *state & LockMask;
1156
1157         if (shift_p || lock_p)
1158           modifiers |= XEMACS_MOD_SHIFT;
1159
1160         if (key_event_p)
1161           {
1162             Lisp_Object keysym;
1163             XKeyEvent *ev = &x_event->xkey;
1164             /* This used to compute the frame from the given X window and
1165                store it here, but we really don't care about the frame. */
1166             emacs_event->channel = DEVICE_CONSOLE (d);
1167             keysym = x_to_emacs_keysym (&x_event->xkey, 0);
1168
1169             /* If the emacs keysym is nil, then that means that the X
1170                keysym was either a Modifier or NoSymbol, which
1171                probably means that we're in the midst of reading a
1172                Multi_key sequence, or a "dead" key prefix, or XIM
1173                input. Ignore it. */
1174             if (NILP (keysym))
1175               return 0;
1176
1177             /* More Caps_Lock garbage: Caps_Lock should *only* add the
1178                shift modifier to two-case keys (that is, A-Z and
1179                related characters). So at this point (after looking up
1180                the keysym) if the keysym isn't a dual-case alphabetic,
1181                and if the caps lock key was down but the shift key
1182                wasn't, then turn off the shift modifier.  Gag barf */
1183             /* #### type lossage: assuming equivalence of emacs and
1184                X keysyms */
1185             /* !!#### maybe fix for Mule */
1186             if (lock_p && !shift_p &&
1187                 ! (CHAR_OR_CHAR_INTP (keysym)
1188                    && keysym_obeys_caps_lock_p
1189                    ((KeySym) XCHAR_OR_CHAR_INT (keysym), d)))
1190               modifiers &= (~XEMACS_MOD_SHIFT);
1191
1192             /* If this key contains two distinct keysyms, that is,
1193                "shift" generates a different keysym than the
1194                non-shifted key, then don't apply the shift modifier
1195                bit: it's implicit.  Otherwise, if there would be no
1196                other way to tell the difference between the shifted
1197                and unshifted version of this key, apply the shift bit.
1198                Non-graphics, like Backspace and F1 get the shift bit
1199                in the modifiers slot.  Neither the characters "a",
1200                "A", "2", nor "@" normally have the shift bit set.
1201                However, "F1" normally does. */
1202             if (modifiers & XEMACS_MOD_SHIFT)
1203               {
1204                 int Mode_switch_p = *state & xd->ModeMask;
1205                 KeySym bot = XLookupKeysym (ev, Mode_switch_p ? 2 : 0);
1206                 KeySym top = XLookupKeysym (ev, Mode_switch_p ? 3 : 1);
1207                 if (top && bot && top != bot)
1208                   modifiers &= ~XEMACS_MOD_SHIFT;
1209               }
1210             emacs_event->event_type          = key_press_event;
1211             emacs_event->timestamp           = ev->time;
1212             emacs_event->event.key.modifiers = modifiers;
1213             emacs_event->event.key.keysym    = keysym;
1214           }
1215         else                    /* Mouse press/release event */
1216           {
1217             XButtonEvent *ev = &x_event->xbutton;
1218             struct frame *frame = x_window_to_frame (d, ev->window);
1219
1220             if (! frame)
1221               return 0; /* not for us */
1222             XSETFRAME (emacs_event->channel, frame);
1223
1224             emacs_event->event_type = (x_event->type == ButtonPress) ?
1225               button_press_event : button_release_event;
1226
1227             emacs_event->event.button.modifiers = modifiers;
1228             emacs_event->timestamp              = ev->time;
1229             emacs_event->event.button.button    = ev->button;
1230             emacs_event->event.button.x         = ev->x;
1231             emacs_event->event.button.y         = ev->y;
1232             /* because we don't seem to get a FocusIn event for button clicks
1233                when a widget-glyph is selected we will assume that we want the
1234                focus if a button gets pressed. */
1235             if (x_event->type == ButtonPress)
1236               handle_focus_event_1 (frame, 1);
1237           }
1238       }
1239     break;
1240
1241     case MotionNotify:
1242       {
1243         XMotionEvent *ev = &x_event->xmotion;
1244         struct frame *frame = x_window_to_frame (d, ev->window);
1245         int modifiers = 0;
1246         XMotionEvent event2;
1247
1248         if (! frame)
1249           return 0; /* not for us */
1250
1251         /* We use MotionHintMask, so we will get only one motion event
1252            until the next time we call XQueryPointer or the user
1253            clicks the mouse.  So call XQueryPointer now (meaning that
1254            the event will be in sync with the server just before
1255            Fnext_event() returns).  If the mouse is still in motion,
1256            then the server will immediately generate exactly one more
1257            motion event, which will be on the queue waiting for us
1258            next time around. */
1259         event2 = *ev;
1260         if (XQueryPointer (event2.display, event2.window,
1261                            &event2.root,   &event2.subwindow,
1262                            &event2.x_root, &event2.y_root,
1263                            &event2.x,      &event2.y,
1264                            &event2.state))
1265           ev = &event2; /* only one structure copy */
1266
1267         DEVICE_X_MOUSE_TIMESTAMP (d) = ev->time;
1268
1269         XSETFRAME (emacs_event->channel, frame);
1270         emacs_event->event_type     = pointer_motion_event;
1271         emacs_event->timestamp      = ev->time;
1272         emacs_event->event.motion.x = ev->x;
1273         emacs_event->event.motion.y = ev->y;
1274         if (ev->state & ShiftMask)      modifiers |= XEMACS_MOD_SHIFT;
1275         if (ev->state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
1276         if (ev->state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
1277         if (ev->state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
1278         if (ev->state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
1279         if (ev->state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
1280         /* Currently ignores Shift_Lock but probably shouldn't
1281            (but it definitely should ignore Caps_Lock). */
1282         emacs_event->event.motion.modifiers = modifiers;
1283       }
1284     break;
1285
1286     case ClientMessage:
1287       {
1288         /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is
1289            passed as the timestamp of the TAKE_FOCUS, which the ICCCM
1290            explicitly prohibits. */
1291         XClientMessageEvent *ev = &x_event->xclient;
1292 #ifdef HAVE_OFFIX_DND
1293         if (DndIsDropMessage(x_event))
1294           {
1295             unsigned int state;
1296             int modifiers = 0;
1297             unsigned int button=0;
1298             struct frame *frame = x_any_window_to_frame (d, ev->window);
1299             Extbyte *data;
1300             unsigned long size, dtype;
1301             Lisp_Object l_type = Qnil, l_data = Qnil;
1302             Lisp_Object l_dndlist = Qnil, l_item = Qnil;
1303             struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1304
1305             GCPRO4 (l_type, l_data, l_dndlist, l_item);
1306
1307             if (! frame)
1308               return 0; /* not for us */
1309             XSETFRAME (emacs_event->channel, frame);
1310
1311             emacs_event->event_type = misc_user_event;
1312             emacs_event->timestamp  = DEVICE_X_LAST_SERVER_TIMESTAMP (d);
1313
1314             state=DndDragButtons(x_event);
1315
1316             if (state & ShiftMask)      modifiers |= XEMACS_MOD_SHIFT;
1317             if (state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
1318             if (state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
1319             if (state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
1320             if (state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
1321             if (state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
1322
1323             if (state & Button5Mask)    button = Button5;
1324             if (state & Button4Mask)    button = Button4;
1325             if (state & Button3Mask)    button = Button3;
1326             if (state & Button2Mask)    button = Button2;
1327             if (state & Button1Mask)    button = Button1;
1328
1329             emacs_event->event.misc.modifiers = modifiers;
1330             emacs_event->event.misc.button    = button;
1331
1332             DndDropCoordinates(FRAME_X_TEXT_WIDGET(frame), x_event,
1333                                &(emacs_event->event.misc.x),
1334                                &(emacs_event->event.misc.y) );
1335
1336             DndGetData(x_event,&data,&size);
1337
1338             dtype=DndDataType(x_event);
1339             switch (dtype)
1340               {
1341               case DndFiles: /* null terminated strings, end null */
1342                 {
1343                   int len;
1344                   char *hurl = NULL;
1345
1346                   while (*data)
1347                     {
1348                       len = strlen ((char*)data);
1349                       hurl = dnd_url_hexify_string ((char *)data, "file:");
1350                       l_item = make_string ((Bufbyte *)hurl, strlen (hurl));
1351                       l_dndlist = Fcons (l_item, l_dndlist);
1352                       data += len + 1;
1353                       xfree (hurl);
1354                     }
1355                   l_type = Qdragdrop_URL;
1356                 }
1357                 break;
1358               case DndText:
1359                 l_type = Qdragdrop_MIME;
1360                 l_dndlist = list1 ( list3 ( list1 ( make_string ((Bufbyte *)"text/plain", 10) ),
1361                                             make_string ((Bufbyte *)"8bit", 4),
1362                                             make_ext_string ((Extbyte *)data,
1363                                                              strlen((char *)data),
1364                                                              Qctext) ) );
1365                 break;
1366               case DndMIME:
1367                 /* we have to parse this in some way to extract
1368                    content-type and params (in the tm way) and
1369                    content encoding.
1370                    OR: if data is string, let tm do the job
1371                        if data is list[2], give the first two
1372                        to tm...
1373                 */
1374                 l_type = Qdragdrop_MIME;
1375                 l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
1376                                                      strlen((char *)data),
1377                                                      Qbinary) );
1378                 break;
1379               case DndFile:
1380               case DndDir:
1381               case DndLink:
1382               case DndExe:
1383                 {
1384                   char *hurl = dnd_url_hexify_string ((char *) data, "file:");
1385
1386                   l_dndlist = list1 ( make_string ((Bufbyte *)hurl,
1387                                                    strlen (hurl)) );
1388                   l_type = Qdragdrop_URL;
1389
1390                   xfree (hurl);
1391                 }
1392                 break;
1393               case DndURL:
1394                 /* as it is a real URL it should already be escaped
1395                    and escaping again will break them (cause % is unsave) */
1396                 l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
1397                                                      strlen ((char *)data),
1398                                                      Qfile_name) );
1399                 l_type = Qdragdrop_URL;
1400                 break;
1401               default: /* Unknown, RawData and any other type */
1402                 l_dndlist = list1 ( list3 ( list1 ( make_string ((Bufbyte *)"application/octet-stream", 24) ),
1403                                             make_string ((Bufbyte *)"8bit", 4),
1404                                             make_ext_string ((Extbyte *)data,
1405                                                              size,
1406                                                              Qbinary) ) );
1407                 l_type = Qdragdrop_MIME;
1408                 break;
1409               }
1410
1411             emacs_event->event.misc.function = Qdragdrop_drop_dispatch;
1412             emacs_event->event.misc.object = Fcons (l_type, l_dndlist);
1413
1414             UNGCPRO;
1415
1416             break;
1417           }
1418 #endif /* HAVE_OFFIX_DND */
1419         if (ev->message_type == DEVICE_XATOM_WM_PROTOCOLS (d)
1420             && (Atom) (ev->data.l[0]) == DEVICE_XATOM_WM_TAKE_FOCUS (d)
1421             && (Atom) (ev->data.l[1]) == 0)
1422           {
1423             ev->data.l[1] = DEVICE_X_LAST_SERVER_TIMESTAMP (d);
1424           }
1425       }
1426     /* fall through */
1427
1428     default: /* it's a magic event */
1429       {
1430         struct frame *frame;
1431         Window w;
1432         XEvent *x_event_copy = &emacs_event->event.magic.underlying_x_event;
1433
1434 #define FROB(event_member, window_member) \
1435         x_event_copy->event_member = x_event->event_member; \
1436         w = x_event->event_member.window_member
1437
1438         switch (x_event->type)
1439           {
1440           case SelectionRequest: FROB(xselectionrequest, owner);  break;
1441           case SelectionClear:   FROB(xselectionclear, window);   break;
1442           case SelectionNotify:  FROB(xselection, requestor);     break;
1443           case PropertyNotify:   FROB(xproperty, window);         break;
1444           case ClientMessage:    FROB(xclient, window);           break;
1445           case ConfigureNotify:  FROB(xconfigure, window);        break;
1446           case Expose:
1447           case GraphicsExpose:   FROB(xexpose, window);           break;
1448           case MapNotify:
1449           case UnmapNotify:      FROB(xmap, window);              break;
1450           case EnterNotify:
1451           case LeaveNotify:      FROB(xcrossing, window);         break;
1452           case FocusIn:
1453           case FocusOut:         FROB(xfocus, window);            break;
1454           case VisibilityNotify: FROB(xvisibility, window);       break;
1455           case CreateNotify: FROB(xcreatewindow, window);         break;
1456           default:
1457             w = x_event->xany.window;
1458             *x_event_copy = *x_event;
1459             break;
1460           }
1461 #undef FROB
1462         frame = x_any_window_to_frame (d, w);
1463
1464         if (!frame)
1465           return 0;
1466
1467         emacs_event->event_type = magic_event;
1468         XSETFRAME (emacs_event->channel, frame);
1469
1470         break;
1471       }
1472     }
1473   return 1;
1474 }
1475
1476
1477 \f
1478 /************************************************************************/
1479 /*                           magic-event handling                       */
1480 /************************************************************************/
1481
1482 static void
1483 handle_focus_event_1 (struct frame *f, int in_p)
1484 {
1485 #if XtSpecificationRelease > 5
1486   Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
1487 #endif
1488 #ifdef HAVE_XIM
1489   XIM_focus_event (f, in_p);
1490 #endif /* HAVE_XIM */
1491   /* On focus change, clear all memory of sticky modifiers
1492      to avoid non-intuitive behavior. */
1493   clear_sticky_modifiers (XDEVICE (FRAME_DEVICE (f)));
1494
1495   /* We don't want to handle the focus change now, because we might
1496      be in an accept-process-output, sleep-for, or sit-for.  So
1497      we enqueue it.
1498
1499      Actually, we half handle it: we handle it as far as changing the
1500      box cursor for redisplay, but we don't call any hooks or do any
1501      select-frame stuff until after the sit-for.
1502
1503      Unfortunately native widgets break the model because they grab
1504      the keyboard focus and nothing sets it back again. I cannot find
1505      any reasonable way to do this elsewhere so we assert here that
1506      the keyboard focus is on the emacs text widget. Menus and dialogs
1507      do this in their selection callback, but we don't want that since
1508      a button having focus is legitimate. An edit field having focus
1509      is mandatory. Weirdly you get a FocusOut event when you click in
1510      a widget-glyph but you don't get a correspondng FocusIn when you
1511      click in the frame. Why is this?  */
1512   if (in_p
1513 #if XtSpecificationRelease > 5
1514       && FRAME_X_TEXT_WIDGET (f) != focus_widget
1515 #endif
1516       )
1517     {
1518       lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f),
1519                              FRAME_X_TEXT_WIDGET (f));
1520     }
1521   /* do the generic event-stream stuff. */
1522   {
1523     Lisp_Object frm;
1524     Lisp_Object conser;
1525     struct gcpro gcpro1;
1526
1527     XSETFRAME (frm, f);
1528     conser = Fcons (frm, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil));
1529     GCPRO1 (conser);
1530     emacs_handle_focus_change_preliminary (conser);
1531     enqueue_magic_eval_event (emacs_handle_focus_change_final,
1532                               conser);
1533     UNGCPRO;
1534   }
1535 }
1536
1537 /* This is called from the external-widget code */
1538
1539 void emacs_Xt_handle_focus_event (XEvent *event);
1540 void
1541 emacs_Xt_handle_focus_event (XEvent *event)
1542 {
1543   struct device *d = get_device_from_display (event->xany.display);
1544   struct frame *f;
1545
1546   if (DEVICE_X_BEING_DELETED (d))
1547     return;
1548
1549   /*
1550    * It's curious that we're using x_any_window_to_frame() instead
1551    * of x_window_to_frame().  I don't know what the impact of this is.
1552    */
1553   f = x_any_window_to_frame (d, event->xfocus.window);
1554   if (!f)
1555     /* focus events are sometimes generated just before
1556        a frame is destroyed. */
1557     return;
1558   handle_focus_event_1 (f, event->type == FocusIn);
1559 }
1560
1561 /* both MapNotify and VisibilityNotify can cause this
1562    JV is_visible has the same semantics as f->visible*/
1563 static void
1564 change_frame_visibility (struct frame *f, int is_visible)
1565 {
1566   Lisp_Object frame;
1567
1568   XSETFRAME (frame, f);
1569
1570   if (!FRAME_VISIBLE_P (f) && is_visible)
1571     {
1572       FRAME_VISIBLE_P (f) = is_visible;
1573       /* This improves the double flicker when uniconifying a frame
1574          some.  A lot of it is not showing a buffer which has changed
1575          while the frame was iconified.  To fix it further requires
1576          the good 'ol double redisplay structure. */
1577       MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1578       va_run_hook_with_args (Qmap_frame_hook, 1, frame);
1579     }
1580   else if (FRAME_VISIBLE_P (f) && !is_visible)
1581     {
1582       FRAME_VISIBLE_P (f) = 0;
1583       va_run_hook_with_args (Qunmap_frame_hook, 1, frame);
1584     }
1585   else if (FRAME_VISIBLE_P (f) * is_visible < 0)
1586     {
1587       FRAME_VISIBLE_P(f) = - FRAME_VISIBLE_P(f);
1588       if (FRAME_REPAINT_P(f))
1589               MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1590       va_run_hook_with_args (Qmap_frame_hook, 1, frame);
1591     }
1592 }
1593
1594 static void
1595 handle_map_event (struct frame *f, XEvent *event)
1596 {
1597   Lisp_Object frame;
1598
1599   XSETFRAME (frame, f);
1600   if (event->type == MapNotify)
1601     {
1602       XWindowAttributes xwa;
1603
1604       /* Bleagh!!!!!!  Apparently some window managers (e.g. MWM)
1605          send synthetic MapNotify events when a window is first
1606          created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE.
1607          Or something like that.  We initially tried a different
1608          solution below, but that ran into a different window-
1609          manager bug.
1610
1611          It seems that the only reliable way is to treat a
1612          MapNotify event as a "hint" that the window might or
1613          might not be visible, and check explicitly. */
1614
1615       XGetWindowAttributes (event->xany.display, event->xmap.window,
1616                             &xwa);
1617       if (xwa.map_state != IsViewable)
1618         {
1619           /* Calling Fframe_iconified_p is the only way we have to
1620              correctly update FRAME_ICONIFIED_P */
1621           Fframe_iconified_p (frame);
1622           return;
1623         }
1624
1625       FRAME_X_TOTALLY_VISIBLE_P (f) = 1;
1626 #if 0
1627       /* Bleagh again!!!!  We initially tried the following hack
1628          around the MWM problem, but it turns out that TWM
1629          has a race condition when you un-iconify, where it maps
1630          the window and then tells the server that the window
1631          is un-iconified.  Usually, XEmacs wakes up between
1632          those two occurrences, and thus thinks that un-iconified
1633          windows are still iconified.
1634
1635          Ah, the joys of X. */
1636
1637       /* By Emacs definition, a frame that is iconified is not
1638          visible.  Marking a frame as visible will automatically cause
1639          frame-iconified-p to return nil, regardless of whether the
1640          frame is actually iconified.  Therefore, we have to ignore
1641          MapNotify events on iconified frames. (It's not obvious
1642          to me why these are being sent, but it happens at startup
1643          with frames that are initially iconified; perhaps they are
1644          synthetic MapNotify events coming from the window manager.)
1645          Note that `frame-iconified-p' queries the server
1646          to determine whether the frame is currently iconified,
1647          rather than consulting some internal (and likely
1648          inaccurate) state flag.  Therefore, ignoring the MapNotify
1649          is correct. */
1650       if (!FRAME_VISIBLE_P (f) && NILP (Fframe_iconified_p (frame)))
1651 #endif /* 0 */
1652         change_frame_visibility (f, 1);
1653     }
1654   else
1655     {
1656       FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
1657       change_frame_visibility (f, 0);
1658       /* Calling Fframe_iconified_p is the only way we have to
1659          correctly update FRAME_ICONIFIED_P */
1660       Fframe_iconified_p (frame);
1661     }
1662 }
1663
1664 static void
1665 handle_client_message (struct frame *f, XEvent *event)
1666 {
1667   struct device *d = XDEVICE (FRAME_DEVICE (f));
1668   Lisp_Object frame;
1669
1670   XSETFRAME (frame, f);
1671
1672   if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) &&
1673       (Atom) (event->xclient.data.l[0]) == DEVICE_XATOM_WM_DELETE_WINDOW (d))
1674     {
1675       /* WM_DELETE_WINDOW is a misc-user event, but other ClientMessages,
1676          such as WM_TAKE_FOCUS, are eval events.  That's because delete-window
1677          was probably executed with a mouse click, while the others could
1678          have been sent as a result of mouse motion or some other implicit
1679          action.  (Call this a "heuristic"...)  The reason for caring about
1680          this is so that clicking on the close-box will make emacs prompt
1681          using a dialog box instead of the minibuffer if there are unsaved
1682          buffers.
1683          */
1684       enqueue_misc_user_event (frame, Qeval,
1685                                list3 (Qdelete_frame, frame, Qt));
1686     }
1687   else if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) &&
1688            (Atom) event->xclient.data.l[0] == DEVICE_XATOM_WM_TAKE_FOCUS (d))
1689     {
1690       handle_focus_event_1 (f, 1);
1691 #if 0
1692       /* If there is a dialog box up, focus on it.
1693
1694          #### Actually, we're raising it too, which is wrong.  We should
1695          #### just focus on it, but lwlib doesn't currently give us an
1696          #### easy way to do that.  This should be fixed.
1697          */
1698       unsigned long take_focus_timestamp = event->xclient.data.l[1];
1699       Widget widget = lw_raise_all_pop_up_widgets ();
1700       if (widget)
1701         {
1702           /* kludge: raise_all returns bottommost widget, but we really
1703              want the topmost.  So just raise it for now. */
1704           XMapRaised (XtDisplay (widget), XtWindow (widget));
1705           /* Grab the focus with the timestamp of the TAKE_FOCUS. */
1706           XSetInputFocus (XtDisplay (widget), XtWindow (widget),
1707                           RevertToParent, take_focus_timestamp);
1708         }
1709 #endif
1710     }
1711 }
1712
1713 static void
1714 emacs_Xt_force_event_pending (struct frame* f)
1715 {
1716   XEvent event;
1717
1718   Display* dpy = DEVICE_X_DISPLAY (XDEVICE (FRAME_DEVICE  (f)));
1719   event.xclient.type            = ClientMessage;
1720   event.xclient.display         = dpy;
1721   event.xclient.message_type    = XInternAtom (dpy, "BumpQueue", False);
1722   event.xclient.format          = 32;
1723   event.xclient.window          = 0;
1724
1725   /* Send the drop message */
1726   XSendEvent(dpy, XtWindow (FRAME_X_SHELL_WIDGET (f)),
1727              True, NoEventMask, &event);
1728   /* Force event pending to check the X queue. */
1729   quit_check_signal_tick_count++;
1730 }
1731
1732 static void
1733 emacs_Xt_handle_magic_event (Lisp_Event *emacs_event)
1734 {
1735   /* This function can GC */
1736   XEvent *event = &emacs_event->event.magic.underlying_x_event;
1737   struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event));
1738
1739   if (!FRAME_LIVE_P (f) || DEVICE_X_BEING_DELETED (XDEVICE (FRAME_DEVICE (f))))
1740     return;
1741
1742   switch (event->type)
1743     {
1744     case SelectionRequest:
1745       x_handle_selection_request (&event->xselectionrequest);
1746       break;
1747
1748     case SelectionClear:
1749       x_handle_selection_clear (&event->xselectionclear);
1750       break;
1751
1752     case SelectionNotify:
1753       x_handle_selection_notify (&event->xselection);
1754       break;
1755
1756     case PropertyNotify:
1757       x_handle_property_notify (&event->xproperty);
1758       break;
1759
1760     case Expose:
1761       if (!check_for_ignored_expose (f, event->xexpose.x, event->xexpose.y,
1762                                      event->xexpose.width, event->xexpose.height)
1763           &&
1764           !find_matching_subwindow (f, event->xexpose.x, event->xexpose.y,
1765           event->xexpose.width, event->xexpose.height))
1766         x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
1767                                event->xexpose.width, event->xexpose.height);
1768       break;
1769
1770     case GraphicsExpose: /* This occurs when an XCopyArea's source area was
1771                             obscured or not available. */
1772       x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
1773                              event->xexpose.width, event->xexpose.height);
1774       break;
1775
1776     case MapNotify:
1777     case UnmapNotify:
1778       handle_map_event (f, event);
1779       break;
1780
1781     case EnterNotify:
1782       if (event->xcrossing.detail != NotifyInferior)
1783         {
1784           Lisp_Object frame;
1785
1786           XSETFRAME (frame, f);
1787           /* FRAME_X_MOUSE_P (f) = 1; */
1788           va_run_hook_with_args (Qmouse_enter_frame_hook, 1, frame);
1789         }
1790       break;
1791
1792     case LeaveNotify:
1793       if (event->xcrossing.detail != NotifyInferior)
1794         {
1795           Lisp_Object frame;
1796
1797           XSETFRAME (frame, f);
1798           /* FRAME_X_MOUSE_P (f) = 0; */
1799           va_run_hook_with_args (Qmouse_leave_frame_hook, 1, frame);
1800         }
1801       break;
1802
1803     case FocusIn:
1804     case FocusOut:
1805
1806 #ifdef EXTERNAL_WIDGET
1807       /* External widget lossage: Ben said:
1808          YUCK.  The only way to make focus changes work properly is to
1809          completely ignore all FocusIn/FocusOut events and depend only
1810          on notifications from the ExternalClient widget. */
1811       if (FRAME_X_EXTERNAL_WINDOW_P (f))
1812         break;
1813 #endif
1814       handle_focus_event_1 (f, event->type == FocusIn);
1815       break;
1816
1817     case ClientMessage:
1818       handle_client_message (f, event);
1819       break;
1820
1821     case VisibilityNotify: /* window visibility has changed */
1822       if (event->xvisibility.window == XtWindow (FRAME_X_SHELL_WIDGET (f)))
1823         {
1824           FRAME_X_TOTALLY_VISIBLE_P (f) =
1825             (event->xvisibility.state == VisibilityUnobscured);
1826           /* Note that the fvwm pager only sends VisibilityNotify when
1827              changing pages. Is this all we need to do ? JV */
1828           /* Nope.  We must at least trigger a redisplay here.
1829              Since this case seems similar to MapNotify, I've
1830              factored out some code to change_frame_visibility().
1831              This triggers the necessary redisplay and runs
1832              (un)map-frame-hook.  - dkindred@cs.cmu.edu */
1833           /* Changed it again to support the tristate visibility flag */
1834           change_frame_visibility (f, (event->xvisibility.state
1835                                        != VisibilityFullyObscured) ? 1 : -1);
1836         }
1837       break;
1838
1839     case ConfigureNotify:
1840 #ifdef HAVE_XIM
1841       XIM_SetGeometry (f);
1842 #endif
1843       break;
1844
1845     case CreateNotify:
1846       break;
1847
1848     default:
1849       break;
1850     }
1851 }
1852
1853 \f
1854 /************************************************************************/
1855 /*                              timeout events                          */
1856 /************************************************************************/
1857
1858 static int timeout_id_tick;
1859
1860 /* Xt interval id's might not fit into an int (they're pointers, as it
1861    happens), so we need to provide a conversion list. */
1862
1863 static struct Xt_timeout
1864 {
1865   int id;
1866   XtIntervalId interval_id;
1867   struct Xt_timeout *next;
1868 } *pending_timeouts, *completed_timeouts;
1869
1870 static struct Xt_timeout_blocktype
1871 {
1872   Blocktype_declare (struct Xt_timeout);
1873 } *the_Xt_timeout_blocktype;
1874
1875 /* called by XtAppNextEvent() */
1876 static void
1877 Xt_timeout_callback (XtPointer closure, XtIntervalId *id)
1878 {
1879   struct Xt_timeout *timeout = (struct Xt_timeout *) closure;
1880   struct Xt_timeout *t2 = pending_timeouts;
1881   /* Remove this one from the list of pending timeouts */
1882   if (t2 == timeout)
1883     pending_timeouts = pending_timeouts->next;
1884   else
1885     {
1886       while (t2->next && t2->next != timeout) t2 = t2->next;
1887       assert (t2->next);
1888       t2->next = t2->next->next;
1889     }
1890   /* Add this one to the list of completed timeouts */
1891   timeout->next = completed_timeouts;
1892   completed_timeouts = timeout;
1893 }
1894
1895 static int
1896 emacs_Xt_add_timeout (EMACS_TIME thyme)
1897 {
1898   struct Xt_timeout *timeout = Blocktype_alloc (the_Xt_timeout_blocktype);
1899   EMACS_TIME current_time;
1900   int milliseconds;
1901
1902   timeout->id = timeout_id_tick++;
1903   timeout->next = pending_timeouts;
1904   pending_timeouts = timeout;
1905   EMACS_GET_TIME (current_time);
1906   EMACS_SUB_TIME (thyme, thyme, current_time);
1907   milliseconds = EMACS_SECS (thyme) * 1000 +
1908     EMACS_USECS (thyme) / 1000;
1909   if (milliseconds < 1)
1910     milliseconds = 1;
1911   timeout->interval_id = XtAppAddTimeOut (Xt_app_con, milliseconds,
1912                                           Xt_timeout_callback,
1913                                           (XtPointer) timeout);
1914   return timeout->id;
1915 }
1916
1917 static void
1918 emacs_Xt_remove_timeout (int id)
1919 {
1920   struct Xt_timeout *timeout, *t2;
1921
1922   timeout = NULL;
1923
1924   /* Find the timeout on the list of pending ones, if it's still there. */
1925   if (pending_timeouts)
1926     {
1927       if (id == pending_timeouts->id)
1928         {
1929           timeout = pending_timeouts;
1930           pending_timeouts = pending_timeouts->next;
1931         }
1932       else
1933         {
1934           t2 = pending_timeouts;
1935           while (t2->next && t2->next->id != id) t2 = t2->next;
1936           if ( t2->next)   /*found it */
1937             {
1938               timeout = t2->next;
1939               t2->next = t2->next->next;
1940             }
1941         }
1942       /* if it was pending, we have removed it from the list */
1943       if (timeout)
1944         XtRemoveTimeOut (timeout->interval_id);
1945     }
1946
1947   /* It could be that the Xt call back was already called but we didn't convert
1948      into an Emacs event yet */
1949   if (!timeout && completed_timeouts)
1950     {
1951       /* Code duplication! */
1952       if (id == completed_timeouts->id)
1953         {
1954           timeout = completed_timeouts;
1955           completed_timeouts = completed_timeouts->next;
1956         }
1957       else
1958         {
1959           t2 = completed_timeouts;
1960           while (t2->next && t2->next->id != id) t2 = t2->next;
1961           if ( t2->next)   /*found it */
1962             {
1963               timeout = t2->next;
1964               t2->next = t2->next->next;
1965             }
1966         }
1967     }
1968
1969   /* If we found the thing on the lists of timeouts,
1970      and removed it, deallocate
1971   */
1972   if (timeout)
1973     Blocktype_free (the_Xt_timeout_blocktype, timeout);
1974 }
1975
1976 static void
1977 Xt_timeout_to_emacs_event (Lisp_Event *emacs_event)
1978 {
1979   struct Xt_timeout *timeout = completed_timeouts;
1980   assert (timeout);
1981   completed_timeouts = completed_timeouts->next;
1982   emacs_event->event_type = timeout_event;
1983   /* timeout events have nil as channel */
1984   emacs_event->timestamp  = 0; /* #### wrong!! */
1985   emacs_event->event.timeout.interval_id = timeout->id;
1986   emacs_event->event.timeout.function = Qnil;
1987   emacs_event->event.timeout.object = Qnil;
1988   Blocktype_free (the_Xt_timeout_blocktype, timeout);
1989 }
1990
1991 \f
1992 /************************************************************************/
1993 /*                      process and tty events                          */
1994 /************************************************************************/
1995
1996 struct what_is_ready_closure
1997 {
1998   int fd;
1999   Lisp_Object what;
2000   XtInputId id;
2001 };
2002
2003 static Lisp_Object *filedesc_with_input;
2004 static struct what_is_ready_closure **filedesc_to_what_closure;
2005
2006 static void
2007 init_what_input_once (void)
2008 {
2009   int i;
2010
2011   filedesc_with_input = xnew_array (Lisp_Object, MAXDESC);
2012   filedesc_to_what_closure =
2013     xnew_array (struct what_is_ready_closure *, MAXDESC);
2014
2015   for (i = 0; i < MAXDESC; i++)
2016     {
2017       filedesc_to_what_closure[i] = 0;
2018       filedesc_with_input[i] = Qnil;
2019     }
2020
2021   process_events_occurred = 0;
2022   tty_events_occurred = 0;
2023 }
2024
2025 static void
2026 mark_what_as_being_ready (struct what_is_ready_closure *closure)
2027 {
2028   if (NILP (filedesc_with_input[closure->fd]))
2029     {
2030       SELECT_TYPE temp_mask;
2031       FD_ZERO (&temp_mask);
2032       FD_SET (closure->fd, &temp_mask);
2033       /* Check to make sure there's *really* input available.
2034          Sometimes things seem to get confused and this gets called
2035          for the tty fd when there's really only input available
2036          on some process's fd.  (It will subsequently get called
2037          for that process's fd, so returning without setting any
2038          flags will take care of it.)  To see the problem, uncomment
2039          the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS
2040          down to 25, do sh -c 'xemacs -nw -q -f shell 2>/tmp/log'
2041          and press return repeatedly.  (Seen under AIX & Linux.)
2042          -dkindred@cs.cmu.edu */
2043       if (!poll_fds_for_input (temp_mask))
2044         {
2045 #if 0
2046           stderr_out ("mark_what_as_being_ready: no input available (fd=%d)\n",
2047                       closure->fd);
2048 #endif
2049           return;
2050         }
2051       filedesc_with_input[closure->fd] = closure->what;
2052       if (PROCESSP (closure->what))
2053       /* Don't increment this if the current process is already marked
2054        *  as having input. */
2055         process_events_occurred++;
2056       else
2057         tty_events_occurred++;
2058     }
2059 }
2060
2061 static void
2062 Xt_what_callback (void *closure, int *source, XtInputId *id)
2063 {
2064   /* If closure is 0, then we got a fake event from a signal handler.
2065      The only purpose of this is to make XtAppProcessEvent() stop
2066      blocking. */
2067   if (closure)
2068     mark_what_as_being_ready ((struct what_is_ready_closure *) closure);
2069   else
2070     {
2071       fake_event_occurred++;
2072       drain_signal_event_pipe ();
2073     }
2074 }
2075
2076 static void
2077 select_filedesc (int fd, Lisp_Object what)
2078 {
2079   struct what_is_ready_closure *closure;
2080
2081   /* If somebody is trying to select something that's already selected
2082      for, then something went wrong.  The generic routines ought to
2083      detect this and error before here. */
2084   assert (!filedesc_to_what_closure[fd]);
2085
2086   closure = xnew (struct what_is_ready_closure);
2087   closure->fd = fd;
2088   closure->what = what;
2089   closure->id =
2090     XtAppAddInput (Xt_app_con, fd,
2091                    (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
2092                    Xt_what_callback, closure);
2093   filedesc_to_what_closure[fd] = closure;
2094 }
2095
2096 static void
2097 unselect_filedesc (int fd)
2098 {
2099   struct what_is_ready_closure *closure = filedesc_to_what_closure[fd];
2100
2101   assert (closure);
2102   if (!NILP (filedesc_with_input[fd]))
2103     {
2104       /* We are unselecting this process before we have drained the rest of
2105          the input from it, probably from status_notify() in the command loop.
2106          This can happen like so:
2107
2108           - We are waiting in XtAppNextEvent()
2109           - Process generates output
2110           - Process is marked as being ready
2111           - Process dies, SIGCHLD gets generated before we return (!?)
2112             It could happen I guess.
2113           - sigchld_handler() marks process as dead
2114           - Somehow we end up getting a new KeyPress event on the queue
2115             at the same time (I'm really so sure how that happens but I'm
2116             not sure it can't either so let's assume it can...).
2117           - Key events have priority so we return that instead of the proc.
2118           - Before dispatching the lisp key event we call status_notify()
2119           - Which deselects the process that SIGCHLD marked as dead.
2120
2121          Thus we never remove it from _with_input and turn it into a lisp
2122          event, so we need to do it here.  But this does not mean that we're
2123          throwing away the last block of output - status_notify() has already
2124          taken care of running the proc filter or whatever.
2125        */
2126       filedesc_with_input[fd] = Qnil;
2127       if (PROCESSP (closure->what))
2128         {
2129           assert (process_events_occurred > 0);
2130           process_events_occurred--;
2131         }
2132       else
2133         {
2134           assert (tty_events_occurred > 0);
2135           tty_events_occurred--;
2136         }
2137     }
2138   XtRemoveInput (closure->id);
2139   xfree (closure);
2140   filedesc_to_what_closure[fd] = 0;
2141 }
2142
2143 static void
2144 emacs_Xt_select_process (Lisp_Process *p)
2145 {
2146   Lisp_Object process;
2147   int infd = event_stream_unixoid_select_process (p);
2148
2149   XSETPROCESS (process, p);
2150   select_filedesc (infd, process);
2151 }
2152
2153 static void
2154 emacs_Xt_unselect_process (Lisp_Process *p)
2155 {
2156   int infd = event_stream_unixoid_unselect_process (p);
2157
2158   unselect_filedesc (infd);
2159 }
2160
2161 static USID
2162 emacs_Xt_create_stream_pair (void* inhandle, void* outhandle,
2163                 Lisp_Object* instream, Lisp_Object* outstream, int flags)
2164 {
2165   USID u = event_stream_unixoid_create_stream_pair
2166                 (inhandle, outhandle, instream, outstream, flags);
2167   if (u != USID_ERROR)
2168     u = USID_DONTHASH;
2169   return u;
2170 }
2171
2172 static USID
2173 emacs_Xt_delete_stream_pair (Lisp_Object instream, Lisp_Object outstream)
2174 {
2175   event_stream_unixoid_delete_stream_pair (instream, outstream);
2176   return USID_DONTHASH;
2177 }
2178
2179 /* This is called from GC when a process object is about to be freed.
2180    If we've still got pointers to it in this file, we're gonna lose hard.
2181  */
2182 void
2183 debug_process_finalization (Lisp_Process *p)
2184 {
2185 #if 0 /* #### */
2186   int i;
2187   Lisp_Object instr, outstr;
2188
2189   get_process_streams (p, &instr, &outstr);
2190   /* if it still has fds, then it hasn't been killed yet. */
2191   assert (NILP(instr));
2192   assert (NILP(outstr));
2193   /* Better not still be in the "with input" table; we know it's got no fds. */
2194   for (i = 0; i < MAXDESC; i++)
2195     {
2196       Lisp_Object process = filedesc_fds_with_input [i];
2197       assert (!PROCESSP (process) || XPROCESS (process) != p);
2198     }
2199 #endif
2200 }
2201
2202 static void
2203 Xt_process_to_emacs_event (Lisp_Event *emacs_event)
2204 {
2205   int i;
2206
2207   assert (process_events_occurred > 0);
2208
2209   for (i = 0; i < MAXDESC; i++)
2210     {
2211       Lisp_Object process = filedesc_with_input[i];
2212       if (PROCESSP (process))
2213         {
2214           filedesc_with_input[i] = Qnil;
2215           process_events_occurred--;
2216           /* process events have nil as channel */
2217           emacs_event->event_type = process_event;
2218           emacs_event->timestamp  = 0; /* #### */
2219           emacs_event->event.process.process = process;
2220           return;
2221         }
2222     }
2223   abort ();
2224 }
2225
2226 static void
2227 emacs_Xt_select_console (struct console *con)
2228 {
2229   Lisp_Object console;
2230   int infd;
2231
2232   if (CONSOLE_X_P (con))
2233     return; /* X consoles are automatically selected for when we
2234                initialize them in Xt */
2235   infd = event_stream_unixoid_select_console (con);
2236   XSETCONSOLE (console, con);
2237   select_filedesc (infd, console);
2238 }
2239
2240 static void
2241 emacs_Xt_unselect_console (struct console *con)
2242 {
2243   Lisp_Object console;
2244   int infd;
2245
2246   if (CONSOLE_X_P (con))
2247     return; /* X consoles are automatically selected for when we
2248                initialize them in Xt */
2249   infd = event_stream_unixoid_unselect_console (con);
2250   XSETCONSOLE (console, con);
2251   unselect_filedesc (infd);
2252 }
2253
2254 /* read an event from a tty, if one is available.  Returns non-zero
2255    if an event was available.  Note that when this function is
2256    called, there should always be a tty marked as ready for input.
2257    However, the input condition might actually be EOF, so there
2258    may not really be any input available. (In this case,
2259    read_event_from_tty_or_stream_desc() will arrange for the TTY device
2260    to be deleted.) */
2261
2262 static int
2263 Xt_tty_to_emacs_event (Lisp_Event *emacs_event)
2264 {
2265   int i;
2266
2267   assert (tty_events_occurred > 0);
2268   for (i = 0; i < MAXDESC; i++)
2269     {
2270       Lisp_Object console = filedesc_with_input[i];
2271       if (CONSOLEP (console))
2272         {
2273           assert (tty_events_occurred > 0);
2274           tty_events_occurred--;
2275           filedesc_with_input[i] = Qnil;
2276           if (read_event_from_tty_or_stream_desc
2277               (emacs_event, XCONSOLE (console), i))
2278             return 1;
2279         }
2280     }
2281
2282   return 0;
2283 }
2284
2285 \f
2286 /************************************************************************/
2287 /*              debugging functions to decipher an event                */
2288 /************************************************************************/
2289
2290 #ifdef DEBUG_XEMACS
2291 #include "xintrinsicp.h"        /* only describe_event() needs this */
2292 #include <X11/Xproto.h>         /* only describe_event() needs this */
2293
2294 static void
2295 describe_event_window (Window window, Display *display)
2296 {
2297   struct frame *f;
2298   Widget w;
2299   stderr_out ("   window: 0x%lx", (unsigned long) window);
2300   w = XtWindowToWidget (display, window);
2301   if (w)
2302     stderr_out (" %s", w->core.widget_class->core_class.class_name);
2303   f = x_any_window_to_frame (get_device_from_display (display), window);
2304   if (f)
2305     {
2306       char *buf = alloca_array (char, XSTRING_LENGTH (f->name) + 4);
2307       sprintf (buf, " \"%s\"", XSTRING_DATA (f->name));
2308       write_string_to_stdio_stream (stderr, 0, (Bufbyte *) buf, 0,
2309                                     strlen (buf), Qterminal, 1);
2310     }
2311   stderr_out ("\n");
2312 }
2313
2314 static const char *
2315 XEvent_mode_to_string (int mode)
2316 {
2317   switch (mode)
2318   {
2319   case NotifyNormal:       return "Normal";
2320   case NotifyGrab:         return "Grab";
2321   case NotifyUngrab:       return "Ungrab";
2322   case NotifyWhileGrabbed: return "WhileGrabbed";
2323   default:                 return "???";
2324   }
2325 }
2326
2327 static const char *
2328 XEvent_detail_to_string (int detail)
2329 {
2330   switch (detail)
2331   {
2332   case NotifyAncestor:          return "Ancestor";
2333   case NotifyInferior:          return "Inferior";
2334   case NotifyNonlinear:         return "Nonlinear";
2335   case NotifyNonlinearVirtual:  return "NonlinearVirtual";
2336   case NotifyPointer:           return "Pointer";
2337   case NotifyPointerRoot:       return "PointerRoot";
2338   case NotifyDetailNone:        return "DetailNone";
2339   default:                      return "???";
2340   }
2341 }
2342
2343 static const char *
2344 XEvent_visibility_to_string (int state)
2345 {
2346   switch (state)
2347   {
2348   case VisibilityFullyObscured:     return "FullyObscured";
2349   case VisibilityPartiallyObscured: return "PartiallyObscured";
2350   case VisibilityUnobscured:        return "Unobscured";
2351   default:                          return "???";
2352   }
2353 }
2354
2355 static void
2356 describe_event (XEvent *event)
2357 {
2358   char buf[100];
2359   struct device *d = get_device_from_display (event->xany.display);
2360
2361   sprintf (buf, "%s%s", x_event_name (event->type),
2362            event->xany.send_event ? " (send)" : "");
2363   stderr_out ("%-30s", buf);
2364   switch (event->type)
2365     {
2366     case FocusIn:
2367     case FocusOut:
2368       {
2369         XFocusChangeEvent *ev = &event->xfocus;
2370         describe_event_window (ev->window, ev->display);
2371         stderr_out ("     mode: %s\n",   XEvent_mode_to_string  (ev->mode));
2372         stderr_out ("     detail: %s\n", XEvent_detail_to_string(ev->detail));
2373         break;
2374       }
2375
2376     case KeyPress:
2377       {
2378         XKeyEvent *ev = &event->xkey;
2379         unsigned int state = ev->state;
2380
2381         describe_event_window (ev->window, ev->display);
2382         stderr_out ("   subwindow: %ld\n", ev->subwindow);
2383         stderr_out ("   state: ");
2384         /* Complete list of modifier key masks */
2385         if (state & ShiftMask)   stderr_out ("Shift ");
2386         if (state & LockMask)    stderr_out ("Lock ");
2387         if (state & ControlMask) stderr_out ("Control ");
2388         if (state & Mod1Mask)    stderr_out ("Mod1 ");
2389         if (state & Mod2Mask)    stderr_out ("Mod2 ");
2390         if (state & Mod3Mask)    stderr_out ("Mod3 ");
2391         if (state & Mod4Mask)    stderr_out ("Mod4 ");
2392         if (state & Mod5Mask)    stderr_out ("Mod5 ");
2393
2394         if (! state)
2395           stderr_out ("vanilla\n");
2396         else
2397           stderr_out ("\n");
2398         if (x_key_is_modifier_p (ev->keycode, d))
2399           stderr_out ("   Modifier key");
2400         stderr_out ("   keycode: 0x%x\n", ev->keycode);
2401       }
2402     break;
2403
2404     case Expose:
2405       if (x_debug_events > 1)
2406         {
2407           XExposeEvent *ev = &event->xexpose;
2408           describe_event_window (ev->window, ev->display);
2409           stderr_out ("   region: x=%d y=%d width=%d height=%d\n",
2410                       ev->x, ev->y, ev->width, ev->height);
2411           stderr_out ("    count: %d\n", ev->count);
2412         }
2413       else
2414         stderr_out ("\n");
2415       break;
2416
2417     case GraphicsExpose:
2418       if (x_debug_events > 1)
2419         {
2420           XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
2421           describe_event_window (ev->drawable, ev->display);
2422           stderr_out ("    major: %s\n",
2423                       (ev ->major_code == X_CopyArea  ? "CopyArea" :
2424                        (ev->major_code == X_CopyPlane ? "CopyPlane" : "?")));
2425           stderr_out ("   region: x=%d y=%d width=%d height=%d\n",
2426                       ev->x, ev->y, ev->width, ev->height);
2427           stderr_out ("    count: %d\n", ev->count);
2428         }
2429       else
2430         stderr_out ("\n");
2431       break;
2432
2433     case EnterNotify:
2434     case LeaveNotify:
2435       if (x_debug_events > 1)
2436         {
2437           XCrossingEvent *ev = &event->xcrossing;
2438           describe_event_window (ev->window, ev->display);
2439 #if 0
2440           stderr_out(" subwindow: 0x%x\n", ev->subwindow);
2441           stderr_out("      pos: %d %d\n", ev->x, ev->y);
2442           stderr_out(" root pos: %d %d\n", ev->x_root, ev->y_root);
2443 #endif
2444           stderr_out("    mode: %s\n",   XEvent_mode_to_string(ev->mode));
2445           stderr_out("    detail: %s\n", XEvent_detail_to_string(ev->detail));
2446           stderr_out("    focus: %d\n", ev->focus);
2447 #if 0
2448           stderr_out("    state: 0x%x\n", ev->state);
2449 #endif
2450         }
2451       else
2452         stderr_out("\n");
2453       break;
2454
2455     case ConfigureNotify:
2456       if (x_debug_events > 1)
2457         {
2458           XConfigureEvent *ev = &event->xconfigure;
2459           describe_event_window (ev->window, ev->display);
2460           stderr_out("    above: 0x%lx\n", ev->above);
2461           stderr_out("     size: %d %d %d %d\n", ev->x, ev->y,
2462                      ev->width, ev->height);
2463           stderr_out("  redirect: %d\n", ev->override_redirect);
2464         }
2465       else
2466         stderr_out("\n");
2467       break;
2468
2469     case VisibilityNotify:
2470       if (x_debug_events > 1)
2471         {
2472           XVisibilityEvent *ev = &event->xvisibility;
2473           describe_event_window (ev->window, ev->display);
2474           stderr_out("    state: %s\n", XEvent_visibility_to_string(ev->state));
2475         }
2476       else
2477         stderr_out ("\n");
2478       break;
2479
2480     case ClientMessage:
2481       {
2482         XClientMessageEvent *ev = &event->xclient;
2483         char *name = XGetAtomName (ev->display, ev->message_type);
2484         stderr_out ("%s", name);
2485         if (!strcmp (name, "WM_PROTOCOLS")) {
2486           char *protname = XGetAtomName (ev->display, ev->data.l[0]);
2487           stderr_out ("(%s)", protname);
2488           XFree (protname);
2489         }
2490         XFree (name);
2491         stderr_out ("\n");
2492         break;
2493       }
2494
2495     default:
2496       stderr_out ("\n");
2497       break;
2498     }
2499
2500   fflush (stdout);
2501 }
2502
2503 #endif /* include describe_event definition */
2504
2505 \f
2506 /************************************************************************/
2507 /*                      get the next event from Xt                      */
2508 /************************************************************************/
2509
2510 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
2511
2512 void
2513 enqueue_Xt_dispatch_event (Lisp_Object event)
2514 {
2515   enqueue_event (event, &dispatch_event_queue, &dispatch_event_queue_tail);
2516 }
2517
2518 static Lisp_Object
2519 dequeue_Xt_dispatch_event (void)
2520 {
2521   return dequeue_event (&dispatch_event_queue, &dispatch_event_queue_tail);
2522 }
2523
2524 /* This business exists because menu events "happen" when
2525    menubar_selection_callback() is called from somewhere deep
2526    within XtAppProcessEvent in emacs_Xt_next_event().  The
2527    callback needs to terminate the modal loop in that function
2528    or else it will continue waiting until another event is
2529    received.
2530
2531    Same business applies to scrollbar events. */
2532
2533 void
2534 signal_special_Xt_user_event (Lisp_Object channel, Lisp_Object function,
2535                               Lisp_Object object)
2536 {
2537   Lisp_Object event = Fmake_event (Qnil, Qnil);
2538
2539   XEVENT (event)->event_type = misc_user_event;
2540   XEVENT (event)->channel = channel;
2541   XEVENT (event)->event.eval.function = function;
2542   XEVENT (event)->event.eval.object = object;
2543
2544   enqueue_Xt_dispatch_event (event);
2545 }
2546
2547 static void
2548 emacs_Xt_next_event (Lisp_Event *emacs_event)
2549 {
2550  we_didnt_get_an_event:
2551
2552   while (NILP (dispatch_event_queue) &&
2553          !completed_timeouts         &&
2554          !fake_event_occurred        &&
2555          !process_events_occurred    &&
2556          !tty_events_occurred)
2557     {
2558
2559       /* Stupid logic in XtAppProcessEvent() dictates that, if process
2560          events and X events are both available, the process event gets
2561          taken first.  This will cause an infinite loop if we're being
2562          called from Fdiscard_input().
2563        */
2564       if (XtAppPending (Xt_app_con) & XtIMXEvent)
2565         XtAppProcessEvent (Xt_app_con, XtIMXEvent);
2566       else
2567         {
2568           Lisp_Object devcons, concons;
2569
2570           /* We're about to block.  Xt has a bug in it (big surprise,
2571              there) in that it blocks using select() and doesn't
2572              flush the Xlib output buffers (XNextEvent() does this
2573              automatically before blocking).  So it's necessary
2574              for us to do this ourselves.  If we don't do it, then
2575              display output may not be seen until the next time
2576              an X event is received. (This happens esp. with
2577              subprocess output that gets sent to a visible buffer.)
2578
2579              #### The above comment may not have any validity. */
2580
2581           DEVICE_LOOP_NO_BREAK (devcons, concons)
2582             {
2583               struct device *d;
2584               d = XDEVICE (XCAR (devcons));
2585
2586               if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d))
2587                 /* emacs may be exiting */
2588                 XFlush (DEVICE_X_DISPLAY (d));
2589             }
2590           XtAppProcessEvent (Xt_app_con, XtIMAll);
2591         }
2592     }
2593
2594   if (!NILP (dispatch_event_queue))
2595     {
2596       Lisp_Object event, event2;
2597       XSETEVENT (event2, emacs_event);
2598       event = dequeue_Xt_dispatch_event ();
2599       Fcopy_event (event, event2);
2600       Fdeallocate_event (event);
2601     }
2602   else if (tty_events_occurred)
2603     {
2604       if (!Xt_tty_to_emacs_event (emacs_event))
2605         goto we_didnt_get_an_event;
2606     }
2607   else if (completed_timeouts)
2608     Xt_timeout_to_emacs_event (emacs_event);
2609   else if (fake_event_occurred)
2610     {
2611       /* A dummy event, so that a cycle of the command loop will occur. */
2612       fake_event_occurred = 0;
2613       /* eval events have nil as channel */
2614       emacs_event->event_type = eval_event;
2615       emacs_event->event.eval.function = Qidentity;
2616       emacs_event->event.eval.object = Qnil;
2617     }
2618   else /* if (process_events_occurred) */
2619     Xt_process_to_emacs_event (emacs_event);
2620
2621   /* No need to call XFilterEvent; Xt does it for us */
2622 }
2623
2624 void
2625 emacs_Xt_event_handler (Widget wid /* unused */,
2626                         XtPointer closure /* unused */,
2627                         XEvent *event,
2628                         Boolean *continue_to_dispatch /* unused */)
2629 {
2630   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
2631
2632 #ifdef DEBUG_XEMACS
2633   if (x_debug_events > 0)
2634     {
2635       describe_event (event);
2636     }
2637 #endif /* DEBUG_XEMACS */
2638   if (x_event_to_emacs_event (event, XEVENT (emacs_event)))
2639     enqueue_Xt_dispatch_event (emacs_event);
2640   else
2641     Fdeallocate_event (emacs_event);
2642 }
2643
2644 \f
2645 /************************************************************************/
2646 /*                      input pending / C-g checking                    */
2647 /************************************************************************/
2648
2649 static Bool
2650 quit_char_predicate (Display *display, XEvent *event, XPointer data)
2651 {
2652   struct device *d = get_device_from_display (display);
2653   struct x_device *xd = DEVICE_X_DATA (d);
2654   char c, quit_char;
2655   Bool *critical = (Bool *) data;
2656   Lisp_Object keysym;
2657
2658   if (critical)
2659     *critical = False;
2660   if ((event->type != KeyPress) ||
2661       (! x_any_window_to_frame (d, event->xany.window)) ||
2662       (event->xkey.state
2663        & (xd->MetaMask | xd->HyperMask | xd->SuperMask | xd->AltMask)))
2664     return 0;
2665
2666   /* This duplicates some code that exists elsewhere, but it's relatively
2667      fast and doesn't cons. */
2668   keysym = x_to_emacs_keysym (&event->xkey, 1);
2669   if (NILP (keysym)) return 0;
2670   if (CHAR_OR_CHAR_INTP (keysym))
2671     c = XCHAR_OR_CHAR_INT (keysym);
2672   /* Highly doubtful that these are the quit character, but... */
2673   else if (EQ (keysym, QKbackspace))    c = '\b';
2674   else if (EQ (keysym, QKtab))          c = '\t';
2675   else if (EQ (keysym, QKlinefeed))     c = '\n';
2676   else if (EQ (keysym, QKreturn))       c = '\r';
2677   else if (EQ (keysym, QKescape))       c = 27;
2678   else if (EQ (keysym, QKspace))        c = ' ';
2679   else if (EQ (keysym, QKdelete))       c = 127;
2680   else return 0;
2681
2682   if (event->xkey.state & xd->MetaMask)     c |= 0x80;
2683   if ((event->xkey.state & ControlMask) && !(c >= 'A' && c <= 'Z'))
2684     c &= 0x1F;                  /* unshifted control characters */
2685   quit_char = CONSOLE_QUIT_CHAR (XCONSOLE (DEVICE_CONSOLE (d)));
2686   if (c == quit_char)
2687     return True;
2688   /* If we've got Control-Shift-G instead of Control-G, that means
2689      we have a critical_quit.  Caps_Lock is its own modifier, so it
2690      won't cause ^G to act differently than before. */
2691   if (event->xkey.state & ControlMask)  c &= 0x1F;
2692   if (c == quit_char)
2693     {
2694       if (critical) *critical = True;
2695       return True;
2696     }
2697   return False;
2698 }
2699
2700 /* This scans the X input queue for a KeyPress event that matches the
2701    quit character, and sets Vquit_flag.  This is called from the
2702    QUIT macro to determine whether we should quit.
2703
2704    In a SIGIO world, this won't be called unless a SIGIO has happened
2705    since the last time we checked.
2706
2707    In a non-SIGIO world, this is called from emacs_Xt_event_pending_p
2708    (which is called from input_pending_p).
2709  */
2710 static void
2711 x_check_for_quit_char (Display *display)
2712 {
2713   XEvent event;
2714   int queued;
2715   Bool critical_quit = False;
2716   XEventsQueued (display, QueuedAfterReading);
2717   queued = XCheckIfEvent (display, &event,
2718                           quit_char_predicate,
2719                           (char *) &critical_quit);
2720   if (queued)
2721     {
2722       Vquit_flag = (critical_quit ? Qcritical : Qt);
2723       /* don't put the event back onto the queue.  Those functions that
2724          wanted to read a ^G directly have arranged to do this. */
2725     }
2726 }
2727
2728 static void
2729 check_for_tty_quit_char (struct device *d)
2730 {
2731   SELECT_TYPE temp_mask;
2732   int infd = DEVICE_INFD (d);
2733   struct console *con = XCONSOLE (DEVICE_CONSOLE (d));
2734   Emchar quit_char = CONSOLE_QUIT_CHAR (con);
2735
2736   FD_ZERO (&temp_mask);
2737   FD_SET (infd, &temp_mask);
2738
2739   while (1)
2740     {
2741       Lisp_Object event;
2742       Emchar the_char;
2743
2744       if (!poll_fds_for_input (temp_mask))
2745         return;
2746
2747       event = Fmake_event (Qnil, Qnil);
2748       if (!read_event_from_tty_or_stream_desc (XEVENT (event), con, infd))
2749         /* EOF, or something ... */
2750         return;
2751       /* #### bogus.  quit-char should be allowed to be any sort
2752          of event. */
2753       the_char = event_to_character (XEVENT (event), 1, 0, 0);
2754       if (the_char >= 0 && the_char == quit_char)
2755         {
2756           Vquit_flag = Qt;
2757           /* do not queue the C-g.  See above. */
2758           return;
2759         }
2760
2761       /* queue the read event to be read for real later. */
2762       enqueue_Xt_dispatch_event (event);
2763     }
2764 }
2765
2766 static void
2767 emacs_Xt_quit_p (void)
2768 {
2769   Lisp_Object devcons, concons;
2770   CONSOLE_LOOP (concons)
2771     {
2772       struct console *con = XCONSOLE (XCAR (concons));
2773       if (!con->input_enabled)
2774         continue;
2775
2776       CONSOLE_DEVICE_LOOP (devcons, con)
2777         {
2778           struct device *d;
2779           d = XDEVICE (XCAR (devcons));
2780
2781           if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d))
2782             /* emacs may be exiting */
2783             x_check_for_quit_char (DEVICE_X_DISPLAY (d));
2784           else if (DEVICE_TTY_P (d))
2785             check_for_tty_quit_char (d);
2786         }
2787     }
2788 }
2789
2790 static void
2791 drain_X_queue (void)
2792 {
2793   while (XtAppPending (Xt_app_con) & XtIMXEvent)
2794     XtAppProcessEvent (Xt_app_con, XtIMXEvent);
2795 }
2796
2797 static int
2798 emacs_Xt_event_pending_p (int user_p)
2799 {
2800   Lisp_Object event;
2801   int tick_count_val;
2802
2803   /* If `user_p' is false, then this function returns whether there are any
2804      X, timeout, or fd events pending (that is, whether emacs_Xt_next_event()
2805      would return immediately without blocking).
2806
2807      if `user_p' is true, then this function returns whether there are any
2808      *user generated* events available (that is, whether there are keyboard
2809      or mouse-click events ready to be read).  This also implies that
2810      emacs_Xt_next_event() would not block.
2811
2812      In a non-SIGIO world, this also checks whether the user has typed ^G,
2813      since this is a convenient place to do so.  We don't need to do this
2814      in a SIGIO world, since input causes an interrupt.
2815    */
2816
2817 #if 0
2818   /* I don't think there's any point to this and it will nullify
2819      the speed gains achieved by the sigio_happened checking below.
2820      Its only advantage is that it may possibly make C-g response
2821      a bit faster.  The C-g will be noticed within 0.25 second, anyway,
2822      even without this. */
2823 #ifndef SIGIO
2824   /* First check for C-g if necessary */
2825   emacs_Xt_quit_p ();
2826 #endif
2827 #endif
2828
2829   /* This function used to simply check whether there were any X
2830      events (or if user_p was 1, it iterated over all the pending
2831      X events using XCheckIfEvent(), looking for keystrokes and
2832      button events).  That worked in the old cheesoid event loop,
2833      which didn't go through XtAppDispatchEvent(), but it doesn't
2834      work any more -- X events may not result in anything.  For
2835      example, a button press in a blank part of the menubar appears
2836      as an X event but will not result in any Emacs events (a
2837      button press that activates the menubar results in an Emacs
2838      event through the stop_next_event mechanism).
2839
2840      The only accurate way of determining whether these X events
2841      translate into Emacs events is to go ahead and dispatch them
2842      until there's something on the dispatch queue. */
2843
2844   /* See if there are any user events already on the queue. */
2845   EVENT_CHAIN_LOOP (event, dispatch_event_queue)
2846     if (!user_p || command_event_p (event))
2847       return 1;
2848
2849   /* See if there's any TTY input available.
2850    */
2851   if (poll_fds_for_input (tty_only_mask))
2852     return 1;
2853
2854   if (!user_p)
2855     {
2856       /* If not user_p and there are any timer or file-desc events
2857          pending, we know there will be an event so we're through. */
2858       XtInputMask pending_value;
2859
2860       /* Note that formerly we just checked the value of XtAppPending()
2861          to determine if there was file-desc input.  This doesn't
2862          work any more with the signal_event_pipe; XtAppPending()
2863          will says "yes" in this case but there isn't really any
2864          input.  Another way of fixing this problem is for the
2865          signal_event_pipe to generate actual input in the form
2866          of an identity eval event or something. (#### maybe this
2867          actually happens?) */
2868
2869       if (poll_fds_for_input (process_only_mask))
2870         return 1;
2871
2872       pending_value = XtAppPending (Xt_app_con);
2873
2874       if (pending_value & XtIMTimer)
2875         return 1;
2876     }
2877
2878   /* XtAppPending() can be super-slow, esp. over a network connection.
2879      Quantify results have indicated that in some cases the
2880      call to detect_input_pending() completely dominates the
2881      running time of redisplay().  Fortunately, in a SIGIO world
2882      we can more quickly determine whether there are any X events:
2883      if an event has happened since the last time we checked, then
2884      a SIGIO will have happened.  On a machine with broken SIGIO,
2885      we'll still be in an OK state -- the sigio_happened flag
2886      will get set at least once a second, so we'll be no more than
2887      one second behind reality. (In general it's OK if we
2888      erroneously report no input pending when input is actually
2889      pending() -- preemption is just a bit less efficient, that's
2890      all.  It's bad bad bad if you err the other way -- you've
2891      promised that `next-event' won't block but it actually will,
2892      and some action might get delayed until the next time you
2893      hit a key.)
2894      */
2895
2896   /* quit_check_signal_tick_count is volatile so try to avoid race conditions
2897      by using a temporary variable */
2898   tick_count_val = quit_check_signal_tick_count;
2899   if (last_quit_check_signal_tick_count != tick_count_val)
2900     {
2901       last_quit_check_signal_tick_count = tick_count_val;
2902
2903       /* We need to drain the entire queue now -- if we only
2904          drain part of it, we may later on end up with events
2905          actually pending but detect_input_pending() returning
2906          false because there wasn't another SIGIO. */
2907       drain_X_queue ();
2908
2909       EVENT_CHAIN_LOOP (event, dispatch_event_queue)
2910         if (!user_p || command_event_p (event))
2911           return 1;
2912     }
2913
2914   return 0;
2915 }
2916
2917 \f
2918 /************************************************************************/
2919 /*            replacement for standard string-to-pixel converter        */
2920 /************************************************************************/
2921
2922 /* This was constructed by ripping off the standard string-to-pixel
2923    converter from Converters.c in the Xt source code and modifying
2924    appropriately. */
2925
2926 #if 0
2927
2928 /* This is exported by the Xt library (at least by mine).  If this
2929    isn't the case somewhere, rename this appropriately and remove
2930    the '#if 0'.  Note, however, that I got "unknown structure"
2931    errors when I tried this. */
2932 XtConvertArgRec Const colorConvertArgs[] = {
2933   { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
2934     sizeof (Screen *) },
2935   { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
2936     sizeof (Colormap) }
2937 };
2938
2939 #endif
2940
2941 #define done(type, value)               \
2942   if (toVal->addr != NULL) {             \
2943     if (toVal->size < sizeof(type)) {    \
2944       toVal->size = sizeof(type);        \
2945       return False;                      \
2946     }                                    \
2947     *(type*)(toVal->addr) = (value);     \
2948   } else {                               \
2949     static type static_val;              \
2950     static_val = (value);                \
2951     toVal->addr = (XPointer)&static_val; \
2952   }                                      \
2953   toVal->size = sizeof(type);            \
2954   return True /* Caller supplies `;' */
2955
2956 /* JH: We use this because I think there's a possibility this
2957    is called before the device is properly set up, in which case
2958    I don't want to abort. */
2959 extern struct device *get_device_from_display_1 (Display *dpy);
2960
2961 static
2962 Boolean EmacsXtCvtStringToPixel (
2963  Display     *dpy,
2964  XrmValuePtr  args,
2965  Cardinal    *num_args,
2966  XrmValuePtr  fromVal,
2967  XrmValuePtr  toVal,
2968  XtPointer   *closure_ret)
2969 {
2970   String       str = (String)fromVal->addr;
2971   XColor       screenColor;
2972   XColor       exactColor;
2973   Screen       *screen;
2974   Colormap     colormap;
2975   Visual       *visual;
2976   struct device *d;
2977   Status       status;
2978   String       params[1];
2979   Cardinal     num_params  = 1;
2980   XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
2981
2982   if (*num_args != 2) {
2983     XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToPixel",
2984                     "XtToolkitError",
2985                     "String to pixel conversion needs screen and colormap arguments",
2986                     (String *)NULL, (Cardinal *)NULL);
2987     return False;
2988   }
2989
2990   screen   = *((Screen **)  args[0].addr);
2991   colormap = *((Colormap *) args[1].addr);
2992
2993   /* The original uses the private function CompareISOLatin1().
2994      Use XmuCompareISOLatin1() if you want, but I don't think it
2995      makes any difference here. */
2996   if (strcmp(str, XtDefaultBackground) == 0) {
2997     *closure_ret = False;
2998     /* This refers to the display's "*reverseVideo" resource.
2999        These display resources aren't documented anywhere that
3000        I can find, so I'm going to ignore this. */
3001     /* if (pd->rv) done(Pixel, BlackPixelOfScreen(screen)) else */
3002     done(Pixel, WhitePixelOfScreen(screen));
3003   }
3004   if (strcmp(str, XtDefaultForeground) == 0) {
3005     *closure_ret = False;
3006     /* if (pd->rv) done(Pixel, WhitePixelOfScreen(screen)) else */
3007     done(Pixel, BlackPixelOfScreen(screen));
3008   }
3009
3010   /* Originally called XAllocNamedColor() here. */
3011   if ((d = get_device_from_display_1(dpy))) {
3012     visual = DEVICE_X_VISUAL(d);
3013     if (colormap != DEVICE_X_COLORMAP(d)) {
3014       XtAppWarningMsg(the_app_con, "wierdColormap", "cvtStringToPixel",
3015                       "XtToolkitWarning",
3016                       "The colormap passed to cvtStringToPixel doesn't match the one registerd to the device.\n",
3017                       NULL, 0);
3018       status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor);
3019     } else {
3020       status = XParseColor (dpy, colormap, (char*)str, &screenColor);
3021       if (status) {
3022         status = allocate_nearest_color (dpy, colormap, visual, &screenColor);
3023       }
3024     }
3025   } else {
3026     /* We haven't set up this device totally yet, so just punt */
3027     status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor);
3028   }
3029   if (status == 0) {
3030     params[0] = str;
3031     /* Server returns a specific error code but Xlib discards it.  Ugh */
3032     if (XLookupColor(DisplayOfScreen(screen), colormap, (char*) str,
3033                      &exactColor, &screenColor)) {
3034       XtAppWarningMsg(the_app_con, "noColormap", "cvtStringToPixel",
3035                       "XtToolkitError",
3036                       "Cannot allocate colormap entry for \"%s\"",
3037                       params, &num_params);
3038
3039     } else {
3040       XtAppWarningMsg(the_app_con, "badValue", "cvtStringToPixel",
3041                       "XtToolkitError",
3042                       "Color name \"%s\" is not defined", params, &num_params);
3043     }
3044
3045     *closure_ret = False;
3046     return False;
3047   } else {
3048     *closure_ret = (char*)True;
3049     done(Pixel, screenColor.pixel);
3050   }
3051 }
3052
3053 /* ARGSUSED */
3054 static void EmacsFreePixel (
3055   XtAppContext app,
3056   XrmValuePtr  toVal,
3057   XtPointer    closure,
3058   XrmValuePtr  args,
3059   Cardinal    *num_args)
3060 {
3061   if (*num_args != 2) {
3062     XtAppWarningMsg(app, "wrongParameters","freePixel","XtToolkitError",
3063                     "Freeing a pixel requires screen and colormap arguments",
3064                     (String *)NULL, (Cardinal *)NULL);
3065     return;
3066   }
3067
3068   if (closure) {
3069     Screen   *screen  = *((Screen **)  args[0].addr);
3070     Colormap colormap = *((Colormap *) args[1].addr);
3071     XFreeColors(DisplayOfScreen(screen), colormap,
3072                 (unsigned long*)toVal->addr, 1, (unsigned long)0);
3073   }
3074 }
3075
3076 \f
3077 /************************************************************************/
3078 /*            handle focus changes for native widgets                  */
3079 /************************************************************************/
3080 static void
3081 emacs_Xt_event_widget_focus_in (Widget   w,
3082                                 XEvent   *event,
3083                                 String   *params,
3084                                 Cardinal *num_params)
3085 {
3086   struct frame* f =
3087     x_any_widget_or_parent_to_frame (get_device_from_display (event->xany.display), w);
3088
3089   XtSetKeyboardFocus (FRAME_X_SHELL_WIDGET (f), w);
3090 }
3091
3092 static void
3093 emacs_Xt_event_widget_focus_out (Widget   w,
3094                                  XEvent   *event,
3095                                  String   *params,
3096                                  Cardinal *num_params)
3097 {
3098 }
3099
3100 static XtActionsRec widgetActionsList[] =
3101 {
3102   {"widget-focus-in",   emacs_Xt_event_widget_focus_in  },
3103   {"widget-focus-out",  emacs_Xt_event_widget_focus_out },
3104 };
3105
3106 static void
3107 emacs_Xt_event_add_widget_actions (XtAppContext ctx)
3108 {
3109   XtAppAddActions (ctx, widgetActionsList, 2);
3110 }
3111
3112 \f
3113 /************************************************************************/
3114 /*                            initialization                            */
3115 /************************************************************************/
3116
3117 void
3118 syms_of_event_Xt (void)
3119 {
3120   defsymbol (&Qkey_mapping, "key-mapping");
3121   defsymbol (&Qsans_modifiers, "sans-modifiers");
3122   defsymbol (&Qself_insert_command, "self-insert-command");
3123 }
3124
3125 void
3126 reinit_vars_of_event_Xt (void)
3127 {
3128   Xt_event_stream = xnew (struct event_stream);
3129   Xt_event_stream->event_pending_p       = emacs_Xt_event_pending_p;
3130   Xt_event_stream->force_event_pending   = emacs_Xt_force_event_pending;
3131   Xt_event_stream->next_event_cb         = emacs_Xt_next_event;
3132   Xt_event_stream->handle_magic_event_cb = emacs_Xt_handle_magic_event;
3133   Xt_event_stream->add_timeout_cb        = emacs_Xt_add_timeout;
3134   Xt_event_stream->remove_timeout_cb     = emacs_Xt_remove_timeout;
3135   Xt_event_stream->select_console_cb     = emacs_Xt_select_console;
3136   Xt_event_stream->unselect_console_cb   = emacs_Xt_unselect_console;
3137   Xt_event_stream->select_process_cb     = emacs_Xt_select_process;
3138   Xt_event_stream->unselect_process_cb   = emacs_Xt_unselect_process;
3139   Xt_event_stream->quit_p_cb             = emacs_Xt_quit_p;
3140   Xt_event_stream->create_stream_pair_cb = emacs_Xt_create_stream_pair;
3141   Xt_event_stream->delete_stream_pair_cb = emacs_Xt_delete_stream_pair;
3142
3143   the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
3144
3145   last_quit_check_signal_tick_count = 0;
3146
3147   /* this function only makes safe calls */
3148   init_what_input_once ();
3149 }
3150
3151 void
3152 vars_of_event_Xt (void)
3153 {
3154   reinit_vars_of_event_Xt ();
3155
3156   dispatch_event_queue = Qnil;
3157   staticpro (&dispatch_event_queue);
3158   dispatch_event_queue_tail = Qnil;
3159   pdump_wire (&dispatch_event_queue_tail);
3160
3161   DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /*
3162 *Non-nil means to allow synthetic events.  Nil means they are ignored.
3163 Beware: allowing emacs to process SendEvents opens a big security hole.
3164 */ );
3165   x_allow_sendevents = 0;
3166
3167 #ifdef DEBUG_XEMACS
3168   DEFVAR_INT ("x-debug-events", &x_debug_events /*
3169 If non-zero, display debug information about X events that XEmacs sees.
3170 Information is displayed on stderr.  Currently defined values are:
3171
3172 1 == non-verbose output
3173 2 == verbose output
3174 */ );
3175   x_debug_events = 0;
3176 #endif
3177 }
3178
3179 /* This mess is a hack that patches the shell widget to treat visual inheritance
3180    the same as colormap and depth inheritance */
3181
3182 static XtInitProc orig_shell_init_proc;
3183
3184 static void ShellVisualPatch(Widget wanted, Widget new,
3185                              ArgList args, Cardinal *num_args)
3186 {
3187   Widget p;
3188   ShellWidget w = (ShellWidget) new;
3189
3190   /* first, call the original setup */
3191   (*orig_shell_init_proc)(wanted, new, args, num_args);
3192
3193   /* if the visual isn't explicitly set, grab it from the nearest shell ancestor */
3194   if (w->shell.visual == CopyFromParent) {
3195     p = XtParent(w);
3196     while (p && !XtIsShell(p)) p = XtParent(p);
3197     if (p) w->shell.visual = ((ShellWidget)p)->shell.visual;
3198   }
3199 }
3200
3201 void
3202 init_event_Xt_late (void) /* called when already initialized */
3203 {
3204   timeout_id_tick = 1;
3205   pending_timeouts = 0;
3206   completed_timeouts = 0;
3207
3208   event_stream = Xt_event_stream;
3209
3210 #if defined(HAVE_XIM) || defined(USE_XFONTSET)
3211   Initialize_Locale();
3212 #endif /* HAVE_XIM || USE_XFONTSET */
3213
3214   XtToolkitInitialize ();
3215   Xt_app_con = XtCreateApplicationContext ();
3216   XtAppSetFallbackResources (Xt_app_con, (String *) x_fallback_resources);
3217
3218   /* In xselect.c */
3219   x_selection_timeout = (XtAppGetSelectionTimeout (Xt_app_con) / 1000);
3220   XSetErrorHandler (x_error_handler);
3221   XSetIOErrorHandler (x_IO_error_handler);
3222
3223 #ifndef WIN32_NATIVE
3224   XtAppAddInput (Xt_app_con, signal_event_pipe[0],
3225                  (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
3226                  Xt_what_callback, 0);
3227 #endif
3228
3229   XtAppSetTypeConverter (Xt_app_con, XtRString, XtRPixel,
3230                          EmacsXtCvtStringToPixel,
3231                          (XtConvertArgList) colorConvertArgs,
3232                          2, XtCacheByDisplay, EmacsFreePixel);
3233
3234 #ifdef XIM_XLIB
3235   XtAppSetTypeConverter (Xt_app_con, XtRString, XtRXimStyles,
3236                          EmacsXtCvtStringToXIMStyles,
3237                          NULL, 0,
3238                          XtCacheByDisplay, EmacsFreeXIMStyles);
3239 #endif /* XIM_XLIB */
3240   /* Add extra actions to native widgets to handle focus and friends. */
3241   emacs_Xt_event_add_widget_actions (Xt_app_con);
3242
3243   /* insert the visual inheritance patch/hack described above */
3244   orig_shell_init_proc = shellClassRec.core_class.initialize;
3245   shellClassRec.core_class.initialize = ShellVisualPatch;
3246
3247 }