/* Display generation from window structure and buffer text.
- Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
+ Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
This file is part of GNU Emacs.
extern Lisp_Object Qface;
-/* Nonzero means print newline before next minibuffer message. */
+/* Nonzero means print newline to stdout before next minibuffer message. */
int noninteractive_need_newline;
+/* Nonzero means print newline to message log before next message. */
+
+static int message_log_need_newline;
+
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
+#define minmax(floor, val, ceil) \
+ ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
/* The buffer position of the first character appearing
entirely or partially on the current frame line.
/* Like mode-line-format, but for the titlebar on an iconified frame. */
Lisp_Object Vicon_title_format;
+/* List of functions to call when a window's size changes. These
+ functions get one arg, a frame on which one or more windows' sizes
+ have changed. */
+static Lisp_Object Vwindow_size_change_functions;
+
/* Values of those variables at last redisplay. */
static Lisp_Object last_arrow_position, last_arrow_string;
/* Nonzero if overlay arrow has been displayed once in this window. */
static int overlay_arrow_seen;
+/* Nonzero if visible end of buffer has already been displayed once
+ in this window. (We need this variable in case there are overlay
+ strings that get displayed there.) */
+static int zv_strings_seen;
+
/* Nonzero means highlight the region even in nonselected windows. */
static int highlight_nonselected_windows;
/* If cursor motion alone moves point off frame,
Try scrolling this many lines up or down if that will bring it back. */
-int scroll_step;
+static int scroll_step;
/* Nonzero if try_window_id has made blank lines at window bottom
since the last redisplay that paused */
static int blank_end_of_window;
-/* Number of windows showing the buffer of the selected window.
+/* Number of windows showing the buffer of the selected window
+ (or another buffer with the same base buffer).
keyboard.c refers to this. */
int buffer_shared;
static int cursor_vpos;
static int cursor_hpos;
-int debug_end_pos;
+static int debug_end_pos;
/* Nonzero means display mode line highlighted */
int mode_line_inverse_video;
+static int message_log_check_duplicate ();
static void echo_area_display ();
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 ();
int line_number_displayed;
/* Maximum buffer size for which to display line numbers. */
-int line_number_display_limit;
+static int line_number_display_limit;
+
+/* Number of lines to keep in the message log buffer.
+ t means infinite. nil means don't log at all. */
+Lisp_Object Vmessage_log_max;
\f
+void
+message_log_maybe_newline ()
+{
+ if (message_log_need_newline)
+ message_dolog ("", 0, 1);
+}
+
+
+/* Add a string to the message log, optionally terminated with a newline.
+ This function calls low-level routines in order to bypass text property
+ hooks, etc. which might not be safe to run. */
+
+void
+message_dolog (m, len, nlflag)
+ char *m;
+ int len, nlflag;
+{
+ if (!NILP (Vmessage_log_max))
+ {
+ struct buffer *oldbuf;
+ int oldpoint, oldbegv, oldzv;
+
+ oldbuf = current_buffer;
+ Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
+ current_buffer->undo_list = Qt;
+ oldpoint = PT;
+ oldbegv = BEGV;
+ oldzv = ZV;
+ BEGV = BEG;
+ ZV = Z;
+ if (oldpoint == Z)
+ oldpoint += len + nlflag;
+ if (oldzv == Z)
+ oldzv += len + nlflag;
+ TEMP_SET_PT (Z);
+ if (len)
+ insert_1 (m, len, 1, 0);
+ if (nlflag)
+ {
+ int this_bol, prev_bol, dup;
+ insert_1 ("\n", 1, 1, 0);
+
+ this_bol = scan_buffer ('\n', Z, 0, -2, 0, 0);
+ if (this_bol > BEG)
+ {
+ prev_bol = scan_buffer ('\n', this_bol, 0, -2, 0, 0);
+ dup = message_log_check_duplicate (prev_bol, this_bol);
+ if (dup)
+ {
+ if (oldpoint > prev_bol)
+ oldpoint -= min (this_bol, oldpoint) - prev_bol;
+ if (oldbegv > prev_bol)
+ oldbegv -= min (this_bol, oldbegv) - prev_bol;
+ if (oldzv > prev_bol)
+ oldzv -= min (this_bol, oldzv) - prev_bol;
+ del_range_1 (prev_bol, this_bol, 0);
+ if (dup > 1)
+ {
+ char dupstr[40];
+ int duplen;
+
+ /* If you change this format, don't forget to also
+ change message_log_check_duplicate. */
+ sprintf (dupstr, " [%d times]", dup);
+ duplen = strlen (dupstr);
+ TEMP_SET_PT (Z-1);
+ if (oldpoint == Z)
+ oldpoint += duplen;
+ if (oldzv == Z)
+ oldzv += duplen;
+ insert_1 (dupstr, duplen, 1, 0);
+ }
+ }
+ }
+
+ if (NATNUMP (Vmessage_log_max))
+ {
+ int pos = scan_buffer ('\n', Z, 0,
+ -XFASTINT (Vmessage_log_max) - 1, 0, 0);
+ oldpoint -= min (pos, oldpoint) - BEG;
+ oldbegv -= min (pos, oldbegv) - BEG;
+ oldzv -= min (pos, oldzv) - BEG;
+ del_range_1 (BEG, pos, 0);
+ }
+ }
+ BEGV = oldbegv;
+ ZV = oldzv;
+ TEMP_SET_PT (oldpoint);
+ set_buffer_internal (oldbuf);
+ message_log_need_newline = !nlflag;
+ }
+}
+
+
+/* We are at the end of the buffer after just having inserted a newline.
+ (Note: We depend on the fact we won't be crossing the gap.)
+ Check to see if the most recent message looks a lot like the previous one.
+ Return 0 if different, 1 if the new one should just replace it, or a
+ value N > 1 if we should also append " [N times]". */
+
+static int
+message_log_check_duplicate (prev_bol, this_bol)
+ int prev_bol, this_bol;
+{
+ int i;
+ int len = Z - 1 - this_bol;
+ int seen_dots = 0;
+ unsigned char *p1 = BUF_CHAR_ADDRESS (current_buffer, prev_bol);
+ unsigned char *p2 = BUF_CHAR_ADDRESS (current_buffer, this_bol);
+
+ for (i = 0; i < len; i++)
+ {
+ if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
+ && p1[i] != '\n')
+ seen_dots = 1;
+ if (p1[i] != p2[i])
+ return seen_dots;
+ }
+ p1 += len;
+ if (*p1 == '\n')
+ return 2;
+ if (*p1++ == ' ' && *p1++ == '[')
+ {
+ int n = 0;
+ while (*p1 >= '0' && *p1 <= '9')
+ n = n * 10 + *p1++ - '0';
+ if (strncmp (p1, " times]\n", 8) == 0)
+ return n+1;
+ }
+ return 0;
+}
+
/* Display an echo area message M with a specified length of LEN chars.
The string may include null characters. If m is 0, clear out any
existing message, and let the minibuffer text show through.
message2 (m, len)
char *m;
int len;
+{
+ /* First flush out any partial line written with print. */
+ message_log_maybe_newline ();
+ if (m)
+ message_dolog (m, len, 1);
+ message2_nolog (m, len);
+}
+
+
+/* The non-logging part of that function. */
+
+void
+message2_nolog (m, len)
+ char *m;
+ int len;
{
if (noninteractive)
{
message2 (m, (m ? strlen (m) : 0));
}
+void
+message1_nolog (m)
+ char *m;
+{
+ message2_nolog (m, (m ? strlen (m) : 0));
+}
+
/* Truncate what will be displayed in the echo area
the next time we display it--but don't redisplay it now. */
}
}
+/* The non-logging version of that function. */
+void
+message_nolog (m, a1, a2, a3)
+ char *m;
+ EMACS_INT a1, a2, a3;
+{
+ Lisp_Object old_log_max;
+ old_log_max = Vmessage_log_max;
+ Vmessage_log_max = Qnil;
+ message (m, a1, a2, a3);
+ Vmessage_log_max = old_log_max;
+}
+
void
update_echo_area ()
{
0, 0, 0, 0, FRAME_WIDTH (f));
/* If desired cursor location is on this line, put it at end of text */
+ if (cursor_in_echo_area)
+ FRAME_CURSOR_Y (f) = vpos;
if (FRAME_CURSOR_Y (f) == vpos)
FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
if (!FRAME_X_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name)
return;
- multiple_frames = !EQ (Fnext_frame (frame, Qnil), frame);
+
+ /* Do we have more than one visible frame on this X display? */
+ {
+ Lisp_Object tail;
+
+ for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ FRAME_PTR tf = XFRAME (XCONS (tail)->car);
+
+ if (tf != f && tf->kboard == f->kboard && !FRAME_MINIBUF_ONLY_P (tf)
+ && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
+ break;
+ }
+
+ multiple_frames = CONSP (tail);
+ }
+
obuf = current_buffer;
Fset_buffer (XWINDOW (f->selected_window)->buffer);
fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format);
#endif
\f
/* Prepare for redisplay by updating menu-bar item lists when appropriate.
- This can't be done in `redisplay' itself because it can call eval. */
+ This can call eval. */
void
prepare_menu_bars ()
{
register struct window *w = XWINDOW (selected_window);
int all_windows;
+ struct gcpro gcpro1, gcpro2;
- if (noninteractive)
- return;
+ all_windows = (update_mode_lines || buffer_shared > 1
+ || clip_changed || windows_or_buffers_changed);
- /* 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;
+ /* 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;
+ int count = specpdl_ptr - specpdl;
- FOR_EACH_FRAME (tail, frame)
- FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
- }
+ record_unwind_protect (Fstore_match_data, Fmatch_data ());
- /* Notice any pending interrupt request to change frame size. */
- do_pending_window_change ();
+ FOR_EACH_FRAME (tail, frame)
+ {
+ /* If a window on this frame changed size,
+ report that to the user and clear the size-change flag. */
+ if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)))
+ {
+ Lisp_Object functions;
+ /* Clear flag first in case we get error below. */
+ FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)) = 0;
+ functions = Vwindow_size_change_functions;
+ GCPRO2 (tail, functions);
+ while (CONSP (functions))
+ {
+ call1 (XCONS (functions)->car, frame);
+ functions = XCONS (functions)->cdr;
+ }
+ UNGCPRO;
+ }
+ GCPRO1 (tail);
+ update_menu_bar (XFRAME (frame), 0);
+ UNGCPRO;
+ }
- if (frame_garbaged)
- {
- redraw_garbaged_frames ();
- frame_garbaged = 0;
+ unbind_to (count, Qnil);
}
+ else
+ update_menu_bar (selected_frame, 1);
- all_windows = (update_mode_lines || buffer_shared > 1
- || clip_changed || windows_or_buffers_changed);
-
+ /* Update all frame titles based on their buffer names, etc.
+ We do this after the menu bars so that the frame will first
+ create its menu bar using the name `emacs' if no other name
+ has yet been specified. */
#ifdef HAVE_X_WINDOWS
if (windows_or_buffers_changed)
{
x_consider_frame_title (frame);
}
#endif
-
- /* 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)
- update_menu_bar (XFRAME (frame));
- }
- else
- update_menu_bar (selected_frame);
}
\f
/* Do a frame update, taking possible shortcuts into account.
int all_windows;
register int tlbufpos, tlendpos;
struct position pos;
- extern int input_pending;
if (noninteractive)
return;
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
- FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
+ {
+ FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
+
+ /* Clear out all the display lines in which we will generate the
+ glyphs to display. */
+ init_desired_glyphs (XFRAME (frame));
+ }
}
/* Notice any pending interrupt request to change frame size. */
frame_garbaged = 0;
}
- if (clip_changed || windows_or_buffers_changed)
+ prepare_menu_bars ();
+
+ if (clip_changed || windows_or_buffers_changed
+ || (!NILP (w->column_number_displayed)
+ && XFASTINT (w->column_number_displayed) != current_column ()))
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)
+ && XFASTINT (w->last_modified) <= SAVE_MODIFF)
{
w->update_mode_line = Qt;
if (buffer_shared > 1)
{
cursor_vpos = -1;
overlay_arrow_seen = 0;
+ zv_strings_seen = 0;
display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
pos_tab_offset (w, tlbufpos));
/* If line contains point, is not continued,
int left = XFASTINT (w->left);
int *charstart_next_line
= FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
- int i;
int adjust;
if (Z - tlendpos == ZV)
}
goto update;
}
- /* If highlighting the region, we can't just move the cursor. */
+ /* If highlighting the region, or if the cursor is in the echo area,
+ then we can't just move the cursor. */
else if (! (!NILP (Vtransient_mark_mode)
&& !NILP (current_buffer->mark_active))
- && NILP (w->region_showing))
+ && NILP (w->region_showing)
+ && !cursor_in_echo_area)
{
pos = *compute_motion (tlbufpos, 0,
XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
+ 0,
PT, 2, - (1 << (SHORTBITS - 1)),
window_internal_width (w) - 1,
XINT (w->hscroll),
pos_tab_offset (w, tlbufpos), w);
if (pos.vpos < 1)
{
+ int width = window_internal_width (w) - 1;
FRAME_CURSOR_X (selected_frame)
- = XFASTINT (w->left) + max (pos.hpos, 0);
+ = XFASTINT (w->left) + minmax (0, pos.hpos, width);
FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
goto update;
}
{
Lisp_Object tail, frame;
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
/* Clear the face cache, only when we do a full redisplay
and not too often either. */
if (clear_face_cache_count > 1000)
FOR_EACH_FRAME (tail, frame)
{
FRAME_PTR f = XFRAME (frame);
+ if (! FRAME_TERMCAP_P (f) || f == selected_frame)
+ {
- /* Mark all the scroll bars to be removed; we'll redeem the ones
- we want when we redisplay their windows. */
- if (condemn_scroll_bars_hook)
- (*condemn_scroll_bars_hook) (f);
+ /* Mark all the scroll bars to be removed; we'll redeem the ones
+ we want when we redisplay their windows. */
+ if (condemn_scroll_bars_hook)
+ (*condemn_scroll_bars_hook) (f);
- if (FRAME_VISIBLE_P (f))
- redisplay_windows (FRAME_ROOT_WINDOW (f));
+ if (FRAME_VISIBLE_P (f))
+ redisplay_windows (FRAME_ROOT_WINDOW (f));
- /* Any scroll bars which redisplay_windows should have nuked
- should now go away. */
- if (judge_scroll_bars_hook)
- (*judge_scroll_bars_hook) (f);
+ /* Any scroll bars which redisplay_windows should have nuked
+ should now go away. */
+ if (judge_scroll_bars_hook)
+ (*judge_scroll_bars_hook) (f);
+ }
}
}
else if (FRAME_VISIBLE_P (selected_frame))
continue;
f = XFRAME (XCONS (tail)->car);
- if (FRAME_VISIBLE_P (f))
+
+ if ((! FRAME_TERMCAP_P (f) || f == selected_frame)
+ && FRAME_VISIBLE_P (f))
{
pause |= update_frame (f, 0, 0);
if (!pause)
{
if (FRAME_VISIBLE_P (selected_frame))
pause = update_frame (selected_frame, 0, 0);
+ else
+ pause = 0;
/* We may have called echo_area_display at the top of this
function. If the echo area is on another frame, that may
\f
/* Update the menu bar item list for frame F.
This has to be done before we start to fill in any display lines,
- because it can call eval. */
+ because it can call eval.
+
+ If SAVE_MATCH_DATA is 1, we must save and restore it here. */
static void
-update_menu_bar (f)
+update_menu_bar (f, save_match_data)
FRAME_PTR f;
+ int save_match_data;
{
struct buffer *old = current_buffer;
Lisp_Object window;
register struct window *w;
+
window = FRAME_SELECTED_WINDOW (f);
w = XWINDOW (window);
|| !NILP (w->update_mode_line)
|| (XFASTINT (w->last_modified) < MODIFF
&& (XFASTINT (w->last_modified)
- <= XBUFFER (w->buffer)->save_modified)))
+ <= BUF_SAVE_MODIFF (XBUFFER (w->buffer)))))
{
struct buffer *prev = current_buffer;
+ int count = specpdl_ptr - specpdl;
+
+ if (!save_match_data)
+ record_unwind_protect (Fstore_match_data, Fmatch_data ());
+
call1 (Vrun_hooks, Qmenu_bar_update_hook);
current_buffer = XBUFFER (w->buffer);
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
#ifdef USE_X_TOOLKIT
set_frame_menubar (f, 0);
#endif /* USE_X_TOOLKIT */
+
+ unbind_to (count, Qnil);
}
}
}
struct position pos;
int opoint = PT;
int tem;
- int window_needs_modeline;
+ int update_mode_line;
if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
abort ();
height = window_internal_height (w);
+ update_mode_line = (!NILP (w->update_mode_line) || update_mode_lines);
if (MINI_WINDOW_P (w))
{
}
}
- if (update_mode_lines)
- w->update_mode_line = Qt;
-
/* Otherwise set up data on this window; select its buffer and point value */
- current_buffer = XBUFFER (w->buffer);
+ if (update_mode_line)
+ set_buffer_internal (XBUFFER (w->buffer));
+ else
+ set_buffer_temp (XBUFFER (w->buffer));
+
opoint = PT;
- /* Count number of windows showing the selected buffer. */
+ /* Count number of windows showing the selected buffer.
+ An indirect buffer counts as its base buffer. */
- if (!just_this_one
- && current_buffer == XBUFFER (XWINDOW (selected_window)->buffer))
- buffer_shared++;
+ if (!just_this_one)
+ {
+ struct buffer *current_base, *window_base;
+ current_base = current_buffer;
+ window_base = XBUFFER (XWINDOW (selected_window)->buffer);
+ if (current_base->base_buffer)
+ current_base = current_base->base_buffer;
+ if (window_base->base_buffer)
+ window_base = window_base->base_buffer;
+ if (current_base == window_base)
+ buffer_shared++;
+ }
/* POINT refers normally to the selected window.
For any other window, set up appropriate value. */
{
/* Forget any recorded base line for line number display. */
w->base_line_number = Qnil;
- w->update_mode_line = Qt;
+ /* Redisplay the mode line. Select the buffer properly for that. */
+ if (!update_mode_line)
+ {
+ set_buffer_temp (old);
+ set_buffer_internal (XBUFFER (w->buffer));
+ update_mode_line = 1;
+ w->update_mode_line = Qt;
+ }
w->force_start = Qnil;
XSETFASTINT (w->last_modified, 0);
if (startp < BEGV) startp = BEGV;
{
/* If point does not appear, move point so it does appear */
pos = *compute_motion (startp, 0,
- ((EQ (window, minibuf_window) && startp == 1)
- ? minibuf_prompt_width : 0)
- +
- (hscroll ? 1 - hscroll : 0),
- ZV, height / 2,
- - (1 << (SHORTBITS - 1)),
- width, hscroll, pos_tab_offset (w, startp), w);
+ (((EQ (window, minibuf_window)
+ && startp == BEG)
+ ? minibuf_prompt_width : 0)
+ + (hscroll ? 1 - hscroll : 0)),
+ 0,
+ ZV, height / 2,
+ - (1 << (SHORTBITS - 1)),
+ width, hscroll, pos_tab_offset (w, startp), w);
BUF_PT (current_buffer) = pos.bufpos;
if (w != XWINDOW (selected_window))
Fset_marker (w->pointm, make_number (PT), Qnil);
{
if (current_buffer == old)
lpoint = PT;
- FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
+ FRAME_CURSOR_X (f) = (XFASTINT (w->left)
+ + minmax (0, pos.hpos, width));
FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
}
/* If we are highlighting the region,
if (XFASTINT (w->last_modified) >= MODIFF
&& PT >= startp && !clip_changed
&& (just_this_one || XFASTINT (w->width) == FRAME_WIDTH (f))
+ /* If force-mode-line-update was called, really redisplay;
+ that's how redisplay is forced after e.g. changing
+ buffer-invisibility-spec. */
+ && NILP (w->update_mode_line)
/* Can't use this case if highlighting a region. */
&& !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
&& NILP (w->region_showing)
&& XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
&& !EQ (window, minibuf_window))
{
- pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0),
- PT, height + 1, 10000, width, hscroll,
+ pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
+ PT, height, 0, width, hscroll,
pos_tab_offset (w, startp), w);
if (pos.vpos < height)
if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
{
/* These variables are supposed to be origin 1 */
- FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
+ FRAME_CURSOR_X (f) = (XFASTINT (w->left)
+ + minmax (0, pos.hpos, width));
FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
}
/* This doesn't do the trick, because if a window to the right of
}
XSETFASTINT (w->last_modified, 0);
- w->update_mode_line = Qt;
+ /* Redisplay the mode line. Select the buffer properly for that. */
+ if (!update_mode_line)
+ {
+ set_buffer_temp (old);
+ set_buffer_internal (XBUFFER (w->buffer));
+ update_mode_line = 1;
+ w->update_mode_line = Qt;
+ }
/* Try to scroll by specified few lines */
{
if (PT > startp)
{
- pos = *vmotion (Z - XFASTINT (w->window_end_pos),
- scroll_step, width, hscroll, window);
+ pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
if (pos.vpos >= height)
goto scroll_fail;
}
- pos = *vmotion (startp, PT < startp ? - scroll_step : scroll_step,
- width, hscroll, window);
+ pos = *vmotion (startp, (PT < startp ? - scroll_step : scroll_step), w);
if (PT >= pos.bufpos)
{
/* Forget any previously recorded base line for line number display. */
w->base_line_number = Qnil;
- pos = *vmotion (PT, - (height / 2), width, hscroll, window);
+ pos = *vmotion (PT, - (height / 2), w);
try_window (window, pos.bufpos);
startp = marker_position (w->start);
- w->start_at_line_beg
+ w->start_at_line_beg
= (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
done:
- if ((!NILP (w->update_mode_line)
+ if ((update_mode_line
/* If window not full width, must redo its mode line
if the window to its side is being redone */
|| (!just_this_one && width < FRAME_WIDTH (f) - 1)
- || INTEGERP (w->base_line_pos))
+ || INTEGERP (w->base_line_pos)
+ || (!NILP (w->column_number_displayed)
+ && XFASTINT (w->column_number_displayed) != current_column ()))
&& height != XFASTINT (w->height))
display_mode_line (w);
if (! line_number_displayed
}
/* When we reach a frame's selected window, redo the frame's menu bar. */
- if (!NILP (w->update_mode_line)
+ if (update_mode_line
#ifdef USE_X_TOOLKIT
&& FRAME_EXTERNAL_MENU_BAR (f)
#else
|| (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
{
whole = ZV - BEGV;
- start = startp - BEGV;
+ start = marker_position (w->start) - BEGV;
/* I don't think this is guaranteed to be right. For the
moment, we'll pretend it is. */
end = (Z - XINT (w->window_end_pos)) - BEGV;
}
BUF_PT (current_buffer) = opoint;
- current_buffer = old;
+ if (update_mode_line)
+ set_buffer_internal (old);
+ else
+ set_buffer_temp (old);
BUF_PT (current_buffer) = lpoint;
}
\f
Fset_marker (w->start, make_number (pos), Qnil);
cursor_vpos = -1;
overlay_arrow_seen = 0;
+ zv_strings_seen = 0;
val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
while (--height >= 0)
{
val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
tab_offset += width;
+ /* For the first line displayed, display_text_line
+ subtracts the prompt width from the tab offset.
+ But it does not affect the value of our variable tab_offset.
+ So we do the subtraction again,
+ for the sake of continuation lines of that first line. */
+ if (MINI_WINDOW_P (w) && vpos == XFASTINT (w->top))
+ tab_offset -= minibuf_prompt_width;
+
if (val.vpos) tab_offset = 0;
vpos++;
if (pos != val.bufpos)
- last_text_vpos
- /* Next line, unless prev line ended in end of buffer with no cr */
- = vpos - (val.vpos && (FETCH_CHAR (val.bufpos - 1) != '\n'
+ {
+ int invis = 0;
#ifdef USE_TEXT_PROPERTIES
- || ! NILP (Fget_char_property (val.bufpos-1,
- Qinvisible,
- window))
+ Lisp_Object invis_prop;
+ invis_prop = Fget_char_property (val.bufpos-1, Qinvisible, window);
+ invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop);
#endif
- ));
+
+ last_text_vpos
+ /* Next line, unless prev line ended in end of buffer with no cr */
+ = vpos - (val.vpos
+ && (FETCH_CHAR (val.bufpos - 1) != '\n' || invis));
+ }
pos = val.bufpos;
}
int width = window_internal_width (w) - 1;
int hscroll = XINT (w->hscroll);
int lmargin = hscroll > 0 ? 1 - hscroll : 0;
+ int did_motion;
register int vpos;
register int i, tem;
int last_text_vpos = 0;
return 0; /* Give up if changes go above top of window */
/* Find position before which nothing is changed. */
- bp = *compute_motion (start, 0, lmargin,
- min (ZV, beg_unchanged + BEG), height + 1, 0,
+ bp = *compute_motion (start, 0, lmargin, 0,
+ min (ZV, beg_unchanged + BEG), height, 0,
width, hscroll, pos_tab_offset (w, start), w);
if (bp.vpos >= height)
{
- if (PT < bp.bufpos && !bp.contin)
+ if (PT < bp.bufpos)
{
/* All changes are below the frame, and point is on the frame.
We don't need to change the frame at all.
But we need to update window_end_pos to account for
any change in buffer size. */
- bp = *compute_motion (start, 0, lmargin,
+ bp = *compute_motion (start, 0, lmargin, 0,
Z, height, 0,
width, hscroll, pos_tab_offset (w, start), w);
XSETFASTINT (w->window_end_vpos, height);
XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
- return 1;
+ goto findpoint;
}
return 0;
}
vpos = bp.vpos;
/* Find beginning of that frame line. Must display from there. */
- bp = *vmotion (bp.bufpos, 0, width, hscroll, window);
+ bp = *vmotion (bp.bufpos, 0, w);
pos = bp.bufpos;
val.hpos = lmargin;
if (pos < start)
return -1;
+ did_motion = 0;
/* If about to start displaying at the beginning of a continuation line,
really start with previous frame line, in case it was not
continued when last redisplayed */
/* Likewise if we have to worry about selective display. */
(selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
{
- bp = *vmotion (bp.bufpos, -1, width, hscroll, window);
+ bp = *vmotion (bp.bufpos, -1, w);
--vpos;
pos = bp.bufpos;
}
if (bp.contin && bp.hpos != lmargin)
{
val.hpos = bp.prevhpos - width + lmargin;
+ did_motion = 1;
pos--;
}
tem = find_next_newline (tem, 1);
/* Compute the cursor position after that newline. */
- ep = *compute_motion (pos, vpos, val.hpos, tem,
+ ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
height, - (1 << (SHORTBITS - 1)),
width, hscroll, pos_tab_offset (w, bp.bufpos), w);
cursor_vpos = -1;
overlay_arrow_seen = 0;
+ zv_strings_seen = 0;
/* If changes do not reach to bottom of window,
figure out how much to scroll the rest of the window */
{
/* Now determine how far up or down the rest of the window has moved */
epto = pos_tab_offset (w, ep.bufpos);
- xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
+ xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
Z - XFASTINT (w->window_end_pos),
10000, 0, width, hscroll, epto, w);
scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
{
if (PT <= xp.bufpos)
{
- pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
+ pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
PT, height, - (1 << (SHORTBITS - 1)),
width, hscroll, epto, w);
}
else
{
- pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos,
+ pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
PT, height, - (1 << (SHORTBITS - 1)),
width, hscroll,
pos_tab_offset (w, xp.bufpos), w);
if (pp.bufpos < PT || pp.vpos == height)
return 0;
cursor_vpos = pp.vpos + top;
- cursor_hpos = pp.hpos + XFASTINT (w->left);
+ cursor_hpos = XFASTINT (w->left) + minmax (0, pp.hpos, width);
}
if (stop_vpos - scroll_amount >= height
|| (delta > 0 && xp.bufpos <= ZV)
|| (delta == 0 && xp.hpos))
{
- val = *vmotion (Z - XFASTINT (w->window_end_pos),
- delta, width, hscroll, window);
+ val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w);
XSETFASTINT (w->window_end_pos, Z - val.bufpos);
XSETFASTINT (w->window_end_vpos,
XFASTINT (w->window_end_vpos) + val.vpos);
/* If point was not in a line that was displayed, find it */
if (cursor_vpos < 0)
{
- val = *compute_motion (start, 0, lmargin, PT, 10000, 10000,
+ findpoint:
+ val = *compute_motion (start, 0, lmargin, 0, PT, 10000, 10000,
width, hscroll, pos_tab_offset (w, start), w);
/* Admit failure if point is off frame now */
if (val.vpos >= height)
return 0;
}
cursor_vpos = val.vpos + top;
- cursor_hpos = val.hpos + XFASTINT (w->left);
+ cursor_hpos = XFASTINT (w->left) + minmax (0, val.hpos, width);
}
- FRAME_CURSOR_X (f) = max (0, cursor_hpos);
+ FRAME_CURSOR_X (f) = cursor_hpos;
FRAME_CURSOR_Y (f) = cursor_vpos;
if (debug_end_pos)
{
- val = *compute_motion (start, 0, lmargin, ZV,
+ val = *compute_motion (start, 0, lmargin, 0, ZV,
height, - (1 << (SHORTBITS - 1)),
width, hscroll, pos_tab_offset (w, start), w);
if (val.vpos != XFASTINT (w->window_end_vpos))
}
/* Increment the buffer's time stamp, but also increment the save
- and autosave timestamps, so as not to screw up that timekeeping. */
- if (BUF_MODIFF (buf) == buf->save_modified)
- buf->save_modified++;
+ and autosave timestamps, so as not to screw up that timekeeping. */
+ if (BUF_MODIFF (buf) == BUF_SAVE_MODIFF (buf))
+ BUF_SAVE_MODIFF (buf)++;
if (BUF_MODIFF (buf) == buf->auto_save_modified)
buf->auto_save_modified++;
int last_code = -1;
int last_merged = 0;
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
if (! FRAME_TERMCAP_P (f))
while (n--)
{
GLYPH glyph;
int cface;
{
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
if (! FRAME_TERMCAP_P (f))
{
if (FAST_GLYPH_FACE (glyph) != 0)
register int pos = start;
register int c;
register GLYPH *p1;
- int end;
register int pause;
register unsigned char *p;
GLYPH *endp;
register GLYPH *leftmargin;
- register GLYPH *p1prev = 0;
+ register GLYPH *p1prev;
register GLYPH *p1start;
+ int prevpos;
int *charstart;
FRAME_PTR f = XFRAME (w->frame);
int tab_width = XINT (current_buffer->tab_width);
struct position val;
int lastpos;
int invis;
+ int last_invis_skip = 0;
+ Lisp_Object last_invis_prop;
int hscroll = XINT (w->hscroll);
int truncate = (hscroll
|| (truncate_partial_width_windows
register struct Lisp_Vector *dp = window_display_table (w);
Lisp_Object default_invis_vector[3];
- /* Nonzero means display something where there are invisible lines.
- The precise value is the number of glyphs to display. */
+ /* Number of characters of ellipsis to display after an invisible line
+ if it calls for an ellipsis.
+ Note that this value can be nonzero regardless of whether
+ selective display is enabled--you must check that separately. */
int selective_rlen
- = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
+ = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
? XVECTOR (DISP_INVIS_VECTOR (dp))->size
- : selective && !NILP (current_buffer->selective_display_ellipses)
- ? 3 : 0);
+ : !NILP (current_buffer->selective_display_ellipses) ? 3 : 0);
/* This is the sequence of Lisp objects to display
when there are invisible lines. */
Lisp_Object *invis_vector_contents
to overlays or text property changes. */
int next_face_change;
-#ifdef USE_TEXT_PROPERTIES
- /* The next location where the `invisible' property changes */
- int next_invisible;
-#endif
-
+ /* The next location where the `invisible' property changes, or an
+ overlay starts or ends. */
+ int next_boundary;
+
/* The face we're currently using. */
int current_face = 0;
int i;
region_beg = region_end = -1;
if (MINI_WINDOW_P (w)
- && start == 1
+ && start == BEG
&& vpos == XFASTINT (w->top))
{
if (! NILP (minibuf_prompt))
minibuf_prompt_width
= (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
XSTRING (minibuf_prompt)->size, hpos,
- (!truncate ? continuer : truncator),
- 1, -1, -1)
+ /* Display a space if we truncate. */
+ ' ',
+ 1, -1,
+ /* Truncate the prompt a little before the
+ margin, so user input can at least start
+ on the first line. */
+ w->width > 10 ? w->width - 4 : -1)
- hpos);
hpos += minibuf_prompt_width;
+ taboffset -= minibuf_prompt_width;
}
else
minibuf_prompt_width = 0;
}
- end = ZV;
-
/* If we're hscrolled at all, use compute_motion to skip over any
text off the left edge of the window. compute_motion may know
tricks to do this faster than we can. */
if (hpos < 0)
{
struct position *left_edge
- = compute_motion (pos, vpos, hpos,
- end, vpos, 0,
+ = compute_motion (pos, vpos, hpos, 0,
+ ZV, vpos, 0,
width, hscroll, taboffset, w);
/* Retrieve the buffer position and column provided by
or at face change. */
pause = pos;
next_face_change = pos;
-#ifdef USE_TEXT_PROPERTIES
- next_invisible = pos;
-#endif
+ next_boundary = pos;
+ p1prev = p1;
+ prevpos = pos;
while (1)
{
- /* Record which glyph starts a character,
- and the character position of that character. */
- if (p1 >= leftmargin)
- charstart[p1 - p1start] = pos;
-
- if (p1 >= endp)
- break;
-
- p1prev = p1;
if (pos >= pause)
{
- /* Did we hit the end of the visible region of the buffer?
- Stop here. */
- if (pos >= end)
- break;
-
- /* Did we reach point? Record the cursor location. */
- if (pos == PT && cursor_vpos < 0)
+ while (pos == next_boundary)
{
- cursor_vpos = vpos;
- cursor_hpos = p1 - leftmargin;
- }
+ Lisp_Object position, limit, prop, ww;
+
+ /* Display the overlay strings here, unless we're at ZV
+ and have already displayed the appropriate strings
+ on an earlier line. */
+ if (pos < ZV || !zv_strings_seen++)
+ {
+ int ovlen;
+ char *ovstr;
+ ovlen = overlay_strings (pos, w, &ovstr);
+ for (; ovlen; ovlen--, ovstr++)
+ {
+ if (p1 >= leftmargin && p1 < endp)
+ *p1 = MAKE_GLYPH (f, *ovstr, current_face);
+ p1++;
+ }
+ }
+
+ /* Did we reach point? Record the cursor location. */
+ if (pos == PT && cursor_vpos < 0)
+ {
+ cursor_vpos = vpos;
+ cursor_hpos = p1 - leftmargin;
+ }
+
+ if (pos >= ZV)
+ break;
-#ifdef USE_TEXT_PROPERTIES
- /* if the `invisible' property is set to t, we can skip to
- the next property change */
- while (pos == next_invisible && pos < end)
- {
- Lisp_Object position, limit, endpos, prop, ww;
XSETFASTINT (position, pos);
- XSETWINDOW (ww, w);
- prop = Fget_char_property (position, Qinvisible, ww);
+ limit = Fnext_overlay_change (position);
+#ifdef USE_TEXT_PROPERTIES
/* This is just an estimate to give reasonable
performance; nothing should go wrong if it is too small. */
- limit = Fnext_overlay_change (position);
if (XFASTINT (limit) > pos + 50)
XSETFASTINT (limit, pos + 50);
- endpos = Fnext_single_property_change (position, Qinvisible,
- Fcurrent_buffer (), limit);
- if (INTEGERP (endpos))
- next_invisible = XINT (endpos);
- else
- next_invisible = end;
- if (! NILP (prop))
+ limit = Fnext_single_property_change (position, Qinvisible,
+ Fcurrent_buffer (), limit);
+#endif
+ next_boundary = XFASTINT (limit);
+ /* if the `invisible' property is set, we can skip to
+ the next property change. */
+ XSETWINDOW (ww, w);
+ prop = Fget_char_property (position, Qinvisible, ww);
+ if (TEXT_PROP_MEANS_INVISIBLE (prop))
{
- if (pos < PT && next_invisible >= PT)
+ if (pos < PT && next_boundary >= PT)
{
cursor_vpos = vpos;
cursor_hpos = p1 - leftmargin;
}
- pos = next_invisible;
+ pos = next_boundary;
+ last_invis_skip = pos;
+ last_invis_prop = prop;
}
}
- if (pos >= end)
+
+ /* Did we reach point? Record the cursor location. */
+ if (pos == PT && cursor_vpos < 0)
+ {
+ cursor_vpos = vpos;
+ cursor_hpos = p1 - leftmargin;
+ }
+
+ /* Did we hit the end of the visible region of the buffer?
+ Stop here. */
+ if (pos >= ZV)
break;
-#endif
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
/* Did we hit a face change? Figure out what face we should
use now. We also hit this the first time through the
loop, to see what face we should start with. */
&next_face_change, pos + 50, 0);
#endif
- pause = end;
+ pause = ZV;
-#ifdef USE_TEXT_PROPERTIES
- if (pos < next_invisible && next_invisible < pause)
- pause = next_invisible;
-#endif
+ if (pos < next_boundary && next_boundary < pause)
+ pause = next_boundary;
if (pos < next_face_change && next_face_change < pause)
pause = next_face_change;
p = &FETCH_CHAR (pos);
}
+
+ if (p1 >= endp)
+ break;
+
+ p1prev = p1;
+
c = *p++;
- if (c >= 040 && c < 0177
- && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c))))
+ /* Let a display table override all standard display methods. */
+ if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
+ {
+ p1 = copy_part_of_rope (f, p1, leftmargin,
+ XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
+ XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
+ current_face);
+ }
+ else if (c >= 040 && c < 0177)
{
if (p1 >= leftmargin)
*p1 = MAKE_GLYPH (f, c, current_face);
else if (c == '\n')
{
invis = 0;
- while (pos + 1 < end
+ if (last_invis_skip == pos
+ && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
+ invis = 1;
+ while (pos + 1 < ZV
&& selective > 0
&& indented_beyond_p (pos + 1, selective))
{
copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
(p1 - p1prev), current_face);
}
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
/* Draw the face of the newline character as extending all the
way to the end of the frame line. */
if (current_face)
*p1++ = FAST_MAKE_GLYPH (' ', current_face);
}
#endif
+
+ /* Update charstarts for the newline that ended this line. */
+ /* Do nothing here for a char that's entirely off the left edge
+ or if it starts at the right edge. */
+ if (p1 >= leftmargin && p1prev != endp)
+ {
+ /* Store the newline's position into charstarts
+ for the column where the newline starts.
+ Store -1 for the rest of the glyphs it occupies. */
+ int *p2x = &charstart[(p1prev < leftmargin
+ ? leftmargin : p1prev)
+ - p1start];
+ int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
+
+ *p2x++ = pos;
+ while (p2x < p2)
+ *p2x++ = -1;
+ }
+
break;
}
else if (c == '\t')
copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
(p1 - p1prev), current_face);
}
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
/* Draw the face of the newline character as extending all the
way to the end of the frame line. */
if (current_face)
*p1++ = FAST_MAKE_GLYPH (' ', current_face);
}
#endif
+
+ /* Update charstarts for the ^M that ended this line. */
+ /* Do nothing here for a char that's entirely off the left edge
+ or if it starts at the right edge. */
+ if (p1 >= leftmargin && p1prev != endp)
+ {
+ /* Store the newline's position into charstarts
+ for the column where the newline starts.
+ Store -1 for the rest of the glyphs it occupies. */
+ int *p2x = &charstart[(p1prev < leftmargin
+ ? leftmargin : p1prev)
+ - p1start];
+ int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
+
+ *p2x++ = pos;
+ while (p2x < p2)
+ *p2x++ = -1;
+ }
break;
}
- else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- {
- p1 = copy_part_of_rope (f, p1, leftmargin,
- XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
- XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
- current_face);
- }
else if (c < 0200 && ctl_arrow)
{
if (p1 >= leftmargin)
p1++;
}
+ prevpos = pos;
+ pos++;
+
+ /* Update charstarts for the character just output. */
+
/* Do nothing here for a char that's entirely off the left edge. */
if (p1 >= leftmargin)
{
- /* For all the glyphs occupied by this character, except for the
- first, store -1 in charstarts. */
+ /* Store the char's position into charstarts
+ for the first glyph occupied by this char.
+ Store -1 for the rest of the glyphs it occupies. */
if (p1 != p1prev)
{
- int *p2x = &charstart[p1prev - p1start];
+ int *p2x = &charstart[(p1prev < leftmargin
+ ? leftmargin : p1prev)
+ - p1start];
int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
- /* The window's left column should always
- contain a character position.
- And don't clobber anything to the left of that. */
- if (p1prev < leftmargin)
- {
- p2x = charstart + (leftmargin - p1start);
- *p2x = pos;
- }
-
- /* This loop skips over the char p2x initially points to. */
- while (++p2x < p2)
- *p2x = -1;
+ if (p2x < p2)
+ *p2x++ = prevpos;
+ while (p2x < p2)
+ *p2x++ = -1;
}
}
-
- pos++;
}
val.hpos = - XINT (w->hscroll);
cursor_hpos += XFASTINT (w->left);
if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
{
- FRAME_CURSOR_Y (f) = cursor_vpos;
- FRAME_CURSOR_X (f) = cursor_hpos;
+ if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f)
+ && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window)))
+ {
+ FRAME_CURSOR_Y (f) = cursor_vpos;
+ FRAME_CURSOR_X (f) = cursor_hpos;
+ }
if (w == XWINDOW (selected_window))
{
if (len > width)
len = width;
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals))
{
/* If the arrow string has text props, obey them when displaying. */
}
}
else
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_FACES */
{
for (i = 0; i < len; i++)
leftmargin[i] = p[i];
XSTRING (string)->data,
XSTRING (string)->size,
hpos, 0, 0, hpos, maxendcol);
- /* Put a gap of 3 spaces between items. */
+ /* Put a space between items. */
if (hpos < maxendcol)
{
- int hpos1 = hpos + 3;
+ int hpos1 = hpos + 1;
hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
min (hpos1, maxendcol), maxendcol);
}
register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
line_number_displayed = 0;
+ w->column_number_displayed = Qnil;
get_display_line (f, vpos, left);
+
+ /* Temporarily make frame F's kboard the current kboard
+ so that kboard-local variables in the mode_line_format
+ will get the right values. */
+ push_frame_kboard (f);
+
display_mode_element (w, vpos, left, 0, right, right,
current_buffer->mode_line_format);
+
+ pop_frame_kboard ();
+
FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
/* Make the mode line inverse video if the entire line
if (XFASTINT (w->width) == FRAME_WIDTH (f)
|| XFASTINT (XWINDOW (w->parent)->width) == FRAME_WIDTH (f))
FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
-#ifdef HAVE_X_WINDOWS
- else if (! FRAME_TERMCAP_P (f))
+#ifdef HAVE_FACES
+ else if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video)
{
/* For a partial width window, explicitly set face of each glyph. */
int i;
depth++;
-#ifdef SWITCH_ENUM_BUG
- switch ((int) XTYPE (elt))
-#else
- switch (XTYPE (elt))
-#endif
+ switch (SWITCH_ENUM_CAST (XTYPE (elt)))
{
case Lisp_String:
{
switch (c)
{
+ case '*':
+ if (!NILP (b->read_only))
+ return "%";
+ if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
+ return "*";
+ return "-";
+
+ case '+':
+ /* This differs from %* only for a modified read-only buffer. */
+ if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
+ return "*";
+ if (!NILP (b->read_only))
+ return "%";
+ return "-";
+
+ case '&':
+ /* This differs from %* in ignoring read-only-ness. */
+ if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
+ return "*";
+ return "-";
+
+ case '%':
+ return "%";
+
+ case '[':
+ {
+ int i;
+ char *p;
+
+ if (command_loop_level > 5)
+ return "[[[... ";
+ p = decode_mode_spec_buf;
+ for (i = 0; i < command_loop_level; i++)
+ *p++ = '[';
+ *p = 0;
+ return decode_mode_spec_buf;
+ }
+
+ case ']':
+ {
+ int i;
+ char *p;
+
+ if (command_loop_level > 5)
+ return " ...]]]";
+ p = decode_mode_spec_buf;
+ for (i = 0; i < command_loop_level; i++)
+ *p++ = ']';
+ *p = 0;
+ return decode_mode_spec_buf;
+ }
+
+ case '-':
+ {
+ register char *p;
+ register int i;
+
+ if (maxwidth < sizeof (lots_of_dashes))
+ return lots_of_dashes;
+ else
+ {
+ for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
+ *p++ = '-';
+ *p = '\0';
+ }
+ return decode_mode_spec_buf;
+ }
+
case 'b':
obj = b->name;
#if 0
#endif
break;
+ case 'c':
+ {
+ int col = current_column ();
+ XSETFASTINT (w->column_number_displayed, col);
+ sprintf (decode_mode_spec_buf, "%d", col);
+ return decode_mode_spec_buf;
+ }
+
+ case 'F':
+ /* %F displays the frame name. */
+ return (char *) XSTRING (selected_frame->name)->data;
+
case 'f':
obj = b->filename;
#if 0
return " Narrow";
break;
- case '*':
- if (!NILP (b->read_only))
- return "%";
- if (BUF_MODIFF (b) > b->save_modified)
- return "*";
- return "-";
-
- case '+':
- /* This differs from %* only for a modified read-only buffer. */
- if (BUF_MODIFF (b) > b->save_modified)
- return "*";
- if (!NILP (b->read_only))
- return "%";
- return "-";
-
- case '&':
- /* This differs from %* in ignoring read-only-ness. */
- if (BUF_MODIFF (b) > b->save_modified)
- return "*";
- return "-";
-
- case 's':
- /* status of process */
- obj = Fget_buffer_process (w->buffer);
- if (NILP (obj))
- return "no process";
-#ifdef subprocesses
- obj = Fsymbol_name (Fprocess_status (obj));
-#endif
- break;
-
- case 't': /* indicate TEXT or BINARY */
-#ifdef MODE_LINE_BINARY_TEXT
- return MODE_LINE_BINARY_TEXT (b);
-#else
- return "T";
-#endif
-
case 'p':
{
int pos = marker_position (w->start);
}
}
- case '%':
- return "%";
-
- case '[':
- {
- int i;
- char *p;
-
- if (command_loop_level > 5)
- return "[[[... ";
- p = decode_mode_spec_buf;
- for (i = 0; i < command_loop_level; i++)
- *p++ = '[';
- *p = 0;
- return decode_mode_spec_buf;
- }
-
- case ']':
- {
- int i;
- char *p;
-
- if (command_loop_level > 5)
- return " ...]]]";
- p = decode_mode_spec_buf;
- for (i = 0; i < command_loop_level; i++)
- *p++ = ']';
- *p = 0;
- return decode_mode_spec_buf;
- }
+ case 's':
+ /* status of process */
+ obj = Fget_buffer_process (w->buffer);
+ if (NILP (obj))
+ return "no process";
+#ifdef subprocesses
+ obj = Fsymbol_name (Fprocess_status (obj));
+#endif
+ break;
- case '-':
- {
- register char *p;
- register int i;
-
- if (maxwidth < sizeof (lots_of_dashes))
- return lots_of_dashes;
- else
- {
- for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
- *p++ = '-';
- *p = '\0';
- }
- return decode_mode_spec_buf;
- }
+ case 't': /* indicate TEXT or BINARY */
+#ifdef MODE_LINE_BINARY_TEXT
+ return MODE_LINE_BINARY_TEXT (b);
+#else
+ return "T";
+#endif
}
if (STRINGP (obj))
else if (c == 0)
break;
- if (c >= 040 && c < 0177
- && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c))))
+ if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
+ {
+ p1 = copy_part_of_rope (f, p1, start,
+ XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
+ XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
+ 0);
+ }
+ else if (c >= 040 && c < 0177)
{
if (p1 >= start)
*p1 = c;
}
while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
}
- else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
- {
- p1 = copy_part_of_rope (f, p1, start,
- XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
- XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
- 0);
- }
else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
{
if (p1 >= start)
}
}
\f
+/* This is like a combination of memq and assq.
+ Return 1 if PROPVAL appears as an element of LIST
+ or as the car of an element of LIST.
+ If PROPVAL is a list, compare each element against LIST
+ in that way, and return 1 if any element of PROPVAL is found in LIST.
+ Otherwise return 0.
+ This function cannot quit. */
+
+int
+invisible_p (propval, list)
+ register Lisp_Object propval;
+ Lisp_Object list;
+{
+ register Lisp_Object tail, proptail;
+ for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ register Lisp_Object tem;
+ tem = XCONS (tail)->car;
+ if (EQ (propval, tem))
+ return 1;
+ if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
+ return 1;
+ }
+ if (CONSP (propval))
+ for (proptail = propval; CONSP (proptail);
+ proptail = XCONS (proptail)->cdr)
+ {
+ Lisp_Object propelt;
+ propelt = XCONS (proptail)->car;
+ for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ register Lisp_Object tem;
+ tem = XCONS (tail)->car;
+ if (EQ (propelt, tem))
+ return 1;
+ if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Return 1 if PROPVAL appears as the car of an element of LIST
+ and the cdr of that element is non-nil.
+ If PROPVAL is a list, check each element of PROPVAL in that way,
+ and the first time some element is found,
+ return 1 if the cdr of that element is non-nil.
+ Otherwise return 0.
+ This function cannot quit. */
+
+int
+invisible_ellipsis_p (propval, list)
+ register Lisp_Object propval;
+ Lisp_Object list;
+{
+ register Lisp_Object tail, proptail;
+ for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ register Lisp_Object tem;
+ tem = XCONS (tail)->car;
+ if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
+ return ! NILP (XCONS (tem)->cdr);
+ }
+ if (CONSP (propval))
+ for (proptail = propval; CONSP (proptail);
+ proptail = XCONS (proptail)->cdr)
+ {
+ Lisp_Object propelt;
+ propelt = XCONS (proptail)->car;
+ for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ register Lisp_Object tem;
+ tem = XCONS (tail)->car;
+ if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
+ return ! NILP (XCONS (tem)->cdr);
+ }
+ }
+ return 0;
+}
+\f
void
syms_of_xdisp ()
{
highlight_nonselected_windows = 1;
DEFVAR_BOOL ("multiple-frames", &multiple_frames,
- "Non-nil means more than one frame is in use, not counting minibuffer frames.\n\
-Not guaranteed to be accurate except while parsing frame-title-format.");
+ "Non-nil if more than one frame is visible on this display.\n\
+Minibuffer-only frames don't count, but iconified frames do.\n\
+This variable is not guaranteed to be accurate except while parsing\n\
+frame-title-format.");
DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
"Template for displaying the titlebar of visible frames.\n\
Fcons (intern ("system-name"),
Qnil)))),
Qnil)));
+
+ DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
+ "Maximum number of lines to keep in the message log buffer.\n\
+If nil, disable message logging. If t, log messages but don't truncate\n\
+the buffer when it becomes large.");
+ XSETFASTINT (Vmessage_log_max, 50);
+
+ DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
+ "Functions called before redisplay, if window sizes have changed.\n\
+The value should be a list of functions that take one argument.\n\
+Just before redisplay, for each frame, if any of its windows have changed\n\
+size since the last redisplay, or have been split or deleted,\n\
+all the functions in the list are called, with the frame as argument.");
+ Vwindow_size_change_functions = Qnil;
}
/* initialize the window system */