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