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