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