emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/src/xterm.c


From: Kenichi Handa
Subject: [Emacs-diffs] Changes to emacs/src/xterm.c
Date: Fri, 10 Jan 2003 02:22:04 -0500

Index: emacs/src/xterm.c
diff -c emacs/src/xterm.c:1.765 emacs/src/xterm.c:1.766
*** emacs/src/xterm.c:1.765     Sun Jan  5 19:45:31 2003
--- emacs/src/xterm.c   Wed Jan  8 15:06:05 2003
***************
*** 9934,9984 ****
  #endif /* not USE_TOOLKIT_SCROLL_BARS */
  }
  
- /* This processes Expose events from the menu-bar specific X event
-    loop in xmenu.c.  This allows to redisplay the frame if necessary
-    when handling menu-bar or pop-up items.  */
- 
- int
- process_expose_from_menu (event)
-      XEvent event;
- {
-   FRAME_PTR f;
-   struct x_display_info *dpyinfo;
-   int frame_exposed_p = 0;
- 
-   BLOCK_INPUT;
- 
-   dpyinfo = x_display_info_for_display (event.xexpose.display);
-   f = x_window_to_frame (dpyinfo, event.xexpose.window);
-   if (f)
-     {
-       if (f->async_visible == 0)
-       {
-         f->async_visible = 1;
-         f->async_iconified = 0;
-         f->output_data.x->has_been_visible = 1;
-         SET_FRAME_GARBAGED (f);
-       }
-       else
-       {
-         expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
-                       event.xexpose.x, event.xexpose.y,
-                       event.xexpose.width, event.xexpose.height);
-         frame_exposed_p = 1;
-       }
-     }
-   else
-     {
-       struct scroll_bar *bar
-       = x_window_to_scroll_bar (event.xexpose.window);
- 
-       if (bar)
-       x_scroll_bar_expose (bar, &event);
-     }
- 
-   UNBLOCK_INPUT;
-   return frame_exposed_p;
- }
  
  /* Define a queue to save up SelectionRequest events for later handling.  */
  
--- 9934,9939 ----
***************
*** 10107,10237 ****
  #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
  #define SET_SAVED_KEY_EVENT    SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
  
- /* Read events coming from the X server.
-    This routine is called by the SIGIO handler.
-    We return as soon as there are no more events to be read.
  
!    Events representing keys are stored in buffer BUFP,
!    which can hold up to NUMCHARS characters.
!    We return the number of characters stored into the buffer,
!    thus pretending to be `read'.
! 
!    EXPECTED is nonzero if the caller knows input is available.  */
  
  static int
! XTread_socket (sd, bufp, numchars, expected)
!      register int sd;
!      /* register */ struct input_event *bufp;
!      /* register */ int numchars;
!      int expected;
  {
    int count = 0;
    int nbytes = 0;
-   XEvent event;
    struct frame *f;
-   int event_found = 0;
-   struct x_display_info *dpyinfo;
    struct coding_system coding;
  
!   if (interrupt_input_blocked)
!     {
!       interrupt_input_pending = 1;
!       return -1;
!     }
  
!   interrupt_input_pending = 0;
!   BLOCK_INPUT;
! 
!   /* So people can tell when we have read the available input.  */
!   input_signal_count++;
! 
!   if (numchars <= 0)
!     abort ();                 /* Don't think this happens.  */
! 
!   ++handling_signal;
! 
!   /* Find the display we are supposed to read input for.
!      It's the one communicating on descriptor SD.  */
!   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
      {
! #if 0 /* This ought to be unnecessary; let's verify it.  */
! #ifdef FIOSNBIO
!       /* If available, Xlib uses FIOSNBIO to make the socket
!        non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
!        FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
!        a read returns 0, which Xlib interprets as equivalent to EPIPE.  */
!       fcntl (dpyinfo->connection, F_SETFL, 0);
! #endif /* ! defined (FIOSNBIO) */
! #endif
! 
! #if 0 /* This code can't be made to work, with multiple displays,
!        and appears not to be used on any system any more.
!        Also keyboard.c doesn't turn O_NDELAY on and off
!        for X connections.  */
! #ifndef SIGIO
! #ifndef HAVE_SELECT
!       if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
!       {
!         extern int read_alarm_should_throw;
!         read_alarm_should_throw = 1;
!         XPeekEvent (dpyinfo->display, &event);
!         read_alarm_should_throw = 0;
!       }
! #endif /* HAVE_SELECT */
! #endif /* SIGIO */
! #endif
! 
!       /* For debugging, this gives a way to fake an I/O error.  */
!       if (dpyinfo == XTread_socket_fake_io_error)
!       {
!         XTread_socket_fake_io_error = 0;
!         x_io_error_quitter (dpyinfo->display);
!       }
! 
! #ifdef HAVE_X_SM
!       BLOCK_INPUT;
!       count += x_session_check_input (bufp, &numchars);
!       UNBLOCK_INPUT;
! #endif
! 
!       while (XPending (dpyinfo->display))
!       {
!         XNextEvent (dpyinfo->display, &event);
! 
! #ifdef HAVE_X_I18N
!         {
!           /* Filter events for the current X input method.
!              XFilterEvent returns non-zero if the input method has
!              consumed the event.  We pass the frame's X window to
!              XFilterEvent because that's the one for which the IC
!              was created.  */
!           struct frame *f1 = x_any_window_to_frame (dpyinfo,
!                                                     event.xclient.window);
!           if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
!             break;
!         }
! #endif
!         event_found = 1;
! 
!         switch (event.type)
!           {
!           case ClientMessage:
!             {
!               if (event.xclient.message_type
!                   == dpyinfo->Xatom_wm_protocols
!                   && event.xclient.format == 32)
!                 {
!                   if (event.xclient.data.l[0]
!                       == dpyinfo->Xatom_wm_take_focus)
!                     {
!                       /* Use x_any_window_to_frame because this
!                          could be the shell widget window
!                          if the frame has no title bar.  */
!                       f = x_any_window_to_frame (dpyinfo, 
event.xclient.window);
  #ifdef HAVE_X_I18N
!                       /* Not quite sure this is needed -pd */
!                       if (f && FRAME_XIC (f))
!                         XSetICFocus (FRAME_XIC (f));
  #endif
  #if 0 /* Emacs sets WM hints whose `input' field is `true'.  This
         instructs the WM to set the input focus automatically for
--- 10062,10122 ----
  #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
  #define SET_SAVED_KEY_EVENT    SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
  
  
! enum
! {
!   X_EVENT_NORMAL,
!   X_EVENT_GOTO_OUT,
!   X_EVENT_DROP
! };
! 
! /* Handles the XEvent EVENT on display DPYINFO.
!    
!    *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
!    *FINISH is zero if caller should continue reading events.
!    *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
! 
!    Events representing keys are stored in buffer *BUFP_R,
!    which can hold up to *NUMCHARSP characters.
!    We return the number of characters stored into the buffer. */
  
  static int
! handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
!      struct x_display_info *dpyinfo;
!      XEvent *eventp;
!      /* register */ struct input_event **bufp_r;
!      /* register */ int *numcharsp;
!      int *finish;
  {
    int count = 0;
    int nbytes = 0;
    struct frame *f;
    struct coding_system coding;
+   struct input_event *bufp = *bufp_r;
+   int numchars = *numcharsp;
+   XEvent event = *eventp;
  
!   *finish = X_EVENT_NORMAL;
  
!   switch (event.type)
      {
!     case ClientMessage:
!       {
!         if (event.xclient.message_type
!             == dpyinfo->Xatom_wm_protocols
!             && event.xclient.format == 32)
!           {
!             if (event.xclient.data.l[0]
!                 == dpyinfo->Xatom_wm_take_focus)
!               {
!                 /* Use x_any_window_to_frame because this
!                    could be the shell widget window
!                    if the frame has no title bar.  */
!                 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
  #ifdef HAVE_X_I18N
!                 /* Not quite sure this is needed -pd */
!                 if (f && FRAME_XIC (f))
!                   XSetICFocus (FRAME_XIC (f));
  #endif
  #if 0 /* Emacs sets WM hints whose `input' field is `true'.  This
         instructs the WM to set the input focus automatically for
***************
*** 10246,11410 ****
         below can generate additional FocusIn events which confuse
         Emacs.  */
  
!                       /* Since we set WM_TAKE_FOCUS, we must call
!                          XSetInputFocus explicitly.  But not if f is null,
!                          since that might be an event for a deleted frame.  */
!                       if (f)
!                         {
!                           Display *d = event.xclient.display;
!                           /* Catch and ignore errors, in case window has been
!                              iconified by a window manager such as GWM.  */
!                           int count = x_catch_errors (d);
!                           XSetInputFocus (d, event.xclient.window,
!                                           /* The ICCCM says this is
!                                              the only valid choice.  */
!                                           RevertToParent,
!                                           event.xclient.data.l[1]);
!                           /* This is needed to detect the error
!                              if there is an error.  */
!                           XSync (d, False);
!                           x_uncatch_errors (d, count);
!                         }
!                       /* Not certain about handling scroll bars here */
  #endif /* 0 */
!                     }
!                   else if (event.xclient.data.l[0]
!                            == dpyinfo->Xatom_wm_save_yourself)
!                     {
!                       /* Save state modify the WM_COMMAND property to
!                          something which can reinstate us.  This notifies
!                          the session manager, who's looking for such a
!                          PropertyNotify.  Can restart processing when
!                          a keyboard or mouse event arrives.  */
!                         /* If we have a session manager, don't set this.
!                            KDE will then start two Emacsen, one for the
!                            session manager and one for this. */
!                       if (numchars > 0
  #ifdef HAVE_X_SM
!                             && ! x_session_have_connection ()
  #endif
!                             )
!                         {
!                           f = x_top_window_to_frame (dpyinfo,
!                                                      event.xclient.window);
!                           /* This is just so we only give real data once
!                              for a single Emacs process.  */
!                           if (f == SELECTED_FRAME ())
!                             XSetCommand (FRAME_X_DISPLAY (f),
!                                          event.xclient.window,
!                                          initial_argv, initial_argc);
!                           else if (f)
!                             XSetCommand (FRAME_X_DISPLAY (f),
!                                          event.xclient.window,
!                                          0, 0);
!                         }
!                     }
!                   else if (event.xclient.data.l[0]
!                            == dpyinfo->Xatom_wm_delete_window)
!                     {
!                       struct frame *f
!                         = x_any_window_to_frame (dpyinfo,
!                                                  event.xclient.window);
! 
!                       if (f)
!                         {
!                           if (numchars == 0)
!                             abort ();
! 
!                           bufp->kind = DELETE_WINDOW_EVENT;
!                           XSETFRAME (bufp->frame_or_window, f);
!                           bufp->arg = Qnil;
!                           bufp++;
! 
!                           count += 1;
!                           numchars -= 1;
!                         }
!                     }
!                 }
!               else if (event.xclient.message_type
!                        == dpyinfo->Xatom_wm_configure_denied)
!                 {
!                 }
!               else if (event.xclient.message_type
!                        == dpyinfo->Xatom_wm_window_moved)
!                 {
!                   int new_x, new_y;
!                   struct frame *f
!                     = x_window_to_frame (dpyinfo, event.xclient.window);
! 
!                   new_x = event.xclient.data.s[0];
!                   new_y = event.xclient.data.s[1];
! 
!                   if (f)
!                     {
!                       f->output_data.x->left_pos = new_x;
!                       f->output_data.x->top_pos = new_y;
!                     }
!                 }
  #ifdef HACK_EDITRES
!               else if (event.xclient.message_type
!                        == dpyinfo->Xatom_editres)
!                 {
!                   struct frame *f
!                     = x_any_window_to_frame (dpyinfo, event.xclient.window);
!                   _XEditResCheckMessages (f->output_data.x->widget, NULL,
!                                           &event, NULL);
!                 }
  #endif /* HACK_EDITRES */
!               else if ((event.xclient.message_type
!                         == dpyinfo->Xatom_DONE)
!                        || (event.xclient.message_type
!                            == dpyinfo->Xatom_PAGE))
!                 {
!                   /* Ghostview job completed.  Kill it.  We could
!                      reply with "Next" if we received "Page", but we
!                      currently never do because we are interested in
!                      images, only, which should have 1 page.  */
!                   Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
!                   struct frame *f
!                     = x_window_to_frame (dpyinfo, event.xclient.window);
!                   x_kill_gs_process (pixmap, f);
!                   expose_frame (f, 0, 0, 0, 0);
!                 }
  #ifdef USE_TOOLKIT_SCROLL_BARS
!               /* Scroll bar callbacks send a ClientMessage from which
!                  we construct an input_event.  */
!               else if (event.xclient.message_type
!                        == dpyinfo->Xatom_Scrollbar)
!                 {
!                   x_scroll_bar_to_input_event (&event, bufp);
!                   ++bufp, ++count, --numchars;
!                   goto out;
!                 }
  #endif /* USE_TOOLKIT_SCROLL_BARS */
!               else
!                 goto OTHER;
!             }
!             break;
  
!           case SelectionNotify:
  #ifdef USE_X_TOOLKIT
!             if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
!               goto OTHER;
  #endif /* not USE_X_TOOLKIT */
!             x_handle_selection_notify (&event.xselection);
!             break;
  
!           case SelectionClear:        /* Someone has grabbed ownership.  */
  #ifdef USE_X_TOOLKIT
!             if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
!               goto OTHER;
  #endif /* USE_X_TOOLKIT */
!             {
!               XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
  
!               if (numchars == 0)
!                 abort ();
  
!               bufp->kind = SELECTION_CLEAR_EVENT;
!               SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
!               SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
!               SELECTION_EVENT_TIME (bufp) = eventp->time;
!               bufp->frame_or_window = Qnil;
!               bufp->arg = Qnil;
!               bufp++;
! 
!               count += 1;
!               numchars -= 1;
!             }
!             break;
  
!           case SelectionRequest:      /* Someone wants our selection.  */
  #ifdef USE_X_TOOLKIT
!             if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
!               goto OTHER;
  #endif /* USE_X_TOOLKIT */
!             if (x_queue_selection_requests)
!               x_queue_event (x_window_to_frame (dpyinfo, 
event.xselectionrequest.owner),
!                              &event);
!             else
!               {
!                 XSelectionRequestEvent *eventp
!                   = (XSelectionRequestEvent *) &event;
! 
!                 if (numchars == 0)
!                   abort ();
! 
!                 bufp->kind = SELECTION_REQUEST_EVENT;
!                 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
!                 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
!                 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
!                 SELECTION_EVENT_TARGET (bufp) = eventp->target;
!                 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
!                 SELECTION_EVENT_TIME (bufp) = eventp->time;
!                 bufp->frame_or_window = Qnil;
!                 bufp->arg = Qnil;
!                 bufp++;
! 
!                 count += 1;
!                 numchars -= 1;
!               }
!             break;
  
!           case PropertyNotify:
  #if 0 /* This is plain wrong.  In the case that we are waiting for a
         PropertyNotify used as an ACK in incremental selection
         transfer, the property will be on the receiver's window.  */
  #if defined USE_X_TOOLKIT
!             if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
!               goto OTHER;
  #endif
  #endif
!             x_handle_property_notify (&event.xproperty);
!             goto OTHER;
  
!           case ReparentNotify:
!             f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
!             if (f)
!               {
!                 int x, y;
!                 f->output_data.x->parent_desc = event.xreparent.parent;
!                 x_real_positions (f, &x, &y);
!                 f->output_data.x->left_pos = x;
!                 f->output_data.x->top_pos = y;
!                   goto OTHER;
!               }
!             break;
! 
!           case Expose:
!             f = x_window_to_frame (dpyinfo, event.xexpose.window);
!             if (f)
!               {
!                   x_check_fullscreen (f);
! 
!                 if (f->async_visible == 0)
!                   {
!                     f->async_visible = 1;
!                     f->async_iconified = 0;
!                     f->output_data.x->has_been_visible = 1;
!                     SET_FRAME_GARBAGED (f);
!                   }
!                 else
!                   expose_frame (x_window_to_frame (dpyinfo,
!                                                    event.xexpose.window),
!                                 event.xexpose.x, event.xexpose.y,
!                                 event.xexpose.width, event.xexpose.height);
!               }
!             else
!               {
  #ifndef USE_TOOLKIT_SCROLL_BARS
!                 struct scroll_bar *bar;
  #endif
  #if defined USE_LUCID
!                 /* Submenus of the Lucid menu bar aren't widgets
!                    themselves, so there's no way to dispatch events
!                    to them.  Recognize this case separately.  */
!                 {
!                   Widget widget
!                     = x_window_to_menu_bar (event.xexpose.window);
!                   if (widget)
!                     xlwmenu_redisplay (widget);
!                 }
  #endif /* USE_LUCID */
  
  #ifdef USE_TOOLKIT_SCROLL_BARS
!                 /* Dispatch event to the widget.  */
!                 goto OTHER;
  #else /* not USE_TOOLKIT_SCROLL_BARS */
!                 bar = x_window_to_scroll_bar (event.xexpose.window);
  
!                 if (bar)
!                   x_scroll_bar_expose (bar, &event);
  #ifdef USE_X_TOOLKIT
!                 else
!                   goto OTHER;
  #endif /* USE_X_TOOLKIT */
  #endif /* not USE_TOOLKIT_SCROLL_BARS */
!               }
!             break;
  
!           case GraphicsExpose:        /* This occurs when an XCopyArea's
!                                          source area was obscured or not
!                                          available.  */
!             f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
!             if (f)
!               {
!                 expose_frame (f,
!                               event.xgraphicsexpose.x, 
event.xgraphicsexpose.y,
!                               event.xgraphicsexpose.width,
!                               event.xgraphicsexpose.height);
!               }
  #ifdef USE_X_TOOLKIT
!             else
!               goto OTHER;
  #endif /* USE_X_TOOLKIT */
!             break;
! 
!           case NoExpose:              /* This occurs when an XCopyArea's
!                                          source area was completely
!                                          available.  */
!             break;
  
!           case UnmapNotify:
!             /* Redo the mouse-highlight after the tooltip has gone.  */
!             if (event.xmap.window == tip_window)
!               {
!                 tip_window = 0;
!                 redo_mouse_highlight ();
!               }
! 
!             f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
!             if (f)            /* F may no longer exist if
!                                  the frame was deleted.  */
!               {
!                 /* While a frame is unmapped, display generation is
!                    disabled; you don't want to spend time updating a
!                    display that won't ever be seen.  */
!                 f->async_visible = 0;
!                 /* We can't distinguish, from the event, whether the window
!                    has become iconified or invisible.  So assume, if it
!                    was previously visible, than now it is iconified.
!                    But x_make_frame_invisible clears both
!                    the visible flag and the iconified flag;
!                    and that way, we know the window is not iconified now.  */
!                 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
!                   {
!                     f->async_iconified = 1;
! 
!                     bufp->kind = ICONIFY_EVENT;
!                     XSETFRAME (bufp->frame_or_window, f);
!                     bufp->arg = Qnil;
!                     bufp++;
!                     count++;
!                     numchars--;
!                   }
!               }
!             goto OTHER;
! 
!           case MapNotify:
!             if (event.xmap.window == tip_window)
!               /* The tooltip has been drawn already.  Avoid
!                  the SET_FRAME_GARBAGED below.  */
!               goto OTHER;
! 
!             /* We use x_top_window_to_frame because map events can
!                come for sub-windows and they don't mean that the
!                frame is visible.  */
!             f = x_top_window_to_frame (dpyinfo, event.xmap.window);
!             if (f)
!               {
!                 f->async_visible = 1;
!                 f->async_iconified = 0;
!                 f->output_data.x->has_been_visible = 1;
! 
!                 /* wait_reading_process_input will notice this and update
!                    the frame's display structures.  */
!                 SET_FRAME_GARBAGED (f);
! 
!                 if (f->iconified)
!                   {
!                     bufp->kind = DEICONIFY_EVENT;
!                     XSETFRAME (bufp->frame_or_window, f);
!                     bufp->arg = Qnil;
!                     bufp++;
!                     count++;
!                     numchars--;
!                   }
!                 else if (! NILP (Vframe_list)
!                          && ! NILP (XCDR (Vframe_list)))
!                   /* Force a redisplay sooner or later
!                      to update the frame titles
!                      in case this is the second frame.  */
!                   record_asynch_buffer_change ();
!               }
!             goto OTHER;
! 
!           case KeyPress:
! 
!             /* Dispatch KeyPress events when in menu.  */
!             if (popup_activated_flag)
!                goto OTHER;
! 
!             f = x_any_window_to_frame (dpyinfo, event.xkey.window);
! 
!             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
!               {
!                 dpyinfo->mouse_face_hidden = 1;
!                 clear_mouse_face (dpyinfo);
!               }
  
  #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
!             if (f == 0)
!               {
!                 /* Scroll bars consume key events, but we want
!                    the keys to go to the scroll bar's frame.  */
!                 Widget widget = XtWindowToWidget (dpyinfo->display,
!                                                   event.xkey.window);
!                 if (widget && XmIsScrollBar (widget))
!                   {
!                     widget = XtParent (widget);
!                     f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
!                   }
!               }
  #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
  
!             if (f != 0)
!               {
!                 KeySym keysym, orig_keysym;
!                 /* address@hidden says that making this 81
!                    instead of 80 fixed a bug whereby meta chars made
!                    his Emacs hang.
! 
!                    It seems that some version of XmbLookupString has
!                    a bug of not returning XBufferOverflow in
!                    status_return even if the input is too long to
!                    fit in 81 bytes.  So, we must prepare sufficient
!                    bytes for copy_buffer.  513 bytes (256 chars for
!                    two-byte character set) seems to be a fairly good
!                    approximation.  -- 2000.8.10 address@hidden  */
!                 unsigned char copy_buffer[513];
!                 unsigned char *copy_bufptr = copy_buffer;
!                 int copy_bufsiz = sizeof (copy_buffer);
!                 int modifiers;
!                 Lisp_Object coding_system = Qlatin_1;
! 
!                 event.xkey.state
!                   |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                              extra_keyboard_modifiers);
!                 modifiers = event.xkey.state;
! 
!                 /* This will have to go some day...  */
! 
!                 /* make_lispy_event turns chars into control chars.
!                    Don't do it here because XLookupString is too eager.  */
!                 event.xkey.state &= ~ControlMask;
!                 event.xkey.state &= ~(dpyinfo->meta_mod_mask
!                                       | dpyinfo->super_mod_mask
!                                       | dpyinfo->hyper_mod_mask
!                                       | dpyinfo->alt_mod_mask);
! 
!                 /* In case Meta is ComposeCharacter,
!                    clear its status.  According to Markus Ehrnsperger
!                    address@hidden
!                    this enables ComposeCharacter to work whether or
!                    not it is combined with Meta.  */
!                 if (modifiers & dpyinfo->meta_mod_mask)
!                   bzero (&compose_status, sizeof (compose_status));
  
  #ifdef HAVE_X_I18N
!                 if (FRAME_XIC (f))
!                   {
!                     Status status_return;
! 
!                     coding_system = Vlocale_coding_system;
!                     nbytes = XmbLookupString (FRAME_XIC (f),
!                                               &event.xkey, copy_bufptr,
!                                               copy_bufsiz, &keysym,
!                                               &status_return);
!                     if (status_return == XBufferOverflow)
!                       {
!                         copy_bufsiz = nbytes + 1;
!                         copy_bufptr = (char *) alloca (copy_bufsiz);
!                         nbytes = XmbLookupString (FRAME_XIC (f),
!                                                   &event.xkey, copy_bufptr,
!                                                   copy_bufsiz, &keysym,
!                                                   &status_return);
!                       }
! /* Xutf8LookupString is a new but already deprecated interface.  -stef  */
  #if 0 && defined X_HAVE_UTF8_STRING
!                     else if (status_return == XLookupKeySym)
!                       {  /* Try again but with utf-8.  */
!                         coding_system = Qutf_8;
!                         nbytes = Xutf8LookupString (FRAME_XIC (f),
!                                                     &event.xkey, copy_bufptr,
!                                                     copy_bufsiz, &keysym,
!                                                     &status_return);
!                         if (status_return == XBufferOverflow)
!                           {
!                             copy_bufsiz = nbytes + 1;
!                             copy_bufptr = (char *) alloca (copy_bufsiz);
!                             nbytes = Xutf8LookupString (FRAME_XIC (f),
!                                                         &event.xkey,
!                                                         copy_bufptr,
!                                                         copy_bufsiz, &keysym,
!                                                         &status_return);
!                           }
!                       }
! #endif
! 
!                     if (status_return == XLookupNone)
!                       break;
!                     else if (status_return == XLookupChars)
!                       {
!                         keysym = NoSymbol;
!                         modifiers = 0;
!                       }
!                     else if (status_return != XLookupKeySym
!                              && status_return != XLookupBoth)
!                       abort ();
!                   }
!                 else
!                   nbytes = XLookupString (&event.xkey, copy_bufptr,
!                                           copy_bufsiz, &keysym,
!                                           &compose_status);
  #else
!                 nbytes = XLookupString (&event.xkey, copy_bufptr,
!                                         copy_bufsiz, &keysym,
!                                         &compose_status);
! #endif
! 
!                 orig_keysym = keysym;
! 
!                 if (numchars > 1)
!                   {
!                     Lisp_Object c;
! 
!                     /* First deal with keysyms which have defined
!                        translations to characters.  */
!                     if (keysym >= 32 && keysym < 128)
!                       /* Avoid explicitly decoding each ASCII character.  */
!                       {
!                         bufp->kind = ASCII_KEYSTROKE_EVENT;
!                         bufp->code = keysym;
!                         XSETFRAME (bufp->frame_or_window, f);
!                         bufp->arg = Qnil;
!                         bufp->modifiers
!                           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                                     modifiers);
!                         bufp->timestamp = event.xkey.time;
!                         bufp++;
!                         count++;
!                         numchars--;
!                       }
!                     /* Now non-ASCII.  */
!                     else if (HASH_TABLE_P (Vx_keysym_table)
!                              && (NATNUMP (c = Fgethash (make_number (keysym),
!                                                         Vx_keysym_table,
!                                                         Qnil))))
!                       {
!                         bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
!                                       ? ASCII_KEYSTROKE_EVENT
!                                       : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
!                         bufp->code = XFASTINT (c);
!                         XSETFRAME (bufp->frame_or_window, f);
!                         bufp->arg = Qnil;
!                         bufp->modifiers
!                           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                                     modifiers);
!                         bufp->timestamp = event.xkey.time;
!                         bufp++;
!                         count++;
!                         numchars--;
!                       }
!                     /* Random non-modifier sorts of keysyms.  */
!                     else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
!                               || keysym == XK_Delete
  #ifdef XK_ISO_Left_Tab
!                               || (keysym >= XK_ISO_Left_Tab
!                                   && keysym <= XK_ISO_Enter)
  #endif
!                               || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 
*/
!                               || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 
VARIES */
  #ifdef HPUX
!                               /* This recognizes the "extended function
!                                  keys".  It seems there's no cleaner way.
!                                  Test IsModifierKey to avoid handling
!                                  mode_switch incorrectly.  */
!                               || ((unsigned) (keysym) >= XK_Select
!                                   && (unsigned)(keysym) < XK_KP_Space)
  #endif
  #ifdef XK_dead_circumflex
!                               || orig_keysym == XK_dead_circumflex
  #endif
  #ifdef XK_dead_grave
!                               || orig_keysym == XK_dead_grave
  #endif
  #ifdef XK_dead_tilde
!                               || orig_keysym == XK_dead_tilde
  #endif
  #ifdef XK_dead_diaeresis
!                               || orig_keysym == XK_dead_diaeresis
  #endif
  #ifdef XK_dead_macron
!                               || orig_keysym == XK_dead_macron
  #endif
  #ifdef XK_dead_degree
!                               || orig_keysym == XK_dead_degree
  #endif
  #ifdef XK_dead_acute
!                               || orig_keysym == XK_dead_acute
  #endif
  #ifdef XK_dead_cedilla
!                               || orig_keysym == XK_dead_cedilla
  #endif
  #ifdef XK_dead_breve
!                               || orig_keysym == XK_dead_breve
  #endif
  #ifdef XK_dead_ogonek
!                               || orig_keysym == XK_dead_ogonek
  #endif
  #ifdef XK_dead_caron
!                               || orig_keysym == XK_dead_caron
  #endif
  #ifdef XK_dead_doubleacute
!                               || orig_keysym == XK_dead_doubleacute
  #endif
  #ifdef XK_dead_abovedot
!                               || orig_keysym == XK_dead_abovedot
  #endif
!                               || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe 
*/
!                               || IsFunctionKey (keysym) /* 0xffbe <= x < 
0xffe1 */
!                               /* Any "vendor-specific" key is ok.  */
!                               || (orig_keysym & (1 << 28))
!                               || (keysym != NoSymbol && nbytes == 0))
!                              && ! (IsModifierKey (orig_keysym)
  #ifndef HAVE_X11R5
  #ifdef XK_Mode_switch
!                                    || ((unsigned)(orig_keysym) == 
XK_Mode_switch)
  #endif
  #ifdef XK_Num_Lock
!                                    || ((unsigned)(orig_keysym) == XK_Num_Lock)
  #endif
  #endif /* not HAVE_X11R5 */
!                                    /* The symbols from XK_ISO_Lock
!                                       to XK_ISO_Last_Group_Lock
!                                       don't have real modifiers but
!                                       should be treated similarly to
!                                       Mode_switch by Emacs. */
  #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
!                                    || ((unsigned)(orig_keysym)
!                                        >=  XK_ISO_Lock
!                                        && (unsigned)(orig_keysym)
!                                        <= XK_ISO_Last_Group_Lock)
! #endif
!                                    ))
!                       {
!                         if (temp_index == sizeof temp_buffer / sizeof (short))
!                           temp_index = 0;
!                         temp_buffer[temp_index++] = keysym;
!                         /* make_lispy_event will convert this to a symbolic
!                            key.  */
!                         bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
!                         bufp->code = keysym;
!                         XSETFRAME (bufp->frame_or_window, f);
!                         bufp->arg = Qnil;
!                         bufp->modifiers
!                           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                                     modifiers);
!                         bufp->timestamp = event.xkey.time;
!                         bufp++;
!                         count++;
!                         numchars--;
!                       }
!                     else if (numchars > nbytes)
!                       {       /* Raw bytes, not keysym.  */
!                         register int i;
!                         register int c;
!                         int nchars, len;
! 
!                         /* The input should be decoded with `coding_system'
!                            which depends on which X*LookupString function
!                            we used just above and the locale.  */
!                         setup_coding_system (coding_system, &coding);
!                         coding.src_multibyte = 0;
!                         coding.dst_multibyte = 1;
!                         /* The input is converted to events, thus we can't
!                            handle composition.  Anyway, there's no XIM that
!                            gives us composition information.  */
!                         coding.composing = COMPOSITION_DISABLED;
! 
!                         for (i = 0; i < nbytes; i++)
!                           {
!                             if (temp_index == (sizeof temp_buffer
!                                                / sizeof (short)))
!                               temp_index = 0;
!                             temp_buffer[temp_index++] = copy_bufptr[i];
!                           }
! 
!                         {
!                           /* Decode the input data.  */
!                           int require;
!                           unsigned char *p;
! 
!                           require = decoding_buffer_size (&coding, nbytes);
!                           p = (unsigned char *) alloca (require);
!                           coding.mode |= CODING_MODE_LAST_BLOCK;
!                           /* We explicitely disable composition
!                              handling because key data should
!                              not contain any composition
!                              sequence.  */
!                           coding.composing = COMPOSITION_DISABLED;
!                           decode_coding (&coding, copy_bufptr, p,
!                                          nbytes, require);
!                           nbytes = coding.produced;
!                           nchars = coding.produced_char;
!                           copy_bufptr = p;
!                         }
! 
!                         /* Convert the input data to a sequence of
!                            character events.  */
!                         for (i = 0; i < nbytes; i += len)
!                           {
!                             if (nchars == nbytes)
!                               c = copy_bufptr[i], len = 1;
!                             else
!                               c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
!                                                           nbytes - i, len);
! 
!                             bufp->kind = (SINGLE_BYTE_CHAR_P (c)
!                                           ? ASCII_KEYSTROKE_EVENT
!                                           : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
!                             bufp->code = c;
!                             XSETFRAME (bufp->frame_or_window, f);
!                             bufp->arg = Qnil;
!                             bufp->modifiers
!                               = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO 
(f),
!                                                         modifiers);
!                             bufp->timestamp = event.xkey.time;
!                             bufp++;
!                           }
! 
!                         count += nchars;
!                         numchars -= nchars;
! 
!                         if (keysym == NoSymbol)
!                           break;
!                       }
!                     else
!                       abort ();
!                   }
!                 else
!                   abort ();
!               }
  #ifdef HAVE_X_I18N
!             /* Don't dispatch this event since XtDispatchEvent calls
!                XFilterEvent, and two calls in a row may freeze the
!                client.  */
!             break;
  #else
!             goto OTHER;
  #endif
  
!           case KeyRelease:
  #ifdef HAVE_X_I18N
!             /* Don't dispatch this event since XtDispatchEvent calls
!                XFilterEvent, and two calls in a row may freeze the
!                client.  */
!             break;
  #else
!             goto OTHER;
  #endif
  
!           case EnterNotify:
!             {
!                 int n;
  
!                 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
!                 if (n > 0)
!                 {
!                   bufp += n, count += n, numchars -= n;
!                 }
  
!               f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
  
  #if 0
!               if (event.xcrossing.focus)
!                 {
!                   /* Avoid nasty pop/raise loops.  */
!                   if (f && (!(f->auto_raise)
!                             || !(f->auto_lower)
!                             || (event.xcrossing.time - enter_timestamp) > 
500))
!                     {
!                       x_new_focus_frame (dpyinfo, f);
!                       enter_timestamp = event.xcrossing.time;
!                     }
!                 }
!               else if (f == dpyinfo->x_focus_frame)
!                 x_new_focus_frame (dpyinfo, 0);
! #endif
! 
!               /* EnterNotify counts as mouse movement,
!                  so update things that depend on mouse position.  */
!               if (f && !f->output_data.x->hourglass_p)
!                 note_mouse_movement (f, &event.xmotion);
!               goto OTHER;
!             }
! 
!           case FocusIn:
                {
!                 int n;
! 
!                 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
!                 if (n > 0)
!                   {
!                     bufp += n, count += n, numchars -= n;
!                   }
                }
  
!             goto OTHER;
  
!           case LeaveNotify:
                {
!                 int n;
! 
!                 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
!                 if (n > 0)
!                 {
!                   bufp += n, count += n, numchars -= n;
!                 }
!               }
! 
!             f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
!             if (f)
!               {
!                 if (f == dpyinfo->mouse_face_mouse_frame)
!                   {
!                     /* If we move outside the frame, then we're
!                        certainly no longer on any text in the frame.  */
!                     clear_mouse_face (dpyinfo);
!                     dpyinfo->mouse_face_mouse_frame = 0;
!                   }
! 
!                 /* Generate a nil HELP_EVENT to cancel a help-echo.
!                    Do it only if there's something to cancel.
!                    Otherwise, the startup message is cleared when
!                    the mouse leaves the frame.  */
!                 if (any_help_event_p)
!                   {
!                     Lisp_Object frame;
!                     int n;
! 
!                     XSETFRAME (frame, f);
!                     help_echo = Qnil;
!                     n = gen_help_event (bufp, numchars,
!                                         Qnil, frame, Qnil, Qnil, 0);
!                     bufp += n, count += n, numchars -= n;
!                   }
  
!               }
!             goto OTHER;
! 
!           case FocusOut:
!               {
!                 int n;
  
!                 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
!                 if (n > 0)
!                 {
!                   bufp += n, count += n, numchars -= n;
!                 }
                }
! 
!             goto OTHER;
! 
!           case MotionNotify:
!             {
!               previous_help_echo = help_echo;
!               help_echo = help_echo_object = help_echo_window = Qnil;
!               help_echo_pos = -1;
! 
!               if (dpyinfo->grabbed && last_mouse_frame
!                   && FRAME_LIVE_P (last_mouse_frame))
!                 f = last_mouse_frame;
!               else
!                 f = x_window_to_frame (dpyinfo, event.xmotion.window);
! 
!               if (dpyinfo->mouse_face_hidden)
!                 {
!                   dpyinfo->mouse_face_hidden = 0;
!                   clear_mouse_face (dpyinfo);
!                 }
! 
!               if (f)
!                 {
! 
!                   /* Generate SELECT_WINDOW_EVENTs when needed.  */
!                   if (mouse_autoselect_window)
!                     {
!                       Lisp_Object window;
!                       int area;
! 
!                       window = window_from_coordinates (f,
!                                                         event.xmotion.x, 
event.xmotion.y,
!                                                         &area, 0);
! 
!                       /* Window will be selected only when it is not selected 
now and
!                          last mouse movement event was not in it.  Minibuffer 
window
!                          will be selected iff it is active.  */
!                       if (WINDOWP(window)
!                           && !EQ (window, last_window)
!                           && !EQ (window, selected_window)
!                           && numchars > 0)
!                         {
!                           bufp->kind = SELECT_WINDOW_EVENT;
!                           bufp->frame_or_window = window;
!                           bufp->arg = Qnil;
!                           ++bufp, ++count, --numchars;
!                         }
! 
!                       last_window=window;
!                     }
!                   note_mouse_movement (f, &event.xmotion);
!                 }
!               else
!                 {
  #ifndef USE_TOOLKIT_SCROLL_BARS
!                   struct scroll_bar *bar
!                     = x_window_to_scroll_bar (event.xmotion.window);
  
!                   if (bar)
!                     x_scroll_bar_note_movement (bar, &event);
  #endif /* USE_TOOLKIT_SCROLL_BARS */
  
!                   /* If we move outside the frame, then we're
!                      certainly no longer on any text in the frame.  */
!                   clear_mouse_face (dpyinfo);
!                 }
! 
!               /* If the contents of the global variable help_echo
!                  has changed, generate a HELP_EVENT.  */
!               if (!NILP (help_echo)
!                   || !NILP (previous_help_echo))
!                 {
!                   Lisp_Object frame;
!                   int n;
! 
!                   if (f)
!                     XSETFRAME (frame, f);
!                   else
!                     frame = Qnil;
! 
!                   any_help_event_p = 1;
!                   n = gen_help_event (bufp, numchars, help_echo, frame,
!                                       help_echo_window, help_echo_object,
!                                       help_echo_pos);
!                   bufp += n, count += n, numchars -= n;
!                 }
! 
!               goto OTHER;
!             }
! 
!           case ConfigureNotify:
!             f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
!             if (f)
!               {
  #ifndef USE_X_TOOLKIT
!                   /* If there is a pending resize for fullscreen, don't
!                      do this one, the right one will come later.
!                    The toolkit version doesn't seem to need this, but we
!                    need to reset it below.  */
!                   int dont_resize =
!                     ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
!                      && FRAME_NEW_WIDTH (f) != 0);
!                 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
!                 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
!                   if (dont_resize)
!                     goto OTHER;
! 
!                 /* In the toolkit version, change_frame_size
!                    is called by the code that handles resizing
!                    of the EmacsFrame widget.  */
! 
!                 /* Even if the number of character rows and columns has
!                    not changed, the font size may have changed, so we need
!                    to check the pixel dimensions as well.  */
!                 if (columns != f->width
!                     || rows != f->height
!                     || event.xconfigure.width != f->output_data.x->pixel_width
!                     || event.xconfigure.height != 
f->output_data.x->pixel_height)
!                   {
!                     change_frame_size (f, rows, columns, 0, 1, 0);
!                     SET_FRAME_GARBAGED (f);
!                     cancel_mouse_face (f);
!                   }
! #endif
! 
!                 f->output_data.x->pixel_width = event.xconfigure.width;
!                 f->output_data.x->pixel_height = event.xconfigure.height;
! 
!                 /* What we have now is the position of Emacs's own window.
!                    Convert that to the position of the window manager window. 
 */
!                 x_real_positions (f, &f->output_data.x->left_pos,
!                                   &f->output_data.x->top_pos);
! 
!                   x_check_fullscreen_move(f);
!                   if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
!                     f->output_data.x->want_fullscreen &=
!                       ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
  #ifdef HAVE_X_I18N
!                 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
!                   xic_set_statusarea (f);
  #endif
  
!                 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO 
(f)->root_window)
!                   {
!                     /* Since the WM decorations come below top_pos now,
!                        we must put them below top_pos in the future.  */
!                     f->output_data.x->win_gravity = NorthWestGravity;
!                     x_wm_set_size_hint (f, (long) 0, 0);
!                   }
!               }
!             goto OTHER;
! 
!           case ButtonPress:
!           case ButtonRelease:
!             {
!               /* If we decide we want to generate an event to be seen
!                  by the rest of Emacs, we put it here.  */
!               struct input_event emacs_event;
!               int tool_bar_p = 0;
! 
!               emacs_event.kind = NO_EVENT;
!               bzero (&compose_status, sizeof (compose_status));
! 
!               if (dpyinfo->grabbed
!                   && last_mouse_frame
!                   && FRAME_LIVE_P (last_mouse_frame))
!                 f = last_mouse_frame;
!               else
!                 f = x_window_to_frame (dpyinfo, event.xbutton.window);
! 
!               if (f)
!                 {
!                   /* Is this in the tool-bar?  */
!                   if (WINDOWP (f->tool_bar_window)
!                       && XFASTINT (XWINDOW (f->tool_bar_window)->height))
!                     {
!                       Lisp_Object window;
!                       int p, x, y;
! 
!                       x = event.xbutton.x;
!                       y = event.xbutton.y;
! 
!                       /* Set x and y.  */
!                       window = window_from_coordinates (f, x, y, &p, 1);
!                       if (EQ (window, f->tool_bar_window))
!                         {
!                           x_handle_tool_bar_click (f, &event.xbutton);
!                           tool_bar_p = 1;
!                         }
!                     }
! 
!                   if (!tool_bar_p)
!                     if (!dpyinfo->x_focus_frame
!                         || f == dpyinfo->x_focus_frame)
!                       construct_mouse_click (&emacs_event, &event, f);
!                 }
!               else
!                 {
  #ifndef USE_TOOLKIT_SCROLL_BARS
!                   struct scroll_bar *bar
!                     = x_window_to_scroll_bar (event.xbutton.window);
  
!                   if (bar)
!                     x_scroll_bar_handle_click (bar, &event, &emacs_event);
  #endif /* not USE_TOOLKIT_SCROLL_BARS */
!                 }
  
!               if (event.type == ButtonPress)
!                 {
!                   dpyinfo->grabbed |= (1 << event.xbutton.button);
!                   last_mouse_frame = f;
!                   /* Ignore any mouse motion that happened
!                      before this event; any subsequent mouse-movement
!                      Emacs events should reflect only motion after
!                      the ButtonPress.  */
!                   if (f != 0)
!                     f->mouse_moved = 0;
! 
!                   if (!tool_bar_p)
!                     last_tool_bar_item = -1;
!                 }
!               else
!                 {
!                   dpyinfo->grabbed &= ~(1 << event.xbutton.button);
!                 }
! 
!               if (numchars >= 1 && emacs_event.kind != NO_EVENT)
!                 {
!                   bcopy (&emacs_event, bufp, sizeof (struct input_event));
!                   bufp++;
!                   count++;
!                   numchars--;
!                 }
  
  #ifdef USE_X_TOOLKIT
!               f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
!               /* For a down-event in the menu bar,
!                  don't pass it to Xt right now.
!                  Instead, save it away
!                  and we will pass it to Xt from kbd_buffer_get_event.
!                  That way, we can run some Lisp code first.  */
!               if (f && event.type == ButtonPress
!                   /* Verify the event is really within the menu bar
!                      and not just sent to it due to grabbing.  */
!                   && event.xbutton.x >= 0
!                   && event.xbutton.x < f->output_data.x->pixel_width
!                   && event.xbutton.y >= 0
!                   && event.xbutton.y < f->output_data.x->menubar_height
!                   && event.xbutton.same_screen)
!                 {
!                   SET_SAVED_BUTTON_EVENT;
!                   XSETFRAME (last_mouse_press_frame, f);
!                 }
!               else if (event.type == ButtonPress)
!                 {
!                   last_mouse_press_frame = Qnil;
!                   goto OTHER;
!                 }
  
  #ifdef USE_MOTIF /* This should do not harm for Lucid,
                    but I am trying to be cautious.  */
!               else if (event.type == ButtonRelease)
!                 {
!                   if (!NILP (last_mouse_press_frame))
!                     {
!                       f = XFRAME (last_mouse_press_frame);
!                       if (f->output_data.x)
!                         SET_SAVED_BUTTON_EVENT;
!                     }
!                   else
!                     goto OTHER;
!                 }
  #endif /* USE_MOTIF */
!               else
!                 goto OTHER;
  #endif /* USE_X_TOOLKIT */
!             }
!             break;
  
!           case CirculateNotify:
!             goto OTHER;
  
!           case CirculateRequest:
!             goto OTHER;
  
!           case VisibilityNotify:
!             goto OTHER;
  
!           case MappingNotify:
!             /* Someone has changed the keyboard mapping - update the
!                local cache.  */
!             switch (event.xmapping.request)
!               {
!               case MappingModifier:
!                 x_find_modifier_meanings (dpyinfo);
!                 /* This is meant to fall through.  */
!               case MappingKeyboard:
!                 XRefreshKeyboardMapping (&event.xmapping);
!               }
!             goto OTHER;
! 
!           default:
!           OTHER:
  #ifdef USE_X_TOOLKIT
!             BLOCK_INPUT;
!             XtDispatchEvent (&event);
!             UNBLOCK_INPUT;
  #endif /* USE_X_TOOLKIT */
!             break;
!           }
        }
      }
  
   out:;
--- 10131,11462 ----
         below can generate additional FocusIn events which confuse
         Emacs.  */
  
!                 /* Since we set WM_TAKE_FOCUS, we must call
!                    XSetInputFocus explicitly.  But not if f is null,
!                    since that might be an event for a deleted frame.  */
!                 if (f)
!                   {
!                     Display *d = event.xclient.display;
!                     /* Catch and ignore errors, in case window has been
!                        iconified by a window manager such as GWM.  */
!                     int count = x_catch_errors (d);
!                     XSetInputFocus (d, event.xclient.window,
!                                     /* The ICCCM says this is
!                                        the only valid choice.  */
!                                     RevertToParent,
!                                     event.xclient.data.l[1]);
!                     /* This is needed to detect the error
!                        if there is an error.  */
!                     XSync (d, False);
!                     x_uncatch_errors (d, count);
!                   }
!                 /* Not certain about handling scroll bars here */
  #endif /* 0 */
!               }
!             else if (event.xclient.data.l[0]
!                      == dpyinfo->Xatom_wm_save_yourself)
!               {
!                 /* Save state modify the WM_COMMAND property to
!                    something which can reinstate us.  This notifies
!                    the session manager, who's looking for such a
!                    PropertyNotify.  Can restart processing when
!                    a keyboard or mouse event arrives.  */
!                 /* If we have a session manager, don't set this.
!                    KDE will then start two Emacsen, one for the
!                    session manager and one for this. */
!                 if (numchars > 0
  #ifdef HAVE_X_SM
!                     && ! x_session_have_connection ()
  #endif
!                     )
!                   {
!                     f = x_top_window_to_frame (dpyinfo,
!                                                event.xclient.window);
!                     /* This is just so we only give real data once
!                        for a single Emacs process.  */
!                     if (f == SELECTED_FRAME ())
!                       XSetCommand (FRAME_X_DISPLAY (f),
!                                    event.xclient.window,
!                                    initial_argv, initial_argc);
!                     else if (f)
!                       XSetCommand (FRAME_X_DISPLAY (f),
!                                    event.xclient.window,
!                                    0, 0);
!                   }
!               }
!             else if (event.xclient.data.l[0]
!                      == dpyinfo->Xatom_wm_delete_window)
!               {
!                 struct frame *f
!                   = x_any_window_to_frame (dpyinfo,
!                                            event.xclient.window);
! 
!                 if (f)
!                   {
!                     if (numchars == 0)
!                       abort ();
! 
!                     bufp->kind = DELETE_WINDOW_EVENT;
!                     XSETFRAME (bufp->frame_or_window, f);
!                     bufp->arg = Qnil;
!                     bufp++;
! 
!                     count += 1;
!                     numchars -= 1;
!                   }
!                 else
!                   goto OTHER; /* May be a dialog that is to be removed  */
!               }
!           }
!         else if (event.xclient.message_type
!                  == dpyinfo->Xatom_wm_configure_denied)
!           {
!           }
!         else if (event.xclient.message_type
!                  == dpyinfo->Xatom_wm_window_moved)
!           {
!             int new_x, new_y;
!             struct frame *f
!               = x_window_to_frame (dpyinfo, event.xclient.window);
! 
!             new_x = event.xclient.data.s[0];
!             new_y = event.xclient.data.s[1];
! 
!             if (f)
!               {
!                 f->output_data.x->left_pos = new_x;
!                 f->output_data.x->top_pos = new_y;
!               }
!           }
  #ifdef HACK_EDITRES
!         else if (event.xclient.message_type
!                  == dpyinfo->Xatom_editres)
!           {
!             struct frame *f
!               = x_any_window_to_frame (dpyinfo, event.xclient.window);
!             _XEditResCheckMessages (f->output_data.x->widget, NULL,
!                                     &event, NULL);
!           }
  #endif /* HACK_EDITRES */
!         else if ((event.xclient.message_type
!                   == dpyinfo->Xatom_DONE)
!                  || (event.xclient.message_type
!                      == dpyinfo->Xatom_PAGE))
!           {
!             /* Ghostview job completed.  Kill it.  We could
!                reply with "Next" if we received "Page", but we
!                currently never do because we are interested in
!                images, only, which should have 1 page.  */
!             Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
!             struct frame *f
!               = x_window_to_frame (dpyinfo, event.xclient.window);
!             x_kill_gs_process (pixmap, f);
!             expose_frame (f, 0, 0, 0, 0);
!           }
  #ifdef USE_TOOLKIT_SCROLL_BARS
!         /* Scroll bar callbacks send a ClientMessage from which
!            we construct an input_event.  */
!         else if (event.xclient.message_type
!                  == dpyinfo->Xatom_Scrollbar)
!           {
!             x_scroll_bar_to_input_event (&event, bufp);
!             ++bufp, ++count, --numchars;
!             goto out;
!           }
  #endif /* USE_TOOLKIT_SCROLL_BARS */
!         else
!           goto OTHER;
!       }
!       break;
  
!     case SelectionNotify:
  #ifdef USE_X_TOOLKIT
!       if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
!         goto OTHER;
  #endif /* not USE_X_TOOLKIT */
!       x_handle_selection_notify (&event.xselection);
!       break;
  
!     case SelectionClear:      /* Someone has grabbed ownership.  */
  #ifdef USE_X_TOOLKIT
!       if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
!         goto OTHER;
  #endif /* USE_X_TOOLKIT */
!       {
!         XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
  
!         if (numchars == 0)
!           abort ();
  
!         bufp->kind = SELECTION_CLEAR_EVENT;
!         SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
!         SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
!         SELECTION_EVENT_TIME (bufp) = eventp->time;
!         bufp->frame_or_window = Qnil;
!         bufp->arg = Qnil;
!         bufp++;
! 
!         count += 1;
!         numchars -= 1;
!       }
!       break;
  
!     case SelectionRequest:    /* Someone wants our selection.  */
  #ifdef USE_X_TOOLKIT
!       if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
!         goto OTHER;
  #endif /* USE_X_TOOLKIT */
!       if (x_queue_selection_requests)
!         x_queue_event (x_window_to_frame (dpyinfo, 
event.xselectionrequest.owner),
!                        &event);
!       else
!         {
!           XSelectionRequestEvent *eventp
!             = (XSelectionRequestEvent *) &event;
! 
!           if (numchars == 0)
!             abort ();
! 
!           bufp->kind = SELECTION_REQUEST_EVENT;
!           SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
!           SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
!           SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
!           SELECTION_EVENT_TARGET (bufp) = eventp->target;
!           SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
!           SELECTION_EVENT_TIME (bufp) = eventp->time;
!           bufp->frame_or_window = Qnil;
!           bufp->arg = Qnil;
!           bufp++;
! 
!           count += 1;
!           numchars -= 1;
!         }
!       break;
  
!     case PropertyNotify:
  #if 0 /* This is plain wrong.  In the case that we are waiting for a
         PropertyNotify used as an ACK in incremental selection
         transfer, the property will be on the receiver's window.  */
  #if defined USE_X_TOOLKIT
!       if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
!         goto OTHER;
  #endif
  #endif
!       x_handle_property_notify (&event.xproperty);
!       goto OTHER;
  
!     case ReparentNotify:
!       f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
!       if (f)
!         {
!           int x, y;
!           f->output_data.x->parent_desc = event.xreparent.parent;
!           x_real_positions (f, &x, &y);
!           f->output_data.x->left_pos = x;
!           f->output_data.x->top_pos = y;
!           goto OTHER;
!         }
!       break;
! 
!     case Expose:
!       f = x_window_to_frame (dpyinfo, event.xexpose.window);
!       if (f)
!         {
!           x_check_fullscreen (f);
! 
!           if (f->async_visible == 0)
!             {
!               f->async_visible = 1;
!               f->async_iconified = 0;
!               f->output_data.x->has_been_visible = 1;
!               SET_FRAME_GARBAGED (f);
!             }
!           else
!             expose_frame (x_window_to_frame (dpyinfo,
!                                              event.xexpose.window),
!                           event.xexpose.x, event.xexpose.y,
!                           event.xexpose.width, event.xexpose.height);
!         }
!       else
!         {
  #ifndef USE_TOOLKIT_SCROLL_BARS
!           struct scroll_bar *bar;
  #endif
  #if defined USE_LUCID
!           /* Submenus of the Lucid menu bar aren't widgets
!              themselves, so there's no way to dispatch events
!              to them.  Recognize this case separately.  */
!           {
!             Widget widget
!               = x_window_to_menu_bar (event.xexpose.window);
!             if (widget)
!               xlwmenu_redisplay (widget);
!           }
  #endif /* USE_LUCID */
  
  #ifdef USE_TOOLKIT_SCROLL_BARS
!           /* Dispatch event to the widget.  */
!           goto OTHER;
  #else /* not USE_TOOLKIT_SCROLL_BARS */
!           bar = x_window_to_scroll_bar (event.xexpose.window);
  
!           if (bar)
!             x_scroll_bar_expose (bar, &event);
  #ifdef USE_X_TOOLKIT
!           else
!             goto OTHER;
  #endif /* USE_X_TOOLKIT */
  #endif /* not USE_TOOLKIT_SCROLL_BARS */
!         }
!       break;
  
!     case GraphicsExpose:      /* This occurs when an XCopyArea's
!                                    source area was obscured or not
!                                    available.  */
!       f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
!       if (f)
!         {
!           expose_frame (f,
!                         event.xgraphicsexpose.x, event.xgraphicsexpose.y,
!                         event.xgraphicsexpose.width,
!                         event.xgraphicsexpose.height);
!         }
  #ifdef USE_X_TOOLKIT
!       else
!         goto OTHER;
  #endif /* USE_X_TOOLKIT */
!       break;
  
!     case NoExpose:            /* This occurs when an XCopyArea's
!                                    source area was completely
!                                    available.  */
!       break;
! 
!     case UnmapNotify:
!       /* Redo the mouse-highlight after the tooltip has gone.  */
!       if (event.xmap.window == tip_window)
!         {
!           tip_window = 0;
!           redo_mouse_highlight ();
!         }
! 
!       f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
!       if (f)          /* F may no longer exist if
!                            the frame was deleted.  */
!         {
!           /* While a frame is unmapped, display generation is
!              disabled; you don't want to spend time updating a
!              display that won't ever be seen.  */
!           f->async_visible = 0;
!           /* We can't distinguish, from the event, whether the window
!              has become iconified or invisible.  So assume, if it
!              was previously visible, than now it is iconified.
!              But x_make_frame_invisible clears both
!              the visible flag and the iconified flag;
!              and that way, we know the window is not iconified now.  */
!           if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
!             {
!               f->async_iconified = 1;
! 
!               bufp->kind = ICONIFY_EVENT;
!               XSETFRAME (bufp->frame_or_window, f);
!               bufp->arg = Qnil;
!               bufp++;
!               count++;
!               numchars--;
!             }
!         }
!       goto OTHER;
! 
!     case MapNotify:
!       if (event.xmap.window == tip_window)
!         /* The tooltip has been drawn already.  Avoid
!            the SET_FRAME_GARBAGED below.  */
!         goto OTHER;
! 
!       /* We use x_top_window_to_frame because map events can
!          come for sub-windows and they don't mean that the
!          frame is visible.  */
!       f = x_top_window_to_frame (dpyinfo, event.xmap.window);
!       if (f)
!         {
!           /* wait_reading_process_input will notice this and update
!              the frame's display structures.
!              If we where iconified, we should not set garbaged,
!              because that stops redrawing on Expose events.  This looks
!              bad if we are called from a recursive event loop
!              (x_dispatch_event), for example when a dialog is up.  */
!           if (! f->async_iconified)
!             SET_FRAME_GARBAGED (f);
! 
!           f->async_visible = 1;
!           f->async_iconified = 0;
!           f->output_data.x->has_been_visible = 1;
! 
!           if (f->iconified)
!             {
!               bufp->kind = DEICONIFY_EVENT;
!               XSETFRAME (bufp->frame_or_window, f);
!               bufp->arg = Qnil;
!               bufp++;
!               count++;
!               numchars--;
!             }
!           else if (! NILP (Vframe_list)
!                    && ! NILP (XCDR (Vframe_list)))
!             /* Force a redisplay sooner or later
!                to update the frame titles
!                in case this is the second frame.  */
!             record_asynch_buffer_change ();
!         }
!       goto OTHER;
! 
!     case KeyPress:
! 
!       /* Dispatch KeyPress events when in menu.  */
!       if (popup_activated_flag)
!         goto OTHER;
!       f = x_any_window_to_frame (dpyinfo, event.xkey.window);
! 
!       if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
!         {
!           dpyinfo->mouse_face_hidden = 1;
!           clear_mouse_face (dpyinfo);
!         }
  
  #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
!       if (f == 0)
!         {
!           /* Scroll bars consume key events, but we want
!              the keys to go to the scroll bar's frame.  */
!           Widget widget = XtWindowToWidget (dpyinfo->display,
!                                             event.xkey.window);
!           if (widget && XmIsScrollBar (widget))
!             {
!               widget = XtParent (widget);
!               f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
!             }
!         }
  #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
  
!       if (f != 0)
!         {
!           KeySym keysym, orig_keysym;
!           /* address@hidden says that making this 81
!              instead of 80 fixed a bug whereby meta chars made
!              his Emacs hang.
! 
!              It seems that some version of XmbLookupString has
!              a bug of not returning XBufferOverflow in
!              status_return even if the input is too long to
!              fit in 81 bytes.  So, we must prepare sufficient
!              bytes for copy_buffer.  513 bytes (256 chars for
!              two-byte character set) seems to be a fairly good
!              approximation.  -- 2000.8.10 address@hidden  */
!           unsigned char copy_buffer[513];
!           unsigned char *copy_bufptr = copy_buffer;
!           int copy_bufsiz = sizeof (copy_buffer);
!           int modifiers;
!           Lisp_Object coding_system = Qlatin_1;
! 
!           event.xkey.state
!             |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                        extra_keyboard_modifiers);
!           modifiers = event.xkey.state;
! 
!           /* This will have to go some day...  */
! 
!           /* make_lispy_event turns chars into control chars.
!              Don't do it here because XLookupString is too eager.  */
!           event.xkey.state &= ~ControlMask;
!           event.xkey.state &= ~(dpyinfo->meta_mod_mask
!                                 | dpyinfo->super_mod_mask
!                                 | dpyinfo->hyper_mod_mask
!                                 | dpyinfo->alt_mod_mask);
! 
!           /* In case Meta is ComposeCharacter,
!              clear its status.  According to Markus Ehrnsperger
!              address@hidden
!              this enables ComposeCharacter to work whether or
!              not it is combined with Meta.  */
!           if (modifiers & dpyinfo->meta_mod_mask)
!             bzero (&compose_status, sizeof (compose_status));
  
  #ifdef HAVE_X_I18N
!           if (FRAME_XIC (f))
!             {
!               Status status_return;
! 
!               coding_system = Vlocale_coding_system;
!               nbytes = XmbLookupString (FRAME_XIC (f),
!                                         &event.xkey, copy_bufptr,
!                                         copy_bufsiz, &keysym,
!                                         &status_return);
!               if (status_return == XBufferOverflow)
!                 {
!                   copy_bufsiz = nbytes + 1;
!                   copy_bufptr = (char *) alloca (copy_bufsiz);
!                   nbytes = XmbLookupString (FRAME_XIC (f),
!                                             &event.xkey, copy_bufptr,
!                                             copy_bufsiz, &keysym,
!                                             &status_return);
!                 }
!               /* Xutf8LookupString is a new but already deprecated interface. 
 -stef  */
  #if 0 && defined X_HAVE_UTF8_STRING
!               else if (status_return == XLookupKeySym)
!                 {  /* Try again but with utf-8.  */
!                   coding_system = Qutf_8;
!                   nbytes = Xutf8LookupString (FRAME_XIC (f),
!                                               &event.xkey, copy_bufptr,
!                                               copy_bufsiz, &keysym,
!                                               &status_return);
!                   if (status_return == XBufferOverflow)
!                     {
!                       copy_bufsiz = nbytes + 1;
!                       copy_bufptr = (char *) alloca (copy_bufsiz);
!                       nbytes = Xutf8LookupString (FRAME_XIC (f),
!                                                   &event.xkey,
!                                                   copy_bufptr,
!                                                   copy_bufsiz, &keysym,
!                                                   &status_return);
!                     }
!                 }
! #endif
! 
!               if (status_return == XLookupNone)
!                 break;
!               else if (status_return == XLookupChars)
!                 {
!                   keysym = NoSymbol;
!                   modifiers = 0;
!                 }
!               else if (status_return != XLookupKeySym
!                        && status_return != XLookupBoth)
!                 abort ();
!             }
!           else
!             nbytes = XLookupString (&event.xkey, copy_bufptr,
!                                     copy_bufsiz, &keysym,
!                                     &compose_status);
  #else
!           nbytes = XLookupString (&event.xkey, copy_bufptr,
!                                   copy_bufsiz, &keysym,
!                                   &compose_status);
! #endif
! 
!           orig_keysym = keysym;
! 
!           if (numchars > 1)
!             {
!               Lisp_Object c;
! 
!               /* First deal with keysyms which have defined
!                  translations to characters.  */
!               if (keysym >= 32 && keysym < 128)
!                 /* Avoid explicitly decoding each ASCII character.  */
!                 {
!                   bufp->kind = ASCII_KEYSTROKE_EVENT;
!                   bufp->code = keysym;
!                   XSETFRAME (bufp->frame_or_window, f);
!                   bufp->arg = Qnil;
!                   bufp->modifiers
!                     = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                               modifiers);
!                   bufp->timestamp = event.xkey.time;
!                   bufp++;
!                   count++;
!                   numchars--;
!                 }
!               /* Now non-ASCII.  */
!               else if (HASH_TABLE_P (Vx_keysym_table)
!                        && (NATNUMP (c = Fgethash (make_number (keysym),
!                                                   Vx_keysym_table,
!                                                   Qnil))))
!                 {
!                   bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
!                                 ? ASCII_KEYSTROKE_EVENT
!                                 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
!                   bufp->code = XFASTINT (c);
!                   XSETFRAME (bufp->frame_or_window, f);
!                   bufp->arg = Qnil;
!                   bufp->modifiers
!                     = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                               modifiers);
!                   bufp->timestamp = event.xkey.time;
!                   bufp++;
!                   count++;
!                   numchars--;
!                 }
!               /* Random non-modifier sorts of keysyms.  */
!               else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
!                         || keysym == XK_Delete
  #ifdef XK_ISO_Left_Tab
!                         || (keysym >= XK_ISO_Left_Tab
!                             && keysym <= XK_ISO_Enter)
  #endif
!                         || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
!                         || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES 
*/
  #ifdef HPUX
!                         /* This recognizes the "extended function
!                            keys".  It seems there's no cleaner way.
!                            Test IsModifierKey to avoid handling
!                            mode_switch incorrectly.  */
!                         || ((unsigned) (keysym) >= XK_Select
!                             && (unsigned)(keysym) < XK_KP_Space)
  #endif
  #ifdef XK_dead_circumflex
!                         || orig_keysym == XK_dead_circumflex
  #endif
  #ifdef XK_dead_grave
!                         || orig_keysym == XK_dead_grave
  #endif
  #ifdef XK_dead_tilde
!                         || orig_keysym == XK_dead_tilde
  #endif
  #ifdef XK_dead_diaeresis
!                         || orig_keysym == XK_dead_diaeresis
  #endif
  #ifdef XK_dead_macron
!                         || orig_keysym == XK_dead_macron
  #endif
  #ifdef XK_dead_degree
!                         || orig_keysym == XK_dead_degree
  #endif
  #ifdef XK_dead_acute
!                         || orig_keysym == XK_dead_acute
  #endif
  #ifdef XK_dead_cedilla
!                         || orig_keysym == XK_dead_cedilla
  #endif
  #ifdef XK_dead_breve
!                         || orig_keysym == XK_dead_breve
  #endif
  #ifdef XK_dead_ogonek
!                         || orig_keysym == XK_dead_ogonek
  #endif
  #ifdef XK_dead_caron
!                         || orig_keysym == XK_dead_caron
  #endif
  #ifdef XK_dead_doubleacute
!                         || orig_keysym == XK_dead_doubleacute
  #endif
  #ifdef XK_dead_abovedot
!                         || orig_keysym == XK_dead_abovedot
  #endif
!                         || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
!                         || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
!                         /* Any "vendor-specific" key is ok.  */
!                         || (orig_keysym & (1 << 28))
!                         || (keysym != NoSymbol && nbytes == 0))
!                        && ! (IsModifierKey (orig_keysym)
  #ifndef HAVE_X11R5
  #ifdef XK_Mode_switch
!                              || ((unsigned)(orig_keysym) == XK_Mode_switch)
  #endif
  #ifdef XK_Num_Lock
!                              || ((unsigned)(orig_keysym) == XK_Num_Lock)
  #endif
  #endif /* not HAVE_X11R5 */
!                              /* The symbols from XK_ISO_Lock
!                                 to XK_ISO_Last_Group_Lock
!                                 don't have real modifiers but
!                                 should be treated similarly to
!                                 Mode_switch by Emacs. */
  #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
!                              || ((unsigned)(orig_keysym)
!                                  >=  XK_ISO_Lock
!                                  && (unsigned)(orig_keysym)
!                                  <= XK_ISO_Last_Group_Lock)
! #endif
!                              ))
!                 {
!                   if (temp_index == sizeof temp_buffer / sizeof (short))
!                     temp_index = 0;
!                   temp_buffer[temp_index++] = keysym;
!                   /* make_lispy_event will convert this to a symbolic
!                      key.  */
!                   bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
!                   bufp->code = keysym;
!                   XSETFRAME (bufp->frame_or_window, f);
!                   bufp->arg = Qnil;
!                   bufp->modifiers
!                     = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                               modifiers);
!                   bufp->timestamp = event.xkey.time;
!                   bufp++;
!                   count++;
!                   numchars--;
!                 }
!               else if (numchars > nbytes)
!                 {     /* Raw bytes, not keysym.  */
!                   register int i;
!                   register int c;
!                   int nchars, len;
! 
!                   /* The input should be decoded with `coding_system'
!                      which depends on which X*LookupString function
!                      we used just above and the locale.  */
!                   setup_coding_system (coding_system, &coding);
!                   coding.src_multibyte = 0;
!                   coding.dst_multibyte = 1;
!                   /* The input is converted to events, thus we can't
!                      handle composition.  Anyway, there's no XIM that
!                      gives us composition information.  */
!                   coding.composing = COMPOSITION_DISABLED;
! 
!                   for (i = 0; i < nbytes; i++)
!                     {
!                       if (temp_index == (sizeof temp_buffer
!                                          / sizeof (short)))
!                         temp_index = 0;
!                       temp_buffer[temp_index++] = copy_bufptr[i];
!                     }
! 
!                   {
!                     /* Decode the input data.  */
!                     int require;
!                     unsigned char *p;
! 
!                     require = decoding_buffer_size (&coding, nbytes);
!                     p = (unsigned char *) alloca (require);
!                     coding.mode |= CODING_MODE_LAST_BLOCK;
!                     /* We explicitely disable composition
!                        handling because key data should
!                        not contain any composition
!                        sequence.  */
!                     coding.composing = COMPOSITION_DISABLED;
!                     decode_coding (&coding, copy_bufptr, p,
!                                    nbytes, require);
!                     nbytes = coding.produced;
!                     nchars = coding.produced_char;
!                     copy_bufptr = p;
!                   }
! 
!                   /* Convert the input data to a sequence of
!                      character events.  */
!                   for (i = 0; i < nbytes; i += len)
!                     {
!                       if (nchars == nbytes)
!                         c = copy_bufptr[i], len = 1;
!                       else
!                         c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
!                                                     nbytes - i, len);
! 
!                       bufp->kind = (SINGLE_BYTE_CHAR_P (c)
!                                     ? ASCII_KEYSTROKE_EVENT
!                                     : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
!                       bufp->code = c;
!                       XSETFRAME (bufp->frame_or_window, f);
!                       bufp->arg = Qnil;
!                       bufp->modifiers
!                         = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
!                                                   modifiers);
!                       bufp->timestamp = event.xkey.time;
!                       bufp++;
!                     }
! 
!                   count += nchars;
!                   numchars -= nchars;
! 
!                   if (keysym == NoSymbol)
!                     break;
!                 }
!               else
!                 abort ();
!             }
!           else
!             abort ();
!         }
  #ifdef HAVE_X_I18N
!       /* Don't dispatch this event since XtDispatchEvent calls
!          XFilterEvent, and two calls in a row may freeze the
!          client.  */
!       break;
  #else
!       goto OTHER;
  #endif
  
!     case KeyRelease:
  #ifdef HAVE_X_I18N
!       /* Don't dispatch this event since XtDispatchEvent calls
!          XFilterEvent, and two calls in a row may freeze the
!          client.  */
!       break;
  #else
!       goto OTHER;
  #endif
  
!     case EnterNotify:
!       {
!         int n;
  
!         n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
!         if (n > 0)
!           {
!             bufp += n, count += n, numchars -= n;
!           }
  
!         f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
  
  #if 0
!         if (event.xcrossing.focus)
!           {
!             /* Avoid nasty pop/raise loops.  */
!             if (f && (!(f->auto_raise)
!                       || !(f->auto_lower)
!                       || (event.xcrossing.time - enter_timestamp) > 500))
                {
!                 x_new_focus_frame (dpyinfo, f);
!                 enter_timestamp = event.xcrossing.time;
                }
+           }
+         else if (f == dpyinfo->x_focus_frame)
+           x_new_focus_frame (dpyinfo, 0);
+ #endif
+ 
+         /* EnterNotify counts as mouse movement,
+            so update things that depend on mouse position.  */
+         if (f && !f->output_data.x->hourglass_p)
+           note_mouse_movement (f, &event.xmotion);
+         goto OTHER;
+       }
+ 
+     case FocusIn:
+       {
+         int n;
+ 
+         n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+         if (n > 0)
+           {
+             bufp += n, count += n, numchars -= n;
+           }
+       }
+ 
+       goto OTHER;
+ 
+     case LeaveNotify:
+       {
+         int n;
+ 
+         n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+         if (n > 0)
+           {
+             bufp += n, count += n, numchars -= n;
+           }
+       }
+ 
+       f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
+       if (f)
+         {
+           if (f == dpyinfo->mouse_face_mouse_frame)
+             {
+               /* If we move outside the frame, then we're
+                  certainly no longer on any text in the frame.  */
+               clear_mouse_face (dpyinfo);
+               dpyinfo->mouse_face_mouse_frame = 0;
+             }
+ 
+           /* Generate a nil HELP_EVENT to cancel a help-echo.
+              Do it only if there's something to cancel.
+              Otherwise, the startup message is cleared when
+              the mouse leaves the frame.  */
+           if (any_help_event_p)
+             {
+               Lisp_Object frame;
+               int n;
+ 
+               XSETFRAME (frame, f);
+               help_echo = Qnil;
+               n = gen_help_event (bufp, numchars,
+                                   Qnil, frame, Qnil, Qnil, 0);
+               bufp += n, count += n, numchars -= n;
+             }
+ 
+         }
+       goto OTHER;
+ 
+     case FocusOut:
+       {
+         int n;
+ 
+         n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+         if (n > 0)
+           {
+             bufp += n, count += n, numchars -= n;
+           }
+       }
+ 
+       goto OTHER;
+ 
+     case MotionNotify:
+       {
+         previous_help_echo = help_echo;
+         help_echo = help_echo_object = help_echo_window = Qnil;
+         help_echo_pos = -1;
+ 
+         if (dpyinfo->grabbed && last_mouse_frame
+             && FRAME_LIVE_P (last_mouse_frame))
+           f = last_mouse_frame;
+         else
+           f = x_window_to_frame (dpyinfo, event.xmotion.window);
+ 
+         if (dpyinfo->mouse_face_hidden)
+           {
+             dpyinfo->mouse_face_hidden = 0;
+             clear_mouse_face (dpyinfo);
+           }
  
!         if (f)
!           {
  
!             /* Generate SELECT_WINDOW_EVENTs when needed.  */
!             if (mouse_autoselect_window)
                {
!                 Lisp_Object window;
!                 int area;
  
!                 window = window_from_coordinates (f,
!                                                   event.xmotion.x, 
event.xmotion.y,
!                                                   &area, 0);
! 
!                 /* Window will be selected only when it is not selected now 
and
!                    last mouse movement event was not in it.  Minibuffer window
!                    will be selected iff it is active.  */
!                 if (WINDOWP(window)
!                     && !EQ (window, last_window)
!                     && !EQ (window, selected_window)
!                     && numchars > 0)
!                   {
!                     bufp->kind = SELECT_WINDOW_EVENT;
!                     bufp->frame_or_window = window;
!                     bufp->arg = Qnil;
!                     ++bufp, ++count, --numchars;
!                   }
  
!                 last_window=window;
                }
!             note_mouse_movement (f, &event.xmotion);
!           }
!         else
!           {
  #ifndef USE_TOOLKIT_SCROLL_BARS
!             struct scroll_bar *bar
!               = x_window_to_scroll_bar (event.xmotion.window);
  
!             if (bar)
!               x_scroll_bar_note_movement (bar, &event);
  #endif /* USE_TOOLKIT_SCROLL_BARS */
  
!             /* If we move outside the frame, then we're
!                certainly no longer on any text in the frame.  */
!             clear_mouse_face (dpyinfo);
!           }
! 
!         /* If the contents of the global variable help_echo
!            has changed, generate a HELP_EVENT.  */
!         if (!NILP (help_echo)
!             || !NILP (previous_help_echo))
!           {
!             Lisp_Object frame;
!             int n;
! 
!             if (f)
!               XSETFRAME (frame, f);
!             else
!               frame = Qnil;
! 
!             any_help_event_p = 1;
!             n = gen_help_event (bufp, numchars, help_echo, frame,
!                                 help_echo_window, help_echo_object,
!                                 help_echo_pos);
!             bufp += n, count += n, numchars -= n;
!           }
! 
!         goto OTHER;
!       }
! 
!     case ConfigureNotify:
!       f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
!       if (f)
!         {
  #ifndef USE_X_TOOLKIT
!           /* If there is a pending resize for fullscreen, don't
!              do this one, the right one will come later.
!              The toolkit version doesn't seem to need this, but we
!              need to reset it below.  */
!           int dont_resize =
!             ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
!              && FRAME_NEW_WIDTH (f) != 0);
!           int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
!           int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
!           if (dont_resize)
!             goto OTHER;
! 
!           /* In the toolkit version, change_frame_size
!              is called by the code that handles resizing
!              of the EmacsFrame widget.  */
! 
!           /* Even if the number of character rows and columns has
!              not changed, the font size may have changed, so we need
!              to check the pixel dimensions as well.  */
!           if (columns != f->width
!               || rows != f->height
!               || event.xconfigure.width != f->output_data.x->pixel_width
!               || event.xconfigure.height != f->output_data.x->pixel_height)
!             {
!               change_frame_size (f, rows, columns, 0, 1, 0);
!               SET_FRAME_GARBAGED (f);
!               cancel_mouse_face (f);
!             }
! #endif
! 
!           f->output_data.x->pixel_width = event.xconfigure.width;
!           f->output_data.x->pixel_height = event.xconfigure.height;
! 
!           /* What we have now is the position of Emacs's own window.
!              Convert that to the position of the window manager window.  */
!           x_real_positions (f, &f->output_data.x->left_pos,
!                             &f->output_data.x->top_pos);
! 
!           x_check_fullscreen_move(f);
!           if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
!             f->output_data.x->want_fullscreen &=
!               ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
  #ifdef HAVE_X_I18N
!           if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
!             xic_set_statusarea (f);
  #endif
  
!           if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO 
(f)->root_window)
!             {
!               /* Since the WM decorations come below top_pos now,
!                  we must put them below top_pos in the future.  */
!               f->output_data.x->win_gravity = NorthWestGravity;
!               x_wm_set_size_hint (f, (long) 0, 0);
!             }
!         }
!       goto OTHER;
! 
!     case ButtonPress:
!     case ButtonRelease:
!       {
!         /* If we decide we want to generate an event to be seen
!            by the rest of Emacs, we put it here.  */
!         struct input_event emacs_event;
!         int tool_bar_p = 0;
! 
!         emacs_event.kind = NO_EVENT;
!         bzero (&compose_status, sizeof (compose_status));
! 
!         if (dpyinfo->grabbed
!             && last_mouse_frame
!             && FRAME_LIVE_P (last_mouse_frame))
!           f = last_mouse_frame;
!         else
!           f = x_window_to_frame (dpyinfo, event.xbutton.window);
! 
!         if (f)
!           {
!             /* Is this in the tool-bar?  */
!             if (WINDOWP (f->tool_bar_window)
!                 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
!               {
!                 Lisp_Object window;
!                 int p, x, y;
! 
!                 x = event.xbutton.x;
!                 y = event.xbutton.y;
! 
!                 /* Set x and y.  */
!                 window = window_from_coordinates (f, x, y, &p, 1);
!                 if (EQ (window, f->tool_bar_window))
!                   {
!                     x_handle_tool_bar_click (f, &event.xbutton);
!                     tool_bar_p = 1;
!                   }
!               }
! 
!             if (!tool_bar_p)
!               if (!dpyinfo->x_focus_frame
!                   || f == dpyinfo->x_focus_frame)
!                 construct_mouse_click (&emacs_event, &event, f);
!           }
!         else
!           {
  #ifndef USE_TOOLKIT_SCROLL_BARS
!             struct scroll_bar *bar
!               = x_window_to_scroll_bar (event.xbutton.window);
  
!             if (bar)
!               x_scroll_bar_handle_click (bar, &event, &emacs_event);
  #endif /* not USE_TOOLKIT_SCROLL_BARS */
!           }
  
!         if (event.type == ButtonPress)
!           {
!             dpyinfo->grabbed |= (1 << event.xbutton.button);
!             last_mouse_frame = f;
!             /* Ignore any mouse motion that happened
!                before this event; any subsequent mouse-movement
!                Emacs events should reflect only motion after
!                the ButtonPress.  */
!             if (f != 0)
!               f->mouse_moved = 0;
! 
!             if (!tool_bar_p)
!               last_tool_bar_item = -1;
!           }
!         else
!           {
!             dpyinfo->grabbed &= ~(1 << event.xbutton.button);
!           }
! 
!         if (numchars >= 1 && emacs_event.kind != NO_EVENT)
!           {
!             bcopy (&emacs_event, bufp, sizeof (struct input_event));
!             bufp++;
!             count++;
!             numchars--;
!           }
  
  #ifdef USE_X_TOOLKIT
!         f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
!         /* For a down-event in the menu bar,
!            don't pass it to Xt right now.
!            Instead, save it away
!            and we will pass it to Xt from kbd_buffer_get_event.
!            That way, we can run some Lisp code first.  */
!         if (f && event.type == ButtonPress
!             /* Verify the event is really within the menu bar
!                and not just sent to it due to grabbing.  */
!             && event.xbutton.x >= 0
!             && event.xbutton.x < f->output_data.x->pixel_width
!             && event.xbutton.y >= 0
!             && event.xbutton.y < f->output_data.x->menubar_height
!             && event.xbutton.same_screen)
!           {
!             SET_SAVED_BUTTON_EVENT;
!             XSETFRAME (last_mouse_press_frame, f);
!           }
!         else if (event.type == ButtonPress)
!           {
!             last_mouse_press_frame = Qnil;
!             goto OTHER;
!           }
  
  #ifdef USE_MOTIF /* This should do not harm for Lucid,
                    but I am trying to be cautious.  */
!         else if (event.type == ButtonRelease)
!           {
!             if (!NILP (last_mouse_press_frame))
!               {
!                 f = XFRAME (last_mouse_press_frame);
!                 if (f->output_data.x)
!                   SET_SAVED_BUTTON_EVENT;
!               }
!             else
!               goto OTHER;
!           }
  #endif /* USE_MOTIF */
!         else
!           goto OTHER;
  #endif /* USE_X_TOOLKIT */
!       }
!       break;
  
!     case CirculateNotify:
!       goto OTHER;
  
!     case CirculateRequest:
!       goto OTHER;
  
!     case VisibilityNotify:
!       goto OTHER;
! 
!     case MappingNotify:
!       /* Someone has changed the keyboard mapping - update the
!          local cache.  */
!       switch (event.xmapping.request)
!         {
!         case MappingModifier:
!           x_find_modifier_meanings (dpyinfo);
!           /* This is meant to fall through.  */
!         case MappingKeyboard:
!           XRefreshKeyboardMapping (&event.xmapping);
!         }
!       goto OTHER;
  
!     default:
!     OTHER:
  #ifdef USE_X_TOOLKIT
!     BLOCK_INPUT;
!     XtDispatchEvent (&event);
!     UNBLOCK_INPUT;
  #endif /* USE_X_TOOLKIT */
!     break;
!     }
! 
!   goto ret;
! 
!  out:
!   *finish = X_EVENT_GOTO_OUT;
! 
!  ret:
!   *bufp_r = bufp;
!   *numcharsp = numchars;
!   *eventp = event;
!   
!   return count;
! }
! 
! 
! /* Handles the XEvent EVENT on display DISPLAY.
!    This is used for event loops outside the normal event handling,
!    i.e. looping while a popup menu or a dialog is posted.  */
! void
! x_dispatch_event (event, display)
!      XEvent *event;
!      Display *display;
! {
!   struct x_display_info *dpyinfo;
!   struct input_event bufp[10];
!   struct input_event *bufpp = bufp;
!   int numchars = 10;
!   int finish;
!       
!   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
!     if (dpyinfo->display == display)
!       break;
!           
!   if (dpyinfo)
!     {
!       int i, events;
!       events = handle_one_xevent (dpyinfo,
!                                   event,
!                                   &bufpp,
!                                   &numchars,
!                                   &finish);
!       for (i = 0; i < events; ++i)
!         kbd_buffer_store_event (&bufp[i]);
!     }
! }
! 
! 
! /* Read events coming from the X server.
!    This routine is called by the SIGIO handler.
!    We return as soon as there are no more events to be read.
! 
!    Events representing keys are stored in buffer BUFP,
!    which can hold up to NUMCHARS characters.
!    We return the number of characters stored into the buffer,
!    thus pretending to be `read'.
! 
!    EXPECTED is nonzero if the caller knows input is available.  */
! 
! static int
! XTread_socket (sd, bufp, numchars, expected)
!      register int sd;
!      /* register */ struct input_event *bufp;
!      /* register */ int numchars;
!      int expected;
! {
!   int count = 0;
!   int nbytes = 0;
!   XEvent event;
!   int event_found = 0;
!   struct x_display_info *dpyinfo;
! 
!   if (interrupt_input_blocked)
!     {
!       interrupt_input_pending = 1;
!       return -1;
!     }
! 
!   interrupt_input_pending = 0;
!   BLOCK_INPUT;
! 
!   /* So people can tell when we have read the available input.  */
!   input_signal_count++;
! 
!   if (numchars <= 0)
!     abort ();                 /* Don't think this happens.  */
! 
!   ++handling_signal;
! 
!   /* Find the display we are supposed to read input for.
!      It's the one communicating on descriptor SD.  */
!   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
!     {
! #if 0 /* This ought to be unnecessary; let's verify it.  */
! #ifdef FIOSNBIO
!       /* If available, Xlib uses FIOSNBIO to make the socket
!        non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
!        FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
!        a read returns 0, which Xlib interprets as equivalent to EPIPE.  */
!       fcntl (dpyinfo->connection, F_SETFL, 0);
! #endif /* ! defined (FIOSNBIO) */
! #endif
! 
! #if 0 /* This code can't be made to work, with multiple displays,
!        and appears not to be used on any system any more.
!        Also keyboard.c doesn't turn O_NDELAY on and off
!        for X connections.  */
! #ifndef SIGIO
! #ifndef HAVE_SELECT
!       if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
!       {
!         extern int read_alarm_should_throw;
!         read_alarm_should_throw = 1;
!         XPeekEvent (dpyinfo->display, &event);
!         read_alarm_should_throw = 0;
!       }
! #endif /* HAVE_SELECT */
! #endif /* SIGIO */
! #endif
! 
!       /* For debugging, this gives a way to fake an I/O error.  */
!       if (dpyinfo == XTread_socket_fake_io_error)
!       {
!         XTread_socket_fake_io_error = 0;
!         x_io_error_quitter (dpyinfo->display);
        }
+ 
+ #ifdef HAVE_X_SM
+       BLOCK_INPUT;
+       count += x_session_check_input (bufp, &numchars);
+       UNBLOCK_INPUT;
+ #endif
+ 
+       while (XPending (dpyinfo->display))
+       {
+           int finish;
+           
+         XNextEvent (dpyinfo->display, &event);
+ 
+ #ifdef HAVE_X_I18N
+         {
+           /* Filter events for the current X input method.
+              XFilterEvent returns non-zero if the input method has
+              consumed the event.  We pass the frame's X window to
+              XFilterEvent because that's the one for which the IC
+              was created.  */
+           struct frame *f1 = x_any_window_to_frame (dpyinfo,
+                                                     event.xclient.window);
+           if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
+             break;
+         }
+ #endif
+         event_found = 1;
+ 
+           count += handle_one_xevent (dpyinfo,
+                                       &event,
+                                       &bufp,
+                                       &numchars,
+                                       &finish);
+ 
+           if (finish == X_EVENT_GOTO_OUT)
+             goto out;
+         }
      }
  
   out:;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]