home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / src / event-Xt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-24  |  54.6 KB  |  1,736 lines

  1. /* The event_stream interface for X11 with Xt, and/or tty screens.
  2.    Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <stdio.h>
  21. #include <X11/X.h>
  22. #include <X11/Xlib.h>
  23. #include <X11/Xatom.h>
  24. #include <X11/keysym.h>
  25. #include <X11/IntrinsicP.h>    /* only describe_event() needs this */
  26. #include <X11/Xproto.h>        /* only describe_event() needs this */
  27. #include "ScreenWidgetP.h"
  28.  
  29. #include "config.h"
  30. #include "lisp.h"
  31. #include "process.h"
  32. #include "events.h"
  33.  
  34. #include "blockio.h"
  35. #include "dispextern.h"
  36. #include "screen.h"
  37. #include "xterm.h"        /* only describe_event() needs this */
  38. #include "lwlib.h"
  39.  
  40. static void describe_event ();
  41. void emacs_Xt_focus_event_handler ();
  42.  
  43. /* The timestamp of the last button or key event used by emacs itself.
  44.    This is used for asserting selections and input focus. */
  45. Time mouse_timestamp;
  46.  
  47. /* This is the timestamp the last button or key event wether it was
  48.    dispatched to emacs or widgets. */
  49. Time global_mouse_timestamp;
  50.  
  51. /* This is the last known timestamp received from the server.  It is 
  52.    maintained by x_event_to_emacs_event and used to patch bogus 
  53.    WM_TAKE_FOCUS messages sent by Mwm. */
  54. static Time last_server_timestamp;
  55.  
  56. extern struct screen *x_window_to_screen (Window),
  57. *x_any_window_to_screen (Window);
  58.  
  59. extern XtAppContext Xt_app_con;
  60.  
  61. extern Lisp_Object QKbackspace, QKtab, QKlinefeed, QKreturn;
  62. extern Lisp_Object QKescape, QKspace, QKdelete, QKnosymbol;
  63.  
  64. extern Lisp_Object Qeval;
  65. extern Lisp_Object Qx_EnterNotify_internal, Qx_LeaveNotify_internal;
  66. extern Lisp_Object Qx_FocusIn_internal, Qx_FocusOut_internal;
  67. extern Lisp_Object Qx_VisibilityNotify_internal;
  68. extern Lisp_Object Qx_non_VisibilityNotify_internal;
  69. extern Lisp_Object Qx_MapNotify_internal, Qx_UnmapNotify_internal;
  70.  
  71. extern Display *x_current_display;
  72. extern Atom Xatom_WM_PROTOCOLS, Xatom_WM_DELETE_WINDOW, Xatom_WM_TAKE_FOCUS;
  73.  
  74. extern void repaint_lines (struct screen *, int, int, int, int);
  75.  
  76. /* X bogusly doesn't define the interpretations of any bits besides
  77.    ModControl, ModShift, and ModLock; so the Interclient Communication
  78.    Conventions Manual says that we have to bend over backwards to figure
  79.    out what the other modifier bits mean.  According to ICCCM:
  80.  
  81.    - Any keycode which is assigned ModControl is a "control" key.
  82.  
  83.    - Any modifier bit which is assigned to a keycode which generates Meta_L
  84.      or Meta_R is the modifier bit meaning "meta".  Likewise for Super, Hyper,
  85.      etc.
  86.  
  87.    - Any keypress event which contains ModControl in its state should be
  88.      interpreted as a "control" character.
  89.  
  90.    - Any keypress event which contains a modifier bit in its state which is
  91.      generated by a keycode whose corresponding keysym is Meta_L or Meta_R
  92.      should be interpreted as a "meta" character.  Likewise for Super, Hyper,
  93.      etc.
  94.  
  95.    - It is illegal for a keysym to be associated with more than one modifier
  96.      bit.
  97.  
  98.    This means that the only thing that emacs can reasonably interpret as a
  99.    "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
  100.    one of the modifier bits Mod1-Mod5.
  101.  
  102.    Unfortunately, many keyboards don't have Meta keys in their default
  103.    configuration.  So, if there are no Meta keys, but there are "Alt" keys,
  104.    emacs will interpret Alt as Meta.  If there are both Meta and Alt keys,
  105.    then the Meta keys mean "Meta", and the Alt keys mean "Symbol".
  106.  
  107.    This works with the default configurations of the 19 keyboard-types I've
  108.    checked.
  109.  
  110.    Emacs detects keyboard configurations which violate the above rules, and
  111.    prints an error message on the standard-error-output.  (Perhaps it should
  112.    use a pop-up-window instead.)
  113.  */
  114.  
  115. static int MetaMask, HyperMask, SuperMask, SymbolMask, ModeMask;
  116. static KeySym lock_interpretation;
  117.  
  118. static XModifierKeymap *x_modifier_keymap;
  119.  
  120. static KeySym *x_keysym_map;
  121. static int x_keysym_map_min_code;
  122. static int x_keysym_map_keysyms_per_code;
  123.  
  124. static void
  125. x_reset_key_mapping (display)
  126.      Display *display;
  127. {
  128.   int max_code;
  129.   BLOCK_INPUT;
  130.   if (x_keysym_map)
  131.     XFree ((char *) x_keysym_map);
  132.   XDisplayKeycodes (display, &x_keysym_map_min_code, &max_code);
  133.   x_keysym_map = XGetKeyboardMapping (display, x_keysym_map_min_code,
  134.                       max_code - x_keysym_map_min_code + 1,
  135.                       &x_keysym_map_keysyms_per_code);
  136.   UNBLOCK_INPUT;
  137. }
  138.  
  139.  
  140. static void
  141. x_reset_modifier_mapping (display)
  142.      Display *display;
  143. {
  144.   int modifier_index, modifier_key, column, mkpm;
  145.   int warned_about_overlapping_modifiers = 0;
  146.   int warned_about_predefined_modifiers = 0;
  147.   int warned_about_duplicate_modifiers = 0;
  148.   int meta_bit = 0;
  149.   int hyper_bit = 0;
  150.   int super_bit = 0;
  151.   int symbol_bit = 0;
  152.   int mode_bit = 0;
  153.  
  154.   lock_interpretation = 0;
  155.  
  156.   if (x_modifier_keymap)
  157.     XFreeModifiermap (x_modifier_keymap);
  158.  
  159.   x_reset_key_mapping (display);
  160.  
  161.   BLOCK_INPUT;
  162.   x_modifier_keymap = XGetModifierMapping (display);
  163.  
  164.   /* Boy, I really wish C had local functions...
  165.    */
  166. #define index_to_name(index) \
  167. ((index == ShiftMapIndex ? "ModShift" : (index == LockMapIndex ? "ModLock" : \
  168.   (index == ControlMapIndex ? "ModControl" : (index == Mod1MapIndex ? "Mod1" : \
  169.    (index == Mod2MapIndex ? "Mod2" : (index == Mod3MapIndex ? "Mod3" : \
  170.     (index == Mod4MapIndex ? "Mod4" : (index == Mod5MapIndex ? "Mod5" : \
  171.      "???")))))))))
  172.  
  173. #define modwarn(name,old,other) \
  174.   fprintf (stderr, \
  175.        "emacs:  %s (0x%x) generates %s, which is generated by %s.\n", \
  176.          name, code, index_to_name (old), other), \
  177.   warned_about_overlapping_modifiers = 1
  178.  
  179. #define modbarf(name,other) \
  180.   fprintf (stderr, "emacs:  %s (0x%x) generates %s, which is nonsensical.\n", \
  181.        name, code, other), \
  182.   warned_about_predefined_modifiers = 1
  183.  
  184. #define check_modifier(name,mask) \
  185.   if ((1<<modifier_index) != mask) \
  186.      fprintf (stderr, \
  187.           "emacs:  %s (0x%x) generates %s, which is nonsensical.\n", \
  188.           name, code, index_to_name (modifier_index)), \
  189.      warned_about_predefined_modifiers = 1
  190.  
  191. #define store_modifier(name,old) \
  192.   if (old && old != modifier_index) \
  193.     fprintf (stderr, \
  194.    "emacs:  %s (0x%x) generates both %s and %s, which is nonsensical.\n",\
  195.          name, code, index_to_name(old), index_to_name(modifier_index)), \
  196.     warned_about_duplicate_modifiers = 1; \
  197.   if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \
  198.   else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \
  199.   else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
  200.   else if (sym == XK_Mode_switch) \
  201.     mode_bit = modifier_index; /* Mode_switch is special, see below... */ \
  202.   else if (modifier_index == meta_bit && old != meta_bit) \
  203.     modwarn (name, meta_bit, "Meta"); \
  204.   else if (modifier_index == super_bit && old != super_bit) \
  205.     modwarn (name, super_bit, "Super"); \
  206.   else if (modifier_index == hyper_bit && old != hyper_bit) \
  207.     modwarn (name, hyper_bit, "Hyper"); \
  208.   else if (modifier_index == symbol_bit && old != symbol_bit) \
  209.     modwarn (name, symbol_bit, "Alt"); \
  210.   else \
  211.     old = modifier_index;
  212.  
  213.   mkpm = x_modifier_keymap->max_keypermod;
  214.   for (modifier_index = 0; modifier_index < 8; modifier_index++)
  215.     for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
  216.       KeySym last_sym = 0;
  217.       for (column = 0; column < 4; column += 2) {
  218.     KeyCode code = x_modifier_keymap->modifiermap [modifier_index * mkpm
  219.                                + modifier_key];
  220.     KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0);
  221.     if (sym == last_sym) continue;
  222.     last_sym = sym;
  223.     switch (sym) {
  224.     case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break;
  225.     case XK_Meta_L:     store_modifier ("Meta_L", meta_bit); break;
  226.     case XK_Meta_R:     store_modifier ("Meta_R", meta_bit); break;
  227.     case XK_Super_L:    store_modifier ("Super_L", super_bit); break;
  228.     case XK_Super_R:    store_modifier ("Super_R", super_bit); break;
  229.     case XK_Hyper_L:    store_modifier ("Hyper_L", hyper_bit); break;
  230.     case XK_Hyper_R:    store_modifier ("Hyper_R", hyper_bit); break;
  231.     case XK_Alt_L:      store_modifier ("Alt_L", symbol_bit); break;
  232.     case XK_Alt_R:      store_modifier ("Alt_R", symbol_bit); break;
  233.     case XK_Control_L:  check_modifier ("Control_L", ControlMask); break;
  234.     case XK_Control_R:  check_modifier ("Control_R", ControlMask); break;
  235.     case XK_Shift_L:    check_modifier ("Shift_L", ShiftMask); break;
  236.     case XK_Shift_R:    check_modifier ("Shift_R", ShiftMask); break;
  237.     case XK_Shift_Lock: check_modifier ("Shift_Lock", LockMask);
  238.       lock_interpretation = XK_Shift_Lock; break;
  239.     case XK_Caps_Lock:  check_modifier ("Caps_Lock", LockMask);
  240.       lock_interpretation = XK_Caps_Lock; break;
  241.  
  242.     /* It probably doesn't make any sense for a modifier bit to be
  243.        assigned to a key that is not one of the above, but OpenWindows
  244.        assigns modifier bits to a couple of random function keys for
  245.        no reason that I can discern, so printing a warning here would
  246.        be annoying.
  247.      */
  248.     }
  249.       }
  250.     }
  251. #undef store_modifier
  252. #undef check_modifier
  253. #undef modwarn
  254. #undef modbarf
  255.  
  256.   /* If there was no Meta key, then try using the Alt key instead.
  257.      If there is both a Meta key and an Alt key, then the Alt key
  258.      is treated as Symbol.
  259.    */
  260.   if (! meta_bit && symbol_bit)
  261.     meta_bit = symbol_bit, symbol_bit = 0;
  262.  
  263.   /* mode_bit overrides everything, since it's processed down inside of
  264.      XLookupString() instead of by us.  If Meta and Mode_switch both
  265.      generate the same modifier bit (which is an error), then we don't
  266.      interpret that bit as Meta, because we can't make XLookupString()
  267.      not interpret it as Mode_switch; and interpreting it as both would
  268.      be totally wrong.
  269.    */
  270.   if (mode_bit)
  271.     {
  272.       char *warn = 0;
  273.       if (mode_bit == meta_bit) warn = "Meta", meta_bit = 0;
  274.       else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
  275.       else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
  276.       else if (mode_bit == symbol_bit) warn = "Symbol", symbol_bit = 0;
  277.       if (warn)
  278.     {
  279.       fprintf (stderr,
  280.            "emacs:  %s is being used for both Mode_switch and %s.\n",
  281.            index_to_name (mode_bit), warn),
  282.       warned_about_overlapping_modifiers = 1;
  283.     }
  284.     }
  285. #undef index_to_name
  286.  
  287.   MetaMask   = (meta_bit   ? (1 << meta_bit)  : 0);
  288.   HyperMask  = (hyper_bit  ? (1 << hyper_bit) : 0);
  289.   SuperMask  = (super_bit  ? (1 << super_bit) : 0);
  290.   SymbolMask = (symbol_bit ? (1 << symbol_bit): 0);
  291.   ModeMask   = (mode_bit   ? (1 << mode_bit)  : 0); /* unused */
  292.  
  293.   UNBLOCK_INPUT;
  294.  
  295.   if (warned_about_overlapping_modifiers)
  296.     fprintf (stderr, "\n\
  297.     Two distinct modifier keys (such as Meta and Hyper) cannot generate\n\
  298.     the same modifier bit, because Emacs won't be able to tell which\n\
  299.     modifier was actually held down when some other key is pressed.  It\n\
  300.     won't be able to tell Meta-x and Hyper-x apart, for example.  Change\n\
  301.     one of these keys to use some other modifier bit.  If you intend for\n\
  302.     these keys to have the same behavior, then change them to have the\n\
  303.     same keysym as well as the same modifier bit.\n");
  304.  
  305.   if (warned_about_predefined_modifiers)
  306.     fprintf (stderr, "\n\
  307.     The semantics of the modifier bits ModShift, ModLock, and ModControl\n\
  308.     are predefined.  It does not make sense to assign ModControl to any\n\
  309.     keysym other than Control_L or Control_R, or to assign any modifier\n\
  310.     bits to the \"control\" keysyms other than ModControl.  You can't\n\
  311.     turn a \"control\" key into a \"meta\" key (or vice versa) by simply\n\
  312.     assigning the key a different modifier bit.  You must also make that\n\
  313.     key generate an appropriate keysym (Control_L, Meta_L, etc).\n");
  314.  
  315.   /* Don\'t need to say anything more for warned_about_duplicate_modifiers. */
  316.  
  317.   if (warned_about_overlapping_modifiers || warned_about_predefined_modifiers)
  318.     fprintf (stderr, "\n\
  319.     The meanings of the modifier bits Mod1 through Mod5 are determined\n\
  320.     by the keysyms used to control those bits.  Mod1 does NOT always\n\
  321.     mean Meta, although some non-ICCCM-compliant programs assume that.\n");
  322.  
  323.   if (warned_about_overlapping_modifiers ||
  324.       warned_about_predefined_modifiers ||
  325.       warned_about_duplicate_modifiers)
  326.     fprintf (stderr, "\n");
  327. }
  328.  
  329. void
  330. x_init_modifier_mapping (display)
  331.      Display *display;
  332. {
  333.   x_keysym_map = 0;
  334.   x_modifier_keymap = 0;
  335.   x_reset_modifier_mapping (display);
  336. }
  337.  
  338.  
  339. static int
  340. x_key_is_modifier_p (keycode)
  341.      KeyCode keycode;
  342. {
  343.   KeySym *syms = &x_keysym_map [(keycode - x_keysym_map_min_code) *
  344.                 x_keysym_map_keysyms_per_code];
  345.   int i;
  346.   for (i = 0; i < x_keysym_map_keysyms_per_code; i++)
  347.     if (IsModifierKey (syms [i]) ||
  348.     syms [i] == XK_Mode_switch) /* why doesn't IsModifierKey count this? */
  349.       return 1;
  350.   return 0;
  351. }
  352.  
  353.  
  354. static int
  355. keysym_obeys_caps_lock_p (sym)
  356.      KeySym sym;
  357. {
  358.   /* Eeeeevil hack.  Don't apply caps-lock to things that aren't alphabetic
  359.      characters, where "alphabetic" means something more than simply A-Z.
  360.      That is, if caps-lock is down, typing ESC doesn't produce Shift-ESC.
  361.      But if shift-lock is down, then it does.
  362.    */
  363.   if (lock_interpretation == XK_Shift_Lock)
  364.     return 1;
  365.   if (((sym >= XK_A) && (sym <= XK_Z)) ||
  366.       ((sym >= XK_a) && (sym <= XK_z)) ||
  367.       ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) ||
  368.       ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) ||
  369.       ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) ||
  370.       ((sym >= XK_oslash) && (sym <= XK_thorn)))
  371.     return 1;
  372.   else
  373.     return 0;
  374. }
  375.  
  376.  
  377. static XComposeStatus *x_compose_status;
  378.  
  379. static Lisp_Object
  380. x_to_emacs_keysym (event, simple_p)
  381.      XEvent *event;
  382.      int simple_p;    /* means don't try too hard (ASCII only) */
  383. {
  384.   char *name;
  385.   KeySym keysym = 0;
  386.   
  387.   BLOCK_INPUT;
  388.   XLookupString (&event->xkey, 0, 0, &keysym, x_compose_status);
  389.   UNBLOCK_INPUT;
  390.   
  391.   if (keysym >= XK_exclam && keysym <= XK_asciitilde)
  392.     /* We must assume that the X keysym numbers for the ASCII graphic
  393.        characters are the same as their ASCII codes.  */
  394.     return keysym;
  395.  
  396.   switch (keysym) {
  397.     /* These would be handled correctly by the default case, but by
  398.        special-casing them here we don't garbage a string or call intern().
  399.        */
  400.   case XK_BackSpace:    return QKbackspace;
  401.   case XK_Tab:        return QKtab;
  402.   case XK_Linefeed:    return QKlinefeed;
  403.   case XK_Return:    return QKreturn;
  404.   case XK_Escape:    return QKescape;
  405.   case XK_space:    return QKspace;
  406.   case XK_Delete:    return QKdelete;
  407.   case 0:        return Qnil;
  408.   default:
  409.     if (simple_p) return Qnil;
  410.     BLOCK_INPUT;
  411.     name = XKeysymToString (keysym);
  412.     UNBLOCK_INPUT;
  413.     if (!name || !name[0])    /* this shouldn't happen... */
  414.       {
  415.     char buf [255];
  416.     sprintf (buf, "unknown_keysym_0x%X", keysym);
  417.     return KEYSYM (buf);
  418.       }
  419.     /* If it's got a one-character name, that's good enough. */
  420.     if (!name[1]) return make_number (name[0]);
  421.  
  422.     /* If it's in the "Keyboard" character set, downcase it.
  423.        The case of those keysyms is too totally random for us to
  424.        force anyone to remember them.
  425.        The case of the other character sets is significant, however.
  426.      */
  427.     if ((((unsigned int) keysym) & (~0xFF)) == ((unsigned int) 0xFF00))
  428.       {
  429.     char buf [255];
  430.     char *s1, *s2;
  431.     for (s1 = name, s2 = buf; *s1; s1++, s2++)
  432.       *s2 = ((*s1 >= 'A' && *s1 <= 'Z') ? (*s1 + ('a'-'A')) : *s1);
  433.     *s2 = 0;
  434.     return KEYSYM (buf);
  435.       }
  436.     return KEYSYM (name);
  437.   }
  438. }
  439.  
  440.  
  441. extern int interrupt_char;
  442. extern int x_allow_sendevents;
  443.  
  444. #ifdef LWLIB_HAS_EXTENSIONS
  445. extern Widget XtWidgetToDispatchTo ();
  446. #endif
  447.  
  448. static void
  449. set_last_server_timestamp (XEvent* x_event)
  450. {
  451.   switch (x_event->xany.type)
  452.     {
  453.     case KeyPress:
  454.     case KeyRelease:
  455.       last_server_timestamp = x_event->xkey.time;
  456.       break;
  457.  
  458.     case ButtonPress:
  459.     case ButtonRelease:
  460.       last_server_timestamp = x_event->xbutton.time;
  461.       break;
  462.  
  463.     case MotionNotify:
  464.       last_server_timestamp = x_event->xmotion.time;
  465.       break;
  466.  
  467.     case EnterNotify:
  468.     case LeaveNotify:
  469.       last_server_timestamp = x_event->xcrossing.time;
  470.       break;
  471.       
  472.     case PropertyNotify:
  473.       last_server_timestamp = x_event->xproperty.time;
  474.       break;
  475.  
  476.     case SelectionClear:
  477.       last_server_timestamp = x_event->xselectionclear.time;
  478.       break;
  479.  
  480.     case SelectionRequest:
  481.       last_server_timestamp = x_event->xselectionrequest.time;
  482.       break;
  483.  
  484.     case SelectionNotify:
  485.       last_server_timestamp = x_event->xselection.time;
  486.       break;
  487.     }
  488. }
  489.  
  490. static void
  491. x_event_to_emacs_event (x_event, emacs_event)
  492.      struct Lisp_Event *emacs_event;
  493.      XEvent *x_event;
  494. {
  495.   Display *display = x_event->xany.display;
  496.  
  497.   set_last_server_timestamp (x_event);
  498.  
  499.   switch (x_event->xany.type) {
  500.   case KeyPress:
  501.   case ButtonPress:
  502.   case ButtonRelease:
  503.     {
  504.       unsigned int modifiers = 0;
  505.       int shift_p = x_event->xkey.state & ShiftMask;
  506.       int lock_p  = x_event->xkey.state & LockMask;
  507. #ifdef LWLIB_HAS_EXTENSIONS
  508.       Widget to_widget;
  509. #endif
  510.  
  511.       /* If this is a synthetic KeyPress or Button event, and the user
  512.      has expressed a disinterest in this security hole, then drop
  513.      it on the floor.  (Actually, turn it into a no-op XAnyEvent,
  514.      and turn that into a magic event.  XtDispatchEvent will ignore
  515.      it.  We have to return some kind of event here, we're committed.
  516.        */
  517.       if (((x_event->xany.type == KeyPress)
  518.        ? x_event->xkey.send_event
  519.        : x_event->xbutton.send_event)
  520.       && !x_allow_sendevents)
  521.     {
  522.       x_event->xany.type = 0;
  523.       goto MAGIC;
  524.     }
  525.  
  526. #ifdef LWLIB_HAS_EXTENSIONS
  527.       BLOCK_INPUT;
  528.       to_widget = XtWidgetToDispatchTo (x_event);
  529.       UNBLOCK_INPUT;
  530. #endif
  531.  
  532.       if (x_event->xany.type == KeyPress)
  533.     global_mouse_timestamp = x_event->xkey.time;
  534.       else
  535.     global_mouse_timestamp = x_event->xbutton.time;
  536.  
  537. #ifdef LWLIB_HAS_EXTENSIONS
  538.       if (to_widget && !XtIsSubclass (to_widget, emacsScreenWidgetClass))
  539.     goto MAGIC;
  540. #endif
  541.  
  542.       /* Ignore the caps-lock key w.r.t. mouse presses and releases. */
  543.       if (x_event->xany.type != KeyPress)
  544.     lock_p = 0;
  545.  
  546.       if (x_event->xkey.state & ControlMask) modifiers |= MOD_CONTROL;
  547.       if (x_event->xkey.state & MetaMask)    modifiers |= MOD_META;
  548.       if (x_event->xkey.state & SuperMask)   modifiers |= MOD_SUPER;
  549.       if (x_event->xkey.state & HyperMask)   modifiers |= MOD_HYPER;
  550.       if (x_event->xkey.state & SymbolMask)  modifiers |= MOD_SYMBOL;
  551.  
  552.       /* Ignore the caps-lock key if any other modifiers are down; this is
  553.      so that Caps doesn't turn C-x into C-X, which would suck. */
  554.       if (modifiers)
  555.     {
  556.       x_event->xkey.state &= (~LockMask);
  557.       lock_p = 0;
  558.     }
  559.  
  560.       if (shift_p || lock_p)
  561.     modifiers |= MOD_SHIFT;
  562.  
  563.       mouse_timestamp = global_mouse_timestamp;
  564.  
  565.       switch (x_event->xany.type) {
  566.       case KeyPress:
  567.     {
  568.       Lisp_Object keysym;
  569.       struct screen *screen = 0;
  570.       KeyCode keycode = x_event->xkey.keycode;
  571.  
  572.  
  573.       if (x_key_is_modifier_p (keycode)) /* it's a modifier key */
  574.         goto MAGIC;
  575.  
  576. #ifdef LWLIB_HAS_EXTENSIONS
  577.       if (to_widget)
  578.         screen = ((EmacsScreenWidget)to_widget)->emacs_screen.screen;
  579. #endif
  580.       if (!screen)
  581.         screen = x_any_window_to_screen (x_event->xkey.window);
  582.  
  583.       /* This doesn't seem right to me: shouldn't this be "goto MAGIC"? */
  584.       if (! screen)
  585.         screen = selected_screen;
  586.  
  587.       /* At this point, screen->display.x->input_p may be false.
  588.          That's ok, because you can get keyboard input even if you
  589.          don't have focus...
  590.        */
  591.       XSET (emacs_event->channel, Lisp_Screen, screen);
  592.       keysym = x_to_emacs_keysym (x_event, 0);
  593.  
  594.       /* If the emacs keysym is nil, then that means that the X keysym
  595.          was NoSymbol, which probably means that we're in the midst of
  596.          reading a Multi_key sequence, or a "dead" key prefix.  Ignore
  597.          it.
  598.        */
  599.       if (NILP (keysym))
  600.         goto MAGIC;
  601.  
  602.       /* More caps-lock garbage: caps-lock should *only* add the shift
  603.          modifier to two-case keys (that is, A-Z and related characters.)
  604.          So at this point (after looking up the keysym) if the keysym
  605.          isn't a dual-case alphabetic, and if the caps lock key was down
  606.          but the shift key wasn't, then turn off the shift modifier.
  607.          Gag barf retch.
  608.        */
  609.       if (! keysym_obeys_caps_lock_p (keysym)
  610.           && lock_p
  611.           && !shift_p)
  612.         modifiers &= (~MOD_SHIFT);
  613.  
  614.       /* If this key contains two distinct keysyms, that is, "shift"
  615.          generates a different keysym than the non-shifted key, then
  616.          don't apply the shift modifier bit: it's implicit.  Otherwise,
  617.          if there would be no other way to tell the difference between
  618.          the shifted and unshifted version of this key, apply the shift
  619.          bit.  Non-graphics, like Backspace and F1 get the shift bit in
  620.          the modifiers slot.  Neither the characters "a", "A", "2",
  621.          nor "@" normally have the shift bit set.  However, "F1"
  622.          normally does.
  623.        */
  624.       if (modifiers & MOD_SHIFT)
  625.         {
  626.           KeySym top, bot;
  627.           if (x_event->xkey.state & ModeMask)
  628.         bot = XLookupKeysym (&x_event->xkey, 2),
  629.         top = XLookupKeysym (&x_event->xkey, 3);
  630.           else
  631.         bot = XLookupKeysym (&x_event->xkey, 0),
  632.         top = XLookupKeysym (&x_event->xkey, 1);
  633.           if (top && bot && top != bot)
  634.         modifiers &= ~MOD_SHIFT;
  635.         }
  636.       emacs_event->event_type       = key_press_event;
  637.       emacs_event->timestamp       = x_event->xkey.time;
  638.       emacs_event->event.key.modifiers = modifiers;
  639.       emacs_event->event.key.key       = keysym;
  640.       break;
  641.     }
  642.       case ButtonPress:
  643.       case ButtonRelease:
  644.     {
  645.       struct screen *screen = x_window_to_screen (x_event->xbutton.window);
  646.       if (! screen)
  647.         goto MAGIC; /* not for us */
  648.       XSET (emacs_event->channel, Lisp_Screen, screen);
  649.     }
  650.  
  651.     if (x_event->type == ButtonPress)
  652.       emacs_event->event_type    = button_press_event;
  653.     else emacs_event->event_type = button_release_event;
  654.     emacs_event->timestamp            = x_event->xbutton.time;
  655.     emacs_event->event.button.modifiers = modifiers;
  656.     emacs_event->event.button.button    = x_event->xbutton.button;
  657.     emacs_event->event.button.x         = x_event->xbutton.x;
  658.     emacs_event->event.button.y         = x_event->xbutton.y;
  659.     break;
  660.       }
  661.     }
  662.     break;
  663.  
  664.   case MotionNotify:
  665.     {
  666.       Window w = x_event->xmotion.window;
  667.       struct screen *screen = x_window_to_screen (w);
  668.       XEvent event2;
  669.  
  670.       if (! screen)
  671.     goto MAGIC; /* not for us */
  672.  
  673.       /* We use MotionHintMask, so we will get only one motion event
  674.      until the next time we call XQueryPointer or the user clicks
  675.      the mouse.  So call XQueryPointer now (meaning that the event
  676.      will be in sync with the server just before Fnext_event()
  677.      returns).  If the mouse is still in motion, then the server
  678.      will immediately generate exactly one more motion event, which
  679.      will be on the queue waiting for us next time around.
  680.        */
  681.       event2 = *x_event;
  682.       BLOCK_INPUT;
  683.       if (XQueryPointer (x_event->xmotion.display, event2.xmotion.window,
  684.              &event2.xmotion.root, &event2.xmotion.subwindow,
  685.              &event2.xmotion.x_root, &event2.xmotion.y_root,
  686.              &event2.xmotion.x, &event2.xmotion.y,
  687.              &event2.xmotion.state))
  688.     *x_event = event2;
  689.       UNBLOCK_INPUT;
  690.  
  691.       mouse_timestamp = x_event->xmotion.time;
  692.  
  693.       XSET (emacs_event->channel, Lisp_Screen, screen);
  694.       emacs_event->event_type      = pointer_motion_event;
  695.       emacs_event->timestamp      = x_event->xmotion.time;
  696.       emacs_event->event.motion.x = x_event->xmotion.x;
  697.       emacs_event->event.motion.y = x_event->xmotion.y;
  698.     }
  699.     break;
  700.     
  701.   case ClientMessage:
  702.     /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is passed as the
  703.        timestamp of the TAKE_FOCUS, which the ICCCM explicitly prohibits. */
  704.     if (x_event->xclient.message_type == Xatom_WM_PROTOCOLS
  705.     && x_event->xclient.data.l[0] == Xatom_WM_TAKE_FOCUS
  706.     && x_event->xclient.data.l[1] == 0)
  707.       {
  708.     x_event->xclient.data.l[1] = last_server_timestamp;
  709.       }
  710.     goto MAGIC;
  711.     break;
  712.  
  713.   default:
  714.   MAGIC:
  715.     emacs_event->event_type = magic_event;
  716.     emacs_event->channel = make_number ((Lisp_Object) display); /* #### */
  717.     memcpy ((char *) &emacs_event->event.magic.underlying_event,
  718.         (char *) x_event,
  719.         sizeof (XEvent));
  720.     break;
  721.   }
  722. }
  723.  
  724.  
  725. extern void x_handle_selection_clear (XSelectionClearEvent *);
  726. extern void x_handle_selection_request (XSelectionRequestEvent *);
  727. extern void x_handle_property_notify (XPropertyEvent *);
  728. extern void x_handle_selection_notify (XSelectionEvent *);
  729.  
  730. static void
  731. emacs_Xt_handle_magic_event (emacs_event)
  732.      struct Lisp_Event *emacs_event;
  733. {
  734.   XEvent *event = (XEvent *) &emacs_event->event.magic.underlying_event;
  735.   struct screen *s;
  736.   Display *display = event->xany.display;
  737.  
  738.   if (display != x_current_display)
  739.     abort ();
  740.  
  741.  KLUDGE_O_RAMA:
  742.  
  743.   switch (event->type) {
  744.  
  745.   case SelectionRequest:
  746.     if (x_window_to_screen (event->xselectionrequest.owner))
  747.       x_handle_selection_request (&event->xselectionrequest);
  748.     else
  749.       goto OTHER;
  750.     break;
  751.  
  752.   case SelectionClear:
  753.     if (x_window_to_screen (event->xselectionclear.window))
  754.       x_handle_selection_clear (&event->xselectionclear);
  755.     else
  756.       goto OTHER;
  757.     break;
  758.  
  759.   case SelectionNotify:
  760.     if (x_window_to_screen (event->xselection.requestor))
  761.       x_handle_selection_notify (&event->xselection);
  762.     else
  763.       goto OTHER;
  764.     break;
  765.  
  766.   case PropertyNotify:
  767.     if (x_window_to_screen (event->xproperty.window))
  768.       x_handle_property_notify (&event->xproperty);
  769.     else
  770.       goto OTHER;
  771.     break;
  772.     
  773.   case Expose:
  774.     if (! (s = x_window_to_screen (event->xexpose.window)))
  775.       goto OTHER;
  776.     repaint_lines (s, event->xexpose.x, event->xexpose.y,
  777.            event->xexpose.width, event->xexpose.height);
  778.     break;
  779.  
  780.   case GraphicsExpose:    /* This occurs when an XCopyArea's source area was
  781.                obscured or not available. */
  782.     if (! (s = x_window_to_screen (event->xexpose.window)))
  783.       goto OTHER;
  784.     repaint_lines (s, event->xgraphicsexpose.x, event->xgraphicsexpose.y,
  785.            event->xgraphicsexpose.width,
  786.            event->xgraphicsexpose.height);
  787.     break;
  788.  
  789.   case MapNotify:
  790.     if (! (s = x_any_window_to_screen (event->xunmap.window)))
  791.       goto OTHER;
  792.     {
  793.       Lisp_Object event = Fallocate_event ();
  794.       XEVENT (event)->event_type = eval_event;
  795.       XEVENT (event)->event.eval.function = Qx_MapNotify_internal;
  796.       XSET (XEVENT (event)->event.eval.object, Lisp_Screen, s);
  797.       enqueue_command_event (event);
  798.     }
  799.     goto OTHER;
  800.     break;
  801.  
  802.   case UnmapNotify:
  803.     if (! (s = x_any_window_to_screen (event->xunmap.window)))
  804.       goto OTHER;
  805.     {
  806.       Lisp_Object event = Fallocate_event ();
  807.       XEVENT (event)->event_type = eval_event;
  808.       XEVENT (event)->event.eval.function = Qx_UnmapNotify_internal;
  809.       XSET (XEVENT (event)->event.eval.object, Lisp_Screen, s);
  810.       enqueue_command_event (event);
  811.     }
  812.     goto OTHER;
  813.     break;
  814.     
  815.   case EnterNotify:
  816.     {
  817.       if (! (s = x_any_window_to_screen (event->xcrossing.window)))
  818.     goto OTHER;
  819.       if (event->xcrossing.detail != NotifyInferior)
  820.     {
  821.       Lisp_Object event = Fallocate_event ();
  822.       XEVENT (event)->event_type = eval_event;
  823.       XEVENT (event)->event.eval.function = Qx_EnterNotify_internal;
  824.       XSET (XEVENT (event)->event.eval.object, Lisp_Screen, s);
  825.       enqueue_command_event (event);
  826.     }
  827.       goto OTHER;
  828.     }
  829.     break;
  830.  
  831.   case LeaveNotify:
  832.     {
  833.       if (! (s = x_any_window_to_screen (event->xexpose.window)))
  834.     goto OTHER;
  835.       if (event->xcrossing.detail != NotifyInferior)
  836.     {
  837.       Lisp_Object event = Fallocate_event ();
  838.       XEVENT (event)->event_type = eval_event;
  839.       XEVENT (event)->event.eval.function = Qx_LeaveNotify_internal;
  840.       XSET (XEVENT (event)->event.eval.object, Lisp_Screen, s);
  841.       enqueue_command_event (event);
  842.     }
  843.       goto OTHER;
  844.     }
  845.     break;
  846.  
  847. #if 0
  848.     /*
  849.      * We were handling some focus events twice: once here, then again
  850.      * because we called XtDispatchEvent, and the EmacsShell widget called
  851.      * emacs_Xt_focus_event_handler() again.  We need to have the shell
  852.      * widget call emacs_Xt_focus_event_handler() because sometimes Motif
  853.      * calls XtDispatchEvent on synthetic focus events that we have no other
  854.      * way of getting our hands on.
  855.      *
  856.      * Possibly we could just avoid the "goto OTHER" here.  I don't know
  857.      * whether that would break something.
  858.      *
  859.      * Also, it's curious that we're using x_any_window_to_screen() instead
  860.      * of x_window_to_screen().  I don't know what the impact of this is.
  861.      *
  862.      * So for now, let's try handing focus events *only* via XtDispatchEvent
  863.      * and the EmacsShell callbacks.  This appears to make there be less
  864.      * focus problems with the Browse Language Element dbox: pasting from
  865.      * emacs into the text field no longer makes the dbox stop accepting
  866.      * keyboard input.
  867.      */
  868.   case FocusIn:
  869.   case FocusOut:
  870.     if (s = x_any_window_to_screen (event->xfocus.window))
  871.       emacs_Xt_focus_event_handler (event, s);
  872.     goto OTHER;
  873.     break;
  874. #endif /* 0 */
  875.  
  876.   case ClientMessage:
  877.     if (! (s = x_any_window_to_screen (event->xclient.window)))
  878.       goto OTHER;
  879.     if (event->xclient.message_type == Xatom_WM_PROTOCOLS &&
  880.     event->xclient.data.l[0] == Xatom_WM_DELETE_WINDOW)
  881.       {
  882.     Lisp_Object scr;
  883.     Lisp_Object next;
  884.     Lisp_Object event = Fallocate_event ();
  885.  
  886.     XSET (scr, Lisp_Screen, s);
  887.     next = next_screen (scr, 0, 0);
  888.     /* WM_DELETE_WINDOW is a menu event, but other ClientMessages, such
  889.        as WM_TAKE_FOCUS, are eval events.  That's because delete-window
  890.        was probably executed with a mouse click, while the others could
  891.        have been sent as a result of mouse motion or some other implicit
  892.        action.  (Call this a "heuristic"...)  The reason for caring about
  893.        this is so that clicking on the close-box will make emacs prompt
  894.        using a dialog box instead of the minibuffer if there are unsaved
  895.        buffers.
  896.      */
  897.     XEVENT (event)->event_type = menu_event;
  898.     if (EQ (next, scr) || EQ (scr, Vglobal_minibuffer_screen))
  899.       {
  900.         XEVENT (event)->event.eval.function =
  901.           intern ("save-buffers-kill-emacs");
  902.         XEVENT (event)->event.eval.object = Qnil;
  903.       }
  904.     else
  905.       {
  906.         XEVENT (event)->event.eval.function = intern ("delete-screen");
  907.         XEVENT (event)->event.eval.object = scr;
  908.       }
  909.     enqueue_command_event (event);
  910.       }
  911. #if 0
  912.     else if (event->xclient.message_type == Xatom_WM_PROTOCOLS &&
  913.          event->xclient.data.l[0] == Xatom_WM_TAKE_FOCUS)
  914.       {
  915.     /* If there is a dialog box up, focus on it.
  916.  
  917.        #### Actually, we're raising it too, which is wrong.  We should
  918.        #### just focus on it, but lwlib doesn't currently give us an
  919.        #### easy way to do that.  This should be fixed.
  920.      */
  921.     unsigned long take_focus_timestamp = event->xclient.data.l[1];
  922.     Widget widget = lw_raise_all_pop_up_widgets ();
  923.     if (widget)
  924.       {
  925.         /* kludge: raise_all returns bottommost widget, but we really
  926.            want the topmost.  So just raise it for now. */
  927.         XMapRaised (XtDisplay (widget), XtWindow (widget));
  928.         /* Grab the focus with the timestamp of the TAKE_FOCUS. */
  929.         XSetInputFocus (XtDisplay (widget), XtWindow (widget),
  930.                 RevertToParent, take_focus_timestamp);
  931.       }
  932.       }
  933. #endif
  934.     else
  935.       goto OTHER;
  936.     break;
  937.  
  938.   case MappingNotify:    /* The user has run xmodmap */
  939.     BLOCK_INPUT;
  940.     XRefreshKeyboardMapping (&event->xmapping);
  941.     UNBLOCK_INPUT;
  942.     /* xmodmap generates about a billion MappingKeyboard events, followed
  943.        by a single MappingModifier event, so it might be worthwhile to
  944.        take extra MappingKeyboard events out of the queue before requesting
  945.        the current keymap from the server.
  946.      */
  947.     if (event->xmapping.request == MappingKeyboard)
  948.       x_reset_key_mapping (display);
  949.     else if (event->xmapping.request == MappingModifier)
  950.       x_reset_modifier_mapping (display);
  951.     goto OTHER;
  952.  
  953.   case VisibilityNotify: /* window visiblity has changed */
  954.     if (! (s = x_any_window_to_screen (event->xvisibility.window)))
  955.       goto OTHER;
  956.     {
  957.       Lisp_Object e = Fallocate_event ();
  958.       Lisp_Object screen;
  959.       XSET (screen, Lisp_Screen, s);
  960.       XEVENT (e)->event_type = eval_event;
  961.       if (event->xvisibility.state == VisibilityUnobscured)
  962.     XEVENT (e)->event.eval.function = Qx_VisibilityNotify_internal;
  963.       else
  964.     XEVENT (e)->event.eval.function = Qx_non_VisibilityNotify_internal;
  965.       XEVENT (e)->event.eval.object = screen;
  966.       enqueue_command_event (e);
  967.     }
  968.     goto OTHER;
  969.     break;
  970.  
  971.   default:
  972.   OTHER:
  973.     if (event->xany.display != x_current_display)
  974.       abort ();
  975.     BLOCK_INPUT;
  976.     XtDispatchEvent (event);
  977.     UNBLOCK_INPUT;
  978.   }
  979.  
  980.   /* #### This is a repulsive kludge!  Rewrite redisplay!!
  981.      Redisplay is too slow; in particular, the function redisplay() takes way
  982.      too long to realize that it doesn't need to do any work!  It regenerates
  983.      the screen arrays too often.  So rather than fixing this, we avoid calling
  984.      redisplay() after every event which is an exposure event (as on the
  985.      debugger-panel buttons, which cause ~15 exposure events per screen) by
  986.      batching up the exposure events.
  987.  
  988.      We process all consecutive Expose events at the same timem without them
  989.      ever getting turned into emacs events.  We used to process all pending
  990.      Expose events, but that doesn't work; it's not ok to take them out of the
  991.      queue out of order.
  992.    */
  993. #define EXPOSE_P(e) \
  994.   (e->type == Expose || e->type == GraphicsExpose || e->type == NoExpose)
  995.  
  996.   if (EXPOSE_P (event))
  997.     {
  998.       Bool duh;
  999.       BLOCK_INPUT;
  1000.       duh = (XtAppPending (Xt_app_con) & XtIMXEvent);
  1001.       UNBLOCK_INPUT;
  1002.       if (duh)
  1003.     {
  1004.       BLOCK_INPUT;
  1005.       XPeekEvent (display, event);
  1006.       UNBLOCK_INPUT;
  1007.       if (EXPOSE_P (event))
  1008.         {
  1009.           /* The event is acceptable, take it off the queue */
  1010.           BLOCK_INPUT;
  1011.           XNextEvent (display, event);
  1012.           UNBLOCK_INPUT;
  1013.           goto KLUDGE_O_RAMA;
  1014.         }
  1015.     }
  1016.     }
  1017. #undef EXPOSE_P
  1018.  
  1019. }
  1020.  
  1021. void
  1022. emacs_Xt_focus_event_handler (x_event, s)
  1023.      XEvent *x_event;
  1024.      struct screen *s;
  1025. {
  1026.   Lisp_Object event = Fallocate_event ();
  1027.   XEVENT (event)->event_type = eval_event;
  1028.   if (x_event->xany.type == FocusIn)
  1029.     XEVENT (event)->event.eval.function = Qx_FocusIn_internal;
  1030.   else if (x_event->xany.type == FocusOut)
  1031.     XEVENT (event)->event.eval.function = Qx_FocusOut_internal;
  1032.   else
  1033.     abort ();
  1034.   if (! s)
  1035.     if (! (s = x_any_window_to_screen (x_event->xfocus.window)))
  1036.       abort ();
  1037.   XSET (XEVENT (event)->event.eval.object, Lisp_Screen, s);
  1038.   enqueue_command_event (event);
  1039. }
  1040.  
  1041.  
  1042.  
  1043.  
  1044. extern char *x_event_name (int);
  1045.  
  1046. static void
  1047. describe_event_window (window)
  1048.      Window window;
  1049. {
  1050.   struct screen *s;
  1051.   Widget w;
  1052.   printf ("   window: 0x%x", (int) window);
  1053.   if (w = XtWindowToWidget (x_current_display, window))
  1054.     printf (" %s", w->core.widget_class->core_class.class_name);
  1055.   if (s = x_any_window_to_screen (window))
  1056.     printf (" \"%s\"", XSTRING (s->name)->data);
  1057.   printf ("\n");
  1058. }
  1059.  
  1060.  
  1061. static void
  1062. describe_event (event)
  1063.      XEvent *event;
  1064. {
  1065.   printf ("%s\n", x_event_name (event->xany.type));
  1066.   switch (event->xany.type) {
  1067.   case Expose:
  1068.     describe_event_window (event->xexpose.window);
  1069.     printf ("   region: %d %d %d %d\n", event->xexpose.x, event->xexpose.y,
  1070.         event->xexpose.width, event->xexpose.height);
  1071.     printf ("    count: %d\n", event->xexpose.count);
  1072.     break;
  1073.   case GraphicsExpose:
  1074.     describe_event_window (event->xgraphicsexpose.drawable);
  1075.     printf ("    major: %s\n",
  1076.         (event->xgraphicsexpose.major_code == X_CopyArea ? "CopyArea"
  1077.          : (event->xgraphicsexpose.major_code == X_CopyPlane ? "CopyPlane"
  1078.         : "?")));
  1079.     printf ("   region: %d %d %d %d\n",
  1080.         event->xgraphicsexpose.x, event->xgraphicsexpose.y,
  1081.         event->xgraphicsexpose.width, event->xgraphicsexpose.height);
  1082.     printf ("    count: %d\n", event->xgraphicsexpose.count);
  1083.     break;
  1084.   case FocusIn:
  1085.   case FocusOut:
  1086.     describe_event_window (event->xfocus.window);
  1087.     printf ("     mode: %s\n",
  1088.         (event->xfocus.mode == NotifyNormal ? "Normal"
  1089.          :(event->xfocus.mode == NotifyGrab ? "Grab"
  1090.            :(event->xfocus.mode == NotifyUngrab ? "Ungrab"
  1091.          :(event->xfocus.mode == NotifyWhileGrabbed ? "WhileGrabbed"
  1092.            : "?")))));
  1093.     printf ("   detail: %s\n",
  1094.      (event->xfocus.detail == NotifyAncestor ? "Ancestor"
  1095.       :(event->xfocus.detail == NotifyVirtual ? "Virtual"
  1096.     :(event->xfocus.detail == NotifyInferior ? "Inferior"
  1097.       :(event->xfocus.detail == NotifyNonlinear ? "Nonlinear"
  1098.         :(event->xfocus.detail == NotifyNonlinearVirtual ?
  1099.           "NonlinearVirtual"
  1100.           :(event->xfocus.detail == NotifyPointer ? "Pointer"
  1101.         :(event->xfocus.detail == NotifyPointerRoot ? "PointerRoot"
  1102.           :(event->xfocus.detail == NotifyDetailNone ?
  1103.             "DetailNone" : "?")))))))));
  1104.     break;
  1105.   case EnterNotify:
  1106.   case LeaveNotify:
  1107.     describe_event_window (event->xcrossing.window);
  1108. /*
  1109.     printf (" subwindow: 0x%x\n", event->xcrossing.subwindow);
  1110.     printf ("      pos: %d %d\n", event->xcrossing.x, event->xcrossing.y);
  1111.     printf (" root pos: %d %d\n",
  1112.         event->xcrossing.x_root, event->xcrossing.y_root);
  1113.  */
  1114.     printf ("     mode: %s\n",
  1115.         (event->xcrossing.mode == NotifyNormal ? "Normal"
  1116.          :(event->xcrossing.mode == NotifyGrab ? "Grab"
  1117.            :(event->xcrossing.mode == NotifyUngrab ? "Ungrab"
  1118.          :(event->xcrossing.mode == NotifyWhileGrabbed ?
  1119.            "WhileGrabbed" : "?")))));
  1120.     printf ("   detail: %s\n",
  1121.      (event->xcrossing.detail == NotifyAncestor ? "Ancestor"
  1122.       :(event->xcrossing.detail == NotifyVirtual ? "Virtual"
  1123.     :(event->xcrossing.detail == NotifyInferior ? "Inferior"
  1124.       :(event->xcrossing.detail == NotifyNonlinear ? "Nonlinear"
  1125.         :(event->xcrossing.detail == NotifyNonlinearVirtual ?
  1126.           "NonlinearVirtual"
  1127.           :(event->xcrossing.detail == NotifyPointer ? "Pointer"
  1128.         :(event->xcrossing.detail == NotifyPointerRoot ?
  1129.           "PointerRoot"
  1130.           :(event->xcrossing.detail == NotifyDetailNone ?
  1131.             "DetailNone" : "?")))))))));
  1132.     printf ("    focus: %d\n", event->xcrossing.focus);
  1133. /*
  1134.     printf ("    state: 0x%x\n", event->xcrossing.state);
  1135.  */
  1136.     break;
  1137.   case ConfigureNotify:
  1138.     describe_event_window (event->xconfigure.window);
  1139.     printf ("    above: 0x%x\n", event->xconfigure.above);
  1140.     printf ("     size: %d %d %d %d\n", event->xconfigure.x,
  1141.         event->xconfigure.y,
  1142.         event->xconfigure.width, event->xconfigure.height);
  1143.     printf ("  redirect: %d\n", event->xconfigure.override_redirect);
  1144.     break;
  1145.   case VisibilityNotify:
  1146.     describe_event_window (event->xvisibility.window);
  1147.     printf ("    state: %s\n",
  1148.         (event->xvisibility.state == VisibilityUnobscured ?
  1149.          "Unobscured"
  1150.          :(event->xvisibility.state == VisibilityPartiallyObscured ?
  1151.            "PartiallyObscured"
  1152.            :(event->xvisibility.state == VisibilityFullyObscured ?
  1153.          "FullyObscured" : "?"))));
  1154.   case KeyPress:
  1155.     {
  1156.       Lisp_Object keysym;
  1157.       describe_event_window (event->xkey.window);
  1158.       printf ("    state: ");
  1159.       if (event->xkey.state & ShiftMask)   printf ("Shift ");
  1160.       if (event->xkey.state & LockMask)    printf ("Lock ");
  1161.       if (event->xkey.state & ControlMask) printf ("Control ");
  1162.       if (event->xkey.state & Mod1Mask)    printf ("Mod1 ");
  1163.       if (event->xkey.state & Mod2Mask)    printf ("Mod2 ");
  1164.       if (event->xkey.state & Mod3Mask)    printf ("Mod3 ");
  1165.       if (event->xkey.state & Mod4Mask)    printf ("Mod4 ");
  1166.       if (event->xkey.state & Mod5Mask)    printf ("Mod5 ");
  1167.       if (event->xkey.state & MetaMask)       printf ("Meta ");
  1168.       if (event->xkey.state & SuperMask)   printf ("Super ");
  1169.       if (event->xkey.state & HyperMask)   printf ("Hyper ");
  1170.       if (event->xkey.state & SymbolMask)  printf ("Symbol ");
  1171.       if (event->xkey.state & ModeMask)    printf ("Mode_switch ");
  1172.  
  1173.       if (! event->xkey.state) printf ("vanilla\n");
  1174.       else printf ("\n");
  1175.       if (x_key_is_modifier_p (event->xkey.keycode))
  1176.     printf ("   Modifier key");
  1177.       printf ("  keycode: 0x%x\n", event->xkey.keycode);
  1178.       keysym = x_to_emacs_keysym (event, 0);
  1179.       if (keysym < 1024)
  1180.     printf ("   keysym: %c\n", keysym);
  1181.       else
  1182.     printf ("   keysym: %s\n", XSYMBOL (keysym)->name->data);
  1183.     }
  1184.     break;
  1185.   }
  1186. }
  1187.  
  1188.  
  1189.  
  1190. static Bool synthetic_event_present_p ();
  1191.  
  1192. static void
  1193. Xt_wake_up (display)
  1194.      Display *display;
  1195. {
  1196.   /* Generate an unnecessary event so that XtAppNextEvent will
  1197.      return right now.  This is done from inside of the callback
  1198.      functions attached to timeouts and file descriptors, because Xt doesn't
  1199.      consider those kinds of events as enough reason to return, and will
  1200.      continue waiting for an X event to arrive, even though there's a
  1201.      perfectly good timeout/fd event sitting around waiting to be processed.
  1202.  
  1203.      I used to do this by simply longjmp()ing out of the callback function,
  1204.      but that causes a small core leak inside of Xt.
  1205.    */
  1206.   XEvent fake_event;
  1207.   fake_event.type = 0;    /* XAnyEvent type, ignored. */
  1208.   fake_event.xany.display = display;
  1209.   fake_event.xany.window  = 0;
  1210.   BLOCK_INPUT;
  1211.   if (! synthetic_event_present_p (display))
  1212.     XPutBackEvent (display, &fake_event);
  1213.   UNBLOCK_INPUT;
  1214. }
  1215.  
  1216. static Bool look_for_synthetic_event ();
  1217.  
  1218. static Bool
  1219. synthetic_event_present_p (Display *dpy)
  1220. {
  1221.   Bool res = False;
  1222.   XEvent event;
  1223.   BLOCK_INPUT;
  1224.   XEventsQueued (dpy, QueuedAfterReading);
  1225.   XCheckIfEvent (dpy, &event, &look_for_synthetic_event, (char *) &res);
  1226.   UNBLOCK_INPUT;
  1227.   return res;
  1228. }
  1229.  
  1230. static Bool
  1231. look_for_synthetic_event (display, event, arg)
  1232.      Display *display;
  1233.      XEvent *event;
  1234.      XtPointer arg;
  1235. {
  1236.   if (event->xany.type == 0)
  1237.     *((Bool *) arg) = True;
  1238.   return False;
  1239. }
  1240.  
  1241.  
  1242. /* timeout events */
  1243.  
  1244. static int timeout_id_tick;
  1245.  
  1246. static struct timeout {
  1247.   unsigned int id;
  1248.   Lisp_Object function, object;
  1249.   unsigned int msecs;
  1250.   unsigned int resignal_msecs;
  1251.   XtIntervalId interval_id;
  1252.   struct timeout *next;
  1253. } *pending_timeouts, *completed_timeouts;
  1254.  
  1255.  
  1256. static void Xt_timeout_callback ();
  1257.  
  1258. static void
  1259. generate_wakeup_internal (id, milliseconds, vanilliseconds, function, object)
  1260.      int id;
  1261.      unsigned int milliseconds, vanilliseconds;
  1262.      Lisp_Object function;
  1263.      Lisp_Object object;
  1264. {
  1265.   struct timeout *timeout = (struct timeout *)
  1266.     xmalloc (sizeof (struct timeout));
  1267.   timeout->id = id;
  1268.   timeout->msecs = milliseconds;
  1269.   timeout->resignal_msecs = vanilliseconds;
  1270.   timeout->function = function;
  1271.   timeout->object = object;
  1272.   timeout->next = pending_timeouts;
  1273.   pending_timeouts = timeout;
  1274.   BLOCK_INPUT;
  1275.   timeout->interval_id =
  1276.     XtAppAddTimeOut (Xt_app_con, milliseconds, Xt_timeout_callback, timeout);
  1277.   UNBLOCK_INPUT;
  1278. }
  1279.  
  1280.  
  1281. static int
  1282. emacs_Xt_generate_wakeup (msec, resignal, function, object)
  1283.      unsigned int msec, resignal;
  1284.      Lisp_Object function;
  1285.      Lisp_Object object;
  1286. {
  1287.   int id = timeout_id_tick++;
  1288.   generate_wakeup_internal (id, msec, resignal, function, object);
  1289.   return id;
  1290. }
  1291.  
  1292.  
  1293. static void
  1294. Xt_timeout_callback (timeout)    /* called by XtAppNextEvent() */
  1295.      struct timeout* timeout;
  1296. {
  1297.   struct timeout *t2 = pending_timeouts;
  1298.   /* Remove this one from the list of pending timeouts */
  1299.   if (t2 == timeout)
  1300.     pending_timeouts = pending_timeouts->next;
  1301.   else {
  1302.     while (t2->next && t2->next != timeout) t2 = t2->next;
  1303.     if (! t2->next) abort();
  1304.     t2->next = t2->next->next;
  1305.   }
  1306.   /* Add this one to the list of completed timeouts */
  1307.   timeout->next = completed_timeouts;
  1308.   completed_timeouts = timeout;
  1309.  
  1310.   /* If this timeout wants to be resignalled, do it now.
  1311.      We don't reuse the same timeout structure, but possibly we could.
  1312.    */
  1313.   if (timeout->resignal_msecs)
  1314.     generate_wakeup_internal (timeout->id,
  1315.                   timeout->resignal_msecs, timeout->resignal_msecs,
  1316.                   timeout->function, timeout->object);
  1317.  
  1318.   Xt_wake_up (x_current_display);
  1319. }
  1320.  
  1321.  
  1322. static void
  1323. emacs_Xt_disable_wakeup (id)
  1324.      int id;
  1325. {
  1326.   struct timeout *timeout, *t2;
  1327.  
  1328.   /* Find the timeout on the list of pending ones, if it's still there. */
  1329.   if (!pending_timeouts) return;
  1330.   if (id == pending_timeouts->id) {
  1331.     timeout = pending_timeouts;
  1332.     pending_timeouts = pending_timeouts->next;
  1333.   }
  1334.   else {
  1335.     t2 = pending_timeouts;
  1336.     while (t2->next && t2->next->id != id) t2 = t2->next;
  1337.     if (! t2->next) return;
  1338.     timeout = t2->next;
  1339.     t2->next = t2->next->next;
  1340.   }
  1341.   /* At this point, we've found the thing on the list of pending timeouts,
  1342.      and removed it.
  1343.    */
  1344.   timeout->function = Qnil;
  1345.   timeout->object = Qnil;
  1346.   timeout->msecs = 0;
  1347.   timeout->resignal_msecs = 0;
  1348.   timeout->id = 0;
  1349.   timeout->next = (struct timeout *) 0xDEADBEEF;
  1350.   BLOCK_INPUT;
  1351.   XtRemoveTimeOut (timeout->interval_id);
  1352.   xfree (timeout);
  1353.   UNBLOCK_INPUT;
  1354. }
  1355.  
  1356.  
  1357. static void
  1358. Xt_timeout_to_emacs_event (emacs_event)
  1359.      struct Lisp_Event *emacs_event;
  1360. {
  1361.   struct timeout *timeout = completed_timeouts;
  1362.   if (! timeout) abort ();
  1363.   completed_timeouts = completed_timeouts->next;
  1364.   emacs_event->event_type = timeout_event;
  1365.   emacs_event->timestamp  = timeout->msecs; /* #### wrong!! */
  1366.   emacs_event->event.timeout.function  = timeout->function;
  1367.   emacs_event->event.timeout.object    = timeout->object;
  1368.   emacs_event->event.timeout.id_number = timeout->id;
  1369.   xfree (timeout);
  1370. }
  1371.  
  1372.  
  1373. /* process events */
  1374.  
  1375. static Lisp_Object *process_fds_with_input;
  1376. static XtInputId   *process_fds_to_input_ids;
  1377. static int process_events_occurred;
  1378.  
  1379. #ifndef MAX_PROC_FDS
  1380. # define MAX_PROC_FDS FD_SETSIZE
  1381. #endif
  1382.  
  1383. void
  1384. mark_process_as_being_ready (process)
  1385.      struct Lisp_Process *process;
  1386. {
  1387.   if (NILP (process_fds_with_input [XFASTINT (process->infd)])) {
  1388.     XSET (process_fds_with_input [XFASTINT (process->infd)],
  1389.       Lisp_Process,
  1390.       process);
  1391.     /* Don't increment this if the current process is already marked
  1392.        as having input.
  1393.        */
  1394.     process_events_occurred++;
  1395.   }
  1396. }
  1397.  
  1398. static void
  1399. Xt_process_callback (closure, source, id)    /* called by XtAppNextEvent() */
  1400.      void *closure;
  1401.      int *source;
  1402.      XtInputId *id;
  1403. {
  1404.   struct Lisp_Process *process = (struct Lisp_Process *) closure;
  1405.   mark_process_as_being_ready (process);
  1406.   Xt_wake_up (x_current_display);
  1407. }
  1408.  
  1409. static void
  1410. emacs_Xt_select_process (process)
  1411.      struct Lisp_Process *process;
  1412. {
  1413.   BLOCK_INPUT;
  1414.   process_fds_to_input_ids[XFASTINT (process->infd)] = 
  1415.     XtAppAddInput (Xt_app_con, XFASTINT (process->infd),
  1416.            (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
  1417.            Xt_process_callback, (void *) process);
  1418.   UNBLOCK_INPUT;
  1419. }
  1420.  
  1421.  
  1422. static void
  1423. emacs_Xt_unselect_process (process)
  1424.      struct Lisp_Process *process;
  1425. {
  1426.   int fd = XFASTINT (process->infd);
  1427.   XtInputId id;
  1428.   /* If the infd is 0, it has already been deleted, and Xt will freak
  1429.      because it's calls to select() will fail. */
  1430.   if (! fd) abort ();
  1431.   id = process_fds_to_input_ids [fd];
  1432.   if (! id) return;
  1433.   process_fds_to_input_ids [fd] = -1;
  1434.   BLOCK_INPUT;
  1435.   XtRemoveInput (id);
  1436.   UNBLOCK_INPUT;
  1437. }
  1438.  
  1439.  
  1440. static void
  1441. Xt_process_to_emacs_event (emacs_event)
  1442.      struct Lisp_Event *emacs_event;
  1443. {
  1444.   int i;
  1445.   Lisp_Object process;
  1446.   if (process_events_occurred <= 0) abort ();
  1447.   for (i = 0; i < MAX_PROC_FDS; i++)
  1448.     if (!NILP (process = process_fds_with_input [i])) {
  1449.       process_fds_with_input [i] = Qnil;
  1450.       break;
  1451.     }
  1452.   if (NILP (process) || !process) abort ();
  1453.  
  1454.   process_events_occurred--;
  1455.   emacs_event->event_type = process_event;
  1456.   emacs_event->timestamp  = 0; /* #### */
  1457.   emacs_event->event.process.process = process;
  1458. }
  1459.  
  1460.  
  1461. /* tty events */
  1462.  
  1463. static void
  1464. emacs_Xt_select_tty (file_descriptor)
  1465.      int file_descriptor;
  1466. {
  1467. }
  1468.  
  1469. static void
  1470. emacs_Xt_unselect_tty (file_descriptor)
  1471.      int file_descriptor;
  1472. {
  1473. }
  1474.  
  1475.  
  1476.  
  1477. static void XtAppNextEvent_non_synthetic ();
  1478.  
  1479.  
  1480. static void
  1481. emacs_Xt_next_event (emacs_event)
  1482.      struct Lisp_Event *emacs_event;
  1483. {
  1484.   XEvent x_event;
  1485.  
  1486.   /* If the event's type is XAnyEvent, then it's a fake, synthetic event
  1487.      that we generated inside a timeout callback just to make XtAppNextEvent
  1488.      return right away.  In order to avoid race conditions, all user input
  1489.      and window-system events must have higher priority than process and
  1490.      timer output.  So if the next event on the queue is one of these
  1491.      synthetic events, and there are non-synthetic events behind it, then
  1492.      take the following events first (leaving the synthetic event at the
  1493.      front of the queue, so that we don't forget to handle the procs/timers
  1494.      when there is nothing else left to handle.)
  1495.    */
  1496.   BLOCK_INPUT;
  1497.   XtAppNextEvent_non_synthetic (x_current_display, Xt_app_con, &x_event);
  1498.   UNBLOCK_INPUT;
  1499.  
  1500.   if (x_event.xany.type == 0 &&
  1501.       (completed_timeouts || process_events_occurred))
  1502.     {
  1503.       /* If we got here, then the only X event on the queue is a dummy event
  1504.      representing timeouts or process output.  This means that all user
  1505.      input has been consumed, and we can now do timeouts and processes.
  1506.        */
  1507.       if (completed_timeouts)
  1508.     Xt_timeout_to_emacs_event (emacs_event);
  1509.       else /* if (process_events_occurred) */
  1510.     Xt_process_to_emacs_event (emacs_event);
  1511.     }
  1512.   else
  1513.     x_event_to_emacs_event (&x_event, emacs_event);
  1514. }
  1515.  
  1516.  
  1517. static Bool
  1518. non_synthetic_event_p (display, event, arg)
  1519.      Display *display;
  1520.      XEvent *event;
  1521.      XtPointer arg;
  1522. {
  1523.   if (event->xany.type)
  1524.     return True;
  1525.   return False;
  1526. }
  1527.  
  1528. static void 
  1529. XtAppNextEvent_non_synthetic (dpy, app, x_event)
  1530.      Display *dpy;
  1531.      XtAppContext app;
  1532.      XEvent *x_event;
  1533. {
  1534.   if (! XCheckIfEvent (dpy, x_event, non_synthetic_event_p, 0))
  1535.     XtAppNextEvent (app, x_event);
  1536. }
  1537.  
  1538.  
  1539. /* Determining whether there is input pending, and noticing the interrupt
  1540.    character in a timely fashion.
  1541.  */
  1542.  
  1543. static void x_check_for_interrupt_char ();
  1544. static Bool look_for_key_or_mouse_event ();
  1545.  
  1546. static int
  1547. emacs_Xt_event_pending_p (user_p)
  1548.      int user_p;
  1549. {
  1550.   /* If `user_p' is false, then this function returns whether there are any
  1551.      X, timeout, or fd events pending (that is, whether emacs_Xt_next_event()
  1552.      would return immediately without blocking.)
  1553.  
  1554.      if `user_p' is false, then this function returns whether there are any
  1555.      *user generated* events available (that is, whether there are keyboard
  1556.      or mouse-click events ready to be read.)  This also implies that
  1557.      emacs_Xt_next_event() would not block.
  1558.  
  1559.      In a non-SIGIO world, this also checks whether the user has typed ^G,
  1560.      since this is a convenient place to do so.  We don't need to do this
  1561.      in a SIGIO world, since input causes an interrupt.
  1562.    */
  1563.   int res;
  1564.   XEvent event;
  1565.   Display *display = x_current_display;
  1566.  
  1567.   BLOCK_INPUT;
  1568.   res = XtAppPending (Xt_app_con);
  1569. #ifndef SIGIO
  1570.   x_check_for_interrupt_char (x_current_display);
  1571. #endif
  1572.   UNBLOCK_INPUT;
  1573.  
  1574.   if (! user_p)
  1575.     return (res != 0);
  1576.  
  1577.   if (! (res & XtIMXEvent)) /* no X events means no user input */
  1578.     return 0;
  1579.  
  1580.   res = 0;
  1581.   BLOCK_INPUT;
  1582.   XEventsQueued (display, QueuedAfterReading);
  1583.   XCheckIfEvent (display, &event, &look_for_key_or_mouse_event, (char *) &res);
  1584.   UNBLOCK_INPUT;
  1585.   return res;
  1586. }
  1587.  
  1588.  
  1589. /* This function is passed to XCheckIfEvent, but always returns 0, so that
  1590.    the event is not removed from the queue (that is, we're using XCheckIfEvent
  1591.    as a means of nondestructively iterating over the queue without blocking.)
  1592.    If one of the events in the queue is a user-input event (that is, a key
  1593.    or mouse-click event that is not a modifier key like shift) then it sets
  1594.    a flag to 1.
  1595.  */
  1596. static Bool
  1597. look_for_key_or_mouse_event (display, event, arg)
  1598.      Display *display;
  1599.      XEvent *event;
  1600.      XtPointer arg;
  1601. {
  1602.   switch (event->xany.type)
  1603.     {
  1604.     case KeyPress:
  1605.       if (x_key_is_modifier_p (event->xkey.keycode))
  1606.     break;
  1607.     case ButtonPress:
  1608.     case ButtonRelease:
  1609.       *((int *) arg) = 1;
  1610.       break;
  1611.     }
  1612.   return False;
  1613. }
  1614.  
  1615.  
  1616. #ifdef SIGIO
  1617. static void
  1618. emacs_Xt_event_sigio_handler ()
  1619. {
  1620.   if (x_input_blocked) return;
  1621.   if (!x_current_display) return; /* emacs is in the process of exiting */
  1622.   BLOCK_INPUT;
  1623.   x_check_for_interrupt_char (x_current_display);
  1624.   UNBLOCK_INPUT;
  1625. }
  1626. #endif
  1627.  
  1628.  
  1629. static Bool interrupt_char_predicate ();
  1630.  
  1631. /* This scans the X input queue for a KeyPress event that matches the
  1632.    interrupt character, and sets Vquit_flag.
  1633.  
  1634.    In a SIGIO world, this function is called from the SIGIO handler.  In
  1635.    a non-SIGIO world, this is called from emacs_Xt_event_pending_p (which
  1636.    is called from input_pending_p.)
  1637.  */
  1638. static void
  1639. x_check_for_interrupt_char (display)
  1640.      Display *display;
  1641. {
  1642.   XEvent event;
  1643.   BLOCK_INPUT;
  1644.   XEventsQueued (display, QueuedAfterReading);
  1645.   if (XCheckIfEvent (display, &event, interrupt_char_predicate, 0))
  1646.     {
  1647.       interrupt_signal (0);
  1648.       /* We have read a ^G.  If that is the only event in the queue, leave
  1649.      it there so that it is read immediately.  If there are other events
  1650.      in the queue (possibly ahead of it) it's ok to discard the ^G event
  1651.      itself, as Vquit_flag is now set.  If we leave the ^G in the queue
  1652.      with other events in front of it, then XCheckIfEvent will notice
  1653.      the ^G multiple times, which is no good.
  1654.        */
  1655.       if (! XEventsQueued (display, QueuedAlready))
  1656.     XPutBackEvent (display, &event);
  1657.     }
  1658.   UNBLOCK_INPUT;
  1659. }
  1660.  
  1661.  
  1662. static Bool
  1663. interrupt_char_predicate (display, event, data)
  1664.      Display *display;
  1665.      XEvent *event;
  1666.      char *data;
  1667. {
  1668.   char c;
  1669.   KeySym keysym;
  1670.   if (event->type != KeyPress) return 0;
  1671.   if (! x_any_window_to_screen (event->xany.window)) return 0;
  1672.   if (event->xkey.state & (MetaMask | HyperMask | SuperMask | SymbolMask))
  1673.     return 0;
  1674.  
  1675.   /* This duplicates some code that exists elsewhere, but it's relatively
  1676.      fast and doesn't cons (important, because this is called from inside
  1677.      the SIGIO interrupt, and there could easily be a GC in progress.)
  1678.    */
  1679.   keysym = x_to_emacs_keysym (event, 1);
  1680.   if (NILP (keysym)) return 0;
  1681.   if (FIXNUMP (keysym))
  1682.     c = XINT (keysym);
  1683.   /* Highly doubtful that these are the interrupt character, but... */
  1684.   else if (EQ (keysym, QKbackspace))    c = '\b';
  1685.   else if (EQ (keysym, QKtab))        c = '\t';
  1686.   else if (EQ (keysym, QKlinefeed))    c = '\n';
  1687.   else if (EQ (keysym, QKreturn))    c = '\r';
  1688.   else if (EQ (keysym, QKescape))    c = 27;
  1689.   else if (EQ (keysym, QKspace))    c = ' ';
  1690.   else if (EQ (keysym, QKdelete))    c = 127;
  1691.   else return 0;
  1692.  
  1693.   /* This makes Control-Shift-G the same as Control-G, which might be bad. */
  1694.   if (event->xkey.state & ControlMask)  c &= 0x1F;
  1695.   if (event->xkey.state & MetaMask)     c |= 0x80;
  1696.   return (c == interrupt_char);
  1697. }
  1698.  
  1699.  
  1700. extern struct event_stream *event_stream;
  1701.  
  1702. void
  1703. emacs_Xt_make_event_stream ()
  1704. {
  1705.   timeout_id_tick = 1;
  1706.   pending_timeouts = 0;
  1707.   completed_timeouts = 0;
  1708.  
  1709.   process_fds_with_input = (Lisp_Object *)
  1710.     xmalloc (MAX_PROC_FDS * sizeof (Lisp_Object));
  1711.   process_fds_to_input_ids = (XtInputId *)
  1712.     xmalloc (MAX_PROC_FDS * sizeof (XtInputId));
  1713.   memset (process_fds_to_input_ids, 0, MAX_PROC_FDS * sizeof (XtInputId));
  1714.   {
  1715.     int i;
  1716.     for (i = 0; i < MAX_PROC_FDS; i++) process_fds_with_input[i] = Qnil;
  1717.   }
  1718.   process_events_occurred = 0;
  1719.  
  1720.   x_compose_status = (XComposeStatus *) calloc (1, sizeof (XComposeStatus));
  1721.  
  1722.   event_stream = (struct event_stream *) malloc (sizeof (struct event_stream));
  1723.   event_stream->event_pending_p     = emacs_Xt_event_pending_p;
  1724.   event_stream->next_event_cb         = emacs_Xt_next_event;
  1725.   event_stream->handle_magic_event_cb    = emacs_Xt_handle_magic_event;
  1726.   event_stream->generate_wakeup_cb     = emacs_Xt_generate_wakeup;
  1727.   event_stream->disable_wakeup_cb     = emacs_Xt_disable_wakeup;
  1728.   event_stream->select_tty_cb         = emacs_Xt_select_tty;
  1729.   event_stream->unselect_tty_cb     = emacs_Xt_unselect_tty;
  1730.   event_stream->select_process_cb     = emacs_Xt_select_process;
  1731.   event_stream->unselect_process_cb     = emacs_Xt_unselect_process;
  1732. #ifdef SIGIO
  1733.   event_stream->sigio_cb        = emacs_Xt_event_sigio_handler;
  1734. #endif
  1735. }
  1736.