From 5f2c76c6cee2b5d2d84ffd409839fd58d2ad16fa Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Sun, 3 Jun 2012 17:03:23 +0800 Subject: Implement default help-echo for mode line. * lisp/bindings.el: Remove explicit help-echo from format-mode-line. (mode-line-front-space, mode-line-end-spaces) (mode-line-misc-info): New variables. (mode-line-modes, mode-line-position): Move the default value to the variable definition. (mode-line-default-help-echo): New defcustom. * src/buffer.c (buffer_local_value_1): New function, split from Fbuffer_local_value; can return Qunbound. (Fbuffer_local_value): Use it. (Vmode_line_format): Docstring tweaks. * src/xdisp.c (calc_pixel_width_or_height): Use Fbuffer_local_value. (note_mode_line_or_margin_highlight): If there is no help echo, use mode-line-default-help-echo. Handle the case where the mouse position is past the end of the mode line string. * doc/lispref/modes.texi (Mode Line Data): Use "mode line construct" terminology for consistency. --- src/ChangeLog | 12 +++++++++ src/buffer.c | 75 ++++++++++++++++++++++++++++++++++------------------- src/buffer.h | 1 + src/xdisp.c | 83 ++++++++++++++++++++++++++++++++++++++++++----------------- 4 files changed, 121 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index b90db0b7fa9..c0098445cb8 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2012-06-03 Chong Yidong + + * xdisp.c (calc_pixel_width_or_height): Use Fbuffer_local_value. + (note_mode_line_or_margin_highlight): If there is no help echo, + use mode-line-default-help-echo. Handle the case where the mouse + position is past the end of the mode line string. + + * buffer.c (buffer_local_value_1): New function, split from + Fbuffer_local_value; can return Qunbound. + (Fbuffer_local_value): Use it. + (Vmode_line_format): Docstring tweaks. + 2012-06-02 Paul Eggert * sysdep.c (system_process_attributes): Improve comment. diff --git a/src/buffer.c b/src/buffer.c index 20260d5a5d8..386d9a78153 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -932,6 +932,21 @@ DEFUN ("buffer-local-value", Fbuffer_local_value, If VARIABLE does not have a buffer-local binding in BUFFER, the value is the default binding of the variable. */) (register Lisp_Object variable, register Lisp_Object buffer) +{ + register Lisp_Object result = buffer_local_value_1 (variable, buffer); + + if (EQ (result, Qunbound)) + xsignal1 (Qvoid_variable, variable); + + return result; +} + + +/* Like Fbuffer_local_value, but return Qunbound if the variable is + locally unbound. */ + +Lisp_Object +buffer_local_value_1 (Lisp_Object variable, Lisp_Object buffer) { register struct buffer *buf; register Lisp_Object result; @@ -985,10 +1000,7 @@ is the default binding of the variable. */) default: abort (); } - if (!EQ (result, Qunbound)) - return result; - - xsignal1 (Qvoid_variable, variable); + return result; } /* Return an alist of the Lisp-level buffer-local bindings of @@ -5329,31 +5341,40 @@ the mode line appears at the bottom. */); DEFVAR_PER_BUFFER ("mode-line-format", &BVAR (current_buffer, mode_line_format), Qnil, doc: /* Template for displaying mode line for current buffer. -Each buffer has its own value of this variable. -Value may be nil, a string, a symbol or a list or cons cell. + +The value may be nil, a string, a symbol or a list. + A value of nil means don't display a mode line. -For a symbol, its value is used (but it is ignored if t or nil). - A string appearing directly as the value of a symbol is processed verbatim - in that the %-constructs below are not recognized. - Note that unless the symbol is marked as a `risky-local-variable', all - properties in any strings, as well as all :eval and :propertize forms - in the value of that symbol will be ignored. -For a list of the form `(:eval FORM)', FORM is evaluated and the result - is used as a mode line element. Be careful--FORM should not load any files, - because that can cause an infinite recursion. -For a list of the form `(:propertize ELT PROPS...)', ELT is displayed - with the specified properties PROPS applied. -For a list whose car is a symbol, the symbol's value is taken, - and if that is non-nil, the cadr of the list is processed recursively. - Otherwise, the caddr of the list (if there is one) is processed. -For a list whose car is a string or list, each element is processed - recursively and the results are effectively concatenated. -For a list whose car is an integer, the cdr of the list is processed - and padded (if the number is positive) or truncated (if negative) - to the width specified by that number. + +For any symbol other than t or nil, the symbol's value is processed as + a mode line construct. As a special exception, if that value is a + string, the string is processed verbatim, without handling any + %-constructs (see below). Also, unless the symbol has a non-nil + `risky-local-variable' property, all properties in any strings, as + well as all :eval and :propertize forms in the value, are ignored. + +A list whose car is a string or list is processed by processing each + of the list elements recursively, as separate mode line constructs, + and concatenating the results. + +A list of the form `(:eval FORM)' is processed by evaluating FORM and + using the result as a mode line construct. Be careful--FORM should + not load any files, because that can cause an infinite recursion. + +A list of the form `(:propertize ELT PROPS...)' is processed by + processing ELT as the mode line construct, and adding the text + properties PROPS to the result. + +A list whose car is a symbol is processed by examining the symbol's + value, and, if that value is non-nil, processing the cadr of the list + recursively; and if that value is nil, processing the caddr of the + list recursively. + +A list whose car is an integer is processed by processing the cadr of + the list, and padding (if the number is positive) or truncating (if + negative) to the width specified by that number. + A string is printed verbatim in the mode line except for %-constructs: - (%-constructs are allowed when the string is the entire mode-line-format - or when it is found in a cons-cell or a list) %b -- print buffer name. %f -- print visited file name. %F -- print frame name. %* -- print %, * or hyphen. %+ -- print *, % or hyphen. diff --git a/src/buffer.h b/src/buffer.h index 97d891f044b..3aa4b11c450 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -912,6 +912,7 @@ extern void validate_region (Lisp_Object *, Lisp_Object *); extern void set_buffer_internal (struct buffer *); extern void set_buffer_internal_1 (struct buffer *); extern void set_buffer_temp (struct buffer *); +extern Lisp_Object buffer_local_value_1 (Lisp_Object, Lisp_Object); extern void record_buffer (Lisp_Object); extern void buffer_slot_type_mismatch (Lisp_Object, int) NO_RETURN; extern void fix_overlays_before (struct buffer *, ptrdiff_t, ptrdiff_t); diff --git a/src/xdisp.c b/src/xdisp.c index 0763fc19c73..6eb7f50c6fc 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -751,6 +751,7 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 }; int redisplaying_p; static Lisp_Object Qinhibit_free_realized_faces; +static Lisp_Object Qmode_line_default_help_echo; /* If a string, XTread_socket generates an event to display that string. (The display is done in read_char.) */ @@ -22091,7 +22092,9 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w)); } - prop = Fbuffer_local_value (prop, it->w->buffer); + prop = buffer_local_value_1 (prop, it->w->buffer); + if (EQ (prop, Qunbound)) + prop = Qnil; } if (INTEGERP (prop) || FLOATP (prop)) @@ -22141,7 +22144,9 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (pixels); } - car = Fbuffer_local_value (car, it->w->buffer); + car = buffer_local_value_1 (car, it->w->buffer); + if (EQ (car, Qunbound)) + car = Qnil; } if (INTEGERP (car) || FLOATP (car)) @@ -27035,7 +27040,6 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, if (!NILP (help)) { help_echo_string = help; - /* Is this correct? ++kfs */ XSETWINDOW (help_echo_window, w); help_echo_object = w->buffer; help_echo_pos = charpos; @@ -27048,46 +27052,77 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, #endif /* HAVE_WINDOW_SYSTEM */ if (STRINGP (string)) + pos = make_number (charpos); + + /* Set the help text and mouse pointer. If the mouse is on a part + of the mode line without any text (e.g. past the right edge of + the mode line text), use the default help text and pointer. */ + if (STRINGP (string) || area == ON_MODE_LINE) { - 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_string to the help string. */ + /* Arrange to display the help by setting the global variables + help_echo_string, help_echo_object, and help_echo_pos. */ if (NILP (help)) { - help = Fget_text_property (pos, Qhelp_echo, string); - if (!NILP (help)) + if (STRINGP (string)) + help = Fget_text_property (pos, Qhelp_echo, string); + + if (STRINGP (help)) { help_echo_string = help; XSETWINDOW (help_echo_window, w); help_echo_object = string; help_echo_pos = charpos; } + else if (area == ON_MODE_LINE) + { + Lisp_Object default_help + = buffer_local_value_1 (Qmode_line_default_help_echo, + w->buffer); + + if (STRINGP (default_help)) + { + help_echo_string = default_help; + XSETWINDOW (help_echo_window, w); + help_echo_object = Qnil; + help_echo_pos = -1; + } + } } #ifdef HAVE_WINDOW_SYSTEM + /* Change the mouse pointer according to what is under it. */ if (FRAME_WINDOW_P (f)) { dpyinfo = FRAME_X_DISPLAY_INFO (f); - cursor = FRAME_X_OUTPUT (f)->nontext_cursor; - if (NILP (pointer)) - pointer = Fget_text_property (pos, Qpointer, string); - - /* Change the mouse pointer according to what is under X/Y. */ - if (NILP (pointer) - && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))) + if (STRINGP (string)) { - Lisp_Object map; - map = Fget_text_property (pos, Qlocal_map, string); - if (!KEYMAPP (map)) - map = Fget_text_property (pos, Qkeymap, string); - if (!KEYMAPP (map)) - cursor = dpyinfo->vertical_scroll_bar_cursor; + cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + + if (NILP (pointer)) + pointer = Fget_text_property (pos, Qpointer, string); + + /* Change the mouse pointer according to what is under X/Y. */ + if (NILP (pointer) + && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))) + { + Lisp_Object map; + map = Fget_text_property (pos, Qlocal_map, string); + if (!KEYMAPP (map)) + map = Fget_text_property (pos, Qkeymap, string); + if (!KEYMAPP (map)) + cursor = dpyinfo->vertical_scroll_bar_cursor; + } } + else + /* Default mode-line pointer. */ + cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor; } #endif + } - /* Change the mouse face according to what is under X/Y. */ + /* Change the mouse face according to what is under X/Y. */ + if (STRINGP (string)) + { mouse_face = Fget_text_property (pos, Qmouse_face, string); if (!NILP (mouse_face) && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)) @@ -28428,6 +28463,8 @@ syms_of_xdisp (void) Vmode_line_unwind_vector = Qnil; staticpro (&Vmode_line_unwind_vector); + DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo"); + help_echo_string = Qnil; staticpro (&help_echo_string); help_echo_object = Qnil; -- cgit v1.2.1