Mercurial > emacs
changeset 5230:8c30e49ddc04
(message): Use message2, not message1.
(display_string): Fix truncation-criterion after main loop
for termination due to LENGTH.
(echo_area_glyphs_length): New variable.
(message1): Set it.
(message2): New function.
(display_string): New arg LENGTH.
(echo_area_display): Pass new arg to display_string.
(redisplay_window): Likewise.
(display_text_line): Likewise.
(display_menu_bar): Likewise.
(display_mode_element): Likewise.
(update_menu_bar, update_menu_bars): New functions.
(prepare_menu_bars): New function.
(redisplay_window): Don't update menu bar here.
(display_menu_bar): Assume item list already updated.
(redisplay_window): Don't alter lpoint when w is
selected window in a non-selected frame.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Thu, 23 Dec 1993 01:04:26 +0000 |
parents | 110539a25499 |
children | 6646271e8d32 |
files | src/xdisp.c |
diffstat | 1 files changed, 257 insertions(+), 59 deletions(-) [+] |
line wrap: on
line diff
--- a/src/xdisp.c Thu Dec 23 01:00:49 1993 +0000 +++ b/src/xdisp.c Thu Dec 23 01:04:26 1993 +0000 @@ -124,6 +124,8 @@ void mark_window_display_accurate (); static void redisplay_windows (); static void redisplay_window (); +static void update_menu_bars (); +static void update_menu_bar (); static void try_window (); static int try_window_id (); static struct position *display_text_line (); @@ -147,6 +149,9 @@ It overrides the minibuf_prompt as well as the buffer. */ char *echo_area_glyphs; +/* This is the length of the message in echo_area_glyphs. */ +int echo_area_glyphs_length; + /* true iff we should redraw the mode lines on the next redisplay */ int update_mode_lines; @@ -182,6 +187,7 @@ /* Specify m, a string, as a message in the minibuf. If m is 0, clear out any existing message, and let the minibuffer text show through. */ + void message1 (m) char *m; @@ -214,7 +220,59 @@ #endif if (m) - echo_area_glyphs = m; + { + echo_area_glyphs = m; + echo_area_glyphs_length = strlen (m); + } + else + echo_area_glyphs = previous_echo_glyphs = 0; + + do_pending_window_change (); + echo_area_display (); + update_frame (XFRAME (XWINDOW (minibuf_window)->frame), 1, 1); + do_pending_window_change (); + } +} + +/* Display an echo area message M with a specified length of LEN chars. + This way, null characters can be included. */ + +void +message2 (m, len) + char *m; + int len; +{ + if (noninteractive) + { + if (noninteractive_need_newline) + putc ('\n', stderr); + noninteractive_need_newline = 0; + fwrite (m, len, 1, stderr); + if (cursor_in_echo_area == 0) + fprintf (stderr, "\n"); + fflush (stderr); + } + /* A null message buffer means that the frame hasn't really been + initialized yet. Error messages get reported properly by + cmd_error, so this must be just an informative message; toss it. */ + else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame)) + { +#ifdef MULTI_FRAME + Lisp_Object minibuf_frame; + + choose_minibuf_frame (); + minibuf_frame = WINDOW_FRAME (XWINDOW (minibuf_window)); + FRAME_SAMPLE_VISIBILITY (XFRAME (minibuf_frame)); + if (FRAME_VISIBLE_P (selected_frame) + && ! FRAME_VISIBLE_P (XFRAME (minibuf_frame))) + Fmake_frame_visible (WINDOW_FRAME (XWINDOW (minibuf_window))); +#endif + + if (m) + { + echo_area_glyphs = m; + echo_area_glyphs_length = len; + } else echo_area_glyphs = previous_echo_glyphs = 0; @@ -269,22 +327,21 @@ { if (m) { - { + int len; #ifdef NO_ARG_ARRAY - int a[3]; - a[0] = a1; - a[1] = a2; - a[2] = a3; - - doprnt (FRAME_MESSAGE_BUF (echo_frame), - FRAME_WIDTH (echo_frame), m, 0, 3, a); + int a[3]; + a[0] = a1; + a[1] = a2; + a[2] = a3; + + len = doprnt (FRAME_MESSAGE_BUF (echo_frame), + FRAME_WIDTH (echo_frame), m, 0, 3, a); #else - doprnt (FRAME_MESSAGE_BUF (echo_frame), - FRAME_WIDTH (echo_frame), m, 0, 3, &a1); + len = doprnt (FRAME_MESSAGE_BUF (echo_frame), + FRAME_WIDTH (echo_frame), m, 0, 3, &a1); #endif /* NO_ARG_ARRAY */ - } - - message1 (FRAME_MESSAGE_BUF (echo_frame)); + + message2 (FRAME_MESSAGE_BUF (echo_frame), len); } else message1 (0); @@ -323,6 +380,7 @@ get_display_line (f, vpos, 0); display_string (XWINDOW (minibuf_window), vpos, echo_area_glyphs ? echo_area_glyphs : "", + echo_area_glyphs ? echo_area_glyphs_length : -1, 0, 0, 0, FRAME_WIDTH (f)); /* If desired cursor location is on this line, put it at end of text */ @@ -338,7 +396,7 @@ { get_display_line (f, i, 0); display_string (XWINDOW (minibuf_window), vpos, - "", 0, 0, 0, FRAME_WIDTH (f)); + "", 0, 0, 0, 0, FRAME_WIDTH (f)); } } } @@ -351,6 +409,77 @@ previous_echo_glyphs = echo_area_glyphs; } +/* Prepare for redisplay by updating menu-bar item lists when appropriate. + This can't be done in `redisplay' itself because it can call eval. */ + +void +prepare_menu_bars () +{ + register struct window *w = XWINDOW (selected_window); + int all_windows; + + if (noninteractive) + return; + + /* Set the visible flags for all frames. + Do this before checking for resized or garbaged frames; they want + to know if their frames are visible. + See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */ + { + Lisp_Object tail, frame; + + FOR_EACH_FRAME (tail, frame) + FRAME_SAMPLE_VISIBILITY (XFRAME (frame)); + } + + /* Notice any pending interrupt request to change frame size. */ + do_pending_window_change (); + + if (frame_garbaged) + { + redraw_garbaged_frames (); + frame_garbaged = 0; + } + + if (clip_changed || windows_or_buffers_changed) + update_mode_lines++; + + /* Detect case that we need to write a star in the mode line. */ + if (XFASTINT (w->last_modified) < MODIFF + && XFASTINT (w->last_modified) <= current_buffer->save_modified) + { + w->update_mode_line = Qt; + if (buffer_shared > 1) + update_mode_lines++; + } + + all_windows = update_mode_lines || buffer_shared > 1; + + /* If specs for an arrow have changed, do thorough redisplay + to ensure we remove any arrow that should no longer exist. */ + if (! EQ (Voverlay_arrow_position, last_arrow_position) + || ! EQ (Voverlay_arrow_string, last_arrow_string)) + all_windows = 1, clip_changed = 1; + + /* Update the menu bar item lists, if appropriate. + This has to be done before any actual redisplay + or generation of display lines. */ + if (all_windows) + { + Lisp_Object tail, frame; + + FOR_EACH_FRAME (tail, frame) + { + FRAME_PTR f = XFRAME (frame); + + if (FRAME_VISIBLE_P (f)) + update_menu_bars (FRAME_ROOT_WINDOW (f)); + } + } + else if (FRAME_VISIBLE_P (selected_frame)) + update_menu_bar (selected_window); +} + /* Do a frame update, taking possible shortcuts into account. This is the main external entry point for redisplay. @@ -358,11 +487,14 @@ message is no longer requested, we clear the echo area or bring back the minibuffer if that is in use. - Everyone would like to have a hook here to call eval, - but that cannot be done safely without a lot of changes elsewhere. - This can be called from signal handlers; with alarms set up; + Do not call eval from within this function. + Calls to eval after the call to echo_area_display would confuse + the display_line mechanism and would cause a crash. + Calls to eval before that point will work most of the time, + but can still lose, because this function + can be called from signal handlers; with alarms set up; or with synchronous processes running. - See the function `echo' in keyboard.c. + See Fcall_process; if you called it from here, it could be entered recursively. */ @@ -400,16 +532,6 @@ frame_garbaged = 0; } - /* Normally the message* functions will have already displayed and - updated the echo area, but the frame may have been trashed, or - the update may have been preempted, so display the echo area - again here. */ - if (echo_area_glyphs || previous_echo_glyphs) - { - echo_area_display (); - must_finish = 1; - } - if (clip_changed || windows_or_buffers_changed) update_mode_lines++; @@ -432,6 +554,16 @@ || ! EQ (Voverlay_arrow_string, last_arrow_string)) all_windows = 1, clip_changed = 1; + /* Normally the message* functions will have already displayed and + updated the echo area, but the frame may have been trashed, or + the update may have been preempted, so display the echo area + again here. */ + if (echo_area_glyphs || previous_echo_glyphs) + { + echo_area_display (); + must_finish = 1; + } + /* If showing region, and mark has changed, must redisplay whole window. */ if (((!NILP (Vtransient_mark_mode) && !NILP (XBUFFER (w->buffer)->mark_active)) @@ -752,8 +884,78 @@ } } +/* Update the menu bar item lists for WINDOW + and its subwindows and siblings. + This has to be done before we start to fill in any display lines, + because it can call eval. */ + +static void +update_menu_bars (window) + Lisp_Object window; +{ + for (; !NILP (window); window = XWINDOW (window)->next) + update_menu_bar (window, 0); +} + +/* Update the menu bar item list for window WINDOW and its subwindows. */ + +static void +update_menu_bar (window, just_this_one) + Lisp_Object window; + int just_this_one; +{ + register struct window *w = XWINDOW (window); + struct buffer *old = current_buffer; + FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); + + /* If this is a combination window, do its children; that's all. */ + + if (!NILP (w->vchild)) + { + update_menu_bars (w->vchild); + return; + } + if (!NILP (w->hchild)) + { + update_menu_bars (w->hchild); + return; + } + if (NILP (w->buffer)) + abort (); + + if (update_mode_lines) + w->update_mode_line = Qt; + + /* When we reach a frame's selected window, redo the frame's menu bar. */ + if (!NILP (w->update_mode_line) + && FRAME_MENU_BAR_LINES (f) > 0 + && EQ (FRAME_SELECTED_WINDOW (f), window)) + { + /* If the user has switched buffers or windows, we need to + recompute to reflect the new bindings. But we'll + recompute when update_mode_lines is set too; that means + that people can use force-mode-line-update to request + that the menu bar be recomputed. The adverse effect on + the rest of the redisplay algorithm is about the same as + windows_or_buffers_changed anyway. */ + if (windows_or_buffers_changed + || update_mode_lines + || (XFASTINT (w->last_modified) < MODIFF + && (XFASTINT (w->last_modified) + <= XBUFFER (w->buffer)->save_modified))) + { + struct buffer *prev = current_buffer; + current_buffer = XBUFFER (w->buffer); + FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (); + current_buffer = prev; + } + } +} + int do_id = 1; +/* Redisplay WINDOW and its subwindows and siblings. */ + static void redisplay_windows (window) Lisp_Object window; @@ -762,6 +964,8 @@ redisplay_window (window, 0); } +/* Redisplay window WINDOW and its subwindows. */ + static void redisplay_window (window, just_this_one) Lisp_Object window; @@ -817,7 +1021,7 @@ for (i = 0; i < height; i++) { get_display_line (f, vpos + i, 0); - display_string (w, vpos + i, "", 0, 0, 0, width); + display_string (w, vpos + i, "", 0, 0, 0, 0, width); } goto finish_scroll_bars; @@ -887,7 +1091,7 @@ - (1 << (SHORTBITS - 1)), width, hscroll, pos_tab_offset (w, startp)); SET_PT (pos.bufpos); - if (w != XWINDOW (FRAME_SELECTED_WINDOW (f))) + if (w != XWINDOW (selected_window)) Fset_marker (w->pointm, make_number (point), Qnil); else { @@ -1765,7 +1969,7 @@ && vpos == XFASTINT (w->top)) { if (minibuf_prompt) - hpos = display_string (w, vpos, minibuf_prompt, hpos, + hpos = display_string (w, vpos, minibuf_prompt, -1, hpos, (!truncate ? continuer : truncator), -1, -1); minibuf_prompt_width = hpos; @@ -2149,25 +2353,6 @@ get_display_line (f, vpos, 0); - /* If the user has switched buffers or windows, we need to - recompute to reflect the new bindings. But we'll - recompute when update_mode_lines is set too; that means - that people can use force-mode-line-update to request - that the menu bar be recomputed. The adverse effect on - the rest of the redisplay algorithm is about the same as - windows_or_buffers_changed anyway. */ - if (windows_or_buffers_changed - || update_mode_lines - || (XFASTINT (w->last_modified) < MODIFF - && (XFASTINT (w->last_modified) - <= XBUFFER (w->buffer)->save_modified))) - { - struct buffer *prev = current_buffer; - current_buffer = XBUFFER (w->buffer); - FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (); - current_buffer = prev; - } - for (tail = FRAME_MENU_BAR_ITEMS (f); CONSP (tail); tail = XCONS (tail)->cdr) { Lisp_Object string; @@ -2180,12 +2365,13 @@ if (hpos < maxendcol) hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos, XSTRING (string)->data, + XSTRING (string)->size, hpos, 0, hpos, maxendcol); /* Put a gap of 3 spaces between items. */ if (hpos < maxendcol) { int hpos1 = hpos + 3; - hpos = display_string (w, vpos, "", hpos, 0, + hpos = display_string (w, vpos, "", 0, hpos, 0, min (hpos1, maxendcol), maxendcol); } } @@ -2195,7 +2381,7 @@ /* Fill out the line with spaces. */ if (maxendcol > hpos) - hpos = display_string (w, vpos, "", hpos, 0, maxendcol, -1); + hpos = display_string (w, vpos, "", 0, hpos, 0, maxendcol, -1); /* Clear the rest of the lines allocated to the menu bar. */ vpos++; @@ -2311,7 +2497,7 @@ if (this - 1 != last) { register int lim = --this - last + hpos; - hpos = display_string (w, vpos, last, hpos, 0, hpos, + hpos = display_string (w, vpos, last, -1, hpos, 0, hpos, min (lim, maxendcol)); } else /* c == '%' */ @@ -2340,6 +2526,7 @@ hpos = display_string (w, vpos, decode_mode_spec (w, c, maxendcol - hpos), + -1, hpos, 0, spec_width, maxendcol); } } @@ -2361,6 +2548,7 @@ don't check for % within it. */ if (XTYPE (tem) == Lisp_String) hpos = display_string (w, vpos, XSTRING (tem)->data, + XSTRING (tem)->size, hpos, 0, minendcol, maxendcol); /* Give up right away for nil or t. */ else if (!EQ (tem, elt)) @@ -2450,13 +2638,13 @@ default: invalid: - return (display_string (w, vpos, "*invalid*", hpos, 0, + return (display_string (w, vpos, "*invalid*", -1, hpos, 0, minendcol, maxendcol)); } end: if (minendcol > hpos) - hpos = display_string (w, vpos, "", hpos, 0, minendcol, -1); + hpos = display_string (w, vpos, "", 0, hpos, 0, minendcol, -1); return hpos; } @@ -2733,6 +2921,7 @@ /* Display STRING on one line of window W, starting at HPOS. Display at position VPOS. Caller should have done get_display_line. If VPOS == -1, display it as the current frame's title. + LENGTH is the length of STRING, or -1 meaning STRING is null-terminated. TRUNCATE is GLYPH to display at end if truncated. Zero for none. @@ -2746,9 +2935,10 @@ Returns ending hpos */ static int -display_string (w, vpos, string, hpos, truncate, mincol, maxcol) +display_string (w, vpos, string, length, hpos, truncate, mincol, maxcol) struct window *w; unsigned char *string; + int length; int vpos, hpos; GLYPH truncate; int mincol, maxcol; @@ -2798,8 +2988,16 @@ while (p1 < end) { + if (length == 0) + break; c = *string++; - if (!c) break; + /* Specified length. */ + if (length >= 0) + length--; + /* Unspecified length (null-terminated string). */ + else if (c == 0) + break; + if (c >= 040 && c < 0177 && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector)) { @@ -2847,7 +3045,7 @@ } } - if (c) + if (c && length > 0) { p1 = end; if (truncate) *p1++ = truncate;