#include <config.h>
#include <stdio.h>
+#define DOC_STRINGS_IN_COMMENTS
#include "lisp.h"
#include "keyboard.h"
#include "frame.h"
#include "macterm.h"
#endif
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
#define INFINITY 10000000
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
static int tool_bar_lines_needed P_ ((struct frame *));
static int single_display_prop_intangible_p P_ ((Lisp_Object));
static void ensure_echo_area_buffers P_ ((void));
-static struct glyph_row *row_containing_pos P_ ((struct window *, int,
- struct glyph_row *,
- struct glyph_row *));
static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
static int with_echo_area_buffer P_ ((struct window *, int,
static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
static void extend_face_to_end_of_line P_ ((struct it *));
static int append_space P_ ((struct it *, int));
-static void make_cursor_line_fully_visible P_ ((struct window *));
+static int make_cursor_line_fully_visible P_ ((struct window *));
static int try_scrolling P_ ((Lisp_Object, int, int, int, int));
static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
static int trailing_whitespace_p P_ ((int));
static int message_log_check_duplicate P_ ((int, int, int, int));
-int invisible_p P_ ((Lisp_Object, Lisp_Object));
-int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object));
static void push_it P_ ((struct it *));
static void pop_it P_ ((struct it *));
static void sync_frame_with_window_matrix_rows P_ ((struct window *));
static int display_mode_lines P_ ((struct window *));
static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object));
static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object));
-static char *decode_mode_spec P_ ((struct window *, int, int, int));
+static char *decode_mode_spec P_ ((struct window *, int, int, int, int *));
static void display_menu_bar P_ ((struct window *));
static int display_count_lines P_ ((int, int, int, int, int *));
static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
at character position CHARPOS. CHARPOS < 0 means that no buffer
position is specified which is useful when the iterator is assigned
a position later. BYTEPOS is the byte position corresponding to
- CHARPOS. BYTEPOS <= 0 means compute it from CHARPOS.
+ CHARPOS. BYTEPOS < 0 means compute it from CHARPOS.
If ROW is not null, calls to produce_glyphs with IT as parameter
will produce glyphs in that row.
/* Some precondition checks. */
xassert (w != NULL && it != NULL);
- xassert (charpos < 0 || (charpos > 0 && charpos <= ZV));
+ xassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
+ && charpos <= ZV));
/* If face attributes have been changed since the last redisplay,
free realized faces now because they depend on face definitions
/* Non-zero if we should highlight the region. */
highlight_region_p
- = (!NILP (Vtransient_mark_mode)
+ = (!NILP (Vtransient_mark_mode)
&& !NILP (current_buffer->mark_active)
&& XMARKER (current_buffer->mark)->buffer != 0);
/* If a buffer position was specified, set the iterator there,
getting overlays and face properties from that position. */
- if (charpos > 0)
+ if (charpos >= BUF_BEG (current_buffer))
{
it->end_charpos = ZV;
it->face_id = -1;
IT_CHARPOS (*it) = charpos;
/* Compute byte position if not specified. */
- if (bytepos <= 0)
+ if (bytepos < charpos)
IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
else
IT_BYTEPOS (*it) = bytepos;
{
prop = Fget_char_property (make_number (charpos - 1), Qinvisible,
window);
- if (TEXT_PROP_MEANS_INVISIBLE (prop)
- && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop))
- ellipses_p = 1;
+ ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
}
return ellipses_p;
val = Vfontification_functions;
specbind (Qfontification_functions, Qnil);
- specbind (Qafter_change_functions, Qnil);
if (!CONSP (val) || EQ (XCAR (val), Qlambda))
safe_call1 (val, pos);
}
else
{
- int visible_p, newpos, next_stop, start_charpos;
+ int invis_p, newpos, next_stop, start_charpos;
Lisp_Object pos, prop, overlay;
/* First of all, is there invisible text at this position? */
pos = make_number (IT_CHARPOS (*it));
prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
&overlay);
-
+ invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
+
/* If we are on invisible text, skip over it. */
- if (TEXT_PROP_MEANS_INVISIBLE (prop)
- && IT_CHARPOS (*it) < it->end_charpos)
+ if (invis_p && IT_CHARPOS (*it) < it->end_charpos)
{
/* Record whether we have to display an ellipsis for the
invisible text. */
- int display_ellipsis_p
- = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
+ int display_ellipsis_p = invis_p == 2;
handled = HANDLED_RECOMPUTE_PROPS;
text in the first place. If everything to the end of
the buffer was skipped, end the loop. */
if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
- visible_p = 1;
+ invis_p = 0;
else
{
/* We skipped some characters but not necessarily
all there are. Check if we ended up on visible
text. Fget_char_property returns the property of
the char before the given position, i.e. if we
- get visible_p = 1, this means that the char at
+ get invis_p = 0, this means that the char at
newpos is visible. */
pos = make_number (newpos);
prop = Fget_char_property (pos, Qinvisible, it->window);
- visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop);
+ invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
}
/* If we ended up on invisible text, proceed to
skip starting with next_stop. */
- if (!visible_p)
+ if (invis_p)
IT_CHARPOS (*it) = next_stop;
}
- while (!visible_p);
+ while (invis_p);
/* The position newpos is now either ZV or on visible text. */
IT_CHARPOS (*it) = newpos;
IT_STRING_BYTEPOS (*it) = -1;
it->string = Qnil;
it->method = next_element_from_buffer;
+ it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
it->sp = 0;
it->face_before_selective_p = 0;
/* Don't get confused by reusing the buffer used for echoing
for a different purpose. */
- if (!echoing && EQ (buffer, echo_message_buffer))
+ if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
cancel_echoing ();
record_unwind_protect (unwind_with_echo_area_buffer,
current_buffer->undo_list = Qt;
current_buffer->read_only = Qnil;
specbind (Qinhibit_read_only, Qt);
+ specbind (Qinhibit_modification_hooks, Qt);
if (clear_buffer_p && Z > BEG)
del_range (BEG, Z);
DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
0, 1, 0,
- "Return the number of lines occupied by the tool bar of FRAME.")
- (frame)
+ /* Return the number of lines occupied by the tool bar of FRAME. */
+ (frame))
Lisp_Object frame;
{
struct frame *f;
&text_area_width, &text_area_height);
/* Scroll when cursor is inside this scroll margin. */
+ /* Shouldn't we export this `5' for customization ? -stef */
hscroll_margin = 5 * CANON_X_UNIT (XFRAME (w->frame));
if ((XFASTINT (w->hscroll)
/* Modify the desired matrix of window W and W->vscroll so that the
- line containing the cursor is fully visible. */
+ line containing the cursor is fully visible. If this requires
+ larger matrices than are allocated, set fonts_changed_p and return
+ 0. */
-static void
+static int
make_cursor_line_fully_visible (w)
struct window *w;
{
/* It's not always possible to find the cursor, e.g, when a window
is full of overlay strings. Don't do anything in that case. */
if (w->cursor.vpos < 0)
- return;
+ return 1;
matrix = w->desired_matrix;
row = MATRIX_ROW (matrix, w->cursor.vpos);
/* If the cursor row is not partially visible, there's nothing
to do. */
if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
- return;
+ return 1;
/* If the row the cursor is in is taller than the window's height,
it's not clear what to do, so do nothing. */
window_height = window_box_height (w);
if (row->height >= window_height)
- return;
+ return 1;
if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
{
the correct y-position. */
if (w == XWINDOW (selected_window))
this_line_y = w->cursor.y;
+
+ /* If vscrolling requires a larger glyph matrix, arrange for a fresh
+ redisplay with larger matrices. */
+ if (matrix->nrows < required_matrix_height (w))
+ {
+ fonts_changed_p = 1;
+ return 0;
+ }
+
+ return 1;
}
-1 if new fonts have been loaded so that we must interrupt
redisplay, adjust glyph matrices, and try again. */
+enum
+{
+ SCROLLING_SUCCESS,
+ SCROLLING_FAILED,
+ SCROLLING_NEED_LARGER_MATRICES
+};
+
static int
try_scrolling (window, just_this_one_p, scroll_conservatively,
scroll_step, temp_scroll_step)
dy = 1 + it.current_y - y0;
if (dy > scroll_max)
- return 0;
+ return SCROLLING_FAILED;
/* Move the window start down. If scrolling conservatively,
move it just enough down to make point visible. If
}
if (amount_to_scroll <= 0)
- return 0;
+ return SCROLLING_FAILED;
move_it_vertically (&it, amount_to_scroll);
startp = it.current.pos;
MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
dy = it.current_y - y0;
if (dy > scroll_max)
- return 0;
+ return SCROLLING_FAILED;
/* Compute new window start. */
start_display (&it, w, startp);
}
if (amount_to_scroll <= 0)
- return 0;
+ return SCROLLING_FAILED;
move_it_vertically (&it, - amount_to_scroll);
startp = it.current.pos;
/* Display the window. Give up if new fonts are loaded, or if point
doesn't appear. */
if (!try_window (window, startp))
- rc = -1;
+ rc = SCROLLING_NEED_LARGER_MATRICES;
else if (w->cursor.vpos < 0)
{
clear_glyph_matrix (w->desired_matrix);
- rc = 0;
+ rc = SCROLLING_FAILED;
}
else
{
w->base_line_number = Qnil;
/* If cursor ends up on a partially visible line, shift display
- lines up or down. */
- make_cursor_line_fully_visible (w);
- rc = 1;
+ lines up or down. If that fails because we need larger
+ matrices, give up. */
+ if (!make_cursor_line_fully_visible (w))
+ rc = SCROLLING_NEED_LARGER_MATRICES;
+ else
+ rc = SCROLLING_SUCCESS;
}
return rc;
/* Try cursor movement in case text has not changes in window WINDOW,
with window start STARTP. Value is
- 1 if successful
+ CURSOR_MOVEMENT_SUCCESS if successful
- 0 if this method cannot be used
-
- -1 if we know we have to scroll the display. *SCROLL_STEP is
- set to 1, under certain circumstances, if we want to scroll as
- if scroll-step were set to 1. See the code. */
+ CURSOR_MOVEMENT_CANNOT_BE_USED if this method cannot be used
+
+ CURSOR_MOVEMENT_MUST_SCROLL if we know we have to scroll the
+ display. *SCROLL_STEP is set to 1, under certain circumstances, if
+ we want to scroll as if scroll-step were set to 1. See the code.
+
+ CURSOR_MOVEMENT_NEED_LARGER_MATRICES if we need larger matrices, in
+ which case we have to abort this redisplay, and adjust matrices
+ first. */
+
+enum
+{
+ CURSOR_MOVEMENT_SUCCESS,
+ CURSOR_MOVEMENT_CANNOT_BE_USED,
+ CURSOR_MOVEMENT_MUST_SCROLL,
+ CURSOR_MOVEMENT_NEED_LARGER_MATRICES
+};
static int
try_cursor_movement (window, startp, scroll_step)
{
struct window *w = XWINDOW (window);
struct frame *f = XFRAME (w->frame);
- int rc = 0;
+ int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
/* Handle case where text has not changed, only point, and it has
not moved off the frame. */
not paused redisplay. Give up if that row is not valid. */
if (w->last_cursor.vpos < 0
|| w->last_cursor.vpos >= w->current_matrix->nrows)
- rc = -1;
+ rc = CURSOR_MOVEMENT_MUST_SCROLL;
else
{
row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
if (row->mode_line_p)
++row;
if (!row->enabled_p)
- rc = -1;
+ rc = CURSOR_MOVEMENT_MUST_SCROLL;
}
- if (rc == 0)
+ if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
{
int scroll_p = 0;
int last_y = window_text_bottom_y (w) - this_scroll_margin;
|| PT > MATRIX_ROW_END_CHARPOS (row))
{
/* if PT is not in the glyph row, give up. */
- rc = -1;
+ rc = CURSOR_MOVEMENT_MUST_SCROLL;
}
else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
{
if (PT == MATRIX_ROW_END_CHARPOS (row)
&& !row->ends_at_zv_p
&& !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
- rc = -1;
+ rc = CURSOR_MOVEMENT_MUST_SCROLL;
else if (row->height > window_box_height (w))
{
/* If we end up in a partially visible line, let's
than the window, in which case we can't do much
about it. */
*scroll_step = 1;
- rc = -1;
+ rc = CURSOR_MOVEMENT_MUST_SCROLL;
}
else
{
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
try_window (window, startp);
- make_cursor_line_fully_visible (w);
- rc = 1;
+ if (!make_cursor_line_fully_visible (w))
+ rc = CURSOR_MOVEMENT_NEED_LARGER_MATRICES;
+ else
+ rc = CURSOR_MOVEMENT_SUCCESS;
}
}
else if (scroll_p)
- rc = -1;
+ rc = CURSOR_MOVEMENT_MUST_SCROLL;
else
{
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
- rc = 1;
+ rc = CURSOR_MOVEMENT_SUCCESS;
}
}
}
{
clear_glyph_matrix (w->desired_matrix);
if (!try_window (window, startp))
- goto finish_scroll_bars;
+ goto need_larger_matrices;
}
}
- make_cursor_line_fully_visible (w);
+ if (!make_cursor_line_fully_visible (w))
+ goto need_larger_matrices;
#if GLYPH_DEBUG
debug_method_add (w, "forced window start");
#endif
not moved off the frame. */
if (current_matrix_up_to_date_p
&& (rc = try_cursor_movement (window, startp, &temp_scroll_step),
- rc != 0))
+ rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
{
- if (rc == -1)
- goto try_to_scroll;
- else
- goto done;
+ switch (rc)
+ {
+ case CURSOR_MOVEMENT_SUCCESS:
+ goto done;
+
+ case CURSOR_MOVEMENT_NEED_LARGER_MATRICES:
+ goto need_larger_matrices;
+
+ case CURSOR_MOVEMENT_MUST_SCROLL:
+ goto try_to_scroll;
+
+ default:
+ abort ();
+ }
}
/* If current starting point was originally the beginning of a line
but no longer is, find a new starting point. */
#endif
if (fonts_changed_p)
- goto finish_scroll_bars;
+ goto need_larger_matrices;
if (tem > 0)
goto done;
}
if (fonts_changed_p)
- goto finish_scroll_bars;
+ goto need_larger_matrices;
if (w->cursor.vpos >= 0)
{
/* Forget any recorded base line for line number display. */
w->base_line_number = Qnil;
- make_cursor_line_fully_visible (w);
+ if (!make_cursor_line_fully_visible (w))
+ goto need_larger_matrices;
goto done;
}
else
scroll_conservatively,
scroll_step,
temp_scroll_step);
- if (rc > 0)
- goto done;
- else if (rc < 0)
- goto finish_scroll_bars;
+ switch (rc)
+ {
+ case SCROLLING_SUCCESS:
+ goto done;
+
+ case SCROLLING_NEED_LARGER_MATRICES:
+ goto need_larger_matrices;
+
+ case SCROLLING_FAILED:
+ break;
+
+ default:
+ abort ();
+ }
}
/* Finally, just choose place to start which centers point */
have to start a new redisplay since we need to re-adjust glyph
matrices. */
if (fonts_changed_p)
- goto finish_scroll_bars;
+ goto need_larger_matrices;
/* If cursor did not appear assume that the middle of the window is
in the first line of the window. Do it again with the next line.
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
}
- make_cursor_line_fully_visible (w);
+ if (!make_cursor_line_fully_visible (w))
+ goto need_larger_matrices;
done:
&& (WINDOW_WANTS_MODELINE_P (w)
|| WINDOW_WANTS_HEADER_LINE_P (w)))
{
- Lisp_Object old_selected_frame;
-
- old_selected_frame = selected_frame;
-
- XSETFRAME (selected_frame, f);
display_mode_lines (w);
- selected_frame = old_selected_frame;
/* If mode line height has changed, arrange for a thorough
immediate redisplay using the correct mode line height. */
}
if (fonts_changed_p)
- goto finish_scroll_bars;
+ goto need_larger_matrices;
}
if (!line_number_displayed
#endif
}
+ need_larger_matrices:
+ ;
finish_scroll_bars:
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
all rows to the end of the display area of W. Value is the row
containing CHARPOS or null. */
-static struct glyph_row *
+struct glyph_row *
row_containing_pos (w, charpos, start, end)
struct window *w;
int charpos;
for instance. This is easier than to set up the iterator
exactly, and it's not a frequent case, so the additional
effort wouldn't really pay off. */
- while (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
+ while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
+ || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
&& last_unchanged_at_beg_row > w->current_matrix->rows)
--last_unchanged_at_beg_row;
stop_pos = 0;
if (first_unchanged_at_end_row)
{
+#if GLYPH_DEBUG
xassert (last_unchanged_at_beg_row == NULL
|| first_unchanged_at_end_row >= last_unchanged_at_beg_row);
+#else
+ /* This is for the release of 21.1 only, and should be removed
+ after the release.
+
+ This case means that unchanged information is probably bogus,
+ which leads to being unable to compute a correct
+ first_unchanged_at_end_row. At least that was the case in
+ one debugging session. I've fixed a bug that can lead to
+ wrong unchanged info, but didn't find a way to reproduce this
+ case. 2001-09-18 gerd. */
+ if (last_unchanged_at_beg_row
+ && first_unchanged_at_end_row < last_unchanged_at_beg_row)
+ GIVE_UP (20);
+#endif
/* If this is a continuation line, move forward to the next one
that isn't. Changes in lines above affect this line.
DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
Sdump_glyph_matrix, 0, 1, "p",
- "Dump the current matrix of the selected window to stderr.\n\
-Shows contents of glyph row structures. With non-nil\n\
-parameter GLYPHS, dump glyphs as well. If GLYPHS is 1 show\n\
-glyphs in short form, otherwise show glyphs in long form.")
- (glyphs)
+ /* Dump the current matrix of the selected window to stderr.
+Shows contents of glyph row structures. With non-nil
+parameter GLYPHS, dump glyphs as well. If GLYPHS is 1 show
+glyphs in short form, otherwise show glyphs in long form. */
+ (glyphs))
Lisp_Object glyphs;
{
struct window *w = XWINDOW (selected_window);
DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "",
- "Dump glyph row ROW to stderr.\n\
-GLYPH 0 means don't dump glyphs.\n\
-GLYPH 1 means dump glyphs in short form.\n\
-GLYPH > 1 or omitted means dump glyphs in long form.")
- (row, glyphs)
+ /* Dump glyph row ROW to stderr.
+GLYPH 0 means don't dump glyphs.
+GLYPH 1 means dump glyphs in short form.
+GLYPH > 1 or omitted means dump glyphs in long form. */
+ (row, glyphs))
Lisp_Object row, glyphs;
{
struct glyph_matrix *matrix;
DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "",
- "Dump glyph row ROW of the tool-bar of the current frame to stderr.\n\
-GLYPH 0 means don't dump glyphs.\n\
-GLYPH 1 means dump glyphs in short form.\n\
-GLYPH > 1 or omitted means dump glyphs in long form.")
- (row, glyphs)
+ /* Dump glyph row ROW of the tool-bar of the current frame to stderr.
+GLYPH 0 means don't dump glyphs.
+GLYPH 1 means dump glyphs in short form.
+GLYPH > 1 or omitted means dump glyphs in long form. */
+ (row, glyphs))
Lisp_Object row, glyphs;
{
struct frame *sf = SELECTED_FRAME ();
DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
- "Toggle tracing of redisplay.\n\
-With ARG, turn tracing on if and only if ARG is positive.")
- (arg)
+ /* Toggle tracing of redisplay.
+With ARG, turn tracing on if and only if ARG is positive. */
+ (arg))
Lisp_Object arg;
{
if (NILP (arg))
DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
- "Like `format', but print result to stderr.")
- (nargs, args)
+ /* Like `format', but print result to stderr. */
+ (nargs, args))
int nargs;
Lisp_Object *args;
{
{
int used_before = row->used[TEXT_AREA];
+ row->ends_in_newline_from_string_p = STRINGP (it->object);
+
/* Add a space at the end of the line that is used to
display the cursor there. */
append_space (it, 0);
|| FRAME_GARBAGED_P (XFRAME (w->frame))
|| !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
{
- Lisp_Object old_selected_frame;
struct text_pos lpoint;
struct buffer *old = current_buffer;
TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
}
- /* Temporarily set up the selected frame. */
- old_selected_frame = selected_frame;
- selected_frame = w->frame;
-
/* Display mode lines. */
clear_glyph_matrix (w->desired_matrix);
if (display_mode_lines (w))
}
/* Restore old settings. */
- selected_frame = old_selected_frame;
set_buffer_internal_1 (old);
TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
}
display_mode_lines (w)
struct window *w;
{
+ Lisp_Object old_selected_window, old_selected_frame;
int n = 0;
+
+ old_selected_frame = selected_frame;
+ selected_frame = w->frame;
+ old_selected_window = selected_window;
+ XSETWINDOW (selected_window, w);
/* These will be set while the mode line specs are processed. */
line_number_displayed = 0;
++n;
}
+ selected_frame = old_selected_frame;
+ selected_window = old_selected_window;
return n;
}
int bytepos = last - lisp_string;
int charpos = string_byte_to_char (elt, bytepos);
n += display_string (NULL, elt, Qnil, 0, charpos,
- it, 0, prec, 0, -1);
+ it, 0, prec, 0,
+ STRING_MULTIBYTE (elt));
}
}
else /* c == '%' */
Vglobal_mode_string);
else if (c != 0)
{
+ int multibyte;
unsigned char *spec
- = decode_mode_spec (it->w, c, field, prec);
-
+ = decode_mode_spec (it->w, c, field, prec, &multibyte);
+
if (frame_title_ptr)
n += store_frame_title (spec, field, prec);
else
{
- int nglyphs_before
- = it->glyph_row->used[TEXT_AREA];
- int bytepos
- = percent_position - XSTRING (elt)->data;
- int charpos
- = string_byte_to_char (elt, bytepos);
- int nwritten
- = display_string (spec, Qnil, elt, charpos, 0, it,
- field, prec, 0, -1);
+ int nglyphs_before, bytepos, charpos, nwritten;
+
+ nglyphs_before = it->glyph_row->used[TEXT_AREA];
+ bytepos = percent_position - XSTRING (elt)->data;
+ charpos = (multibyte
+ ? string_byte_to_char (elt, bytepos)
+ : bytepos);
+ nwritten = display_string (spec, Qnil, elt,
+ charpos, 0, it,
+ field, prec, 0,
+ multibyte);
/* Assign to the glyphs written above the
string where the `%x' came from, position
n += store_frame_title (XSTRING (tem)->data, -1, prec);
else
n += display_string (NULL, tem, Qnil, 0, 0, it,
- 0, prec, 0, -1);
+ 0, prec, 0, STRING_MULTIBYTE (tem));
}
else if (!EQ (tem, elt))
{
/* Return a string for the output of a mode line %-spec for window W,
generated by character C. PRECISION >= 0 means don't return a
string longer than that value. FIELD_WIDTH > 0 means pad the
- string returned with spaces to that value. */
+ string returned with spaces to that value. Return 1 in *MULTIBYTE
+ if the result is multibyte text. */
static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
static char *
-decode_mode_spec (w, c, field_width, precision)
+decode_mode_spec (w, c, field_width, precision, multibyte)
struct window *w;
register int c;
int field_width, precision;
+ int *multibyte;
{
Lisp_Object obj;
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct buffer *b = XBUFFER (w->buffer);
obj = Qnil;
+ *multibyte = 0;
switch (c)
{
}
if (STRINGP (obj))
- return (char *) XSTRING (obj)->data;
+ {
+ *multibyte = STRING_MULTIBYTE (obj);
+ return (char *) XSTRING (obj)->data;
+ }
else
return "";
}
\f
-/* This is like a combination of memq and assq. Return 1 if PROPVAL
+/* This is like a combination of memq and assq. Return 1/2 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. */
+ way, and return 1/2 if any element of PROPVAL is found in LIST.
+ Otherwise return 0. This function cannot quit.
+ The return value is 2 if the text is invisible but with an ellipsis
+ and 1 if it's invisible and without an ellipsis. */
int
invisible_p (propval, list)
if (EQ (propval, tem))
return 1;
if (CONSP (tem) && EQ (propval, XCAR (tem)))
- return 1;
+ return NILP (XCDR (tem)) ? 1 : 2;
}
if (CONSP (propval))
if (EQ (propelt, tem))
return 1;
if (CONSP (tem) && EQ (propelt, XCAR (tem)))
- return 1;
+ return NILP (XCDR (tem)) ? 1 : 2;
}
}
}
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 = XCDR (tail))
- {
- register Lisp_Object tem;
- tem = XCAR (tail);
- if (CONSP (tem) && EQ (propval, XCAR (tem)))
- return ! NILP (XCDR (tem));
- }
-
- if (CONSP (propval))
- for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
- {
- Lisp_Object propelt;
- propelt = XCAR (proptail);
- for (tail = list; CONSP (tail); tail = XCDR (tail))
- {
- register Lisp_Object tem;
- tem = XCAR (tail);
- if (CONSP (tem) && EQ (propelt, XCAR (tem)))
- return ! NILP (XCDR (tem));
- }
- }
-
- return 0;
-}
-
-
\f
/***********************************************************************
Initialization
Vmessages_buffer_name = build_string ("*Messages*");
staticpro (&Vmessages_buffer_name);
- DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
- "Non-nil means highlight trailing whitespace.\n\
-The face used for trailing whitespace is `trailing-whitespace'.");
+ DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace
+ /* Non-nil means highlight trailing whitespace.
+The face used for trailing whitespace is `trailing-whitespace'. */);
Vshow_trailing_whitespace = Qnil;
- DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
- "Non-nil means don't actually do any redisplay.\n\
-This is used for internal purposes.");
+ DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay
+ /* Non-nil means don't actually do any redisplay.
+This is used for internal purposes. */);
Vinhibit_redisplay = Qnil;
- DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
- "String (or mode line construct) included (normally) in `mode-line-format'.");
+ DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string
+ /* String (or mode line construct) included (normally) in `mode-line-format'. */);
Vglobal_mode_string = Qnil;
- DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
- "Marker for where to display an arrow on top of the buffer text.\n\
-This must be the beginning of a line in order to work.\n\
-See also `overlay-arrow-string'.");
+ DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position
+ /* Marker for where to display an arrow on top of the buffer text.
+This must be the beginning of a line in order to work.
+See also `overlay-arrow-string'. */);
Voverlay_arrow_position = Qnil;
- DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
- "String to display as an arrow. See also `overlay-arrow-position'.");
+ DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string
+ /* String to display as an arrow. See also `overlay-arrow-position'. */);
Voverlay_arrow_string = Qnil;
- DEFVAR_INT ("scroll-step", &scroll_step,
- "*The number of lines to try scrolling a window by when point moves out.\n\
-If that fails to bring point back on frame, point is centered instead.\n\
-If this is zero, point is always centered after it moves off frame.\n\
-If you want scrolling to always be a line at a time, you should set\n\
- `scroll-conservatively' to a large value rather than set this to 1.");
-
- DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
- "*Scroll up to this many lines, to bring point back on screen.\n\
-A value of zero means to scroll the text to center point vertically\n\
-in the window.");
+ DEFVAR_INT ("scroll-step", &scroll_step
+ /* *The number of lines to try scrolling a window by when point moves out.
+If that fails to bring point back on frame, point is centered instead.
+If this is zero, point is always centered after it moves off frame.
+If you want scrolling to always be a line at a time, you should set
+`scroll-conservatively' to a large value rather than set this to 1. */);
+
+ DEFVAR_INT ("scroll-conservatively", &scroll_conservatively
+ /* *Scroll up to this many lines, to bring point back on screen.
+A value of zero means to scroll the text to center point vertically
+in the window. */);
scroll_conservatively = 0;
- DEFVAR_INT ("scroll-margin", &scroll_margin,
- "*Number of lines of margin at the top and bottom of a window.\n\
-Recenter the window whenever point gets within this many lines\n\
-of the top or bottom of the window.");
+ DEFVAR_INT ("scroll-margin", &scroll_margin
+ /* *Number of lines of margin at the top and bottom of a window.
+Recenter the window whenever point gets within this many lines
+of the top or bottom of the window. */);
scroll_margin = 0;
#if GLYPH_DEBUG
- DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
+ DEFVAR_INT ("debug-end-pos", &debug_end_pos /* Don't ask. */);
#endif
DEFVAR_BOOL ("truncate-partial-width-windows",
- &truncate_partial_width_windows,
- "*Non-nil means truncate lines in all windows less than full frame wide.");
+ &truncate_partial_width_windows
+ /* *Non-nil means truncate lines in all windows less than full frame wide. */);
truncate_partial_width_windows = 1;
- DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
- "nil means display the mode-line/header-line/menu-bar in the default face.\n\
-Any other value means to use the appropriate face, `mode-line',\n\
-`header-line', or `menu' respectively.\n\
-\n\
-This variable is deprecated; please change the above faces instead.");
+ DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video
+ /* nil means display the mode-line/header-line/menu-bar in the default face.
+Any other value means to use the appropriate face, `mode-line',
+`header-line', or `menu' respectively.
+
+This variable is deprecated; please change the above faces instead. */);
mode_line_inverse_video = 1;
- DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
- "*Maximum buffer size for which line number should be displayed.\n\
-If the buffer is bigger than this, the line number does not appear\n\
-in the mode line. A value of nil means no limit.");
+ DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit
+ /* *Maximum buffer size for which line number should be displayed.
+If the buffer is bigger than this, the line number does not appear
+in the mode line. A value of nil means no limit. */);
Vline_number_display_limit = Qnil;
DEFVAR_INT ("line-number-display-limit-width",
- &line_number_display_limit_width,
- "*Maximum line width (in characters) for line number display.\n\
-If the average length of the lines near point is bigger than this, then the\n\
-line number may be omitted from the mode line.");
+ &line_number_display_limit_width
+ /* *Maximum line width (in characters) for line number display.
+If the average length of the lines near point is bigger than this, then the
+line number may be omitted from the mode line. */);
line_number_display_limit_width = 200;
- DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
- "*Non-nil means highlight region even in nonselected windows.");
+ DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows
+ /* *Non-nil means highlight region even in nonselected windows. */);
highlight_nonselected_windows = 0;
- DEFVAR_BOOL ("multiple-frames", &multiple_frames,
- "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 processing\n\
-`frame-title-format' and `icon-title-format'.");
-
- DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
- "Template for displaying the title bar of visible frames.\n\
-\(Assuming the window manager supports this feature.)\n\
-This variable has the same structure as `mode-line-format' (which see),\n\
-and is used only on frames for which no explicit name has been set\n\
-\(see `modify-frame-parameters').");
- DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
- "Template for displaying the title bar of an iconified frame.\n\
-\(Assuming the window manager supports this feature.)\n\
-This variable has the same structure as `mode-line-format' (which see),\n\
-and is used only on frames for which no explicit name has been set\n\
-\(see `modify-frame-parameters').");
+ DEFVAR_BOOL ("multiple-frames", &multiple_frames
+ /* Non-nil if more than one frame is visible on this display.
+Minibuffer-only frames don't count, but iconified frames do.
+This variable is not guaranteed to be accurate except while processing
+`frame-title-format' and `icon-title-format'. */);
+
+ DEFVAR_LISP ("frame-title-format", &Vframe_title_format
+ /* Template for displaying the title bar of visible frames.
+\(Assuming the window manager supports this feature.)
+This variable has the same structure as `mode-line-format' (which see),
+and is used only on frames for which no explicit name has been set
+\(see `modify-frame-parameters'). */);
+ DEFVAR_LISP ("icon-title-format", &Vicon_title_format
+ /* Template for displaying the title bar of an iconified frame.
+\(Assuming the window manager supports this feature.)
+This variable has the same structure as `mode-line-format' (which see),
+and is used only on frames for which no explicit name has been set
+\(see `modify-frame-parameters'). */);
Vicon_title_format
= Vframe_title_format
= Fcons (intern ("multiple-frames"),
Fcons (build_string ("%b"),
- Fcons (Fcons (build_string (""),
+ Fcons (Fcons (empty_string,
Fcons (intern ("invocation-name"),
Fcons (build_string ("@"),
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.");
+ DEFVAR_LISP ("message-log-max", &Vmessage_log_max
+ /* Maximum number of lines to keep in the message log buffer.
+If nil, disable message logging. If t, log messages but don't truncate
+the buffer when it becomes large. */);
Vmessage_log_max = make_number (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.");
+ DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions
+ /* Functions called before redisplay, if window sizes have changed.
+The value should be a list of functions that take one argument.
+Just before redisplay, for each frame, if any of its windows have changed
+size since the last redisplay, or have been split or deleted,
+all the functions in the list are called, with the frame as argument. */);
Vwindow_size_change_functions = Qnil;
- DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
- "List of Functions to call before redisplaying a window with scrolling.\n\
-Each function is called with two arguments, the window\n\
-and its new display-start position. Note that the value of `window-end'\n\
-is not valid when these functions are called.");
+ DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions
+ /* List of Functions to call before redisplaying a window with scrolling.
+Each function is called with two arguments, the window
+and its new display-start position. Note that the value of `window-end'
+is not valid when these functions are called. */);
Vwindow_scroll_functions = Qnil;
- DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
- "*Non-nil means automatically resize tool-bars.\n\
-This increases a tool-bar's height if not all tool-bar items are visible.\n\
-It decreases a tool-bar's height when it would display blank lines\n\
-otherwise.");
+ DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p
+ /* *Non-nil means automatically resize tool-bars.
+This increases a tool-bar's height if not all tool-bar items are visible.
+It decreases a tool-bar's height when it would display blank lines
+otherwise. */);
auto_resize_tool_bars_p = 1;
- DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
- "*Non-nil means raise tool-bar buttons when the mouse moves over them.");
+ DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p
+ /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */);
auto_raise_tool_bar_buttons_p = 1;
- DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
- "*Margin around tool-bar buttons in pixels.\n\
-If an integer, use that for both horizontal and vertical margins.\n\
-Otherwise, value should be a pair of integers `(HORZ : VERT)' with\n\
-HORZ specifying the horizontal margin, and VERT specifying the\n\
-vertical margin.");
+ DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin
+ /* *Margin around tool-bar buttons in pixels.
+If an integer, use that for both horizontal and vertical margins.
+Otherwise, value should be a pair of integers `(HORZ : VERT)' with
+HORZ specifying the horizontal margin, and VERT specifying the
+vertical margin. */);
Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
- DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
- "Relief thickness of tool-bar buttons.");
+ DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief
+ /* Relief thickness of tool-bar buttons. */);
tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
- DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
- "List of functions to call to fontify regions of text.\n\
-Each function is called with one argument POS. Functions must\n\
-fontify a region starting at POS in the current buffer, and give\n\
-fontified regions the property `fontified'.\n\
-This variable automatically becomes buffer-local when set.");
+ DEFVAR_LISP ("fontification-functions", &Vfontification_functions
+ /* List of functions to call to fontify regions of text.
+Each function is called with one argument POS. Functions must
+fontify a region starting at POS in the current buffer, and give
+fontified regions the property `fontified'. */);
Vfontification_functions = Qnil;
Fmake_variable_buffer_local (Qfontification_functions);
DEFVAR_BOOL ("unibyte-display-via-language-environment",
- &unibyte_display_via_language_environment,
- "*Non-nil means display unibyte text according to language environment.\n\
-Specifically this means that unibyte non-ASCII characters\n\
-are displayed by converting them to the equivalent multibyte characters\n\
-according to the current language environment. As a result, they are\n\
-displayed according to the current fontset.");
+ &unibyte_display_via_language_environment
+ /* *Non-nil means display unibyte text according to language environment.
+Specifically this means that unibyte non-ASCII characters
+are displayed by converting them to the equivalent multibyte characters
+according to the current language environment. As a result, they are
+displayed according to the current fontset. */);
unibyte_display_via_language_environment = 0;
- DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
- "*Maximum height for resizing mini-windows.\n\
-If a float, it specifies a fraction of the mini-window frame's height.\n\
-If an integer, it specifies a number of lines.");
+ DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height
+ /* *Maximum height for resizing mini-windows.
+If a float, it specifies a fraction of the mini-window frame's height.
+If an integer, it specifies a number of lines. */);
Vmax_mini_window_height = make_float (0.25);
- DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows,
- "*How to resize mini-windows.\n\
-A value of nil means don't automatically resize mini-windows.\n\
-A value of t means resize them to fit the text displayed in them.\n\
-A value of `grow-only', the default, means let mini-windows grow\n\
-only, until their display becomes empty, at which point the windows\n\
-go back to their normal size.");
+ DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows
+ /* *How to resize mini-windows.
+A value of nil means don't automatically resize mini-windows.
+A value of t means resize them to fit the text displayed in them.
+A value of `grow-only', the default, means let mini-windows grow
+only, until their display becomes empty, at which point the windows
+go back to their normal size. */);
Vresize_mini_windows = Qgrow_only;
DEFVAR_BOOL ("cursor-in-non-selected-windows",
- &cursor_in_non_selected_windows,
- "*Non-nil means display a hollow cursor in non-selected windows.\n\
-Nil means don't display a cursor there.");
+ &cursor_in_non_selected_windows
+ /* *Non-nil means display a hollow cursor in non-selected windows.
+Nil means don't display a cursor there. */);
cursor_in_non_selected_windows = 1;
- DEFVAR_BOOL ("automatic-hscrolling", &automatic_hscrolling_p,
- "*Non-nil means scroll the display automatically to make point visible.");
+ DEFVAR_BOOL ("automatic-hscrolling", &automatic_hscrolling_p
+ /* *Non-nil means scroll the display automatically to make point visible. */);
automatic_hscrolling_p = 1;
- DEFVAR_LISP ("image-types", &Vimage_types,
- "List of supported image types.\n\
-Each element of the list is a symbol for a supported image type.");
+ DEFVAR_LISP ("image-types", &Vimage_types
+ /* List of supported image types.
+Each element of the list is a symbol for a supported image type. */);
Vimage_types = Qnil;
- DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
- "If non-nil, messages are truncated instead of resizing the echo area.\n\
-Bind this around calls to `message' to let it take effect.");
+ DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines
+ /* If non-nil, messages are truncated instead of resizing the echo area.
+Bind this around calls to `message' to let it take effect. */);
message_truncate_lines = 0;
- DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook,
- "Normal hook run for clicks on menu bar, before displaying a submenu.\n\
-Can be used to update submenus whose contents should vary.");
+ DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook
+ /* Normal hook run for clicks on menu bar, before displaying a submenu.
+Can be used to update submenus whose contents should vary. */);
Vmenu_bar_update_hook = Qnil;
- DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
- "Non-nil means don't update menu bars. Internal use only.");
+ DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update
+ /* Non-nil means don't update menu bars. Internal use only. */);
inhibit_menubar_update = 0;
- DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
- "Non-nil means don't eval Lisp during redisplay.");
+ DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay
+ /* Non-nil means don't eval Lisp during redisplay. */);
inhibit_eval_during_redisplay = 0;
}