]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
(temp_output_buffer_setup): Use new type for overlays_(before|after).
[gnu-emacs] / src / keyboard.c
index c8780867bb0cdca91f31a980635746886273570b..ba137f67cb6615e793fdf656dc882c97d12d0335 100644 (file)
@@ -547,9 +547,6 @@ Lisp_Object Qhelp_echo;
 /* Symbols to denote kinds of events.  */
 Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
-#if defined(WINDOWSNT) || defined(MAC_OSX)
-Lisp_Object Qmouse_wheel;
-#endif
 #ifdef WINDOWSNT
 Lisp_Object Qlanguage_change;
 #endif
@@ -3737,6 +3734,7 @@ discard_mouse_events ()
        sp = kbd_buffer;
 
       if (sp->kind == MOUSE_CLICK_EVENT
+         || sp->kind == WHEEL_EVENT
 #ifdef WINDOWSNT
          || sp->kind == W32_SCROLL_BAR_CLICK_EVENT
 #endif
@@ -4436,9 +4434,7 @@ timer_check (do_it_now)
 static Lisp_Object accent_key_syms;
 static Lisp_Object func_key_syms;
 static Lisp_Object mouse_syms;
-#if defined(WINDOWSNT) || defined(MAC_OSX)
-static Lisp_Object mouse_wheel_syms;
-#endif
+static Lisp_Object wheel_syms;
 static Lisp_Object drag_n_drop_syms;
 
 /* This is a list of keysym codes for special "accent" characters.
@@ -4892,21 +4888,11 @@ static char *iso_lispy_function_keys[] =
 
 Lisp_Object Vlispy_mouse_stem;
 
-#if defined(WINDOWSNT) || defined(MAC_OSX)
-/* mouse-wheel events are generated by the wheel on devices such as
-   the MS Intellimouse.  The wheel sits in between the left and right
-   mouse buttons, and is typically used to scroll or zoom the window
-   underneath the pointer.  mouse-wheel events specify the object on
-   which they operate, and a delta corresponding to the amount and
-   direction that the wheel is rotated.  Clicking the mouse-wheel
-   generates a mouse-2 event.  */
-static char *lispy_mouse_wheel_names[] =
-{
-  "mouse-wheel"
+static char *lispy_wheel_names[] =
+{
+  "wheel-up", "wheel-down"
 };
 
-#endif /* WINDOWSNT */
-
 /* drag-n-drop events are generated when a set of selected files are
    dragged from another application and dropped onto an Emacs window.  */
 static char *lispy_drag_n_drop_names[] =
@@ -5115,6 +5101,7 @@ make_lispy_event (event)
            Lisp_Object posn;
            Lisp_Object string_info = Qnil;
            int row, column;
+           int wx, wy;
 
            /* Ignore mouse events that were made on frame that
               have been deleted.  */
@@ -5186,7 +5173,8 @@ make_lispy_event (event)
            /* 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, 0);
+                                             XINT (event->y),
+                                             &part, &wx, &wy, 0);
 
            if (!WINDOWP (window))
              {
@@ -5199,11 +5187,6 @@ make_lispy_event (event)
                   event->x/ event->y.  */
                struct window *w = XWINDOW (window);
 
-               /* Get window relative coordinates.  Original code
-                  `rounded' this to glyph boundaries.  */
-               int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x));
-               int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y));
-
                /* Set event coordinates to window-relative coordinates
                   for constructing the Lisp event below.  */
                XSETINT (event->x, wx);
@@ -5419,6 +5402,192 @@ 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))))));
+
+       /* Set double or triple modifiers to indicate the wheel speed.  */
+       {
+         /* On window-system frames, use the value of
+            double-click-fuzz as is.  On other frames, interpret it
+            as a multiple of 1/8 characters.  */
+         struct frame *f;
+         int fuzz;
+         int is_double;
+
+         if (WINDOWP (event->frame_or_window))
+           f = XFRAME (XWINDOW (event->frame_or_window)->frame);
+         else if (FRAMEP (event->frame_or_window))
+           f = XFRAME (event->frame_or_window);
+         else
+           abort ();
+
+         if (FRAME_WINDOW_P (f))
+           fuzz = double_click_fuzz;
+         else
+           fuzz = double_click_fuzz / 8;
+
+         is_double = (last_mouse_button < 0
+                      && (abs (XINT (event->x) - last_mouse_x) <= fuzz)
+                      && (abs (XINT (event->y) - last_mouse_y) <= fuzz)
+                      && button_down_time != 0
+                      && (EQ (Vdouble_click_time, Qt)
+                          || (INTEGERP (Vdouble_click_time)
+                              && ((int)(event->timestamp - button_down_time)
+                                  < XINT (Vdouble_click_time)))));
+         if (is_double)
+           {
+             double_click_count++;
+             event->modifiers |= ((double_click_count > 2)
+                                  ? triple_modifier
+                                  : double_modifier);
+           }
+         else
+           {
+             double_click_count = 1;
+             event->modifiers |= click_modifier;
+           }
+
+         button_down_time = event->timestamp;
+         /* Use a negative value to distinguish wheel from mouse button.  */
+         last_mouse_button = -1;
+         last_mouse_x = XINT (event->x);
+         last_mouse_y = XINT (event->y);
+       }
+
+       {
+         int symbol_num;
+
+         if (event->modifiers & up_modifier)
+           {
+             /* Emit a wheel-up event.  */
+             event->modifiers &= ~up_modifier;
+             symbol_num = 0;
+           }
+         else if (event->modifiers & down_modifier)
+           {
+             /* Emit a wheel-down event.  */
+             event->modifiers &= ~down_modifier;
+             symbol_num = 1;
+           }
+         else
+           /* Every wheel event should either have the down_modifier or
+              the up_modifier set.  */
+           abort ();
+
+         /* Get the symbol we should use for the wheel event.  */
+         head = modify_event_symbol (symbol_num,
+                                     event->modifiers,
+                                     Qmouse_click,
+                                     Qnil,
+                                     lispy_wheel_names,
+                                     &wheel_syms,
+                                     ASIZE (wheel_syms));
+       }
+
+       if (event->modifiers & (double_modifier | triple_modifier))
+         return Fcons (head,
+                       Fcons (position,
+                              Fcons (make_number (double_click_count),
+                                     Qnil)));
+       else
+         return Fcons (head,
+                       Fcons (position,
+                              Qnil));
+      }
+
+
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
       /* We don't have down and up events if using toolkit scroll bars,
@@ -5517,79 +5686,6 @@ make_lispy_event (event)
        }
       }
 #endif /* WINDOWSNT */
-#if defined(WINDOWSNT) || defined(MAC_OSX)
-    case MOUSE_WHEEL_EVENT:
-      {
-       enum window_part part;
-       FRAME_PTR f = XFRAME (event->frame_or_window);
-       Lisp_Object window;
-       Lisp_Object posn;
-       Lisp_Object head, position;
-       int row, column;
-
-       /* Ignore mouse events that were made on frame that
-          have been deleted.  */
-       if (! FRAME_LIVE_P (f))
-         return Qnil;
-       pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
-                              &column, &row, NULL, 1);
-       window = window_from_coordinates (f, XINT (event->x),
-                                          XINT (event->y), &part, 0);
-
-       if (!WINDOWP (window))
-         {
-           window = event->frame_or_window;
-           posn = Qnil;
-         }
-       else
-         {
-           int pixcolumn, pixrow;
-           column -= XINT (XWINDOW (window)->left);
-           row -= XINT (XWINDOW (window)->top);
-           glyph_to_pixel_coords (XWINDOW(window), column, row,
-                                   &pixcolumn, &pixrow);
-           XSETINT (event->x, pixcolumn);
-           XSETINT (event->y, pixrow);
-
-           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 (XWINDOW (window), &column, &row,
-                                        &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,
-                                     Qmouse_wheel, Qnil,
-                                     lispy_mouse_wheel_names,
-                                     &mouse_wheel_syms, 1);
-         return Fcons (head,
-                       Fcons (position,
-                              /* Insert 1 here so event-click-count works.  */
-                              Fcons (make_number (1),
-                                     Fcons (make_number (event->code),
-                                            Qnil))));
-       }
-      }
-#endif /* WINDOWSNT || MAC_OSX */
 
     case DRAG_N_DROP_EVENT:
       {
@@ -5598,6 +5694,7 @@ make_lispy_event (event)
        Lisp_Object window;
        Lisp_Object posn;
        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
@@ -5614,7 +5711,8 @@ make_lispy_event (event)
          return Qnil;
 
        window = window_from_coordinates (f, XINT (event->x),
-                                          XINT (event->y), &part, 0);
+                                          XINT (event->y),
+                                         &part, &wx, &wy, 0);
 
        if (!WINDOWP (window))
          {
@@ -5627,10 +5725,6 @@ make_lispy_event (event)
               event->x/ event->y.  */
            struct window *w = XWINDOW (window);
 
-           /* Get window relative coordinates.  */
-           int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x));
-           int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y));
-
            /* Set event coordinates to window-relative coordinates
               for constructing the Lisp event below.  */
            XSETINT (event->x, wx);
@@ -5745,21 +5839,20 @@ make_lispy_movement (frame, bar_window, part, x, y, time)
       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, 0);
+       window = window_from_coordinates (frame, XINT (x), XINT (y),
+                                         &area, &wx, &wy, 0);
       else
        window = Qnil;
 
       if (WINDOWP (window))
        {
          struct window *w = XWINDOW (window);
-         int wx, wy;
 
-         /* Get window relative coordinates.  */
-         wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (x));
-         wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (y));
+         /* Set window relative coordinates.  */
          XSETINT (x, wx);
          XSETINT (y, wy);
 
@@ -6534,6 +6627,7 @@ record_asynch_buffer_change ()
 {
   struct input_event event;
   Lisp_Object tem;
+  EVENT_INIT (event);
 
   event.kind = BUFFER_SWITCH_EVENT;
   event.frame_or_window = Qnil;
@@ -6592,6 +6686,9 @@ read_avail_input (expected)
   register int i;
   int nread;
 
+  for (i = 0; i < KBD_BUFFER_SIZE; i++)
+    EVENT_INIT (buf[i]);
+
   if (read_socket_hook)
     /* No need for FIONREAD or fcntl; just say don't wait.  */
     nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE, expected);
@@ -6621,7 +6718,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)
@@ -7929,7 +8031,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
   register Lisp_Object name;
   int nlength;
   /* FIXME: Use the minibuffer's frame width.  */
-  int width = FRAME_WIDTH (SELECTED_FRAME ()) - 4;
+  int width = FRAME_COLS (SELECTED_FRAME ()) - 4;
   int idx = -1;
   int nobindings = 1;
   Lisp_Object rest, vector;
@@ -9324,6 +9426,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;
            }
@@ -10680,10 +10784,6 @@ syms_of_keyboard ()
   staticpro (&Qfunction_key);
   Qmouse_click = intern ("mouse-click");
   staticpro (&Qmouse_click);
-#if defined(WINDOWSNT) || defined(MAC_OSX)
-  Qmouse_wheel = intern ("mouse-wheel");
-  staticpro (&Qmouse_wheel);
-#endif
 #ifdef WINDOWSNT
   Qlanguage_change = intern ("language-change");
   staticpro (&Qlanguage_change);
@@ -10798,6 +10898,8 @@ syms_of_keyboard ()
   staticpro (&button_down_location);
   mouse_syms = Fmake_vector (make_number (1), Qnil);
   staticpro (&mouse_syms);
+  wheel_syms = Fmake_vector (make_number (2), Qnil);
+  staticpro (&wheel_syms);
 
   {
     int i;
@@ -10832,12 +10934,8 @@ syms_of_keyboard ()
   func_key_syms = Qnil;
   staticpro (&func_key_syms);
 
-#if defined(WINDOWSNT) || defined(MAC_OSX)
-  mouse_wheel_syms = Qnil;
-  staticpro (&mouse_wheel_syms);
   drag_n_drop_syms = Qnil;
   staticpro (&drag_n_drop_syms);
-#endif
 
   unread_switch_frame = Qnil;
   staticpro (&unread_switch_frame);
@@ -11289,3 +11387,42 @@ keys_of_keyboard ()
   initial_define_lispy_key (Vspecial_event_map, "save-session",
                            "handle-save-session");
 }
+
+/* Mark the pointers in the kboard objects.
+   Called by the Fgarbage_collector.  */
+void
+mark_kboards ()
+{
+  KBOARD *kb;
+  Lisp_Object *p;
+  for (kb = all_kboards; kb; kb = kb->next_kboard)
+    {
+      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);
+    }
+  {
+    struct input_event *event;
+    for (event = kbd_fetch_ptr; event != kbd_store_ptr; event++)
+      {
+       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);
+      }
+  }
+}