(handle_async_input): New fun, extracted from input_available_signal.
[bpt/emacs.git] / src / keyboard.c
index ad25732..d6a7434 100644 (file)
@@ -1,5 +1,5 @@
 /* Keyboard and mouse input; editor command loop.
-   Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99,2000,01,02,03
+   Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99,2000,01,02,03,04
      Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -586,6 +586,8 @@ Lisp_Object Qvertical_line;
 Lisp_Object Qvertical_scroll_bar;
 Lisp_Object Qmenu_bar;
 extern Lisp_Object Qleft_margin, Qright_margin;
+extern Lisp_Object Qleft_fringe, Qright_fringe;
+extern Lisp_Object QCmap;
 
 Lisp_Object recursive_edit_unwind (), command_loop ();
 Lisp_Object Fthis_command_keys ();
@@ -2941,13 +2943,13 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
     {
       Lisp_Object posn;
 
-      posn = POSN_BUFFER_POSN (EVENT_START (c));
+      posn = POSN_POSN (EVENT_START (c));
       /* Handle menu-bar events:
         insert the dummy prefix event `menu-bar'.  */
       if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
        {
          /* Change menu-bar to (menu-bar) as the event "position".  */
-         POSN_BUFFER_SET_POSN (EVENT_START (c), Fcons (posn, Qnil));
+         POSN_SET_POSN (EVENT_START (c), Fcons (posn, Qnil));
 
          also_record = c;
          Vunread_command_events = Fcons (c, Vunread_command_events);
@@ -4955,6 +4957,169 @@ EMACS_INT double_click_fuzz;
 
 int double_click_count;
 
+/* Return position of a mouse click or wheel event */
+
+static Lisp_Object
+make_lispy_position (f, x, y, time)
+     struct frame *f;
+     Lisp_Object *x, *y;
+     unsigned long time;
+{
+  Lisp_Object window;
+  enum window_part part;
+  Lisp_Object posn = Qnil;
+  Lisp_Object extra_info = Qnil;
+  int wx, wy;
+
+  /* Set `window' to the window under frame pixel coordinates (x,y)  */
+  if (f)
+    window = window_from_coordinates (f, XINT (*x), XINT (*y),
+                                     &part, &wx, &wy, 0);
+  else
+    window = Qnil;
+
+  if (WINDOWP (window))
+    {
+      /* It's a click in window window at frame coordinates (x,y)  */
+      struct window *w = XWINDOW (window);
+      Lisp_Object string_info = Qnil;
+      int textpos = -1, rx = -1, ry = -1;
+      int dx = -1, dy = -1;
+      int width = -1, height = -1;
+      Lisp_Object object = Qnil;
+
+      /* Set event coordinates to window-relative coordinates
+        for constructing the Lisp event below.  */
+      XSETINT (*x, wx);
+      XSETINT (*y, wy);
+
+      if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
+       {
+         /* Mode line or header line.  Look for a string under
+            the mouse that may have a `local-map' property.  */
+         Lisp_Object string;
+         int charpos;
+
+         posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
+         rx = wx, ry = wy;
+         string = mode_line_string (w, part, &rx, &ry, &charpos,
+                                    &object, &dx, &dy, &width, &height);
+         if (STRINGP (string))
+           string_info = Fcons (string, make_number (charpos));
+         if (w == XWINDOW (selected_window))
+           textpos = PT;
+         else
+           textpos = XMARKER (w->pointm)->charpos;
+       }
+      else if (part == ON_VERTICAL_BORDER)
+       {
+         posn = Qvertical_line;
+         wx = -1;
+         dx = 0;
+         width = 1;
+       }
+      else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
+       {
+         Lisp_Object string;
+         int charpos;
+         
+         posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
+         rx = wx, ry = wy;
+         string = marginal_area_string (w, part, &rx, &ry, &charpos,
+                                        &object, &dx, &dy, &width, &height);
+         if (STRINGP (string))
+           string_info = Fcons (string, make_number (charpos));
+       }
+      else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
+       {
+         posn = (part == ON_LEFT_FRINGE) ? Qleft_fringe : Qright_fringe;
+         rx = 0;
+         dx = wx;
+         if (part == ON_RIGHT_FRINGE)
+           dx -= (window_box_width (w, LEFT_MARGIN_AREA)
+                  + window_box_width (w, TEXT_AREA)
+                  + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                     ? window_box_width (w, RIGHT_MARGIN_AREA)
+                     : 0));
+         else if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
+           dx -= window_box_width (w, LEFT_MARGIN_AREA);
+       }
+
+      if (textpos < 0)
+       {
+         Lisp_Object string2, object2 = Qnil;
+         struct display_pos p;
+         int dx2, dy2;
+         int width2, height2;
+         wx = max (WINDOW_LEFT_MARGIN_WIDTH (w), wx);
+         string2 = buffer_posn_from_coords (w, &wx, &wy, &p,
+                                            &object2, &dx2, &dy2,
+                                            &width2, &height2);
+         textpos = CHARPOS (p.pos);
+         if (rx < 0) rx = wx;
+         if (ry < 0) ry = wy;
+         if (dx < 0) dx = dx2;
+         if (dy < 0) dy = dy2;
+         if (width < 0) width = width2;
+         if (height < 0) height = height2;
+
+         if (NILP (posn))
+           {
+             posn = make_number (textpos);
+             if (STRINGP (string2))
+               string_info = Fcons (string2,
+                                    make_number (CHARPOS (p.string_pos)));
+           }
+         if (NILP (object))
+           object = object2;
+       }
+
+#ifdef HAVE_WINDOW_SYSTEM
+      if (IMAGEP (object))
+       {
+         Lisp_Object image_map, hotspot;
+         if ((image_map = Fplist_get (XCDR (object), QCmap),
+              !NILP (image_map))
+             && (hotspot = find_hot_spot (image_map, dx, dy),
+                 CONSP (hotspot))
+             && (hotspot = XCDR (hotspot), CONSP (hotspot)))
+           posn = XCAR (hotspot);
+       }
+#endif
+
+      /* Object info */
+      extra_info = Fcons (object,
+                         Fcons (Fcons (make_number (dx),
+                                       make_number (dy)),
+                                Fcons (Fcons (make_number (width),
+                                              make_number (height)),
+                                       Qnil)));
+
+      /* String info */
+      extra_info = Fcons (string_info,
+                         Fcons (make_number (textpos),
+                                Fcons (Fcons (make_number (rx),
+                                              make_number (ry)),
+                                       extra_info)));
+    }
+  else if (f != 0)
+    {
+      XSETFRAME (window, f);
+    }
+  else
+    {
+      window = Qnil;
+      XSETFASTINT (*x, 0);
+      XSETFASTINT (*y, 0);
+    }
+
+  return Fcons (window,
+               Fcons (posn,
+                      Fcons (Fcons (*x, *y),
+                             Fcons (make_number (time),
+                                    extra_info))));
+}
+
 /* Given a struct input_event, build the lisp event which represents
    it.  If EVENT is 0, build a mouse movement event from the mouse
    movement buffer, which should have a movement event in it.
@@ -5089,25 +5254,23 @@ make_lispy_event (event)
        Lisp_Object position;
        Lisp_Object *start_pos_ptr;
        Lisp_Object start_pos;
-       Lisp_Object window;
 
        position = Qnil;
 
        /* Build the position as appropriate for this mouse click.  */
        if (event->kind == MOUSE_CLICK_EVENT)
          {
-           enum window_part part;
            struct frame *f = XFRAME (event->frame_or_window);
-           Lisp_Object posn;
-           Lisp_Object string_info = Qnil;
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
            int row, column;
-           int wx, wy;
+#endif
 
            /* Ignore mouse events that were made on frame that
               have been deleted.  */
            if (! FRAME_LIVE_P (f))
              return Qnil;
 
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
            /* EVENT->x and EVENT->y are frame-relative pixel
               coordinates at this place.  Under old redisplay, COLUMN
               and ROW are set to frame relative glyph coordinates
@@ -5116,7 +5279,6 @@ make_lispy_event (event)
            pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
                                   &column, &row, NULL, 1);
 
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
            /* In the non-toolkit version, clicks on the menu bar
               are ordinary button events in the event buffer.
               Distinguish them, and invoke the menu.
@@ -5170,77 +5332,14 @@ make_lispy_event (event)
              }
 #endif /* not USE_X_TOOLKIT && not USE_GTK */
 
-           /* Set `window' to the window under frame pixel coordinates
-              event->x/event->y.  */
-           window = window_from_coordinates (f, XINT (event->x),
-                                             XINT (event->y),
-                                             &part, &wx, &wy, 0);
-
-           if (!WINDOWP (window))
-             {
-               window = event->frame_or_window;
-               posn = Qnil;
-             }
-           else
-             {
-               /* It's a click in window window at frame coordinates
-                  event->x/ event->y.  */
-               struct window *w = XWINDOW (window);
-
-               /* Set event coordinates to window-relative coordinates
-                  for constructing the Lisp event below.  */
-               XSETINT (event->x, wx);
-               XSETINT (event->y, wy);
-
-               if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
-                 {
-                   /* Mode line or header line.  Look for a string under
-                      the mouse that may have a `local-map' property.  */
-                   Lisp_Object string;
-                   int charpos;
-
-                   posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
-                   string = mode_line_string (w, wx, wy, part, &charpos);
-                   if (STRINGP (string))
-                     string_info = Fcons (string, make_number (charpos));
-                 }
-               else if (part == ON_VERTICAL_BORDER)
-                 posn = Qvertical_line;
-               else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
-                 {
-                   int charpos;
-                   Lisp_Object object = marginal_area_string (w, wx, wy, part,
-                                                              &charpos);
-                   posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
-                   if (STRINGP (object))
-                     string_info = Fcons (object, make_number (charpos));
-                 }
-               else
-                 {
-                   Lisp_Object object;
-                   struct display_pos p;
-                   buffer_posn_from_coords (w, &wx, &wy, &object, &p);
-                   posn = make_number (CHARPOS (p.pos));
-                   if (STRINGP (object))
-                     string_info
-                       = Fcons (object,
-                                make_number (CHARPOS (p.string_pos)));
-                 }
-             }
-
-           position
-             = Fcons (window,
-                      Fcons (posn,
-                             Fcons (Fcons (event->x, event->y),
-                                    Fcons (make_number (event->timestamp),
-                                           (NILP (string_info)
-                                            ? Qnil
-                                            : Fcons (string_info, Qnil))))));
+           position = make_lispy_position (f, &event->x, &event->y,
+                                           event->timestamp);
          }
 #ifndef USE_TOOLKIT_SCROLL_BARS
        else
          {
            /* It's a scrollbar click.  */
+           Lisp_Object window;
            Lisp_Object portion_whole;
            Lisp_Object part;
 
@@ -5405,97 +5504,18 @@ make_lispy_event (event)
     case WHEEL_EVENT:
       {
        Lisp_Object position;
-       Lisp_Object window;
        Lisp_Object head;
        
        /* Build the position as appropriate for this mouse click.  */
-       enum window_part part;
        struct frame *f = XFRAME (event->frame_or_window);
-       Lisp_Object posn;
-       Lisp_Object string_info = Qnil;
-       int row, column;
-       int wx, wy;
-       position = Qnil;
 
        /* Ignore wheel events that were made on frame that have been
           deleted.  */
        if (! FRAME_LIVE_P (f))
          return Qnil;
 
-       /* EVENT->x and EVENT->y are frame-relative pixel
-          coordinates at this place.  Under old redisplay, COLUMN
-          and ROW are set to frame relative glyph coordinates
-          which are then used to determine whether this click is
-          in a menu (non-toolkit version).  */
-       pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
-                              &column, &row, NULL, 1);
-
-       /* Set `window' to the window under frame pixel coordinates
-          event->x/event->y.  */
-       window = window_from_coordinates (f, XINT (event->x),
-                                         XINT (event->y),
-                                         &part, &wx, &wy, 0);
-
-       if (!WINDOWP (window))
-         {
-           window = event->frame_or_window;
-           posn = Qnil;
-         }
-       else
-         {
-           /* It's a click in window window at frame coordinates
-              event->x/ event->y.  */
-           struct window *w = XWINDOW (window);
-       
-           /* Set event coordinates to window-relative coordinates
-              for constructing the Lisp event below.  */
-           XSETINT (event->x, wx);
-           XSETINT (event->y, wy);
-       
-           if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
-             {
-               /* Mode line or header line.  Look for a string under
-                  the mouse that may have a `local-map' property.  */
-               Lisp_Object string;
-               int charpos;
-
-               posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
-               string = mode_line_string (w, wx, wy, part, &charpos);
-               if (STRINGP (string))
-                 string_info = Fcons (string, make_number (charpos));
-             }
-           else if (part == ON_VERTICAL_BORDER)
-             posn = Qvertical_line;
-           else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
-             {
-               int charpos;
-               Lisp_Object object = marginal_area_string (w, wx, wy, part,
-                                                          &charpos);
-               posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
-               if (STRINGP (object))
-                 string_info = Fcons (object, make_number (charpos));
-             }
-           else
-             {
-               Lisp_Object object;
-               struct display_pos p;
-               buffer_posn_from_coords (w, &wx, &wy, &object, &p);
-               posn = make_number (CHARPOS (p.pos));
-               if (STRINGP (object))
-                 string_info
-                   = Fcons (object,
-                            make_number (CHARPOS (p.string_pos)));
-             }
-         }
-       
-       position
-         = Fcons (window,
-                  Fcons (posn,
-                         Fcons (Fcons (event->x, event->y),
-                                Fcons (make_number (event->timestamp),
-                                       (NILP (string_info)
-                                        ? Qnil
-                                        : Fcons (string_info, Qnil))))));
+       position = make_lispy_position (f, &event->x, &event->y,
+                                       event->timestamp);
 
        /* Set double or triple modifiers to indicate the wheel speed.  */
        {
@@ -5689,12 +5709,9 @@ make_lispy_event (event)
 
     case DRAG_N_DROP_EVENT:
       {
-       enum window_part part;
        FRAME_PTR f;
-       Lisp_Object window;
-       Lisp_Object posn;
+       Lisp_Object head, position;
        Lisp_Object files;
-       int wx, wy;
 
        /* The frame_or_window field should be a cons of the frame in
           which the event occurred and a list of the filenames
@@ -5710,60 +5727,17 @@ make_lispy_event (event)
        if (! FRAME_LIVE_P (f))
          return Qnil;
 
-       window = window_from_coordinates (f, XINT (event->x),
-                                          XINT (event->y),
-                                         &part, &wx, &wy, 0);
-
-       if (!WINDOWP (window))
-         {
-           window = XCAR (event->frame_or_window);
-           posn = Qnil;
-         }
-       else
-         {
-           /* It's an event in window `window' at frame coordinates
-              event->x/ event->y.  */
-           struct window *w = XWINDOW (window);
-
-           /* Set event coordinates to window-relative coordinates
-              for constructing the Lisp event below.  */
-           XSETINT (event->x, wx);
-           XSETINT (event->y, wy);
-
-           if (part == ON_MODE_LINE)
-             posn = Qmode_line;
-           else if (part == ON_VERTICAL_BORDER)
-             posn = Qvertical_line;
-           else if (part == ON_HEADER_LINE)
-             posn = Qheader_line;
-           else
-             {
-               Lisp_Object object;
-               struct display_pos p;
-               buffer_posn_from_coords (w, &wx, &wy, &object, &p);
-               posn = make_number (CHARPOS (p.pos));
-             }
-         }
-
-       {
-         Lisp_Object head, position;
-
-         position
-           = Fcons (window,
-                    Fcons (posn,
-                           Fcons (Fcons (event->x, event->y),
-                                  Fcons (make_number (event->timestamp),
-                                         Qnil))));
-
-         head = modify_event_symbol (0, event->modifiers,
-                                     Qdrag_n_drop, Qnil,
-                                     lispy_drag_n_drop_names,
-                                     &drag_n_drop_syms, 1);
-         return Fcons (head,
-                       Fcons (position,
-                              Fcons (files,
-                                     Qnil)));
-       }
+       position = make_lispy_position (f, &event->x, &event->y,
+                                       event->timestamp);
+
+       head = modify_event_symbol (0, event->modifiers,
+                                   Qdrag_n_drop, Qnil,
+                                   lispy_drag_n_drop_names,
+                                   &drag_n_drop_syms, 1);
+       return Fcons (head,
+                     Fcons (position,
+                            Fcons (files,
+                                   Qnil)));
       }
 #endif /* HAVE_MOUSE */
 
@@ -5836,59 +5810,12 @@ make_lispy_movement (frame, bar_window, part, x, y, time)
   /* Or is it an ordinary mouse movement?  */
   else
     {
-      enum window_part area;
-      Lisp_Object window;
-      Lisp_Object posn;
-      int wx, wy;
-
-      if (frame)
-       /* It's in a frame; which window on that frame?  */
-       window = window_from_coordinates (frame, XINT (x), XINT (y),
-                                         &area, &wx, &wy, 0);
-      else
-       window = Qnil;
+      Lisp_Object position;
 
-      if (WINDOWP (window))
-       {
-         struct window *w = XWINDOW (window);
-
-         /* Set window relative coordinates.  */
-         XSETINT (x, wx);
-         XSETINT (y, wy);
-
-         if (area == ON_MODE_LINE)
-           posn = Qmode_line;
-         else if (area == ON_VERTICAL_BORDER)
-           posn = Qvertical_line;
-         else if (area == ON_HEADER_LINE)
-           posn = Qheader_line;
-         else
-           {
-             Lisp_Object object;
-             struct display_pos p;
-             buffer_posn_from_coords (w, &wx, &wy, &object, &p);
-             posn = make_number (CHARPOS (p.pos));
-           }
-       }
-      else if (frame != 0)
-       {
-         XSETFRAME (window, frame);
-         posn = Qnil;
-       }
-      else
-       {
-         window = Qnil;
-         posn = Qnil;
-         XSETFASTINT (x, 0);
-         XSETFASTINT (y, 0);
-       }
+      position = make_lispy_position (frame, &x, &y, time);
 
       return Fcons (Qmouse_movement,
-                   Fcons (Fcons (window,
-                                 Fcons (posn,
-                                        Fcons (Fcons (x, y),
-                                               Fcons (make_number (time),
-                                                      Qnil)))),
+                   Fcons (position,
                           Qnil));
     }
 }
@@ -6126,7 +6053,7 @@ parse_modifiers (symbol)
                                         SBYTES (SYMBOL_NAME (symbol)) - end),
                            Qnil);
 
-      if (modifiers & ~VALMASK)
+      if (modifiers & ~INTMASK)
        abort ();
       XSETFASTINT (mask, modifiers);
       elements = Fcons (unmodified, Fcons (mask, Qnil));
@@ -6163,7 +6090,7 @@ apply_modifiers (modifiers, base)
   Lisp_Object cache, index, entry, new_symbol;
 
   /* Mask out upper bits.  We don't know where this value's been.  */
-  modifiers &= VALMASK;
+  modifiers &= INTMASK;
 
   /* The click modifier never figures into cache indices.  */
   cache = Fget (base, Qmodifier_cache);
@@ -6718,7 +6645,12 @@ read_avail_input (expected)
        /* ??? Is it really right to send the signal just to this process
           rather than to the whole process group?
           Perhaps on systems with FIONREAD Emacs is alone in its group.  */
-       kill (getpid (), SIGHUP);
+       {
+         if (! noninteractive)
+           kill (getpid (), SIGHUP);
+         else
+           n_to_read = 0;
+       }
       if (n_to_read == 0)
        return 0;
       if (n_to_read > sizeof cbuf)
@@ -6815,6 +6747,30 @@ read_avail_input (expected)
 }
 #endif /* not VMS */
 \f
+void
+handle_async_input ()
+{
+#ifdef BSD4_1
+  extern int select_alarmed;
+#endif
+  interrupt_input_pending = 0;
+
+  while (1)
+    {
+      int nread;
+      nread = read_avail_input (1);
+      /* -1 means it's not ok to read the input now.
+        UNBLOCK_INPUT will read it later; now, avoid infinite loop.
+        0 means there was no keyboard input available.  */
+      if (nread <= 0)
+       break;
+
+#ifdef BSD4_1
+      select_alarmed = 1;  /* Force the select emulator back to life */
+#endif
+    }
+}
+
 #ifdef SIGIO   /* for entire page */
 /* Note SIGIO has been undef'd if FIONREAD is missing.  */
 
@@ -6824,9 +6780,6 @@ input_available_signal (signo)
 {
   /* Must preserve main program's value of errno.  */
   int old_errno = errno;
-#ifdef BSD4_1
-  extern int select_alarmed;
-#endif
 
 #if defined (USG) && !defined (POSIX_SIGNALS)
   /* USG systems forget handlers when they are used;
@@ -6841,20 +6794,11 @@ input_available_signal (signo)
   if (input_available_clear_time)
     EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
 
-  while (1)
-    {
-      int nread;
-      nread = read_avail_input (1);
-      /* -1 means it's not ok to read the input now.
-        UNBLOCK_INPUT will read it later; now, avoid infinite loop.
-        0 means there was no keyboard input available.  */
-      if (nread <= 0)
-       break;
-
-#ifdef BSD4_1
-      select_alarmed = 1;  /* Force the select emulator back to life */
+#ifdef SYNC_INPUT
+  interrupt_input_pending = 1;
+#else
+  handle_async_input ();
 #endif
-    }
 
 #ifdef BSD4_1
   sigfree ();
@@ -6873,7 +6817,7 @@ void
 reinvoke_input_signal ()
 {
 #ifdef SIGIO
-  kill (getpid (), SIGIO);
+  handle_async_input ();
 #endif
 }
 
@@ -8928,6 +8872,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
       if (EVENT_HAS_PARAMETERS (key))
        {
          Lisp_Object kind;
+         Lisp_Object string;
 
          kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
          if (EQ (kind, Qmouse_click))
@@ -8935,7 +8880,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
              Lisp_Object window, posn;
 
              window = POSN_WINDOW      (EVENT_START (key));
-             posn   = POSN_BUFFER_POSN (EVENT_START (key));
+             posn   = POSN_POSN (EVENT_START (key));
 
              if (CONSP (posn)
                  || (!NILP (fake_prefixed_keys)
@@ -8993,7 +8938,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                  localized_local_map = 1;
                  start = EVENT_START (key);
 
-                 if (CONSP (start) && CONSP (XCDR (start)))
+                 if (CONSP (start) && POSN_INBUFFER_P (start))
                    {
                      pos = POSN_BUFFER_POSN (start);
                      if (INTEGERP (pos)
@@ -9044,11 +8989,11 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 
                  /* If on a mode line string with a local keymap,
                     reconsider the key sequence with that keymap.  */
-                 if (CONSP (POSN_STRING (EVENT_START (key))))
+                 if (string = POSN_STRING (EVENT_START (key)),
+                     (CONSP (string) && STRINGP (XCAR (string))))
                    {
-                     Lisp_Object string, pos, map, map2;
+                     Lisp_Object pos, map, map2;
 
-                     string = POSN_STRING (EVENT_START (key));
                      pos = XCDR (string);
                      string = XCAR (string);
                       if (XINT (pos) >= 0
@@ -9067,16 +9012,16 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 
                  goto replay_key;
                }
-             else if (CONSP (POSN_STRING (EVENT_START (key)))
-                      && NILP (from_string))
+             else if (NILP (from_string)
+                      && (string = POSN_STRING (EVENT_START (key)),
+                          (CONSP (string) && STRINGP (XCAR (string)))))
                {
                  /* For a click on a string, i.e. overlay string or a
                     string displayed via the `display' property,
                     consider `local-map' and `keymap' properties of
                     that string.  */
-                 Lisp_Object string, pos, map, map2;
+                 Lisp_Object pos, map, map2;
 
-                 string = POSN_STRING (EVENT_START (key));
                  pos = XCDR (string);
                  string = XCAR (string);
                  if (XINT (pos) >= 0
@@ -9103,7 +9048,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
            {
              Lisp_Object posn;
 
-             posn = POSN_BUFFER_POSN (EVENT_START (key));
+             posn = POSN_POSN (EVENT_START (key));
              /* Handle menu-bar events:
                 insert the dummy prefix event `menu-bar'.  */
              if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
@@ -9115,8 +9060,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 
                  /* Zap the position in key, so we know that we've
                     expanded it, and don't try to do so again.  */
-                 POSN_BUFFER_SET_POSN (EVENT_START (key),
-                                       Fcons (posn, Qnil));
+                 POSN_SET_POSN (EVENT_START (key),
+                                Fcons (posn, Qnil));
 
                  mock_input = t + 2;
                  goto replay_sequence;
@@ -9421,6 +9366,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 
              keybuf[t - 1] = new_key;
              mock_input = max (t, mock_input);
+             fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
+             keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
 
              goto replay_sequence;
            }
@@ -11392,19 +11339,19 @@ mark_kboards ()
     {
       if (kb->kbd_macro_buffer)
        for (p = kb->kbd_macro_buffer; p < kb->kbd_macro_ptr; p++)
-         mark_object (p);
-      mark_object (&kb->Voverriding_terminal_local_map);
-      mark_object (&kb->Vlast_command);
-      mark_object (&kb->Vreal_last_command);
-      mark_object (&kb->Vprefix_arg);
-      mark_object (&kb->Vlast_prefix_arg);
-      mark_object (&kb->kbd_queue);
-      mark_object (&kb->defining_kbd_macro);
-      mark_object (&kb->Vlast_kbd_macro);
-      mark_object (&kb->Vsystem_key_alist);
-      mark_object (&kb->system_key_syms);
-      mark_object (&kb->Vdefault_minibuffer_frame);
-      mark_object (&kb->echo_string);
+         mark_object (*p);
+      mark_object (kb->Voverriding_terminal_local_map);
+      mark_object (kb->Vlast_command);
+      mark_object (kb->Vreal_last_command);
+      mark_object (kb->Vprefix_arg);
+      mark_object (kb->Vlast_prefix_arg);
+      mark_object (kb->kbd_queue);
+      mark_object (kb->defining_kbd_macro);
+      mark_object (kb->Vlast_kbd_macro);
+      mark_object (kb->Vsystem_key_alist);
+      mark_object (kb->system_key_syms);
+      mark_object (kb->Vdefault_minibuffer_frame);
+      mark_object (kb->echo_string);
     }
   {
     struct input_event *event;
@@ -11412,10 +11359,13 @@ mark_kboards ()
       {
        if (event == kbd_buffer + KBD_BUFFER_SIZE)
          event = kbd_buffer;
-       mark_object (&event->x);
-       mark_object (&event->y);
-       mark_object (&event->frame_or_window);
-       mark_object (&event->arg);
+       mark_object (event->x);
+       mark_object (event->y);
+       mark_object (event->frame_or_window);
+       mark_object (event->arg);
       }
   }
 }
+
+/* arch-tag: 774e34d7-6d31-42f3-8397-e079a4e4c9ca
+   (do not change this comment) */