bug-gnu-emacs
[Top][All Lists]
Advanced

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

fix for mouse-sensitive marginal text


From: Dave Love
Subject: fix for mouse-sensitive marginal text
Date: 10 Apr 2002 23:28:59 +0100
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.1.95

These changes (against 21.1-ish code) fix mouse-sensitive text in
marginal regions.  Someone might like to use them to extend GUD,
e.g. to mark breakpoints (and to replace the overlay arrow, at least
on ttys when the redisplay is sorted out).

This doesn't work with xterm-mouse on a tty, but tty redisplay get
messed up by margins anyhow.  [To see that, in *scratch*, set a left
margin, type RET at the start of the second line and then C-l.]  It
probably needs primitive support to get at the glyph string to make
this work.

It seems to need redisplay changes (i.e. recursive display properties)
to have mouse-sensitive images in the margins.  Other systems need the
equivalent of the xterm.c change, of course.

2002-04-05  Dave Love  <address@hidden>

        * dispnew.c (marginal_area_string): New.

        * window.c (window_part): Add ON_LEFT_MARGIN, ON_RIGHT_MARGIN.
        (Qleft_margin, Qright_margin): Declare.
        (coordinates_in_window, (Fcoordinates_in_window_p): Deal with
        margins.

        * xterm.c (note_mode_line_or_margin_highlight): Renamed from
        note_mode_line_highlight and extended.

        * keyboard.c (Qleft_margin, Qright_margin): Declare.
        (make_lispy_event): Deal with mouse events in margins.

2002-04-05  Dave Love  <address@hidden>

        * help.el (string-key-binding): Deal with margin events.

Index: src/dispnew.c
===================================================================
RCS file: /cvs/emacs/src/dispnew.c,v
retrieving revision 1.284.4.4
diff -u -p -r1.284.4.4 dispnew.c
--- src/dispnew.c       15 Nov 2001 10:30:41 -0000      1.284.4.4
+++ src/dispnew.c       8 Apr 2002 12:48:24 -0000
@@ -1,5 +1,5 @@
 /* Updating of data structures for redisplay.
-   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999, 2000, 2001
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999, 2000, 2001, 2002
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -5811,6 +5811,50 @@ mode_line_string (w, x, y, mode_line_p, 
            break;
          }
     }
+
+  return string;
+}
+
+
+/* Value is the string under window-relative coordinates X/Y in either
+   marginal area, or nil if none.  *CHARPOS is set to the position in
+   the string returned.  */
+
+Lisp_Object
+marginal_area_string (w, x, y, area, charpos)
+     struct window *w;
+     int x, y;
+     int *charpos;
+     int area;
+{
+  struct glyph_row *row = w->current_matrix->rows;
+  struct glyph *glyph, *end;
+  int x0, i, wy = y;
+  Lisp_Object string = Qnil;
+
+  if (area != 6 && area != 7)
+    abort ();
+
+  for (i = 0; i < w->current_matrix->nrows; ++i, ++row)
+    if (wy >= row->y && wy < MATRIX_ROW_BOTTOM_Y (row))
+      break;
+
+  /* Find the glyph under X.  If we find one with a string object,
+     it's the one we were looking for.  */
+  glyph = row->glyphs[(area == 6) ? LEFT_MARGIN_AREA : RIGHT_MARGIN_AREA];
+  end = glyph + row->used[(area == 6) ? LEFT_MARGIN_AREA : RIGHT_MARGIN_AREA];
+  if (area == 7)
+    x0 = window_box_width (w, TEXT_AREA)
+      + window_box_width (w, LEFT_MARGIN_AREA);
+  else
+    x0 = 0;
+  for (; glyph < end; x0 += glyph->pixel_width, ++glyph)
+    if (x >= x0 && x < x0 + glyph->pixel_width)
+      {
+       string = glyph->object;
+       *charpos = glyph->charpos;
+       break;
+      }
 
   return string;
 }
Index: src/xterm.c
===================================================================
RCS file: /cvs/emacs/src/xterm.c,v
retrieving revision 1.650.4.22
diff -u -p -r1.650.4.22 xterm.c
--- src/xterm.c 1 Feb 2002 21:13:00 -0000       1.650.4.22
+++ src/xterm.c 8 Apr 2002 12:49:25 -0000
@@ -1,5 +1,5 @@
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
+   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -412,7 +412,8 @@ static int fast_find_string_pos P_ ((str
 static void set_output_cursor P_ ((struct cursor_pos *));
 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
                                           int *, int *, int *, int));
-static void note_mode_line_highlight P_ ((struct window *, int, int));
+static void note_mode_line_or_margin_highlight P_ ((struct window *, int,
+                                                   int, int));
 static void note_mouse_highlight P_ ((struct frame *, int, int));
 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
@@ -6774,78 +6775,52 @@ frame_to_window_pixel_xy (w, x, y)
 }
 
 
-/* Take proper action when mouse has moved to the mode or header line of
-   window W, x-position X.  MODE_LINE_P non-zero means mouse is on the
-   mode line.  X is relative to the start of the text display area of
-   W, so the width of bitmap areas and scroll bars must be subtracted
-   to get a position relative to the start of the mode line.  */
+/* Take proper action when mouse has moved to the mode or header line
+   or marginal area of window W, x-position X and y-position Y.  Area
+   is 1, 3, 6 or 7 for the mode line, header line, left and right
+   marginal area respectively.  X is relative to the start of the text
+   display area of W, so the width of bitmap areas and scroll bars
+   must be subtracted to get a position relative to the start of the
+   mode line.  */
 
 static void
-note_mode_line_highlight (w, x, mode_line_p)
+note_mode_line_or_margin_highlight (w, x, y, portion)
      struct window *w;
-     int x, mode_line_p;
+     int x, y, portion;
 {
   struct frame *f = XFRAME (w->frame);
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
   struct glyph_row *row;
+  int i, area, charpos;
+  Lisp_Object string, help, map, pos;
 
-  if (mode_line_p)
-    row = MATRIX_MODE_LINE_ROW (w->current_matrix);
+  if (portion == 1 || portion == 3)
+    string = mode_line_string (w, x, y, portion == 1, &charpos);
   else
-    row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
+    string = marginal_area_string (w, x, y, portion, &charpos);
 
-  if (row->enabled_p)
+  if (STRINGP (string))
     {
-      struct glyph *glyph, *end;
-      Lisp_Object help, map;
-      int x0;
-      
-      /* Find the glyph under X.  */
-      glyph = row->glyphs[TEXT_AREA];
-      end = glyph + row->used[TEXT_AREA];
-      x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
-             + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
-      
-      while (glyph < end
-            && x >= x0 + glyph->pixel_width)
-       {
-         x0 += glyph->pixel_width;
-         ++glyph;
-       }
-
-      if (glyph < end
-         && STRINGP (glyph->object)
-         && XSTRING (glyph->object)->intervals
-         && glyph->charpos >= 0
-         && glyph->charpos < XSTRING (glyph->object)->size)
-       {
-         /* If we're on a string with `help-echo' text property,
-            arrange for the help to be displayed.  This is done by
-            setting the global variable help_echo to the help string.  */
-         help = Fget_text_property (make_number (glyph->charpos),
-                                    Qhelp_echo, glyph->object);
-         if (!NILP (help))
-           {
-             help_echo = help;
-             XSETWINDOW (help_echo_window, w);
-             help_echo_object = glyph->object;
-             help_echo_pos = glyph->charpos;
-           }
-
-         /* Change the mouse pointer according to what is under X/Y.  */
-         map = Fget_text_property (make_number (glyph->charpos),
-                                   Qlocal_map, glyph->object);
-         if (KEYMAPP (map))
-           cursor = f->output_data.x->nontext_cursor;
-         else
-           {
-             map = Fget_text_property (make_number (glyph->charpos),
-                                       Qkeymap, glyph->object);
-             if (KEYMAPP (map))
-               cursor = f->output_data.x->nontext_cursor;
-           }
-       }
+      pos = make_number (charpos);
+      /* If we're on a string with `help-echo' text property, arrange
+        for the help to be displayed.  This is done by setting the
+        global variable help_echo to the help string.  */
+      help = Fget_text_property (pos, Qhelp_echo, string);
+      if (!NILP (help))
+       {
+         help_echo = help;
+         XSETWINDOW (help_echo_window, w);
+         help_echo_object = string;
+         help_echo_pos = charpos;
+       }
+
+      /* Change the mouse pointer according to what is under X/Y.  */
+      map = Fget_text_property (pos, Qlocal_map, string);
+      if (!KEYMAPP (map))
+       map = Fget_text_property (pos, Qkeymap, string);
+      if (KEYMAPP (map))
+       cursor = f->output_data.x->nontext_cursor;
     }
 
   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
@@ -6915,10 +6890,10 @@ note_mouse_highlight (f, x, y)
       return;
     }
 
-  /* Mouse is on the mode or header line?  */
-  if (portion == 1 || portion == 3)
+  /* Mouse is on the mode, header line or margin?  */
+  if (portion == 1 || portion == 3 || portion == 6 || portion == 7)
     {
-      note_mode_line_highlight (w, x, portion == 1);
+      note_mode_line_or_margin_highlight (w, x, y, portion);
       return;
     }
   
Index: src/keyboard.c
===================================================================
RCS file: /cvs/emacs/src/keyboard.c,v
retrieving revision 1.626.4.2
diff -u -p -r1.626.4.2 keyboard.c
--- src/keyboard.c      24 Jan 2002 17:20:15 -0000      1.626.4.2
+++ src/keyboard.c      8 Apr 2002 12:50:04 -0000
@@ -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, 2001
+   Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99, 2000, 2001, 2002
      Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -584,6 +584,7 @@ Lisp_Object Qmode_line;
 Lisp_Object Qvertical_line;
 Lisp_Object Qvertical_scroll_bar;
 Lisp_Object Qmenu_bar;
+extern Lisp_Object Qleft_margin, Qright_margin;
 
 Lisp_Object recursive_edit_unwind (), command_loop ();
 Lisp_Object Fthis_command_keys ();
@@ -4828,6 +4829,15 @@ make_lispy_event (event)
                  }
                else if (part == 2)
                  posn = Qvertical_line;
+               else if (part == 6 || part == 7)
+                 {
+                   int charpos;
+                   Lisp_Object object = marginal_area_string (w, wx, wy, part,
+                                                              &charpos);
+                   posn = (part == 6) ? Qleft_margin : Qright_margin;
+                   if (STRINGP (object))
+                     string_info = Fcons (object, make_number (charpos));
+                 }
                else
                  {
                    Lisp_Object object;
Index: src/window.c
===================================================================
RCS file: /cvs/emacs/src/window.c,v
retrieving revision 1.376.4.7
diff -u -p -r1.376.4.7 window.c
--- src/window.c        2 Feb 2002 08:16:26 -0000       1.376.4.7
+++ src/window.c        8 Apr 2002 12:50:44 -0000
@@ -1,6 +1,6 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985,86,87,93,94,95,96,97,1998,2000, 2001
+   Copyright (C) 1985,86,87,93,94,95,96,97,1998,2000, 2001, 2002
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -61,12 +61,15 @@ enum window_part
   ON_VERTICAL_BORDER,
   ON_HEADER_LINE,
   ON_LEFT_FRINGE,
-  ON_RIGHT_FRINGE
+  ON_RIGHT_FRINGE,
+  ON_LEFT_MARGIN,
+  ON_RIGHT_MARGIN
 };
 
 
 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
 Lisp_Object Qwindow_size_fixed, Qleft_fringe, Qright_fringe;
+extern Lisp_Object Qleft_margin, Qright_margin;
 extern Lisp_Object Qheight, Qwidth;
 
 static int displayed_window_lines P_ ((struct window *));
@@ -503,7 +506,9 @@ and BOTTOM is one more than the bottommo
       return 3.
    if it is on the window's top line, return 4;
    if it is in the bitmap area to the left/right of the window,
-   return 5 or 6, and convert *X and *Y to window-relative corrdinates.
+   return 5 or 6, and convert *X and *Y to window-relative corrdinates;
+   if it is in the marginal area to the left/right of the window,
+   return 7 or 8, and convert *X and *Y to window-relative corrdinates.
 
    X and Y are frame relative pixel coordinates.  */
 
@@ -618,9 +623,16 @@ coordinates_in_window (w, x, y)
        }
       else
        {
-         *x -= left_x;
-         *y -= top_y;
-         part = ON_TEXT;
+         if (*x <= window_box_right (w, LEFT_MARGIN_AREA))
+           part = ON_LEFT_MARGIN;
+         else if (*x >= window_box_left (w, RIGHT_MARGIN_AREA))
+           part = ON_RIGHT_MARGIN;
+         else
+           {
+             part = ON_TEXT;
+             *x -= left_x;
+             *y -= top_y;
+           }
        }
     }
   else
@@ -648,10 +660,17 @@ coordinates_in_window (w, x, y)
        }
       else
        {
-         /* Convert X and Y to window-relative pixel coordinates.  */
-         *x -= left_x;
-         *y -= top_y;
-         part = ON_TEXT;
+         if (*x <= window_box_right (w, LEFT_MARGIN_AREA))
+           part = ON_LEFT_MARGIN;
+         else if (*x >= window_box_left (w, RIGHT_MARGIN_AREA))
+           part = ON_RIGHT_MARGIN;
+         else
+           {
+             part = ON_TEXT;
+             /* Convert X and Y to window-relative pixel coordinates.  */
+             *x -= left_x;
+             *y -= top_y;
+           }
        }
     }
 
@@ -674,7 +693,9 @@ If they are in the fringe to the left of
    `left-fringe' is returned, if they are in the area on the right of\n\
    the window, `right-fringe' is returned.\n\
 If they are on the border between WINDOW and its right sibling,\n\
-   `vertical-line' is returned.")
+   `vertical-line' is returned.\n\
+If they are in the windows's left or right marginal areas, `left-margin'\n\
+   or `right-margin' is returned.")
   (coordinates, window)
      register Lisp_Object coordinates, window;
 {
@@ -719,6 +740,12 @@ If they are on the border between WINDOW
       
     case ON_RIGHT_FRINGE:
       return Qright_fringe;
+
+    case ON_LEFT_MARGIN:
+      return Qleft_margin;
+      
+    case ON_RIGHT_MARGIN:
+      return Qright_margin;
 
     default:
       abort ();
Index: lisp/help.el
===================================================================
RCS file: /cvs/emacs/lisp/help.el,v
retrieving revision 1.231
diff -u -p -r1.231 help.el
--- lisp/help.el        1 Oct 2001 07:01:24 -0000       1.231
+++ lisp/help.el        5 Apr 2002 20:07:29 -0000
@@ -212,7 +212,8 @@ If KEY is an event on a string, and that
 or `keymap' property, return the binding of KEY in the string's keymap."
   (let* ((defn nil)
         (start (when (vectorp key)
-                 (if (memq (aref key 0) '(mode-line header-line))
+                 (if (memq (aref key 0) '(mode-line header-line
+                                          left-margin right-margin))
                      (event-start (aref key 1))
                    (and (consp (aref key 0)) 
                         (event-start (aref key 0))))))
@@ -220,7 +220,9 @@ or `keymap' property, return the binding
     (when string-info
       (let* ((string (car string-info))
             (pos (cdr string-info))
-            (local-map (and (> pos 0)
+            (local-map (and (or (> pos 0) ; ??
+                                (and (eq 'margin (aref key 0))
+                                     (>= pos 0)))
                             (< pos (length string))
                             (or (get-text-property pos 'local-map string)
                                 (get-text-property pos 'keymap string)))))
Index: lispref/commands.texi
===================================================================
RCS file: /cvs/emacs/lispref/commands.texi,v
retrieving revision 1.33
diff -u -p -r1.33 commands.texi
--- lispref/commands.texi       10 Sep 2001 05:06:03 -0000      1.33
+++ lispref/commands.texi       8 Apr 2002 12:47:16 -0000
@@ -1110,6 +1110,15 @@ this form:
  @var{click-count})
 @end example
 
+or, for clicks on strings in the mode line, header line or marginal
+areas:
+
address@hidden
+(@var{event-type}
+ (@var{window} @var{buffer-pos} (@var{x} . @var{y}) @var{timestamp} 
(@var{string} . @var{string-pos})
+ @var{click-count})
address@hidden example
+
 Here is what the elements normally mean:
 
 @table @asis
@@ -1140,7 +1149,16 @@ This is the buffer position of the chara
 @item @var{timestamp}
 This is the time at which the event occurred, in milliseconds.  (Since
 this value wraps around the entire range of Emacs Lisp integers in about
-five hours, it is useful only for relating the times of nearby events.)
+five hours, it is useful only for relating the times of nearby
+events.)
+
address@hidden @var{string}
+This is the string on which the click occurred, including any
+properties.
+
address@hidden @var{string-pos}
+This is the position in the string on which the click occurred,
+relevant if properties at the click need to be looked up.
 
 @item @var{click-count}
 This is the number of rapid repeated presses so far of the same mouse
@@ -1158,10 +1176,11 @@ If the location is in a scroll bar, then
 the top or left end of the scroll bar, and @var{whole} is the length of
 the entire scroll bar.
 
-If the position is on a mode line or the vertical line separating
address@hidden from its neighbor to the right, then @var{buffer-pos} is
-the symbol @code{mode-line}, @code{header-line}, or
address@hidden  For the mode line, @var{y} does not have
+If the position is on a mode line, the vertical line separating
address@hidden from its neighbor to the right, or in a marginal area,
+then @var{buffer-pos} is the symbol @code{mode-line},
address@hidden, @code{vertical-line}, @code{left-margin}, or
address@hidden  For the mode line, @var{y} does not have
 meaningful data.  For the vertical line, @var{x} does not have
 meaningful data.
 



reply via email to

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