b9ef39225ef96e69518c4bfe25088f0ea436861e
[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 debug_x_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 == ButtonPress
691           || (type == KeyPress
692               && ((xd->last_downkey
693                    && ((keycode != xd->last_downkey
694                         || ev->xkey.time != xd->release_time)))
695                   || (INTP (Vmodifier_keys_sticky_time)
696                       && ev->xkey.time
697                       > (xd->modifier_release_time
698                          + XINT (Vmodifier_keys_sticky_time))))))
699         {
700           xd->need_to_add_mask = 0;
701           xd->last_downkey = 0;
702         }
703       else if (type == KeyPress && !xd->last_downkey)
704         xd->last_downkey = keycode;
705
706       if (type == KeyPress)
707         xd->release_time = 0;
708       if (type == KeyPress || type == ButtonPress)
709         {
710           xd->down_mask = 0;
711           xd->modifier_release_time = 0;
712         }
713
714       if (key_event_p)
715         ev->xkey.state    |= xd->need_to_add_mask;
716       else
717         ev->xbutton.state |= xd->need_to_add_mask;
718
719       if (type == KeyRelease && keycode == xd->last_downkey)
720         /* If I hold press-and-release the Control key and then press
721            and hold down the right arrow, I want it to auto-repeat
722            Control-Right.  On the other hand, if I do the same but
723            manually press the Right arrow a bunch of times, I want
724            to see one Control-Right and then a bunch of Rights.
725            This means that we need to distinguish between an
726            auto-repeated key and a key pressed and released a bunch
727            of times.
728
729            Naturally, the designers of the X spec didn't see fit
730            to provide an obvious way to distinguish these cases.
731            So we assume that if the release and the next press
732            occur at the same time, the key was actually auto-
733            repeated.  Under Open-Windows, at least, this works. */
734         xd->modifier_release_time = xd->release_time
735           = key_event_p ? ev->xkey.time : ev->xbutton.time;
736     }
737   else                          /* Modifier key pressed */
738     {
739       int i;
740       KeySym *syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) *
741                                         xd->x_keysym_map_keysyms_per_code];
742
743       /* If a non-modifier key was pressed in the middle of a bunch
744          of modifiers, then it unsticks all the modifiers that were
745          previously pressed.  We cannot unstick the modifiers until
746          now because we want to check for auto-repeat of the
747          non-modifier key. */
748
749       if (xd->last_downkey)
750         {
751           xd->last_downkey = 0;
752           xd->need_to_add_mask = 0;
753         }
754
755       if (xd->modifier_release_time
756           && INTP (Vmodifier_keys_sticky_time)
757           && (ev->xkey.time
758               > xd->modifier_release_time + XINT (Vmodifier_keys_sticky_time)))
759         {
760           xd->need_to_add_mask = 0;
761           xd->down_mask = 0;
762         }
763
764 #define FROB(mask)                              \
765 do {                                            \
766   if (type == KeyPress)                         \
767     {                                           \
768       /* If modifier key is already sticky,     \
769          then unstick it.  Note that we do      \
770          not test down_mask to deal with the    \
771          unlikely but possible case that the    \
772          modifier key auto-repeats. */          \
773       if (xd->need_to_add_mask & mask)          \
774         {                                       \
775           xd->need_to_add_mask &= ~mask;        \
776           xd->down_mask &= ~mask;               \
777         }                                       \
778       else                                      \
779         xd->down_mask |= mask;                  \
780     }                                           \
781   else                                          \
782     {                                           \
783       if (xd->down_mask & mask)                 \
784         {                                       \
785           xd->down_mask &= ~mask;               \
786           xd->need_to_add_mask |= mask;         \
787         }                                       \
788     }                                           \
789   xd->modifier_release_time = ev->xkey.time;    \
790 } while (0)
791
792       for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
793         switch (syms[i])
794           {
795           case XK_Control_L: case XK_Control_R: FROB (ControlMask);   break;
796           case XK_Shift_L:   case XK_Shift_R:   FROB (ShiftMask);     break;
797           case XK_Meta_L:    case XK_Meta_R:    FROB (xd->MetaMask);  break;
798           case XK_Super_L:   case XK_Super_R:   FROB (xd->SuperMask); break;
799           case XK_Hyper_L:   case XK_Hyper_R:   FROB (xd->HyperMask); break;
800           case XK_Alt_L:     case XK_Alt_R:     FROB (xd->AltMask);   break;
801           }
802     }
803 #undef FROB
804 }
805
806 static void
807 clear_sticky_modifiers (struct device *d)
808 {
809   struct x_device *xd = DEVICE_X_DATA (d);
810
811   xd->need_to_add_mask = 0;
812   xd->last_downkey     = 0;
813   xd->release_time     = 0;
814   xd->down_mask        = 0;
815 }
816
817 static int
818 keysym_obeys_caps_lock_p (KeySym sym, struct device *d)
819 {
820   struct x_device *xd = DEVICE_X_DATA (d);
821   /* Eeeeevil hack.  Don't apply Caps_Lock to things that aren't alphabetic
822      characters, where "alphabetic" means something more than simply A-Z.
823      That is, if Caps_Lock is down, typing ESC doesn't produce Shift-ESC.
824      But if shift-lock is down, then it does. */
825   if (xd->lock_interpretation == XK_Shift_Lock)
826     return 1;
827
828   return
829     ((sym >= XK_A)        && (sym <= XK_Z))          ||
830     ((sym >= XK_a)        && (sym <= XK_z))          ||
831     ((sym >= XK_Agrave)   && (sym <= XK_Odiaeresis)) ||
832     ((sym >= XK_agrave)   && (sym <= XK_odiaeresis)) ||
833     ((sym >= XK_Ooblique) && (sym <= XK_Thorn))      ||
834     ((sym >= XK_oslash)   && (sym <= XK_thorn));
835 }
836
837 /* called from EmacsFrame.c (actually from Xt itself) when a
838    MappingNotify event is received.  In its infinite wisdom, Xt
839    decided that Xt event handlers never get MappingNotify events.
840    O'Reilly Xt Programming Manual 9.1.2 says:
841
842    MappingNotify is automatically handled by Xt, so it isn't passed
843    to event handlers and you don't need to worry about it.
844
845    Of course, we DO worry about it, so we need a special translation. */
846 void
847 emacs_Xt_mapping_action (Widget w, XEvent* event)
848 {
849   struct device *d = get_device_from_display (event->xany.display);
850
851   if (DEVICE_X_BEING_DELETED (d))
852     return;
853 #if 0
854   /* nyet.  Now this is handled by Xt. */
855   XRefreshKeyboardMapping (&event->xmapping);
856 #endif
857   /* xmodmap generates about a billion MappingKeyboard events, followed
858      by a single MappingModifier event, so it might be worthwhile to
859      take extra MappingKeyboard events out of the queue before requesting
860      the current keymap from the server. */
861   switch (event->xmapping.request)
862     {
863     case MappingKeyboard:  x_reset_key_mapping      (d); break;
864     case MappingModifier:  x_reset_modifier_mapping (d); break;
865     case MappingPointer:   /* Do something here? */      break;
866     default: abort();
867     }
868 }
869
870 \f
871 /************************************************************************/
872 /*                  X to Emacs event conversion                         */
873 /************************************************************************/
874
875 static Lisp_Object
876 x_keysym_to_emacs_keysym (KeySym keysym, int simple_p)
877 {
878   char *name;
879   if (keysym >= XK_exclam && keysym <= XK_asciitilde)
880     /* We must assume that the X keysym numbers for the ASCII graphic
881        characters are the same as their ASCII codes.  */
882     return make_char (keysym);
883
884   switch (keysym)
885     {
886       /* These would be handled correctly by the default case, but by
887          special-casing them here we don't garbage a string or call
888          intern().  */
889     case XK_BackSpace:  return QKbackspace;
890     case XK_Tab:        return QKtab;
891     case XK_Linefeed:   return QKlinefeed;
892     case XK_Return:     return QKreturn;
893     case XK_Escape:     return QKescape;
894     case XK_space:      return QKspace;
895     case XK_Delete:     return QKdelete;
896     case 0:             return Qnil;
897     default:
898       if (simple_p) return Qnil;
899       /* !!#### not Mule-ized */
900       name = XKeysymToString (keysym);
901       if (!name || !name[0])
902         /* This happens if there is a mismatch between the Xlib of
903            XEmacs and the Xlib of the X server...
904
905            Let's hard-code in some knowledge of common keysyms introduced
906            in recent X11 releases.  Snarfed from X11/keysymdef.h
907
908            Probably we should add some stuff here for X11R6. */
909         switch (keysym)
910           {
911           case 0xFF95: return KEYSYM ("kp-home");
912           case 0xFF96: return KEYSYM ("kp-left");
913           case 0xFF97: return KEYSYM ("kp-up");
914           case 0xFF98: return KEYSYM ("kp-right");
915           case 0xFF99: return KEYSYM ("kp-down");
916           case 0xFF9A: return KEYSYM ("kp-prior");
917           case 0xFF9B: return KEYSYM ("kp-next");
918           case 0xFF9C: return KEYSYM ("kp-end");
919           case 0xFF9D: return KEYSYM ("kp-begin");
920           case 0xFF9E: return KEYSYM ("kp-insert");
921           case 0xFF9F: return KEYSYM ("kp-delete");
922
923           case 0x1005FF10: return KEYSYM ("SunF36"); /* labeled F11 */
924           case 0x1005FF11: return KEYSYM ("SunF37"); /* labeled F12 */
925           default:
926             {
927               char buf [64];
928               sprintf (buf, "unknown-keysym-0x%X", (int) keysym);
929               return KEYSYM (buf);
930             }
931           }
932       /* If it's got a one-character name, that's good enough. */
933       if (!name[1])
934         return make_char (name[0]);
935
936       /* If it's in the "Keyboard" character set, downcase it.
937          The case of those keysyms is too totally random for us to
938          force anyone to remember them.
939          The case of the other character sets is significant, however.
940          */
941       if ((((unsigned int) keysym) & (~0x1FF)) == ((unsigned int) 0xFE00))
942         {
943           char buf [255];
944           char *s1, *s2;
945           for (s1 = name, s2 = buf; *s1; s1++, s2++) {
946             if (*s1 == '_') {
947               *s2 = '-';
948             } else {
949               *s2 = tolower (* (unsigned char *) s1);
950             }
951           }
952           *s2 = 0;
953           return KEYSYM (buf);
954         }
955       return KEYSYM (name);
956     }
957 }
958
959 static Lisp_Object
960 x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p)
961      /* simple_p means don't try too hard (ASCII only) */
962 {
963   KeySym keysym = 0;
964
965 #ifdef HAVE_XIM
966   int len;
967   /* Some implementations of XmbLookupString don't return
968      XBufferOverflow correctly, so increase the size of the xim input
969      buffer from 64 to the more reasonable size 513, as Emacs has done.
970      From Kenichi Handa. */
971   char buffer[513];
972   char *bufptr = buffer;
973   int   bufsiz = sizeof (buffer);
974   Status status;
975 #ifdef XIM_XLIB
976   XIC xic = FRAME_X_XIC (x_any_window_to_frame
977                          (get_device_from_display (event->display),
978                           event->window));
979 #endif /* XIM_XLIB */
980 #endif /* HAVE_XIM */
981
982   /* We use XLookupString if we're not using XIM, or are using
983      XIM_XLIB but input context creation failed. */
984 #if ! (defined (HAVE_XIM) && defined (XIM_MOTIF))
985 #if defined (HAVE_XIM) && defined (XIM_XLIB)
986      if (!xic)
987 #endif /* XIM_XLIB */
988     {
989       /* Apparently it's necessary to specify a dummy here (rather
990          than passing in 0) to avoid crashes on German IRIX */
991       char dummy[256];
992       XLookupString (event, dummy, 200, &keysym, 0);
993       return (IsModifierKey (keysym) || keysym == XK_Mode_switch )
994         ? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p);
995     }
996 #endif /* ! XIM_MOTIF */
997
998 #ifdef HAVE_XIM
999  Lookup_String: /* Come-From XBufferOverflow */
1000 #ifdef XIM_MOTIF
1001   len = XmImMbLookupString (XtWindowToWidget (event->display, event->window),
1002                             event, bufptr, bufsiz, &keysym, &status);
1003 #else /* XIM_XLIB */
1004   if (xic)
1005     len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status);
1006 #endif /* HAVE_XIM */
1007
1008 #ifdef DEBUG_XEMACS
1009   if (debug_x_events > 0)
1010     {
1011       stderr_out ("   status=");
1012 #define print_status_when(S) if (status == S) stderr_out (#S)
1013       print_status_when (XLookupKeySym);
1014       print_status_when (XLookupBoth);
1015       print_status_when (XLookupChars);
1016       print_status_when (XLookupNone);
1017       print_status_when (XBufferOverflow);
1018
1019       if (status == XLookupKeySym || status == XLookupBoth)
1020         stderr_out (" keysym=%s",  XKeysymToString (keysym));
1021       if (status == XLookupChars  || status == XLookupBoth)
1022         {
1023           if (len != 1)
1024             {
1025               int j;
1026               stderr_out (" chars=\"");
1027               for (j=0; j<len; j++)
1028                 stderr_out ("%c", bufptr[j]);
1029               stderr_out ("\"");
1030             }
1031           else if (bufptr[0] <= 32 || bufptr[0] >= 127)
1032             stderr_out (" char=0x%x", bufptr[0]);
1033           else
1034             stderr_out (" char=%c", bufptr[0]);
1035         }
1036       stderr_out ("\n");
1037     }
1038 #endif /* DEBUG_XEMACS */
1039
1040   switch (status)
1041     {
1042     case XLookupKeySym:
1043     case XLookupBoth:
1044       return (IsModifierKey (keysym) || keysym == XK_Mode_switch )
1045         ? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p);
1046
1047     case XLookupChars:
1048       {
1049         /* Generate multiple emacs events */
1050         struct device *d = get_device_from_display (event->display);
1051         Emchar ch;
1052         Lisp_Object instream, fb_instream;
1053         Lstream *istr;
1054         struct gcpro gcpro1, gcpro2;
1055
1056         fb_instream = make_fixed_buffer_input_stream (bufptr, len);
1057
1058         /* #### Use Fget_coding_system (Vcomposed_input_coding_system) */
1059         instream =
1060           make_decoding_input_stream (XLSTREAM (fb_instream),
1061                                       Fget_coding_system (Qundecided));
1062
1063         istr = XLSTREAM (instream);
1064
1065         GCPRO2 (instream, fb_instream);
1066         while ((ch = Lstream_get_emchar (istr)) != EOF)
1067           {
1068             Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
1069             Lisp_Event *ev          = XEVENT (emacs_event);
1070             ev->channel             = DEVICE_CONSOLE (d);
1071             ev->event_type          = key_press_event;
1072             ev->timestamp           = event->time;
1073             ev->event.key.modifiers = 0;
1074             ev->event.key.keysym    = make_char (ch);
1075             enqueue_Xt_dispatch_event (emacs_event);
1076           }
1077         Lstream_close (istr);
1078         UNGCPRO;
1079         Lstream_delete (istr);
1080         Lstream_delete (XLSTREAM (fb_instream));
1081         return Qnil;
1082       }
1083     case XLookupNone: return Qnil;
1084     case XBufferOverflow:
1085       bufptr = (char *) alloca (len+1);
1086       bufsiz = len+1;
1087       goto Lookup_String;
1088     }
1089   return Qnil; /* not reached */
1090 #endif /* HAVE_XIM */
1091 }
1092
1093 static void
1094 set_last_server_timestamp (struct device *d, XEvent *x_event)
1095 {
1096   Time t;
1097   switch (x_event->type)
1098     {
1099     case KeyPress:
1100     case KeyRelease:       t = x_event->xkey.time;              break;
1101     case ButtonPress:
1102     case ButtonRelease:    t = x_event->xbutton.time;           break;
1103     case EnterNotify:
1104     case LeaveNotify:      t = x_event->xcrossing.time;         break;
1105     case MotionNotify:     t = x_event->xmotion.time;           break;
1106     case PropertyNotify:   t = x_event->xproperty.time;         break;
1107     case SelectionClear:   t = x_event->xselectionclear.time;   break;
1108     case SelectionRequest: t = x_event->xselectionrequest.time; break;
1109     case SelectionNotify:  t = x_event->xselection.time;        break;
1110     default: return;
1111     }
1112   DEVICE_X_LAST_SERVER_TIMESTAMP (d) = t;
1113 }
1114
1115 static int
1116 x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
1117 {
1118   Display *display    = x_event->xany.display;
1119   struct device *d    = get_device_from_display (display);
1120   struct x_device *xd = DEVICE_X_DATA (d);
1121
1122   if (DEVICE_X_BEING_DELETED (d))
1123      /* #### Uh, is this 0 correct? */
1124      return 0;
1125
1126   set_last_server_timestamp (d, x_event);
1127
1128   switch (x_event->type)
1129     {
1130     case KeyRelease:
1131       x_handle_sticky_modifiers (x_event, d);
1132       return 0;
1133
1134     case KeyPress:
1135     case ButtonPress:
1136     case ButtonRelease:
1137       {
1138         int modifiers = 0;
1139         int shift_p, lock_p;
1140         Bool key_event_p = (x_event->type == KeyPress);
1141         unsigned int *state =
1142           key_event_p ? &x_event->xkey.state : &x_event->xbutton.state;
1143
1144         /* If this is a synthetic KeyPress or Button event, and the user
1145            has expressed a disinterest in this security hole, then drop
1146            it on the floor. */
1147         if ((key_event_p
1148              ? x_event->xkey.send_event
1149              : x_event->xbutton.send_event)
1150 #ifdef EXTERNAL_WIDGET
1151             /* ben: events get sent to an ExternalShell using XSendEvent.
1152                This is not a perfect solution. */
1153             && !FRAME_X_EXTERNAL_WINDOW_P
1154             (x_any_window_to_frame (d, x_event->xany.window))
1155 #endif
1156             && !x_allow_sendevents)
1157           return 0;
1158
1159         DEVICE_X_MOUSE_TIMESTAMP (d) =
1160           DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d) =
1161           key_event_p ? x_event->xkey.time : x_event->xbutton.time;
1162
1163         x_handle_sticky_modifiers (x_event, d);
1164
1165         if (*state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
1166         if (*state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
1167         if (*state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
1168         if (*state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
1169         if (*state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
1170         {
1171           int numero_de_botao = -1;
1172
1173           if (!key_event_p)
1174             numero_de_botao = x_event->xbutton.button;
1175
1176           /* the button gets noted either in the button or the modifiers
1177              field, but not both. */
1178           if (numero_de_botao != 1 && (*state & Button1Mask))
1179             modifiers |= XEMACS_MOD_BUTTON1;
1180           if (numero_de_botao != 2 && (*state & Button2Mask))
1181             modifiers |= XEMACS_MOD_BUTTON2;
1182           if (numero_de_botao != 3 && (*state & Button3Mask))
1183             modifiers |= XEMACS_MOD_BUTTON3;
1184           if (numero_de_botao != 4 && (*state & Button4Mask))
1185             modifiers |= XEMACS_MOD_BUTTON4;
1186           if (numero_de_botao != 5 && (*state & Button5Mask))
1187             modifiers |= XEMACS_MOD_BUTTON5;
1188         }
1189
1190         /* Ignore the Caps_Lock key if:
1191            - any other modifiers are down, so that Caps_Lock doesn't
1192              turn C-x into C-X, which would suck.
1193            - the event was a mouse event. */
1194         if (modifiers || ! key_event_p)
1195           *state &= (~LockMask);
1196
1197         shift_p = *state & ShiftMask;
1198         lock_p  = *state & LockMask;
1199
1200         if (shift_p || lock_p)
1201           modifiers |= XEMACS_MOD_SHIFT;
1202
1203         if (key_event_p)
1204           {
1205             Lisp_Object keysym;
1206             XKeyEvent *ev = &x_event->xkey;
1207             /* This used to compute the frame from the given X window and
1208                store it here, but we really don't care about the frame. */
1209             emacs_event->channel = DEVICE_CONSOLE (d);
1210             keysym = x_to_emacs_keysym (&x_event->xkey, 0);
1211
1212             /* If the emacs keysym is nil, then that means that the X
1213                keysym was either a Modifier or NoSymbol, which
1214                probably means that we're in the midst of reading a
1215                Multi_key sequence, or a "dead" key prefix, or XIM
1216                input. Ignore it. */
1217             if (NILP (keysym))
1218               return 0;
1219
1220             /* More Caps_Lock garbage: Caps_Lock should *only* add the
1221                shift modifier to two-case keys (that is, A-Z and
1222                related characters). So at this point (after looking up
1223                the keysym) if the keysym isn't a dual-case alphabetic,
1224                and if the caps lock key was down but the shift key
1225                wasn't, then turn off the shift modifier.  Gag barf */
1226             /* #### type lossage: assuming equivalence of emacs and
1227                X keysyms */
1228             /* !!#### maybe fix for Mule */
1229             if (lock_p && !shift_p &&
1230                 ! (CHAR_OR_CHAR_INTP (keysym)
1231                    && keysym_obeys_caps_lock_p
1232                    ((KeySym) XCHAR_OR_CHAR_INT (keysym), d)))
1233               modifiers &= (~XEMACS_MOD_SHIFT);
1234
1235             /* If this key contains two distinct keysyms, that is,
1236                "shift" generates a different keysym than the
1237                non-shifted key, then don't apply the shift modifier
1238                bit: it's implicit.  Otherwise, if there would be no
1239                other way to tell the difference between the shifted
1240                and unshifted version of this key, apply the shift bit.
1241                Non-graphics, like Backspace and F1 get the shift bit
1242                in the modifiers slot.  Neither the characters "a",
1243                "A", "2", nor "@" normally have the shift bit set.
1244                However, "F1" normally does. */
1245             if (modifiers & XEMACS_MOD_SHIFT)
1246               {
1247                 int Mode_switch_p = *state & xd->ModeMask;
1248                 KeySym bot = XLookupKeysym (ev, Mode_switch_p ? 2 : 0);
1249                 KeySym top = XLookupKeysym (ev, Mode_switch_p ? 3 : 1);
1250                 if (top && bot && top != bot)
1251                   modifiers &= ~XEMACS_MOD_SHIFT;
1252               }
1253             emacs_event->event_type          = key_press_event;
1254             emacs_event->timestamp           = ev->time;
1255             emacs_event->event.key.modifiers = modifiers;
1256             emacs_event->event.key.keysym    = keysym;
1257           }
1258         else                    /* Mouse press/release event */
1259           {
1260             XButtonEvent *ev = &x_event->xbutton;
1261             struct frame *frame = x_window_to_frame (d, ev->window);
1262
1263             if (! frame)
1264               return 0; /* not for us */
1265             XSETFRAME (emacs_event->channel, frame);
1266
1267             emacs_event->event_type = (x_event->type == ButtonPress) ?
1268               button_press_event : button_release_event;
1269
1270             emacs_event->event.button.modifiers = modifiers;
1271             emacs_event->timestamp              = ev->time;
1272             emacs_event->event.button.button    = ev->button;
1273             emacs_event->event.button.x         = ev->x;
1274             emacs_event->event.button.y         = ev->y;
1275             /* because we don't seem to get a FocusIn event for button clicks
1276                when a widget-glyph is selected we will assume that we want the
1277                focus if a button gets pressed. */
1278             if (x_event->type == ButtonPress)
1279               handle_focus_event_1 (frame, 1);
1280           }
1281       }
1282     break;
1283
1284     case MotionNotify:
1285       {
1286         XMotionEvent *ev = &x_event->xmotion;
1287         struct frame *frame = x_window_to_frame (d, ev->window);
1288         int modifiers = 0;
1289         XMotionEvent event2;
1290
1291         if (! frame)
1292           return 0; /* not for us */
1293
1294         /* We use MotionHintMask, so we will get only one motion event
1295            until the next time we call XQueryPointer or the user
1296            clicks the mouse.  So call XQueryPointer now (meaning that
1297            the event will be in sync with the server just before
1298            Fnext_event() returns).  If the mouse is still in motion,
1299            then the server will immediately generate exactly one more
1300            motion event, which will be on the queue waiting for us
1301            next time around. */
1302         event2 = *ev;
1303         if (XQueryPointer (event2.display, event2.window,
1304                            &event2.root,   &event2.subwindow,
1305                            &event2.x_root, &event2.y_root,
1306                            &event2.x,      &event2.y,
1307                            &event2.state))
1308           ev = &event2; /* only one structure copy */
1309
1310         DEVICE_X_MOUSE_TIMESTAMP (d) = ev->time;
1311
1312         XSETFRAME (emacs_event->channel, frame);
1313         emacs_event->event_type     = pointer_motion_event;
1314         emacs_event->timestamp      = ev->time;
1315         emacs_event->event.motion.x = ev->x;
1316         emacs_event->event.motion.y = ev->y;
1317         if (ev->state & ShiftMask)      modifiers |= XEMACS_MOD_SHIFT;
1318         if (ev->state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
1319         if (ev->state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
1320         if (ev->state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
1321         if (ev->state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
1322         if (ev->state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
1323         if (ev->state & Button1Mask)    modifiers |= XEMACS_MOD_BUTTON1;
1324         if (ev->state & Button2Mask)    modifiers |= XEMACS_MOD_BUTTON2;
1325         if (ev->state & Button3Mask)    modifiers |= XEMACS_MOD_BUTTON3;
1326         if (ev->state & Button4Mask)    modifiers |= XEMACS_MOD_BUTTON4;
1327         if (ev->state & Button5Mask)    modifiers |= XEMACS_MOD_BUTTON5;
1328         /* Currently ignores Shift_Lock but probably shouldn't
1329            (but it definitely should ignore Caps_Lock). */
1330         emacs_event->event.motion.modifiers = modifiers;
1331       }
1332     break;
1333
1334     case ClientMessage:
1335       {
1336         /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is
1337            passed as the timestamp of the TAKE_FOCUS, which the ICCCM
1338            explicitly prohibits. */
1339         XClientMessageEvent *ev = &x_event->xclient;
1340 #ifdef HAVE_OFFIX_DND
1341         if (DndIsDropMessage(x_event))
1342           {
1343             unsigned int state;
1344             int modifiers = 0;
1345             unsigned int button=0;
1346             struct frame *frame = x_any_window_to_frame (d, ev->window);
1347             Extbyte *data;
1348             unsigned long size, dtype;
1349             Lisp_Object l_type = Qnil, l_data = Qnil;
1350             Lisp_Object l_dndlist = Qnil, l_item = Qnil;
1351             struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1352
1353             if (! frame)
1354               return 0; /* not for us */
1355
1356             GCPRO4 (l_type, l_data, l_dndlist, l_item);
1357             XSETFRAME (emacs_event->channel, frame);
1358
1359             emacs_event->event_type = misc_user_event;
1360             emacs_event->timestamp  = DEVICE_X_LAST_SERVER_TIMESTAMP (d);
1361
1362             state=DndDragButtons(x_event);
1363
1364             if (state & ShiftMask)      modifiers |= XEMACS_MOD_SHIFT;
1365             if (state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
1366             if (state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
1367             if (state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
1368             if (state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
1369             if (state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
1370             if (state & Button1Mask)    modifiers |= XEMACS_MOD_BUTTON1;
1371             if (state & Button2Mask)    modifiers |= XEMACS_MOD_BUTTON2;
1372             if (state & Button3Mask)    modifiers |= XEMACS_MOD_BUTTON3;
1373             if (state & Button4Mask)    modifiers |= XEMACS_MOD_BUTTON4;
1374             if (state & Button5Mask)    modifiers |= XEMACS_MOD_BUTTON5;
1375
1376             if (state & Button5Mask)    button = Button5;
1377             if (state & Button4Mask)    button = Button4;
1378             if (state & Button3Mask)    button = Button3;
1379             if (state & Button2Mask)    button = Button2;
1380             if (state & Button1Mask)    button = Button1;
1381
1382             emacs_event->event.misc.modifiers = modifiers;
1383             emacs_event->event.misc.button    = button;
1384
1385             DndDropCoordinates(FRAME_X_TEXT_WIDGET(frame), x_event,
1386                                &(emacs_event->event.misc.x),
1387                                &(emacs_event->event.misc.y) );
1388
1389             DndGetData(x_event,&data,&size);
1390
1391             dtype=DndDataType(x_event);
1392             switch (dtype)
1393               {
1394               case DndFiles: /* null terminated strings, end null */
1395                 {
1396                   int len;
1397                   char *hurl = NULL;
1398
1399                   while (*data)
1400                     {
1401                       len = strlen ((char*)data);
1402                       hurl = dnd_url_hexify_string ((char *)data, "file:");
1403                       l_item = make_string ((Bufbyte *)hurl, strlen (hurl));
1404                       l_dndlist = Fcons (l_item, l_dndlist);
1405                       data += len + 1;
1406                       xfree (hurl);
1407                     }
1408                   l_type = Qdragdrop_URL;
1409                 }
1410                 break;
1411               case DndText:
1412                 l_type = Qdragdrop_MIME;
1413                 l_dndlist = list1 ( list3 ( list1 ( make_string ((Bufbyte *)"text/plain", 10) ),
1414                                             make_string ((Bufbyte *)"8bit", 4),
1415                                             make_ext_string ((Extbyte *)data,
1416                                                              strlen((char *)data),
1417                                                              Qctext) ) );
1418                 break;
1419               case DndMIME:
1420                 /* we have to parse this in some way to extract
1421                    content-type and params (in the tm way) and
1422                    content encoding.
1423                    OR: if data is string, let tm do the job
1424                        if data is list[2], give the first two
1425                        to tm...
1426                 */
1427                 l_type = Qdragdrop_MIME;
1428                 l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
1429                                                      strlen((char *)data),
1430                                                      Qbinary) );
1431                 break;
1432               case DndFile:
1433               case DndDir:
1434               case DndLink:
1435               case DndExe:
1436                 {
1437                   char *hurl = dnd_url_hexify_string ((char *) data, "file:");
1438
1439                   l_dndlist = list1 ( make_string ((Bufbyte *)hurl,
1440                                                    strlen (hurl)) );
1441                   l_type = Qdragdrop_URL;
1442
1443                   xfree (hurl);
1444                 }
1445                 break;
1446               case DndURL:
1447                 /* as it is a real URL it should already be escaped
1448                    and escaping again will break them (cause % is unsave) */
1449                 l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
1450                                                      strlen ((char *)data),
1451                                                      Qfile_name) );
1452                 l_type = Qdragdrop_URL;
1453                 break;
1454               default: /* Unknown, RawData and any other type */
1455                 l_dndlist = list1 ( list3 ( list1 ( make_string ((Bufbyte *)"application/octet-stream", 24) ),
1456                                             make_string ((Bufbyte *)"8bit", 4),
1457                                             make_ext_string ((Extbyte *)data,
1458                                                              size,
1459                                                              Qbinary) ) );
1460                 l_type = Qdragdrop_MIME;
1461                 break;
1462               }
1463
1464             emacs_event->event.misc.function = Qdragdrop_drop_dispatch;
1465             emacs_event->event.misc.object = Fcons (l_type, l_dndlist);
1466
1467             UNGCPRO;
1468
1469             break;
1470           }
1471 #endif /* HAVE_OFFIX_DND */
1472         if (ev->message_type == DEVICE_XATOM_WM_PROTOCOLS (d)
1473             && (Atom) (ev->data.l[0]) == DEVICE_XATOM_WM_TAKE_FOCUS (d)
1474             && (Atom) (ev->data.l[1]) == 0)
1475           {
1476             ev->data.l[1] = DEVICE_X_LAST_SERVER_TIMESTAMP (d);
1477           }
1478       }
1479     /* fall through */
1480
1481     default: /* it's a magic event */
1482       {
1483         struct frame *frame;
1484         Window w;
1485         XEvent *x_event_copy = &emacs_event->event.magic.underlying_x_event;
1486
1487 #define FROB(event_member, window_member) \
1488         x_event_copy->event_member = x_event->event_member; \
1489         w = x_event->event_member.window_member
1490
1491         switch (x_event->type)
1492           {
1493           case SelectionRequest: FROB(xselectionrequest, owner);  break;
1494           case SelectionClear:   FROB(xselectionclear, window);   break;
1495           case SelectionNotify:  FROB(xselection, requestor);     break;
1496           case PropertyNotify:   FROB(xproperty, window);         break;
1497           case ClientMessage:    FROB(xclient, window);           break;
1498           case ConfigureNotify:  FROB(xconfigure, window);        break;
1499           case Expose:
1500           case GraphicsExpose:   FROB(xexpose, window);           break;
1501           case MapNotify:
1502           case UnmapNotify:      FROB(xmap, window);              break;
1503           case EnterNotify:
1504           case LeaveNotify:      FROB(xcrossing, window);         break;
1505           case FocusIn:
1506           case FocusOut:         FROB(xfocus, window);            break;
1507           case VisibilityNotify: FROB(xvisibility, window);       break;
1508           case CreateNotify: FROB(xcreatewindow, window);         break;
1509           default:
1510             w = x_event->xany.window;
1511             *x_event_copy = *x_event;
1512             break;
1513           }
1514 #undef FROB
1515         frame = x_any_window_to_frame (d, w);
1516
1517         if (!frame)
1518           return 0;
1519
1520         emacs_event->event_type = magic_event;
1521         XSETFRAME (emacs_event->channel, frame);
1522
1523         break;
1524       }
1525     }
1526   return 1;
1527 }
1528
1529
1530 \f
1531 /************************************************************************/
1532 /*                           magic-event handling                       */
1533 /************************************************************************/
1534
1535 static void
1536 handle_focus_event_1 (struct frame *f, int in_p)
1537 {
1538 #if XtSpecificationRelease > 5
1539   Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
1540 #endif
1541 #ifdef HAVE_XIM
1542   XIM_focus_event (f, in_p);
1543 #endif /* HAVE_XIM */
1544   /* On focus change, clear all memory of sticky modifiers
1545      to avoid non-intuitive behavior. */
1546   clear_sticky_modifiers (XDEVICE (FRAME_DEVICE (f)));
1547
1548   /* We don't want to handle the focus change now, because we might
1549      be in an accept-process-output, sleep-for, or sit-for.  So
1550      we enqueue it.
1551
1552      Actually, we half handle it: we handle it as far as changing the
1553      box cursor for redisplay, but we don't call any hooks or do any
1554      select-frame stuff until after the sit-for.
1555
1556      Unfortunately native widgets break the model because they grab
1557      the keyboard focus and nothing sets it back again. I cannot find
1558      any reasonable way to do this elsewhere so we assert here that
1559      the keyboard focus is on the emacs text widget. Menus and dialogs
1560      do this in their selection callback, but we don't want that since
1561      a button having focus is legitimate. An edit field having focus
1562      is mandatory. Weirdly you get a FocusOut event when you click in
1563      a widget-glyph but you don't get a corresponding FocusIn when you
1564      click in the frame. Why is this?  */
1565   if (in_p
1566 #if XtSpecificationRelease > 5
1567       && FRAME_X_TEXT_WIDGET (f) != focus_widget
1568 #endif
1569       )
1570     {
1571       lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f),
1572                              FRAME_X_TEXT_WIDGET (f));
1573     }
1574   /* do the generic event-stream stuff. */
1575   {
1576     Lisp_Object frm;
1577     Lisp_Object conser;
1578     struct gcpro gcpro1;
1579
1580     XSETFRAME (frm, f);
1581     conser = Fcons (frm, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil));
1582     GCPRO1 (conser);
1583     emacs_handle_focus_change_preliminary (conser);
1584     enqueue_magic_eval_event (emacs_handle_focus_change_final,
1585                               conser);
1586     UNGCPRO;
1587   }
1588 }
1589
1590 /* This is called from the external-widget code */
1591
1592 void emacs_Xt_handle_focus_event (XEvent *event);
1593 void
1594 emacs_Xt_handle_focus_event (XEvent *event)
1595 {
1596   struct device *d = get_device_from_display (event->xany.display);
1597   struct frame *f;
1598
1599   if (DEVICE_X_BEING_DELETED (d))
1600     return;
1601
1602   /*
1603    * It's curious that we're using x_any_window_to_frame() instead
1604    * of x_window_to_frame().  I don't know what the impact of this is.
1605    */
1606   f = x_any_window_to_frame (d, event->xfocus.window);
1607   if (!f)
1608     /* focus events are sometimes generated just before
1609        a frame is destroyed. */
1610     return;
1611   handle_focus_event_1 (f, event->type == FocusIn);
1612 }
1613
1614 /* both MapNotify and VisibilityNotify can cause this
1615    JV is_visible has the same semantics as f->visible*/
1616 static void
1617 change_frame_visibility (struct frame *f, int is_visible)
1618 {
1619   Lisp_Object frame;
1620
1621   XSETFRAME (frame, f);
1622
1623   if (!FRAME_VISIBLE_P (f) && is_visible)
1624     {
1625       FRAME_VISIBLE_P (f) = is_visible;
1626       /* This improves the double flicker when uniconifying a frame
1627          some.  A lot of it is not showing a buffer which has changed
1628          while the frame was iconified.  To fix it further requires
1629          the good 'ol double redisplay structure. */
1630       MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1631       va_run_hook_with_args (Qmap_frame_hook, 1, frame);
1632     }
1633   else if (FRAME_VISIBLE_P (f) && !is_visible)
1634     {
1635       FRAME_VISIBLE_P (f) = 0;
1636       va_run_hook_with_args (Qunmap_frame_hook, 1, frame);
1637     }
1638   else if (FRAME_VISIBLE_P (f) * is_visible < 0)
1639     {
1640       FRAME_VISIBLE_P(f) = - FRAME_VISIBLE_P(f);
1641       if (FRAME_REPAINT_P(f))
1642               MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1643       va_run_hook_with_args (Qmap_frame_hook, 1, frame);
1644     }
1645 }
1646
1647 static void
1648 handle_map_event (struct frame *f, XEvent *event)
1649 {
1650   Lisp_Object frame;
1651
1652   XSETFRAME (frame, f);
1653   if (event->type == MapNotify)
1654     {
1655       XWindowAttributes xwa;
1656
1657       /* Bleagh!!!!!!  Apparently some window managers (e.g. MWM)
1658          send synthetic MapNotify events when a window is first
1659          created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE.
1660          Or something like that.  We initially tried a different
1661          solution below, but that ran into a different window-
1662          manager bug.
1663
1664          It seems that the only reliable way is to treat a
1665          MapNotify event as a "hint" that the window might or
1666          might not be visible, and check explicitly. */
1667
1668       XGetWindowAttributes (event->xany.display, event->xmap.window,
1669                             &xwa);
1670       if (xwa.map_state != IsViewable)
1671         {
1672           /* Calling Fframe_iconified_p is the only way we have to
1673              correctly update FRAME_ICONIFIED_P */
1674           Fframe_iconified_p (frame);
1675           return;
1676         }
1677
1678       FRAME_X_TOTALLY_VISIBLE_P (f) = 1;
1679 #if 0
1680       /* Bleagh again!!!!  We initially tried the following hack
1681          around the MWM problem, but it turns out that TWM
1682          has a race condition when you un-iconify, where it maps
1683          the window and then tells the server that the window
1684          is un-iconified.  Usually, XEmacs wakes up between
1685          those two occurrences, and thus thinks that un-iconified
1686          windows are still iconified.
1687
1688          Ah, the joys of X. */
1689
1690       /* By Emacs definition, a frame that is iconified is not
1691          visible.  Marking a frame as visible will automatically cause
1692          frame-iconified-p to return nil, regardless of whether the
1693          frame is actually iconified.  Therefore, we have to ignore
1694          MapNotify events on iconified frames. (It's not obvious
1695          to me why these are being sent, but it happens at startup
1696          with frames that are initially iconified; perhaps they are
1697          synthetic MapNotify events coming from the window manager.)
1698          Note that `frame-iconified-p' queries the server
1699          to determine whether the frame is currently iconified,
1700          rather than consulting some internal (and likely
1701          inaccurate) state flag.  Therefore, ignoring the MapNotify
1702          is correct. */
1703       if (!FRAME_VISIBLE_P (f) && NILP (Fframe_iconified_p (frame)))
1704 #endif /* 0 */
1705         change_frame_visibility (f, 1);
1706     }
1707   else
1708     {
1709       FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
1710       change_frame_visibility (f, 0);
1711       /* Calling Fframe_iconified_p is the only way we have to
1712          correctly update FRAME_ICONIFIED_P */
1713       Fframe_iconified_p (frame);
1714     }
1715 }
1716
1717 static void
1718 handle_client_message (struct frame *f, XEvent *event)
1719 {
1720   struct device *d = XDEVICE (FRAME_DEVICE (f));
1721   Lisp_Object frame;
1722
1723   XSETFRAME (frame, f);
1724
1725   if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) &&
1726       (Atom) (event->xclient.data.l[0]) == DEVICE_XATOM_WM_DELETE_WINDOW (d))
1727     {
1728       /* WM_DELETE_WINDOW is a misc-user event, but other ClientMessages,
1729          such as WM_TAKE_FOCUS, are eval events.  That's because delete-window
1730          was probably executed with a mouse click, while the others could
1731          have been sent as a result of mouse motion or some other implicit
1732          action.  (Call this a "heuristic"...)  The reason for caring about
1733          this is so that clicking on the close-box will make emacs prompt
1734          using a dialog box instead of the minibuffer if there are unsaved
1735          buffers.
1736          */
1737       enqueue_misc_user_event (frame, Qeval,
1738                                list3 (Qdelete_frame, frame, Qt));
1739     }
1740   else if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) &&
1741            (Atom) event->xclient.data.l[0] == DEVICE_XATOM_WM_TAKE_FOCUS (d))
1742     {
1743       handle_focus_event_1 (f, 1);
1744 #if 0
1745       /* If there is a dialog box up, focus on it.
1746
1747          #### Actually, we're raising it too, which is wrong.  We should
1748          #### just focus on it, but lwlib doesn't currently give us an
1749          #### easy way to do that.  This should be fixed.
1750          */
1751       unsigned long take_focus_timestamp = event->xclient.data.l[1];
1752       Widget widget = lw_raise_all_pop_up_widgets ();
1753       if (widget)
1754         {
1755           /* kludge: raise_all returns bottommost widget, but we really
1756              want the topmost.  So just raise it for now. */
1757           XMapRaised (XtDisplay (widget), XtWindow (widget));
1758           /* Grab the focus with the timestamp of the TAKE_FOCUS. */
1759           XSetInputFocus (XtDisplay (widget), XtWindow (widget),
1760                           RevertToParent, take_focus_timestamp);
1761         }
1762 #endif
1763     }
1764 }
1765
1766 /* #### I'm struggling to understand how the X event loop really works. 
1767    Here is the problem:
1768    
1769    When widgets get mapped / changed etc the actual display updates
1770    are done asynchronously via X events being processed - this
1771    normally happens when XtAppProcessEvent() gets called. However, if
1772    we are executing lisp code or even doing redisplay we won't
1773    necessarily process X events for a very long time. This has the
1774    effect of widgets only getting updated when XEmacs only goes into
1775    idle, or some other event causes processing of the X event queue.
1776
1777    XtAppProcessEvent can get called from the following places:
1778
1779      emacs_Xt_next_event () - this is normal event processing, almost
1780      any non-X event will take precedence and this means that we
1781      cannot rely on it to do the right thing at the right time for
1782      widget display.
1783
1784      drain_X_queue () - this happens when SIGIO gets tripped,
1785      processing the event queue allows C-g to be checked for. It gets
1786      called from emacs_Xt_event_pending_p ().
1787
1788    In order to solve this I have tried introducing a list primitive -
1789    dispatch-non-command-events - which forces processing of X events
1790    related to display. Unfortunately this has a number of problems,
1791    one is that it is possible for event_stream_event_pending_p to
1792    block for ever if there isn't actually an event. I guess this can
1793    happen if we drop the synthetic event for reason. It also relies on
1794    SIGIO processing which makes things rather fragile.
1795
1796    People have seen behaviour whereby XEmacs blocks until you move the
1797    mouse. This seems to indicate that dispatch-non-command-events is
1798    blocking. It may be that in a SIGIO world forcing SIGIO processing
1799    does the wrong thing.
1800 */
1801 static void
1802 emacs_Xt_force_event_pending (struct frame* f)
1803 {
1804   XEvent event;
1805
1806   Display* dpy = DEVICE_X_DISPLAY (XDEVICE (FRAME_DEVICE  (f)));
1807   event.xclient.type            = ClientMessage;
1808   event.xclient.display         = dpy;
1809   event.xclient.message_type    = XInternAtom (dpy, "BumpQueue", False);
1810   event.xclient.format          = 32;
1811   event.xclient.window          = 0;
1812
1813   /* Send the drop message */
1814   XSendEvent(dpy, XtWindow (FRAME_X_SHELL_WIDGET (f)),
1815              True, NoEventMask, &event);
1816   /* We rely on SIGIO and friends to realise we have generated an
1817      event. */
1818 }
1819
1820 static void
1821 emacs_Xt_handle_magic_event (Lisp_Event *emacs_event)
1822 {
1823   /* This function can GC */
1824   XEvent *event = &emacs_event->event.magic.underlying_x_event;
1825   struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event));
1826
1827   if (!FRAME_LIVE_P (f) || DEVICE_X_BEING_DELETED (XDEVICE (FRAME_DEVICE (f))))
1828     return;
1829
1830   switch (event->type)
1831     {
1832     case SelectionRequest:
1833       x_handle_selection_request (&event->xselectionrequest);
1834       break;
1835
1836     case SelectionClear:
1837       x_handle_selection_clear (&event->xselectionclear);
1838       break;
1839
1840     case SelectionNotify:
1841       x_handle_selection_notify (&event->xselection);
1842       break;
1843
1844     case PropertyNotify:
1845       x_handle_property_notify (&event->xproperty);
1846       break;
1847
1848     case Expose:
1849       if (!check_for_ignored_expose (f, event->xexpose.x, event->xexpose.y,
1850                                      event->xexpose.width, event->xexpose.height)
1851           &&
1852           !find_matching_subwindow (f, event->xexpose.x, event->xexpose.y,
1853           event->xexpose.width, event->xexpose.height))
1854         x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
1855                                event->xexpose.width, event->xexpose.height);
1856       break;
1857
1858     case GraphicsExpose: /* This occurs when an XCopyArea's source area was
1859                             obscured or not available. */
1860       x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
1861                              event->xexpose.width, event->xexpose.height);
1862       break;
1863
1864     case MapNotify:
1865     case UnmapNotify:
1866       handle_map_event (f, event);
1867       break;
1868
1869     case EnterNotify:
1870       if (event->xcrossing.detail != NotifyInferior)
1871         {
1872           Lisp_Object frame;
1873
1874           XSETFRAME (frame, f);
1875           /* FRAME_X_MOUSE_P (f) = 1; */
1876           va_run_hook_with_args (Qmouse_enter_frame_hook, 1, frame);
1877         }
1878       break;
1879
1880     case LeaveNotify:
1881       if (event->xcrossing.detail != NotifyInferior)
1882         {
1883           Lisp_Object frame;
1884
1885           XSETFRAME (frame, f);
1886           /* FRAME_X_MOUSE_P (f) = 0; */
1887           va_run_hook_with_args (Qmouse_leave_frame_hook, 1, frame);
1888         }
1889       break;
1890
1891     case FocusIn:
1892     case FocusOut:
1893
1894 #ifdef EXTERNAL_WIDGET
1895       /* External widget lossage: Ben said:
1896          YUCK.  The only way to make focus changes work properly is to
1897          completely ignore all FocusIn/FocusOut events and depend only
1898          on notifications from the ExternalClient widget. */
1899       if (FRAME_X_EXTERNAL_WINDOW_P (f))
1900         break;
1901 #endif
1902       handle_focus_event_1 (f, event->type == FocusIn);
1903       break;
1904
1905     case ClientMessage:
1906       handle_client_message (f, event);
1907       break;
1908
1909     case VisibilityNotify: /* window visibility has changed */
1910       if (event->xvisibility.window == XtWindow (FRAME_X_SHELL_WIDGET (f)))
1911         {
1912           FRAME_X_TOTALLY_VISIBLE_P (f) =
1913             (event->xvisibility.state == VisibilityUnobscured);
1914           /* Note that the fvwm pager only sends VisibilityNotify when
1915              changing pages. Is this all we need to do ? JV */
1916           /* Nope.  We must at least trigger a redisplay here.
1917              Since this case seems similar to MapNotify, I've
1918              factored out some code to change_frame_visibility().
1919              This triggers the necessary redisplay and runs
1920              (un)map-frame-hook.  - dkindred@cs.cmu.edu */
1921           /* Changed it again to support the tristate visibility flag */
1922           change_frame_visibility (f, (event->xvisibility.state
1923                                        != VisibilityFullyObscured) ? 1 : -1);
1924         }
1925       break;
1926
1927     case ConfigureNotify:
1928 #ifdef HAVE_XIM
1929       XIM_SetGeometry (f);
1930 #endif
1931       break;
1932
1933     case CreateNotify:
1934       break;
1935
1936     default:
1937       break;
1938     }
1939 }
1940
1941 \f
1942 /************************************************************************/
1943 /*                              timeout events                          */
1944 /************************************************************************/
1945
1946 static int timeout_id_tick;
1947
1948 /* Xt interval id's might not fit into an int (they're pointers, as it
1949    happens), so we need to provide a conversion list. */
1950
1951 static struct Xt_timeout
1952 {
1953   int id;
1954   XtIntervalId interval_id;
1955   struct Xt_timeout *next;
1956 } *pending_timeouts, *completed_timeouts;
1957
1958 static struct Xt_timeout_blocktype
1959 {
1960   Blocktype_declare (struct Xt_timeout);
1961 } *the_Xt_timeout_blocktype;
1962
1963 /* called by XtAppNextEvent() */
1964 static void
1965 Xt_timeout_callback (XtPointer closure, XtIntervalId *id)
1966 {
1967   struct Xt_timeout *timeout = (struct Xt_timeout *) closure;
1968   struct Xt_timeout *t2 = pending_timeouts;
1969   /* Remove this one from the list of pending timeouts */
1970   if (t2 == timeout)
1971     pending_timeouts = pending_timeouts->next;
1972   else
1973     {
1974       while (t2->next && t2->next != timeout) t2 = t2->next;
1975       assert (t2->next);
1976       t2->next = t2->next->next;
1977     }
1978   /* Add this one to the list of completed timeouts */
1979   timeout->next = completed_timeouts;
1980   completed_timeouts = timeout;
1981 }
1982
1983 static int
1984 emacs_Xt_add_timeout (EMACS_TIME thyme)
1985 {
1986   struct Xt_timeout *timeout = Blocktype_alloc (the_Xt_timeout_blocktype);
1987   EMACS_TIME current_time;
1988   int milliseconds;
1989
1990   timeout->id = timeout_id_tick++;
1991   timeout->next = pending_timeouts;
1992   pending_timeouts = timeout;
1993   EMACS_GET_TIME (current_time);
1994   EMACS_SUB_TIME (thyme, thyme, current_time);
1995   milliseconds = EMACS_SECS (thyme) * 1000 +
1996     EMACS_USECS (thyme) / 1000;
1997   if (milliseconds < 1)
1998     milliseconds = 1;
1999   timeout->interval_id = XtAppAddTimeOut (Xt_app_con, milliseconds,
2000                                           Xt_timeout_callback,
2001                                           (XtPointer) timeout);
2002   return timeout->id;
2003 }
2004
2005 static void
2006 emacs_Xt_remove_timeout (int id)
2007 {
2008   struct Xt_timeout *timeout, *t2;
2009
2010   timeout = NULL;
2011
2012   /* Find the timeout on the list of pending ones, if it's still there. */
2013   if (pending_timeouts)
2014     {
2015       if (id == pending_timeouts->id)
2016         {
2017           timeout = pending_timeouts;
2018           pending_timeouts = pending_timeouts->next;
2019         }
2020       else
2021         {
2022           t2 = pending_timeouts;
2023           while (t2->next && t2->next->id != id) t2 = t2->next;
2024           if ( t2->next)   /*found it */
2025             {
2026               timeout = t2->next;
2027               t2->next = t2->next->next;
2028             }
2029         }
2030       /* if it was pending, we have removed it from the list */
2031       if (timeout)
2032         XtRemoveTimeOut (timeout->interval_id);
2033     }
2034
2035   /* It could be that the Xt call back was already called but we didn't convert
2036      into an Emacs event yet */
2037   if (!timeout && completed_timeouts)
2038     {
2039       /* Code duplication! */
2040       if (id == completed_timeouts->id)
2041         {
2042           timeout = completed_timeouts;
2043           completed_timeouts = completed_timeouts->next;
2044         }
2045       else
2046         {
2047           t2 = completed_timeouts;
2048           while (t2->next && t2->next->id != id) t2 = t2->next;
2049           if ( t2->next)   /*found it */
2050             {
2051               timeout = t2->next;
2052               t2->next = t2->next->next;
2053             }
2054         }
2055     }
2056
2057   /* If we found the thing on the lists of timeouts,
2058      and removed it, deallocate
2059   */
2060   if (timeout)
2061     Blocktype_free (the_Xt_timeout_blocktype, timeout);
2062 }
2063
2064 static void
2065 Xt_timeout_to_emacs_event (Lisp_Event *emacs_event)
2066 {
2067   struct Xt_timeout *timeout = completed_timeouts;
2068   assert (timeout);
2069   completed_timeouts = completed_timeouts->next;
2070   emacs_event->event_type = timeout_event;
2071   /* timeout events have nil as channel */
2072   emacs_event->timestamp  = 0; /* #### wrong!! */
2073   emacs_event->event.timeout.interval_id = timeout->id;
2074   emacs_event->event.timeout.function = Qnil;
2075   emacs_event->event.timeout.object = Qnil;
2076   Blocktype_free (the_Xt_timeout_blocktype, timeout);
2077 }
2078
2079 \f
2080 /************************************************************************/
2081 /*                      process and tty events                          */
2082 /************************************************************************/
2083
2084 struct what_is_ready_closure
2085 {
2086   int fd;
2087   Lisp_Object what;
2088   XtInputId id;
2089 };
2090
2091 static Lisp_Object *filedesc_with_input;
2092 static struct what_is_ready_closure **filedesc_to_what_closure;
2093
2094 static void
2095 init_what_input_once (void)
2096 {
2097   int i;
2098
2099   filedesc_with_input = xnew_array (Lisp_Object, MAXDESC);
2100   filedesc_to_what_closure =
2101     xnew_array (struct what_is_ready_closure *, MAXDESC);
2102
2103   for (i = 0; i < MAXDESC; i++)
2104     {
2105       filedesc_to_what_closure[i] = 0;
2106       filedesc_with_input[i] = Qnil;
2107     }
2108
2109   process_events_occurred = 0;
2110   tty_events_occurred = 0;
2111 }
2112
2113 static void
2114 mark_what_as_being_ready (struct what_is_ready_closure *closure)
2115 {
2116   if (NILP (filedesc_with_input[closure->fd]))
2117     {
2118       SELECT_TYPE temp_mask;
2119       FD_ZERO (&temp_mask);
2120       FD_SET (closure->fd, &temp_mask);
2121       /* Check to make sure there's *really* input available.
2122          Sometimes things seem to get confused and this gets called
2123          for the tty fd when there's really only input available
2124          on some process's fd.  (It will subsequently get called
2125          for that process's fd, so returning without setting any
2126          flags will take care of it.)  To see the problem, uncomment
2127          the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS
2128          down to 25, do sh -c 'xemacs -nw -q -f shell 2>/tmp/log'
2129          and press return repeatedly.  (Seen under AIX & Linux.)
2130          -dkindred@cs.cmu.edu */
2131       if (!poll_fds_for_input (temp_mask))
2132         {
2133 #if 0
2134           stderr_out ("mark_what_as_being_ready: no input available (fd=%d)\n",
2135                       closure->fd);
2136 #endif
2137           return;
2138         }
2139       filedesc_with_input[closure->fd] = closure->what;
2140       if (PROCESSP (closure->what))
2141       /* Don't increment this if the current process is already marked
2142        *  as having input. */
2143         process_events_occurred++;
2144       else
2145         tty_events_occurred++;
2146     }
2147 }
2148
2149 static void
2150 Xt_what_callback (void *closure, int *source, XtInputId *id)
2151 {
2152   /* If closure is 0, then we got a fake event from a signal handler.
2153      The only purpose of this is to make XtAppProcessEvent() stop
2154      blocking. */
2155   if (closure)
2156     mark_what_as_being_ready ((struct what_is_ready_closure *) closure);
2157   else
2158     {
2159       fake_event_occurred++;
2160       drain_signal_event_pipe ();
2161     }
2162 }
2163
2164 static void
2165 select_filedesc (int fd, Lisp_Object what)
2166 {
2167   struct what_is_ready_closure *closure;
2168
2169   /* If somebody is trying to select something that's already selected
2170      for, then something went wrong.  The generic routines ought to
2171      detect this and error before here. */
2172   assert (!filedesc_to_what_closure[fd]);
2173
2174   closure = xnew (struct what_is_ready_closure);
2175   closure->fd = fd;
2176   closure->what = what;
2177   closure->id =
2178     XtAppAddInput (Xt_app_con, fd,
2179                    (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
2180                    Xt_what_callback, closure);
2181   filedesc_to_what_closure[fd] = closure;
2182 }
2183
2184 static void
2185 unselect_filedesc (int fd)
2186 {
2187   struct what_is_ready_closure *closure = filedesc_to_what_closure[fd];
2188
2189   assert (closure);
2190   if (!NILP (filedesc_with_input[fd]))
2191     {
2192       /* We are unselecting this process before we have drained the rest of
2193          the input from it, probably from status_notify() in the command loop.
2194          This can happen like so:
2195
2196           - We are waiting in XtAppNextEvent()
2197           - Process generates output
2198           - Process is marked as being ready
2199           - Process dies, SIGCHLD gets generated before we return (!?)
2200             It could happen I guess.
2201           - sigchld_handler() marks process as dead
2202           - Somehow we end up getting a new KeyPress event on the queue
2203             at the same time (I'm really so sure how that happens but I'm
2204             not sure it can't either so let's assume it can...).
2205           - Key events have priority so we return that instead of the proc.
2206           - Before dispatching the lisp key event we call status_notify()
2207           - Which deselects the process that SIGCHLD marked as dead.
2208
2209          Thus we never remove it from _with_input and turn it into a lisp
2210          event, so we need to do it here.  But this does not mean that we're
2211          throwing away the last block of output - status_notify() has already
2212          taken care of running the proc filter or whatever.
2213        */
2214       filedesc_with_input[fd] = Qnil;
2215       if (PROCESSP (closure->what))
2216         {
2217           assert (process_events_occurred > 0);
2218           process_events_occurred--;
2219         }
2220       else
2221         {
2222           assert (tty_events_occurred > 0);
2223           tty_events_occurred--;
2224         }
2225     }
2226   XtRemoveInput (closure->id);
2227   xfree (closure);
2228   filedesc_to_what_closure[fd] = 0;
2229 }
2230
2231 static void
2232 emacs_Xt_select_process (Lisp_Process *p)
2233 {
2234   Lisp_Object process;
2235   int infd = event_stream_unixoid_select_process (p);
2236
2237   XSETPROCESS (process, p);
2238   select_filedesc (infd, process);
2239 }
2240
2241 static void
2242 emacs_Xt_unselect_process (Lisp_Process *p)
2243 {
2244   int infd = event_stream_unixoid_unselect_process (p);
2245
2246   unselect_filedesc (infd);
2247 }
2248
2249 static USID
2250 emacs_Xt_create_stream_pair (void* inhandle, void* outhandle,
2251                 Lisp_Object* instream, Lisp_Object* outstream, int flags)
2252 {
2253   USID u = event_stream_unixoid_create_stream_pair
2254                 (inhandle, outhandle, instream, outstream, flags);
2255   if (u != USID_ERROR)
2256     u = USID_DONTHASH;
2257   return u;
2258 }
2259
2260 static USID
2261 emacs_Xt_delete_stream_pair (Lisp_Object instream, Lisp_Object outstream)
2262 {
2263   event_stream_unixoid_delete_stream_pair (instream, outstream);
2264   return USID_DONTHASH;
2265 }
2266
2267 /* This is called from GC when a process object is about to be freed.
2268    If we've still got pointers to it in this file, we're gonna lose hard.
2269  */
2270 void
2271 debug_process_finalization (Lisp_Process *p)
2272 {
2273 #if 0 /* #### */
2274   int i;
2275   Lisp_Object instr, outstr;
2276
2277   get_process_streams (p, &instr, &outstr);
2278   /* if it still has fds, then it hasn't been killed yet. */
2279   assert (NILP(instr));
2280   assert (NILP(outstr));
2281   /* Better not still be in the "with input" table; we know it's got no fds. */
2282   for (i = 0; i < MAXDESC; i++)
2283     {
2284       Lisp_Object process = filedesc_fds_with_input [i];
2285       assert (!PROCESSP (process) || XPROCESS (process) != p);
2286     }
2287 #endif
2288 }
2289
2290 static void
2291 Xt_process_to_emacs_event (Lisp_Event *emacs_event)
2292 {
2293   int i;
2294
2295   assert (process_events_occurred > 0);
2296
2297   for (i = 0; i < MAXDESC; i++)
2298     {
2299       Lisp_Object process = filedesc_with_input[i];
2300       if (PROCESSP (process))
2301         {
2302           filedesc_with_input[i] = Qnil;
2303           process_events_occurred--;
2304           /* process events have nil as channel */
2305           emacs_event->event_type = process_event;
2306           emacs_event->timestamp  = 0; /* #### */
2307           emacs_event->event.process.process = process;
2308           return;
2309         }
2310     }
2311   abort ();
2312 }
2313
2314 static void
2315 emacs_Xt_select_console (struct console *con)
2316 {
2317   Lisp_Object console;
2318   int infd;
2319
2320   if (CONSOLE_X_P (con))
2321     return; /* X consoles are automatically selected for when we
2322                initialize them in Xt */
2323   infd = event_stream_unixoid_select_console (con);
2324   XSETCONSOLE (console, con);
2325   select_filedesc (infd, console);
2326 }
2327
2328 static void
2329 emacs_Xt_unselect_console (struct console *con)
2330 {
2331   Lisp_Object console;
2332   int infd;
2333
2334   if (CONSOLE_X_P (con))
2335     return; /* X consoles are automatically selected for when we
2336                initialize them in Xt */
2337   infd = event_stream_unixoid_unselect_console (con);
2338   XSETCONSOLE (console, con);
2339   unselect_filedesc (infd);
2340 }
2341
2342 /* read an event from a tty, if one is available.  Returns non-zero
2343    if an event was available.  Note that when this function is
2344    called, there should always be a tty marked as ready for input.
2345    However, the input condition might actually be EOF, so there
2346    may not really be any input available. (In this case,
2347    read_event_from_tty_or_stream_desc() will arrange for the TTY device
2348    to be deleted.) */
2349
2350 static int
2351 Xt_tty_to_emacs_event (Lisp_Event *emacs_event)
2352 {
2353   int i;
2354
2355   assert (tty_events_occurred > 0);
2356   for (i = 0; i < MAXDESC; i++)
2357     {
2358       Lisp_Object console = filedesc_with_input[i];
2359       if (CONSOLEP (console))
2360         {
2361           assert (tty_events_occurred > 0);
2362           tty_events_occurred--;
2363           filedesc_with_input[i] = Qnil;
2364           if (read_event_from_tty_or_stream_desc
2365               (emacs_event, XCONSOLE (console), i))
2366             return 1;
2367         }
2368     }
2369
2370   return 0;
2371 }
2372
2373 \f
2374 /************************************************************************/
2375 /*              debugging functions to decipher an event                */
2376 /************************************************************************/
2377
2378 #ifdef DEBUG_XEMACS
2379 #include "xintrinsicp.h"        /* only describe_event() needs this */
2380 #include <X11/Xproto.h>         /* only describe_event() needs this */
2381
2382 static void
2383 describe_event_window (Window window, Display *display)
2384 {
2385   struct frame *f;
2386   Widget w;
2387   stderr_out ("   window: 0x%lx", (unsigned long) window);
2388   w = XtWindowToWidget (display, window);
2389   if (w)
2390     stderr_out (" %s", w->core.widget_class->core_class.class_name);
2391   f = x_any_window_to_frame (get_device_from_display (display), window);
2392   if (f)
2393     {
2394       char *buf = alloca_array (char, XSTRING_LENGTH (f->name) + 4);
2395       sprintf (buf, " \"%s\"", XSTRING_DATA (f->name));
2396       write_string_to_stdio_stream (stderr, 0, (Bufbyte *) buf, 0,
2397                                     strlen (buf), Qterminal, 1);
2398     }
2399   stderr_out ("\n");
2400 }
2401
2402 static const char *
2403 XEvent_mode_to_string (int mode)
2404 {
2405   switch (mode)
2406   {
2407   case NotifyNormal:       return "Normal";
2408   case NotifyGrab:         return "Grab";
2409   case NotifyUngrab:       return "Ungrab";
2410   case NotifyWhileGrabbed: return "WhileGrabbed";
2411   default:                 return "???";
2412   }
2413 }
2414
2415 static const char *
2416 XEvent_detail_to_string (int detail)
2417 {
2418   switch (detail)
2419   {
2420   case NotifyAncestor:          return "Ancestor";
2421   case NotifyInferior:          return "Inferior";
2422   case NotifyNonlinear:         return "Nonlinear";
2423   case NotifyNonlinearVirtual:  return "NonlinearVirtual";
2424   case NotifyPointer:           return "Pointer";
2425   case NotifyPointerRoot:       return "PointerRoot";
2426   case NotifyDetailNone:        return "DetailNone";
2427   default:                      return "???";
2428   }
2429 }
2430
2431 static const char *
2432 XEvent_visibility_to_string (int state)
2433 {
2434   switch (state)
2435   {
2436   case VisibilityFullyObscured:     return "FullyObscured";
2437   case VisibilityPartiallyObscured: return "PartiallyObscured";
2438   case VisibilityUnobscured:        return "Unobscured";
2439   default:                          return "???";
2440   }
2441 }
2442
2443 static void
2444 describe_event (XEvent *event)
2445 {
2446   char buf[100];
2447   struct device *d = get_device_from_display (event->xany.display);
2448
2449   sprintf (buf, "%s%s", x_event_name (event->type),
2450            event->xany.send_event ? " (send)" : "");
2451   stderr_out ("%-30s", buf);
2452   switch (event->type)
2453     {
2454     case FocusIn:
2455     case FocusOut:
2456       {
2457         XFocusChangeEvent *ev = &event->xfocus;
2458         describe_event_window (ev->window, ev->display);
2459         stderr_out ("     mode: %s\n",   XEvent_mode_to_string  (ev->mode));
2460         stderr_out ("     detail: %s\n", XEvent_detail_to_string(ev->detail));
2461         break;
2462       }
2463
2464     case KeyPress:
2465       {
2466         XKeyEvent *ev = &event->xkey;
2467         unsigned int state = ev->state;
2468
2469         describe_event_window (ev->window, ev->display);
2470         stderr_out ("   subwindow: %ld\n", ev->subwindow);
2471         stderr_out ("   state: ");
2472         /* Complete list of modifier key masks */
2473         if (state & ShiftMask)   stderr_out ("Shift ");
2474         if (state & LockMask)    stderr_out ("Lock ");
2475         if (state & ControlMask) stderr_out ("Control ");
2476         if (state & Mod1Mask)    stderr_out ("Mod1 ");
2477         if (state & Mod2Mask)    stderr_out ("Mod2 ");
2478         if (state & Mod3Mask)    stderr_out ("Mod3 ");
2479         if (state & Mod4Mask)    stderr_out ("Mod4 ");
2480         if (state & Mod5Mask)    stderr_out ("Mod5 ");
2481
2482         if (! state)
2483           stderr_out ("vanilla\n");
2484         else
2485           stderr_out ("\n");
2486         if (x_key_is_modifier_p (ev->keycode, d))
2487           stderr_out ("   Modifier key");
2488         stderr_out ("   keycode: 0x%x\n", ev->keycode);
2489       }
2490     break;
2491
2492     case Expose:
2493       if (debug_x_events > 1)
2494         {
2495           XExposeEvent *ev = &event->xexpose;
2496           describe_event_window (ev->window, ev->display);
2497           stderr_out ("   region: x=%d y=%d width=%d height=%d\n",
2498                       ev->x, ev->y, ev->width, ev->height);
2499           stderr_out ("    count: %d\n", ev->count);
2500         }
2501       else
2502         stderr_out ("\n");
2503       break;
2504
2505     case GraphicsExpose:
2506       if (debug_x_events > 1)
2507         {
2508           XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
2509           describe_event_window (ev->drawable, ev->display);
2510           stderr_out ("    major: %s\n",
2511                       (ev ->major_code == X_CopyArea  ? "CopyArea" :
2512                        (ev->major_code == X_CopyPlane ? "CopyPlane" : "?")));
2513           stderr_out ("   region: x=%d y=%d width=%d height=%d\n",
2514                       ev->x, ev->y, ev->width, ev->height);
2515           stderr_out ("    count: %d\n", ev->count);
2516         }
2517       else
2518         stderr_out ("\n");
2519       break;
2520
2521     case EnterNotify:
2522     case LeaveNotify:
2523       if (debug_x_events > 1)
2524         {
2525           XCrossingEvent *ev = &event->xcrossing;
2526           describe_event_window (ev->window, ev->display);
2527 #if 0
2528           stderr_out(" subwindow: 0x%x\n", ev->subwindow);
2529           stderr_out("      pos: %d %d\n", ev->x, ev->y);
2530           stderr_out(" root pos: %d %d\n", ev->x_root, ev->y_root);
2531 #endif
2532           stderr_out("    mode: %s\n",   XEvent_mode_to_string(ev->mode));
2533           stderr_out("    detail: %s\n", XEvent_detail_to_string(ev->detail));
2534           stderr_out("    focus: %d\n", ev->focus);
2535 #if 0
2536           stderr_out("    state: 0x%x\n", ev->state);
2537 #endif
2538         }
2539       else
2540         stderr_out("\n");
2541       break;
2542
2543     case ConfigureNotify:
2544       if (debug_x_events > 1)
2545         {
2546           XConfigureEvent *ev = &event->xconfigure;
2547           describe_event_window (ev->window, ev->display);
2548           stderr_out("    above: 0x%lx\n", ev->above);
2549           stderr_out("     size: %d %d %d %d\n", ev->x, ev->y,
2550                      ev->width, ev->height);
2551           stderr_out("  redirect: %d\n", ev->override_redirect);
2552         }
2553       else
2554         stderr_out("\n");
2555       break;
2556
2557     case VisibilityNotify:
2558       if (debug_x_events > 1)
2559         {
2560           XVisibilityEvent *ev = &event->xvisibility;
2561           describe_event_window (ev->window, ev->display);
2562           stderr_out("    state: %s\n", XEvent_visibility_to_string(ev->state));
2563         }
2564       else
2565         stderr_out ("\n");
2566       break;
2567
2568     case ClientMessage:
2569       {
2570         XClientMessageEvent *ev = &event->xclient;
2571         char *name = XGetAtomName (ev->display, ev->message_type);
2572         stderr_out ("%s", name);
2573         if (!strcmp (name, "WM_PROTOCOLS")) {
2574           char *protname = XGetAtomName (ev->display, ev->data.l[0]);
2575           stderr_out ("(%s)", protname);
2576           XFree (protname);
2577         }
2578         XFree (name);
2579         stderr_out ("\n");
2580         break;
2581       }
2582
2583     default:
2584       stderr_out ("\n");
2585       break;
2586     }
2587
2588   fflush (stdout);
2589 }
2590
2591 #endif /* include describe_event definition */
2592
2593 \f
2594 /************************************************************************/
2595 /*                      get the next event from Xt                      */
2596 /************************************************************************/
2597
2598 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
2599
2600 void
2601 enqueue_Xt_dispatch_event (Lisp_Object event)
2602 {
2603   enqueue_event (event, &dispatch_event_queue, &dispatch_event_queue_tail);
2604 }
2605
2606 static Lisp_Object
2607 dequeue_Xt_dispatch_event (void)
2608 {
2609   return dequeue_event (&dispatch_event_queue, &dispatch_event_queue_tail);
2610 }
2611
2612 /* This business exists because menu events "happen" when
2613    menubar_selection_callback() is called from somewhere deep
2614    within XtAppProcessEvent in emacs_Xt_next_event().  The
2615    callback needs to terminate the modal loop in that function
2616    or else it will continue waiting until another event is
2617    received.
2618
2619    Same business applies to scrollbar events. */
2620
2621 void
2622 signal_special_Xt_user_event (Lisp_Object channel, Lisp_Object function,
2623                               Lisp_Object object)
2624 {
2625   Lisp_Object event = Fmake_event (Qnil, Qnil);
2626
2627   XEVENT (event)->event_type = misc_user_event;
2628   XEVENT (event)->channel = channel;
2629   XEVENT (event)->event.eval.function = function;
2630   XEVENT (event)->event.eval.object = object;
2631
2632   enqueue_Xt_dispatch_event (event);
2633 }
2634
2635 static void
2636 emacs_Xt_next_event (Lisp_Event *emacs_event)
2637 {
2638  we_didnt_get_an_event:
2639
2640   while (NILP (dispatch_event_queue) &&
2641          !completed_timeouts         &&
2642          !fake_event_occurred        &&
2643          !process_events_occurred    &&
2644          !tty_events_occurred)
2645     {
2646
2647       /* Stupid logic in XtAppProcessEvent() dictates that, if process
2648          events and X events are both available, the process event gets
2649          taken first.  This will cause an infinite loop if we're being
2650          called from Fdiscard_input().
2651        */
2652       if (XtAppPending (Xt_app_con) & XtIMXEvent)
2653         XtAppProcessEvent (Xt_app_con, XtIMXEvent);
2654       else
2655         {
2656           Lisp_Object devcons, concons;
2657
2658           /* We're about to block.  Xt has a bug in it (big surprise,
2659              there) in that it blocks using select() and doesn't
2660              flush the Xlib output buffers (XNextEvent() does this
2661              automatically before blocking).  So it's necessary
2662              for us to do this ourselves.  If we don't do it, then
2663              display output may not be seen until the next time
2664              an X event is received. (This happens esp. with
2665              subprocess output that gets sent to a visible buffer.)
2666
2667              #### The above comment may not have any validity. */
2668
2669           DEVICE_LOOP_NO_BREAK (devcons, concons)
2670             {
2671               struct device *d;
2672               d = XDEVICE (XCAR (devcons));
2673
2674               if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d))
2675                 /* emacs may be exiting */
2676                 XFlush (DEVICE_X_DISPLAY (d));
2677             }
2678           XtAppProcessEvent (Xt_app_con, XtIMAll);
2679         }
2680     }
2681
2682   if (!NILP (dispatch_event_queue))
2683     {
2684       Lisp_Object event, event2;
2685       XSETEVENT (event2, emacs_event);
2686       event = dequeue_Xt_dispatch_event ();
2687       Fcopy_event (event, event2);
2688       Fdeallocate_event (event);
2689     }
2690   else if (tty_events_occurred)
2691     {
2692       if (!Xt_tty_to_emacs_event (emacs_event))
2693         goto we_didnt_get_an_event;
2694     }
2695   else if (completed_timeouts)
2696     Xt_timeout_to_emacs_event (emacs_event);
2697   else if (fake_event_occurred)
2698     {
2699       /* A dummy event, so that a cycle of the command loop will occur. */
2700       fake_event_occurred = 0;
2701       /* eval events have nil as channel */
2702       emacs_event->event_type = eval_event;
2703       emacs_event->event.eval.function = Qidentity;
2704       emacs_event->event.eval.object = Qnil;
2705     }
2706   else /* if (process_events_occurred) */
2707     Xt_process_to_emacs_event (emacs_event);
2708
2709   /* No need to call XFilterEvent; Xt does it for us */
2710 }
2711
2712 void
2713 emacs_Xt_event_handler (Widget wid /* unused */,
2714                         XtPointer closure /* unused */,
2715                         XEvent *event,
2716                         Boolean *continue_to_dispatch /* unused */)
2717 {
2718   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
2719
2720 #ifdef DEBUG_XEMACS
2721   if (debug_x_events > 0)
2722     {
2723       describe_event (event);
2724     }
2725 #endif /* DEBUG_XEMACS */
2726   if (x_event_to_emacs_event (event, XEVENT (emacs_event)))
2727     enqueue_Xt_dispatch_event (emacs_event);
2728   else
2729     Fdeallocate_event (emacs_event);
2730 }
2731
2732 \f
2733 /************************************************************************/
2734 /*                      input pending / C-g checking                    */
2735 /************************************************************************/
2736
2737 static Bool
2738 quit_char_predicate (Display *display, XEvent *event, XPointer data)
2739 {
2740   struct device *d = get_device_from_display (display);
2741   struct x_device *xd = DEVICE_X_DATA (d);
2742   char c, quit_char;
2743   Bool *critical = (Bool *) data;
2744   Lisp_Object keysym;
2745
2746   if (critical)
2747     *critical = False;
2748   if ((event->type != KeyPress) ||
2749       (! x_any_window_to_frame (d, event->xany.window)) ||
2750       (event->xkey.state
2751        & (xd->MetaMask | xd->HyperMask | xd->SuperMask | xd->AltMask)))
2752     return 0;
2753
2754   /* This duplicates some code that exists elsewhere, but it's relatively
2755      fast and doesn't cons. */
2756   keysym = x_to_emacs_keysym (&event->xkey, 1);
2757   if (NILP (keysym)) return 0;
2758   if (CHAR_OR_CHAR_INTP (keysym))
2759     c = XCHAR_OR_CHAR_INT (keysym);
2760   /* Highly doubtful that these are the quit character, but... */
2761   else if (EQ (keysym, QKbackspace))    c = '\b';
2762   else if (EQ (keysym, QKtab))          c = '\t';
2763   else if (EQ (keysym, QKlinefeed))     c = '\n';
2764   else if (EQ (keysym, QKreturn))       c = '\r';
2765   else if (EQ (keysym, QKescape))       c = 27;
2766   else if (EQ (keysym, QKspace))        c = ' ';
2767   else if (EQ (keysym, QKdelete))       c = 127;
2768   else return 0;
2769
2770   if (event->xkey.state & xd->MetaMask)     c |= 0x80;
2771   if ((event->xkey.state & ControlMask) && !(c >= 'A' && c <= 'Z'))
2772     c &= 0x1F;                  /* unshifted control characters */
2773   quit_char = CONSOLE_QUIT_CHAR (XCONSOLE (DEVICE_CONSOLE (d)));
2774   if (c == quit_char)
2775     return True;
2776   /* If we've got Control-Shift-G instead of Control-G, that means
2777      we have a critical_quit.  Caps_Lock is its own modifier, so it
2778      won't cause ^G to act differently than before. */
2779   if (event->xkey.state & ControlMask)  c &= 0x1F;
2780   if (c == quit_char)
2781     {
2782       if (critical) *critical = True;
2783       return True;
2784     }
2785   return False;
2786 }
2787
2788 /* This scans the X input queue for a KeyPress event that matches the
2789    quit character, and sets Vquit_flag.  This is called from the
2790    QUIT macro to determine whether we should quit.
2791
2792    In a SIGIO world, this won't be called unless a SIGIO has happened
2793    since the last time we checked.
2794
2795    In a non-SIGIO world, this is called from emacs_Xt_event_pending_p
2796    (which is called from input_pending_p).
2797  */
2798 static void
2799 x_check_for_quit_char (Display *display)
2800 {
2801   XEvent event;
2802   int queued;
2803   Bool critical_quit = False;
2804   XEventsQueued (display, QueuedAfterReading);
2805   queued = XCheckIfEvent (display, &event,
2806                           quit_char_predicate,
2807                           (char *) &critical_quit);
2808   if (queued)
2809     {
2810       Vquit_flag = (critical_quit ? Qcritical : Qt);
2811       /* don't put the event back onto the queue.  Those functions that
2812          wanted to read a ^G directly have arranged to do this. */
2813     }
2814 }
2815
2816 static void
2817 check_for_tty_quit_char (struct device *d)
2818 {
2819   SELECT_TYPE temp_mask;
2820   int infd = DEVICE_INFD (d);
2821   struct console *con = XCONSOLE (DEVICE_CONSOLE (d));
2822   Emchar quit_char = CONSOLE_QUIT_CHAR (con);
2823
2824   FD_ZERO (&temp_mask);
2825   FD_SET (infd, &temp_mask);
2826
2827   while (1)
2828     {
2829       Lisp_Object event;
2830       Emchar the_char;
2831
2832       if (!poll_fds_for_input (temp_mask))
2833         return;
2834
2835       event = Fmake_event (Qnil, Qnil);
2836       if (!read_event_from_tty_or_stream_desc (XEVENT (event), con, infd))
2837         /* EOF, or something ... */
2838         return;
2839       /* #### bogus.  quit-char should be allowed to be any sort
2840          of event. */
2841       the_char = event_to_character (XEVENT (event), 1, 0, 0);
2842       if (the_char >= 0 && the_char == quit_char)
2843         {
2844           Vquit_flag = Qt;
2845           /* do not queue the C-g.  See above. */
2846           return;
2847         }
2848
2849       /* queue the read event to be read for real later. */
2850       enqueue_Xt_dispatch_event (event);
2851     }
2852 }
2853
2854 static void
2855 emacs_Xt_quit_p (void)
2856 {
2857   Lisp_Object devcons, concons;
2858   CONSOLE_LOOP (concons)
2859     {
2860       struct console *con = XCONSOLE (XCAR (concons));
2861       if (!con->input_enabled)
2862         continue;
2863
2864       CONSOLE_DEVICE_LOOP (devcons, con)
2865         {
2866           struct device *d;
2867           d = XDEVICE (XCAR (devcons));
2868
2869           if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d))
2870             /* emacs may be exiting */
2871             x_check_for_quit_char (DEVICE_X_DISPLAY (d));
2872           else if (DEVICE_TTY_P (d))
2873             check_for_tty_quit_char (d);
2874         }
2875     }
2876 }
2877
2878 static void
2879 drain_X_queue (void)
2880 {
2881   while (XtAppPending (Xt_app_con) & XtIMXEvent)
2882     XtAppProcessEvent (Xt_app_con, XtIMXEvent);
2883 }
2884
2885 static int
2886 emacs_Xt_event_pending_p (int user_p)
2887 {
2888   Lisp_Object event;
2889   int tick_count_val;
2890
2891   /* If `user_p' is false, then this function returns whether there are any
2892      X, timeout, or fd events pending (that is, whether emacs_Xt_next_event()
2893      would return immediately without blocking).
2894
2895      if `user_p' is true, then this function returns whether there are any
2896      *user generated* events available (that is, whether there are keyboard
2897      or mouse-click events ready to be read).  This also implies that
2898      emacs_Xt_next_event() would not block.
2899
2900      In a non-SIGIO world, this also checks whether the user has typed ^G,
2901      since this is a convenient place to do so.  We don't need to do this
2902      in a SIGIO world, since input causes an interrupt.
2903    */
2904
2905 #if 0
2906   /* I don't think there's any point to this and it will nullify
2907      the speed gains achieved by the sigio_happened checking below.
2908      Its only advantage is that it may possibly make C-g response
2909      a bit faster.  The C-g will be noticed within 0.25 second, anyway,
2910      even without this. */
2911 #ifndef SIGIO
2912   /* First check for C-g if necessary */
2913   emacs_Xt_quit_p ();
2914 #endif
2915 #endif
2916
2917   /* This function used to simply check whether there were any X
2918      events (or if user_p was 1, it iterated over all the pending
2919      X events using XCheckIfEvent(), looking for keystrokes and
2920      button events).  That worked in the old cheesoid event loop,
2921      which didn't go through XtAppDispatchEvent(), but it doesn't
2922      work any more -- X events may not result in anything.  For
2923      example, a button press in a blank part of the menubar appears
2924      as an X event but will not result in any Emacs events (a
2925      button press that activates the menubar results in an Emacs
2926      event through the stop_next_event mechanism).
2927
2928      The only accurate way of determining whether these X events
2929      translate into Emacs events is to go ahead and dispatch them
2930      until there's something on the dispatch queue. */
2931
2932   /* See if there are any user events already on the queue. */
2933   EVENT_CHAIN_LOOP (event, dispatch_event_queue)
2934     if (!user_p || command_event_p (event))
2935       return 1;
2936
2937   /* See if there's any TTY input available.
2938    */
2939   if (poll_fds_for_input (tty_only_mask))
2940     return 1;
2941
2942   if (!user_p)
2943     {
2944       /* If not user_p and there are any timer or file-desc events
2945          pending, we know there will be an event so we're through. */
2946       XtInputMask pending_value;
2947
2948       /* Note that formerly we just checked the value of XtAppPending()
2949          to determine if there was file-desc input.  This doesn't
2950          work any more with the signal_event_pipe; XtAppPending()
2951          will says "yes" in this case but there isn't really any
2952          input.  Another way of fixing this problem is for the
2953          signal_event_pipe to generate actual input in the form
2954          of an identity eval event or something. (#### maybe this
2955          actually happens?) */
2956
2957       if (poll_fds_for_input (process_only_mask))
2958         return 1;
2959
2960       pending_value = XtAppPending (Xt_app_con);
2961
2962       if (pending_value & XtIMTimer)
2963         return 1;
2964     }
2965
2966   /* XtAppPending() can be super-slow, esp. over a network connection.
2967      Quantify results have indicated that in some cases the
2968      call to detect_input_pending() completely dominates the
2969      running time of redisplay().  Fortunately, in a SIGIO world
2970      we can more quickly determine whether there are any X events:
2971      if an event has happened since the last time we checked, then
2972      a SIGIO will have happened.  On a machine with broken SIGIO,
2973      we'll still be in an OK state -- the sigio_happened flag
2974      will get set at least once a second, so we'll be no more than
2975      one second behind reality. (In general it's OK if we
2976      erroneously report no input pending when input is actually
2977      pending() -- preemption is just a bit less efficient, that's
2978      all.  It's bad bad bad if you err the other way -- you've
2979      promised that `next-event' won't block but it actually will,
2980      and some action might get delayed until the next time you
2981      hit a key.)
2982      */
2983
2984   /* quit_check_signal_tick_count is volatile so try to avoid race conditions
2985      by using a temporary variable */
2986   tick_count_val = quit_check_signal_tick_count;
2987   if (last_quit_check_signal_tick_count != tick_count_val
2988 #if !defined (SIGIO) || defined (CYGWIN)
2989       || (XtIMXEvent & XtAppPending (Xt_app_con))
2990 #endif 
2991       )
2992     {
2993       last_quit_check_signal_tick_count = tick_count_val;
2994
2995       /* We need to drain the entire queue now -- if we only
2996          drain part of it, we may later on end up with events
2997          actually pending but detect_input_pending() returning
2998          false because there wasn't another SIGIO. */
2999       drain_X_queue ();
3000
3001       EVENT_CHAIN_LOOP (event, dispatch_event_queue)
3002         if (!user_p || command_event_p (event))
3003           return 1;
3004     }
3005
3006   return 0;
3007 }
3008
3009 static int
3010 emacs_Xt_current_event_timestamp (struct console *c)
3011 {
3012   /* semi-yuck. */
3013   Lisp_Object devs = CONSOLE_DEVICE_LIST (c);
3014
3015   if (NILP (devs))
3016     return 0;
3017   else
3018     {
3019       struct device *d = XDEVICE (XCAR (devs));
3020       return DEVICE_X_LAST_SERVER_TIMESTAMP (d);
3021     }
3022 }
3023
3024 \f
3025 /************************************************************************/
3026 /*            replacement for standard string-to-pixel converter        */
3027 /************************************************************************/
3028
3029 /* This was constructed by ripping off the standard string-to-pixel
3030    converter from Converters.c in the Xt source code and modifying
3031    appropriately. */
3032
3033 #if 0
3034
3035 /* This is exported by the Xt library (at least by mine).  If this
3036    isn't the case somewhere, rename this appropriately and remove
3037    the '#if 0'.  Note, however, that I got "unknown structure"
3038    errors when I tried this. */
3039 XtConvertArgRec Const colorConvertArgs[] = {
3040   { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
3041     sizeof (Screen *) },
3042   { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
3043     sizeof (Colormap) }
3044 };
3045
3046 #endif
3047
3048 #define done(type, value)               \
3049   if (toVal->addr != NULL) {             \
3050     if (toVal->size < sizeof(type)) {    \
3051       toVal->size = sizeof(type);        \
3052       return False;                      \
3053     }                                    \
3054     *(type*)(toVal->addr) = (value);     \
3055   } else {                               \
3056     static type static_val;              \
3057     static_val = (value);                \
3058     toVal->addr = (XPointer)&static_val; \
3059   }                                      \
3060   toVal->size = sizeof(type);            \
3061   return True /* Caller supplies `;' */
3062
3063 /* JH: We use this because I think there's a possibility this
3064    is called before the device is properly set up, in which case
3065    I don't want to abort. */
3066 extern struct device *get_device_from_display_1 (Display *dpy);
3067
3068 static
3069 Boolean EmacsXtCvtStringToPixel (
3070  Display     *dpy,
3071  XrmValuePtr  args,
3072  Cardinal    *num_args,
3073  XrmValuePtr  fromVal,
3074  XrmValuePtr  toVal,
3075  XtPointer   *closure_ret)
3076 {
3077   String       str = (String)fromVal->addr;
3078   XColor       screenColor;
3079   XColor       exactColor;
3080   Screen       *screen;
3081   Colormap     colormap;
3082   Visual       *visual;
3083   struct device *d;
3084   Status       status;
3085   String       params[1];
3086   Cardinal     num_params  = 1;
3087   XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
3088
3089   if (*num_args != 2) {
3090     XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToPixel",
3091                     "XtToolkitError",
3092                     "String to pixel conversion needs screen and colormap arguments",
3093                     (String *)NULL, (Cardinal *)NULL);
3094     return False;
3095   }
3096
3097   screen   = *((Screen **)  args[0].addr);
3098   colormap = *((Colormap *) args[1].addr);
3099
3100   /* The original uses the private function CompareISOLatin1().
3101      Use XmuCompareISOLatin1() if you want, but I don't think it
3102      makes any difference here. */
3103   if (strcmp(str, XtDefaultBackground) == 0) {
3104     *closure_ret = False;
3105     /* This refers to the display's "*reverseVideo" resource.
3106        These display resources aren't documented anywhere that
3107        I can find, so I'm going to ignore this. */
3108     /* if (pd->rv) done(Pixel, BlackPixelOfScreen(screen)) else */
3109     done(Pixel, WhitePixelOfScreen(screen));
3110   }
3111   if (strcmp(str, XtDefaultForeground) == 0) {
3112     *closure_ret = False;
3113     /* if (pd->rv) done(Pixel, WhitePixelOfScreen(screen)) else */
3114     done(Pixel, BlackPixelOfScreen(screen));
3115   }
3116
3117   /* Originally called XAllocNamedColor() here. */
3118   if ((d = get_device_from_display_1(dpy))) {
3119     visual = DEVICE_X_VISUAL(d);
3120     if (colormap != DEVICE_X_COLORMAP(d)) {
3121       XtAppWarningMsg(the_app_con, "weirdColormap", "cvtStringToPixel",
3122                       "XtToolkitWarning",
3123                       "The colormap passed to cvtStringToPixel doesn't match the one registered to the device.\n",
3124                       NULL, 0);
3125       status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor);
3126     } else {
3127       status = XParseColor (dpy, colormap, (char*)str, &screenColor);
3128       if (status) {
3129         status = allocate_nearest_color (dpy, colormap, visual, &screenColor);
3130       }
3131     }
3132   } else {
3133     /* We haven't set up this device totally yet, so just punt */
3134     status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor);
3135   }
3136   if (status == 0) {
3137     params[0] = str;
3138     /* Server returns a specific error code but Xlib discards it.  Ugh */
3139     if (XLookupColor(DisplayOfScreen(screen), colormap, (char*) str,
3140                      &exactColor, &screenColor)) {
3141       XtAppWarningMsg(the_app_con, "noColormap", "cvtStringToPixel",
3142                       "XtToolkitError",
3143                       "Cannot allocate colormap entry for \"%s\"",
3144                       params, &num_params);
3145
3146     } else {
3147       XtAppWarningMsg(the_app_con, "badValue", "cvtStringToPixel",
3148                       "XtToolkitError",
3149                       "Color name \"%s\" is not defined", params, &num_params);
3150     }
3151
3152     *closure_ret = False;
3153     return False;
3154   } else {
3155     *closure_ret = (char*)True;
3156     done(Pixel, screenColor.pixel);
3157   }
3158 }
3159
3160 /* ARGSUSED */
3161 static void EmacsFreePixel (
3162   XtAppContext app,
3163   XrmValuePtr  toVal,
3164   XtPointer    closure,
3165   XrmValuePtr  args,
3166   Cardinal    *num_args)
3167 {
3168   if (*num_args != 2) {
3169     XtAppWarningMsg(app, "wrongParameters","freePixel","XtToolkitError",
3170                     "Freeing a pixel requires screen and colormap arguments",
3171                     (String *)NULL, (Cardinal *)NULL);
3172     return;
3173   }
3174
3175   if (closure) {
3176     Screen   *screen  = *((Screen **)  args[0].addr);
3177     Colormap colormap = *((Colormap *) args[1].addr);
3178     XFreeColors(DisplayOfScreen(screen), colormap,
3179                 (unsigned long*)toVal->addr, 1, (unsigned long)0);
3180   }
3181 }
3182
3183 \f
3184 /************************************************************************/
3185 /*            handle focus changes for native widgets                  */
3186 /************************************************************************/
3187 static void
3188 emacs_Xt_event_widget_focus_in (Widget   w,
3189                                 XEvent   *event,
3190                                 String   *params,
3191                                 Cardinal *num_params)
3192 {
3193   struct frame* f =
3194     x_any_widget_or_parent_to_frame (get_device_from_display (event->xany.display), w);
3195
3196   XtSetKeyboardFocus (FRAME_X_SHELL_WIDGET (f), w);
3197 }
3198
3199 static void
3200 emacs_Xt_event_widget_focus_out (Widget   w,
3201                                  XEvent   *event,
3202                                  String   *params,
3203                                  Cardinal *num_params)
3204 {
3205 }
3206
3207 static XtActionsRec widgetActionsList[] =
3208 {
3209   {"widget-focus-in",   emacs_Xt_event_widget_focus_in  },
3210   {"widget-focus-out",  emacs_Xt_event_widget_focus_out },
3211 };
3212
3213 static void
3214 emacs_Xt_event_add_widget_actions (XtAppContext ctx)
3215 {
3216   XtAppAddActions (ctx, widgetActionsList, 2);
3217 }
3218
3219 \f
3220 /************************************************************************/
3221 /*                            initialization                            */
3222 /************************************************************************/
3223
3224 void
3225 syms_of_event_Xt (void)
3226 {
3227   defsymbol (&Qkey_mapping, "key-mapping");
3228   defsymbol (&Qsans_modifiers, "sans-modifiers");
3229   defsymbol (&Qself_insert_command, "self-insert-command");
3230 }
3231
3232 void
3233 reinit_vars_of_event_Xt (void)
3234 {
3235   Xt_event_stream = xnew (struct event_stream);
3236   Xt_event_stream->event_pending_p       = emacs_Xt_event_pending_p;
3237   Xt_event_stream->force_event_pending   = emacs_Xt_force_event_pending;
3238   Xt_event_stream->next_event_cb         = emacs_Xt_next_event;
3239   Xt_event_stream->handle_magic_event_cb = emacs_Xt_handle_magic_event;
3240   Xt_event_stream->add_timeout_cb        = emacs_Xt_add_timeout;
3241   Xt_event_stream->remove_timeout_cb     = emacs_Xt_remove_timeout;
3242   Xt_event_stream->select_console_cb     = emacs_Xt_select_console;
3243   Xt_event_stream->unselect_console_cb   = emacs_Xt_unselect_console;
3244   Xt_event_stream->select_process_cb     = emacs_Xt_select_process;
3245   Xt_event_stream->unselect_process_cb   = emacs_Xt_unselect_process;
3246   Xt_event_stream->quit_p_cb             = emacs_Xt_quit_p;
3247   Xt_event_stream->create_stream_pair_cb = emacs_Xt_create_stream_pair;
3248   Xt_event_stream->delete_stream_pair_cb = emacs_Xt_delete_stream_pair;
3249   Xt_event_stream->current_event_timestamp_cb =
3250     emacs_Xt_current_event_timestamp;
3251
3252   the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
3253
3254   last_quit_check_signal_tick_count = 0;
3255
3256   /* this function only makes safe calls */
3257   init_what_input_once ();
3258 }
3259
3260 void
3261 vars_of_event_Xt (void)
3262 {
3263   reinit_vars_of_event_Xt ();
3264
3265   dispatch_event_queue = Qnil;
3266   staticpro (&dispatch_event_queue);
3267   dispatch_event_queue_tail = Qnil;
3268   pdump_wire (&dispatch_event_queue_tail);
3269
3270   DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /*
3271 *Non-nil means to allow synthetic events.  Nil means they are ignored.
3272 Beware: allowing emacs to process SendEvents opens a big security hole.
3273 */ );
3274   x_allow_sendevents = 0;
3275
3276 #ifdef DEBUG_XEMACS
3277   DEFVAR_INT ("debug-x-events", &debug_x_events /*
3278 If non-zero, display debug information about X events that XEmacs sees.
3279 Information is displayed on stderr.  Currently defined values are:
3280
3281 1 == non-verbose output
3282 2 == verbose output
3283 */ );
3284   debug_x_events = 0;
3285 #endif
3286 }
3287
3288 /* This mess is a hack that patches the shell widget to treat visual inheritance
3289    the same as colormap and depth inheritance */
3290
3291 static XtInitProc orig_shell_init_proc;
3292
3293 static void ShellVisualPatch(Widget wanted, Widget new,
3294                              ArgList args, Cardinal *num_args)
3295 {
3296   Widget p;
3297   ShellWidget w = (ShellWidget) new;
3298
3299   /* first, call the original setup */
3300   (*orig_shell_init_proc)(wanted, new, args, num_args);
3301
3302   /* if the visual isn't explicitly set, grab it from the nearest shell ancestor */
3303   if (w->shell.visual == CopyFromParent) {
3304     p = XtParent(w);
3305     while (p && !XtIsShell(p)) p = XtParent(p);
3306     if (p) w->shell.visual = ((ShellWidget)p)->shell.visual;
3307   }
3308 }
3309
3310 void
3311 init_event_Xt_late (void) /* called when already initialized */
3312 {
3313   timeout_id_tick = 1;
3314   pending_timeouts = 0;
3315   completed_timeouts = 0;
3316
3317   event_stream = Xt_event_stream;
3318
3319 #if defined(HAVE_XIM) || defined(USE_XFONTSET)
3320   Initialize_Locale();
3321 #endif /* HAVE_XIM || USE_XFONTSET */
3322
3323   XtToolkitInitialize ();
3324   Xt_app_con = XtCreateApplicationContext ();
3325   XtAppSetFallbackResources (Xt_app_con, (String *) x_fallback_resources);
3326
3327   /* In select-x.c */
3328   x_selection_timeout = (XtAppGetSelectionTimeout (Xt_app_con) / 1000);
3329   XSetErrorHandler (x_error_handler);
3330   XSetIOErrorHandler (x_IO_error_handler);
3331
3332 #ifndef WIN32_NATIVE
3333   XtAppAddInput (Xt_app_con, signal_event_pipe[0],
3334                  (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
3335                  Xt_what_callback, 0);
3336 #endif
3337
3338   XtAppSetTypeConverter (Xt_app_con, XtRString, XtRPixel,
3339                          EmacsXtCvtStringToPixel,
3340                          (XtConvertArgList) colorConvertArgs,
3341                          2, XtCacheByDisplay, EmacsFreePixel);
3342
3343 #ifdef XIM_XLIB
3344   XtAppSetTypeConverter (Xt_app_con, XtRString, XtRXimStyles,
3345                          EmacsXtCvtStringToXIMStyles,
3346                          NULL, 0,
3347                          XtCacheByDisplay, EmacsFreeXIMStyles);
3348 #endif /* XIM_XLIB */
3349   /* Add extra actions to native widgets to handle focus and friends. */
3350   emacs_Xt_event_add_widget_actions (Xt_app_con);
3351
3352   /* insert the visual inheritance patch/hack described above */
3353   orig_shell_init_proc = shellClassRec.core_class.initialize;
3354   shellClassRec.core_class.initialize = ShellVisualPatch;
3355
3356 }