From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Dave Love Newsgroups: gmane.emacs.bugs Subject: fix for mouse-sensitive marginal text Date: 10 Apr 2002 23:28:59 +0100 Sender: bug-gnu-emacs-admin@gnu.org Message-ID: NNTP-Posting-Host: localhost.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: main.gmane.org 1018477820 16552 127.0.0.1 (10 Apr 2002 22:30:20 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Wed, 10 Apr 2002 22:30:20 +0000 (UTC) Return-path: Original-Received: from fencepost.gnu.org ([199.232.76.164]) by main.gmane.org with esmtp (Exim 3.33 #1 (Debian)) id 16vQbb-0004Ip-00 for ; Thu, 11 Apr 2002 00:30:19 +0200 Original-Received: from localhost ([127.0.0.1] helo=fencepost.gnu.org) by fencepost.gnu.org with esmtp (Exim 3.34 #1 (Debian)) id 16vQbW-0006WF-00; Wed, 10 Apr 2002 18:30:14 -0400 Original-Received: from djlvig.dl.ac.uk ([148.79.112.146]) by fencepost.gnu.org with smtp (Exim 3.34 #1 (Debian)) id 16vQaN-0006Nc-00 for ; Wed, 10 Apr 2002 18:29:03 -0400 Original-Received: from fx by djlvig.dl.ac.uk with local (Exim 3.12 #1 (Debian)) id 16vQaL-0004aS-00 for ; Wed, 10 Apr 2002 23:29:01 +0100 X-Face: "_!nmR@11ZNuumt0oqG"Y3Hfy|;FGz)`"ul[G?ah6k-oNyDW?3/Nq3Qab$kUnUQ_d4};kPl R=}-Vqfo|S5mThi-kaBR=>%g5a3-OvnEhdHu{^APIaP:b}0m!$bDC>SX zz'r)e?`at?tpD*+~b+pf Original-To: bug-gnu-emacs@gnu.org Original-Lines: 482 User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.1.95 Errors-To: bug-gnu-emacs-admin@gnu.org X-BeenThere: bug-gnu-emacs@gnu.org X-Mailman-Version: 2.0.9 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Bug reports for GNU Emacs, the Swiss army knife of text editors List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.emacs.bugs:554 X-Report-Spam: http://spam.gmane.org/gmane.emacs.bugs:554 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 * 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 * 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: + +@example +(@var{event-type} + (@var{window} @var{buffer-pos} (@var{x} . @var{y}) @var{timestamp} (@var{string} . @var{string-pos}) + @var{click-count}) +@end 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.) + +@item @var{string} +This is the string on which the click occurred, including any +properties. + +@item @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 -@var{window} from its neighbor to the right, then @var{buffer-pos} is -the symbol @code{mode-line}, @code{header-line}, or -@code{vertical-line}. For the mode line, @var{y} does not have +If the position is on a mode line, the vertical line separating +@var{window} from its neighbor to the right, or in a marginal area, +then @var{buffer-pos} is the symbol @code{mode-line}, +@code{header-line}, @code{vertical-line}, @code{left-margin}, or +@code{right-margin}. For the mode line, @var{y} does not have meaningful data. For the vertical line, @var{x} does not have meaningful data.