/* 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))
/* 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;
/* 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 ();
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 ()
+{
+ message2 (echo_area_glyphs, echo_area_glyphs_length);
+}
+
static void
echo_area_display ()
{
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];
#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;
-
- /* 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 ();
+ all_windows = (update_mode_lines || buffer_shared > 1
+ || clip_changed || windows_or_buffers_changed);
- if (frame_garbaged)
+ /* 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)
{
- redraw_garbaged_frames ();
- frame_garbaged = 0;
- }
+ Lisp_Object tail, frame;
- all_windows = (update_mode_lines || buffer_shared > 1
- || clip_changed || windows_or_buffers_changed);
+ 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));
+ UNGCPRO;
+ }
+ }
+ else
+ update_menu_bar (selected_frame);
+ /* 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.
static int do_verify_charstarts;
+/* Counter is used to clear the face cache
+ no more than once ever 1000 redisplays. */
+static int clear_face_cache_count;
+
void
redisplay ()
{
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)
&& GPT >= tlbufpos
/* If selective display, can't optimize
if the changes start at the beginning of the line. */
- && ((XTYPE (current_buffer->selective_display) == Lisp_Int
+ && ((INTEGERP (current_buffer->selective_display)
&& XINT (current_buffer->selective_display) > 0
? (beg_unchanged >= tlbufpos
&& GPT > tlbufpos)
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,
this_line_bufpos = 0;
all_windows |= buffer_shared > 1;
+ clear_face_cache_count++;
+
if (all_windows)
{
Lisp_Object tail, frame;
-#ifdef HAVE_X_WINDOWS
- /* Since we're doing a thorough redisplay, we might as well
- recompute all our display faces. */
- clear_face_vector ();
+#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)
+ {
+ clear_face_cache ();
+ clear_face_cache_count = 0;
+ }
#endif
/* Recompute # windows showing selected buffer.
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))
{
FRAME_PTR f;
- if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
+ if (!FRAMEP (XCONS (tail)->car))
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
beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
end_unchanged = BUF_Z (b) - BUF_GPT (b);
- XFASTINT (w->last_point) = BUF_PT (b);
- XFASTINT (w->last_point_x) = FRAME_CURSOR_X (selected_frame);
- XFASTINT (w->last_point_y) = FRAME_CURSOR_Y (selected_frame);
+ XSETFASTINT (w->last_point, BUF_PT (b));
+ XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
+ XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
if (all_windows)
mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
else
{
w->update_mode_line = Qnil;
- XFASTINT (w->last_modified) = BUF_MODIFF (b);
+ XSETFASTINT (w->last_modified, BUF_MODIFF (b));
w->window_end_valid = w->buffer;
last_arrow_position = Voverlay_arrow_position;
last_arrow_string = Voverlay_arrow_string;
for (;!NILP (window); window = w->next)
{
- if (XTYPE (window) != Lisp_Window) abort ();
+ if (!WINDOWP (window)) abort ();
w = XWINDOW (window);
if (!NILP (w->buffer))
{
- XFASTINT (w->last_modified)
- = !flag ? 0
- : XBUFFER (w->buffer) == current_buffer
- ? MODIFF : BUF_MODIFF (XBUFFER (w->buffer));
+ XSETFASTINT (w->last_modified,
+ !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
/* Record if we are showing a region, so can make sure to
update it fully at next redisplay. */
|| !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;
call1 (Vrun_hooks, Qmenu_bar_update_hook);
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. */
BUF_PT (current_buffer) = new_pt;
}
+ /* If any of the character widths specified in the display table
+ have changed, invalidate the width run cache. It's true that this
+ may be a bit late to catch such changes, but the rest of
+ redisplay goes (non-fatally) haywire when the display table is
+ changed, so why should we worry about doing any better? */
+ if (current_buffer->width_run_cache)
+ {
+ struct Lisp_Vector *disptab = buffer_display_table ();
+
+ if (! disptab_matches_widthtab (disptab,
+ XVECTOR (current_buffer->width_table)))
+ {
+ invalidate_region_cache (current_buffer,
+ current_buffer->width_run_cache,
+ BEG, Z);
+ recompute_width_table (current_buffer, disptab);
+ }
+ }
+
/* If window-start is screwed up, choose a new one. */
if (XMARKER (w->start)->buffer != current_buffer)
goto recenter;
{
/* 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;
- XFASTINT (w->last_modified) = 0;
+ XSETFASTINT (w->last_modified, 0);
if (startp < BEGV) startp = BEGV;
if (startp > ZV) startp = ZV;
try_window (window, startp);
if (cursor_vpos < 0)
{
- /* ??? What should happen here if highlighting a region? */
/* If point does not appear, move point so it does appear */
pos = *compute_motion (startp, 0,
((EQ (window, minibuf_window) && startp == 1)
FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
}
+ /* If we are highlighting the region,
+ then we just changed the region, so redisplay to show it. */
+ if (!NILP (Vtransient_mark_mode)
+ && !NILP (current_buffer->mark_active))
+ {
+ cancel_my_columns (XWINDOW (window));
+ try_window (window, startp);
+ }
}
goto done;
}
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)
&& !EQ (window, minibuf_window))
{
pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0),
- PT, height + 1, 10000, width, hscroll,
+ PT, height, 0, width, hscroll,
pos_tab_offset (w, startp), w);
if (pos.vpos < height)
cancel_my_columns (w);
}
- XFASTINT (w->last_modified) = 0;
- w->update_mode_line = Qt;
+ XSETFASTINT (w->last_modified, 0);
+ /* 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 */
goto scroll_fail;
}
- pos = *vmotion (startp, PT < startp ? - scroll_step : scroll_step,
+ pos = *vmotion (startp,
+ (PT < startp ? - scroll_step : scroll_step),
width, hscroll, window);
if (PT >= pos.bufpos)
= (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
{
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;
}
w->update_mode_line = Qt;
/* Say where last char on frame will be, once redisplay is finished. */
- XFASTINT (w->window_end_pos) = Z - pos;
- XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top);
+ XSETFASTINT (w->window_end_pos, Z - pos);
+ XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
/* But that is not valid info until redisplay finishes. */
w->window_end_valid = Qnil;
}
register int i, tem;
int last_text_vpos = 0;
int stop_vpos;
- int selective
- = XTYPE (current_buffer->selective_display) == Lisp_Int
- ? XINT (current_buffer->selective_display)
- : !NILP (current_buffer->selective_display) ? -1 : 0;
+ int selective = (INTEGERP (current_buffer->selective_display)
+ ? XINT (current_buffer->selective_display)
+ : !NILP (current_buffer->selective_display) ? -1 : 0);
struct position val, bp, ep, xp, pp;
int scroll_amount = 0;
/* Find position before which nothing is changed. */
bp = *compute_motion (start, 0, lmargin,
- min (ZV, beg_unchanged + BEG), height + 1, 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.
bp = *compute_motion (start, 0, lmargin,
Z, height, 0,
width, hscroll, pos_tab_offset (w, start), w);
- XFASTINT (w->window_end_vpos) = height;
- XFASTINT (w->window_end_pos) = Z - bp.bufpos;
- return 1;
+ XSETFASTINT (w->window_end_vpos, height);
+ XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
+ goto findpoint;
}
return 0;
}
if (i == xp.bufpos)
return -2;
- XFASTINT (w->window_end_vpos) += scroll_amount;
+ XSETFASTINT (w->window_end_vpos,
+ XFASTINT (w->window_end_vpos) + scroll_amount);
/* Before doing any scrolling, verify that point will be on frame. */
if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
include the split character in the text considered on the frame */
if (val.hpos < lmargin)
val.bufpos++;
- XFASTINT (w->window_end_vpos) = last_text_vpos;
- XFASTINT (w->window_end_pos) = Z - val.bufpos;
+ XSETFASTINT (w->window_end_vpos, last_text_vpos);
+ XSETFASTINT (w->window_end_pos, Z - val.bufpos);
}
/* If scrolling made blank lines at window bottom,
{
val = *vmotion (Z - XFASTINT (w->window_end_pos),
delta, width, hscroll, window);
- XFASTINT (w->window_end_pos) = Z - val.bufpos;
- XFASTINT (w->window_end_vpos) += val.vpos;
+ 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)
{
+ findpoint:
val = *compute_motion (start, 0, lmargin, PT, 10000, 10000,
width, hscroll, pos_tab_offset (w, start), w);
/* Admit failure if point is off frame now */
}
/* 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)
return glyph;
}
\f
-/* Display one line of window w, starting at position START in W's buffer.
- Display starting at horizontal position HPOS, which is normally zero
- or negative. A negative value causes output up to hpos = 0 to be discarded.
- This is done for negative hscroll, or when this is a continuation line
- and the continuation occurred in the middle of a multi-column character.
+/* Display one line of window W, starting at position START in W's buffer.
+
+ Display starting at horizontal position HPOS, expressed relative to
+ W's left edge. In situations where the text at START shouldn't
+ start at the left margin (i.e. when the window is hscrolled, or
+ we're continuing a line which left off in the midst of a
+ multi-column character), HPOS should be negative; we throw away
+ characters up 'til hpos = 0. So, HPOS must take hscrolling into
+ account.
TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
- Display on position VPOS on the frame. (origin 0).
+ Display on position VPOS on the frame. It is origin 0, relative to
+ the top of the frame, not W.
Returns a STRUCT POSITION giving character to start next line with
and where to display it, including a zero or negative hpos.
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
= !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active);
int region_beg, region_end;
- int selective
- = XTYPE (current_buffer->selective_display) == Lisp_Int
- ? XINT (current_buffer->selective_display)
- : !NILP (current_buffer->selective_display) ? -1 : 0;
+ int selective = (INTEGERP (current_buffer->selective_display)
+ ? XINT (current_buffer->selective_display)
+ : !NILP (current_buffer->selective_display) ? -1 : 0);
register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
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 && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector
+ = (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
- = (dp && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector
+ = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
: default_invis_vector);
- GLYPH truncator = (dp == 0 || XTYPE (DISP_TRUNC_GLYPH (dp)) != Lisp_Int
+ GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
- GLYPH continuer = (dp == 0 || XTYPE (DISP_CONTINUE_GLYPH (dp)) != Lisp_Int
+ GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
/* The next buffer location at which the face should change, due
int current_face = 0;
int i;
- XFASTINT (default_invis_vector[2]) = '.';
+ XSETFASTINT (default_invis_vector[2], '.');
default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
hpos += XFASTINT (w->left);
else
region_beg = region_end = -1;
- if (MINI_WINDOW_P (w) && start == 1
+ if (MINI_WINDOW_P (w)
+ && start == 1
&& 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;
}
- desired_glyphs->bufp[vpos] = pos;
+ 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,
+ width, hscroll, taboffset, w);
+
+ /* Retrieve the buffer position and column provided by
+ compute_motion. We can't assume that the column will be
+ zero, because you may have multi-column characters crossing
+ the left margin.
+
+ compute_motion may have moved us past the screen position we
+ requested, if we hit a multi-column character, or the end of
+ the line. If so, back up. */
+ if (left_edge->vpos > vpos
+ || left_edge->hpos > 0)
+ {
+ pos = left_edge->bufpos - 1;
+ hpos = left_edge->prevhpos;
+ }
+ else
+ {
+ pos = left_edge->bufpos;
+ hpos = left_edge->hpos;
+ }
+ }
+
+ desired_glyphs->bufp[vpos] = start;
p1 = desired_glyphs->glyphs[vpos] + hpos;
p1start = p1;
charstart = desired_glyphs->charstarts[vpos] + hpos;
/* In case we don't ever write anything into it... */
desired_glyphs->charstarts[vpos][XFASTINT (w->left)] = -1;
- end = ZV;
leftmargin = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
endp = leftmargin + width;
while (pos == next_invisible && pos < end)
{
Lisp_Object position, limit, endpos, prop, ww;
- XFASTINT (position) = pos;
- XSET (ww, Lisp_Window, w);
+ XSETFASTINT (position, pos);
+ XSETWINDOW (ww, w);
prop = Fget_char_property (position, Qinvisible, ww);
/* 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)
- XFASTINT (limit) = pos + 50;
+ XSETFASTINT (limit, pos + 50);
endpos = Fnext_single_property_change (position, Qinvisible,
- Fcurrent_buffer (), limit);
+ Fcurrent_buffer (),
+ limit);
if (INTEGERP (endpos))
next_invisible = XINT (endpos);
else
next_invisible = end;
- if (! NILP (prop))
+ if (TEXT_PROP_MEANS_INVISIBLE (prop))
{
if (pos < PT && next_invisible >= PT)
{
cursor_hpos = p1 - leftmargin;
}
pos = next_invisible;
+ last_invis_skip = pos;
+ last_invis_prop = prop;
}
}
if (pos >= end)
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. */
p = &FETCH_CHAR (pos);
}
c = *p++;
- if (c >= 040 && c < 0177
- && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector))
+ /* 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;
+ if (last_invis_skip == pos
+ && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
+ invis = 1;
while (pos + 1 < end
&& 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)
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)
#endif
break;
}
- else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector)
- {
- 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 = fix_glyph (f, (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int
+ *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
current_face);
p1++;
else
{
if (p1 >= leftmargin)
- *p1 = fix_glyph (f, (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int
+ *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
current_face);
p1++;
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 the start of this line is the overlay arrow-position,
then put the arrow string into the display-line. */
- if (XTYPE (Voverlay_arrow_position) == Lisp_Marker
+ if (MARKERP (Voverlay_arrow_position)
&& current_buffer == XMARKER (Voverlay_arrow_position)->buffer
&& start == marker_position (Voverlay_arrow_position)
- && XTYPE (Voverlay_arrow_string) == Lisp_String
+ && STRINGP (Voverlay_arrow_string)
&& ! overlay_arrow_seen)
{
unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
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. */
Lisp_Object face, ilisp;
int newface;
- XFASTINT (ilisp) = i;
+ XSETFASTINT (ilisp, i);
face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
newface = compute_glyph_face_1 (f, face, 0);
leftmargin[i] = FAST_MAKE_GLYPH (c, newface);
}
}
else
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_FACES */
{
for (i = 0; i < len; i++)
leftmargin[i] = p[i];
if (NILP (string))
break;
- XFASTINT (XVECTOR (items)->contents[i + 2]) = hpos;
+ XSETFASTINT (XVECTOR (items)->contents[i + 2], hpos);
if (hpos < maxendcol)
hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
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:
{
tem = Fsymbol_value (elt);
/* If value is a string, output that string literally:
don't check for % within it. */
- if (XTYPE (tem) == Lisp_String)
+ if (STRINGP (tem))
{
if (frame_title_ptr)
hpos = store_frame_title (XSTRING (tem)->data,
If first element is a symbol, process the cadr or caddr recursively
according to whether the symbol's value is non-nil or nil. */
car = XCONS (elt)->car;
- if (XTYPE (car) == Lisp_Symbol)
+ if (SYMBOLP (car))
{
tem = Fboundp (car);
elt = XCONS (elt)->cdr;
- if (XTYPE (elt) != Lisp_Cons)
+ if (!CONSP (elt))
goto invalid;
/* elt is now the cdr, and we know it is a cons cell.
Use its car if CAR has a non-nil value. */
elt = XCONS (elt)->cdr;
if (NILP (elt))
break;
- else if (XTYPE (elt) != Lisp_Cons)
+ else if (!CONSP (elt))
goto invalid;
elt = XCONS (elt)->car;
goto tail_recurse;
}
- else if (XTYPE (car) == Lisp_Int)
+ else if (INTEGERP (car))
{
register int lim = XINT (car);
elt = XCONS (elt)->cdr;
}
goto tail_recurse;
}
- else if (XTYPE (car) == Lisp_String || XTYPE (car) == Lisp_Cons)
+ else if (STRINGP (car) || CONSP (car))
{
register int limit = 50;
/* LIMIT is to protect against circular lists. */
- while (XTYPE (elt) == Lisp_Cons && --limit > 0
+ while (CONSP (elt) && --limit > 0
&& hpos < maxendcol)
{
hpos = display_mode_element (w, vpos, hpos, depth,
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
if (NILP (obj))
return "[none]";
- else if (XTYPE (obj) == Lisp_String && XSTRING (obj)->size > maxwidth)
+ else if (STRINGP (obj) && XSTRING (obj)->size > maxwidth)
{
bcopy ("...", decode_mode_spec_buf, 3);
bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
go back past it. */
if (startpos == BUF_BEGV (b))
{
- XFASTINT (w->base_line_number) = topline;
- XFASTINT (w->base_line_pos) = BUF_BEGV (b);
+ XSETFASTINT (w->base_line_number, topline);
+ XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
}
else if (nlines < height + 25 || nlines > height * 3 + 50
|| linepos == BUF_BEGV (b))
return "??";
}
- XFASTINT (w->base_line_number) = topline - nlines;
- XFASTINT (w->base_line_pos) = position;
+ XSETFASTINT (w->base_line_number, topline - nlines);
+ XSETFASTINT (w->base_line_pos, position);
}
/* Now count lines from the start pos to point. */
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 (XTYPE (obj) == Lisp_String)
+ if (STRINGP (obj))
return (char *) XSTRING (obj)->data;
else
return "";
check only for newlines. */
if (! (!NILP (current_buffer->selective_display)
&& !INTEGERP (current_buffer->selective_display)))
- return scan_buffer ('\n', start, count, shortage, 0);
+ return scan_buffer ('\n', start, 0, count, shortage, 0);
/* The code that follows is like scan_buffer
but checks for either newline or carriage return. */
register struct Lisp_Vector *dp = 0;
int i;
- if (XTYPE (Vstandard_display_table) == Lisp_Vector
+ if (VECTORP (Vstandard_display_table)
&& XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE)
dp = XVECTOR (Vstandard_display_table);
else if (c == 0)
break;
- if (c >= 040 && c < 0177
- && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector))
+ 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 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector)
- {
- 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)
- *p1 = fix_glyph (f, (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int
+ *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
0);
p1++;
else
{
if (p1 >= start)
- *p1 = fix_glyph (f, (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int
+ *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
0);
p1++;
}
}
\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 ()
{
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 */
if (!noninteractive)
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
- XFASTINT (XWINDOW (root_window)->top) = 0;
+ XSETFASTINT (XWINDOW (root_window)->top, 0);
set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
- XFASTINT (mini_w->top) = FRAME_HEIGHT (f) - 1;
+ XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
set_window_height (minibuf_window, 1, 0);
- XFASTINT (XWINDOW (root_window)->width) = FRAME_WIDTH (f);
- XFASTINT (mini_w->width) = FRAME_WIDTH (f);
+ XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
+ XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
}
}