/* Display generation from window structure and buffer text.
-Copyright (C) 1985-1988, 1993-1995, 1997-2012 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation,
+Inc.
This file is part of GNU Emacs.
static Lisp_Object Qmargin, Qpointer;
static Lisp_Object Qline_height;
-/* These setters are used only in this file, so they can be private. */
-static void
-wset_base_line_number (struct window *w, Lisp_Object val)
-{
- w->base_line_number = val;
-}
-static void
-wset_base_line_pos (struct window *w, Lisp_Object val)
-{
- w->base_line_pos = val;
-}
-static void
-wset_column_number_displayed (struct window *w, Lisp_Object val)
-{
- w->column_number_displayed = val;
-}
-static void
-wset_region_showing (struct window *w, Lisp_Object val)
-{
- w->region_showing = val;
-}
-
#ifdef HAVE_WINDOW_SYSTEM
/* Test if overflow newline into fringe. Called with iterator IT
static int overlay_arrow_seen;
-/* Number of windows showing the buffer of the selected
- window (or another buffer with the same base buffer). */
-
-int buffer_shared;
-
/* Vector containing glyphs for an ellipsis `...'. */
static Lisp_Object default_invis_vector[3];
static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object);
static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
static int with_echo_area_buffer (struct window *, int,
- int (*) (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t),
- ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t);
+ int (*) (ptrdiff_t, Lisp_Object),
+ ptrdiff_t, Lisp_Object);
static void clear_garbaged_frames (void);
-static int current_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t);
+static int current_message_1 (ptrdiff_t, Lisp_Object);
static void pop_message (void);
-static int truncate_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t);
-static void set_message (const char *, Lisp_Object, ptrdiff_t, int);
-static int set_message_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t);
+static int truncate_message_1 (ptrdiff_t, Lisp_Object);
+static void set_message (Lisp_Object);
+static int set_message_1 (ptrdiff_t, Lisp_Object);
static int display_echo_area (struct window *);
-static int display_echo_area_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t);
-static int resize_mini_window_1 (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t);
+static int display_echo_area_1 (ptrdiff_t, Lisp_Object);
+static int resize_mini_window_1 (ptrdiff_t, Lisp_Object);
static Lisp_Object unwind_redisplay (Lisp_Object);
static int string_char_and_length (const unsigned char *, int *);
static struct text_pos display_prop_end (struct it *, Lisp_Object,
static void iterate_out_of_display_property (struct it *);
static void pop_it (struct it *);
static void sync_frame_with_window_matrix_rows (struct window *);
-static void select_frame_for_redisplay (Lisp_Object);
static void redisplay_internal (void);
static int echo_area_display (int);
static void redisplay_windows (Lisp_Object);
static struct text_pos string_pos_nchars_ahead (struct text_pos,
Lisp_Object, ptrdiff_t);
static struct text_pos string_pos (ptrdiff_t, Lisp_Object);
-static struct text_pos c_string_pos (ptrdiff_t, const char *, int);
-static ptrdiff_t number_of_chars (const char *, int);
+static struct text_pos c_string_pos (ptrdiff_t, const char *, bool);
+static ptrdiff_t number_of_chars (const char *, bool);
static void compute_stop_pos (struct it *);
static void compute_string_pos (struct text_pos *, struct text_pos,
Lisp_Object);
BVAR (current_buffer, header_line_format));
start_display (&it, w, top);
- move_it_to (&it, charpos, -1, it.last_visible_y-1, -1,
+ move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
(charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
if (charpos >= 0
&& IT_CHARPOS (it) >= charpos)
/* When scanning backwards under bidi iteration, move_it_to
stops at or _before_ CHARPOS, because it stops at or to
- the _right_ of the character at CHARPOS. */
+ the _right_ of the character at CHARPOS. */
|| (it.bidi_p && it.bidi_it.scan_dir == -1
&& IT_CHARPOS (it) <= charpos)))
{
Lisp_Object cpos = make_number (charpos);
Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
Lisp_Object string = string_from_display_spec (spec);
- int newline_in_string = 0;
-
- if (STRINGP (string))
- {
- const char *s = SSDATA (string);
- const char *e = s + SBYTES (string);
- while (s < e)
- {
- if (*s++ == '\n')
- {
- newline_in_string = 1;
- break;
- }
- }
- }
+ bool newline_in_string
+ = (STRINGP (string)
+ && memchr (SDATA (string), '\n', SBYTES (string)));
/* The tricky code below is needed because there's a
discrepancy between move_it_to and how we set cursor
when the display line ends in a newline from a
means recognize multibyte characters. */
static struct text_pos
-c_string_pos (ptrdiff_t charpos, const char *s, int multibyte_p)
+c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
{
struct text_pos pos;
non-zero means recognize multibyte characters. */
static ptrdiff_t
-number_of_chars (const char *s, int multibyte_p)
+number_of_chars (const char *s, bool multibyte_p)
{
ptrdiff_t nchars;
static void
check_window_end (struct window *w)
{
- if (!MINI_WINDOW_P (w)
- && !NILP (w->window_end_valid))
+ if (!MINI_WINDOW_P (w) && w->window_end_valid)
{
struct glyph_row *row;
eassert ((row = MATRIX_ROW (w->current_matrix,
#endif /* GLYPH_DEBUG and ENABLE_CHECKING */
+/* Return mark position if current buffer has the region of non-zero length,
+ or -1 otherwise. */
+
+static ptrdiff_t
+markpos_of_region (void)
+{
+ if (!NILP (Vtransient_mark_mode)
+ && !NILP (BVAR (current_buffer, mark_active))
+ && XMARKER (BVAR (current_buffer, mark))->buffer != NULL)
+ {
+ ptrdiff_t markpos = XMARKER (BVAR (current_buffer, mark))->charpos;
+
+ if (markpos != PT)
+ return markpos;
+ }
+ return -1;
+}
-\f
/***********************************************************************
Iterator initialization
***********************************************************************/
ptrdiff_t charpos, ptrdiff_t bytepos,
struct glyph_row *row, enum face_id base_face_id)
{
- int highlight_region_p;
+ ptrdiff_t markpos;
enum face_id remapped_base_face_id = base_face_id;
/* Some precondition checks. */
/* Are multibyte characters enabled in current_buffer? */
it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
- /* Non-zero if we should highlight the region. */
- highlight_region_p
- = (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active))
- && XMARKER (BVAR (current_buffer, mark))->buffer != 0);
-
- /* Set IT->region_beg_charpos and IT->region_end_charpos to the
- start and end of a visible region in window IT->w. Set both to
- -1 to indicate no region. */
- if (highlight_region_p
+ /* If visible region is of non-zero length, set IT->region_beg_charpos
+ and IT->region_end_charpos to the start and end of a visible region
+ in window IT->w. Set both to -1 to indicate no region. */
+ markpos = markpos_of_region ();
+ if (0 <= markpos
/* Maybe highlight only in selected window. */
&& (/* Either show region everywhere. */
highlight_nonselected_windows
&& WINDOWP (minibuf_selected_window)
&& w == XWINDOW (minibuf_selected_window))))
{
- ptrdiff_t markpos = marker_position (BVAR (current_buffer, mark));
it->region_beg_charpos = min (PT, markpos);
it->region_end_charpos = max (PT, markpos);
}
if (new_face_id != it->face_id)
{
struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
+ /* If it->face_id is -1, old_face below will be NULL, see
+ the definition of FACE_FROM_ID. This will happen if this
+ is the initial call that gets the face. */
+ struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
- /* If new face has a box but old face has not, this is
- the start of a run of characters with box, i.e. it has
- a shadow on the left side. The value of face_id of the
- iterator will be -1 if this is the initial call that gets
- the face. In this case, we have to look in front of IT's
- position and see whether there is a face != new_face_id. */
- it->start_of_box_run_p
- = (new_face->box != FACE_NO_BOX
- && (it->face_id >= 0
- || IT_CHARPOS (*it) == BEG
- || new_face_id != face_before_it_pos (it)));
+ /* If the value of face_id of the iterator is -1, we have to
+ look in front of IT's position and see whether there is a
+ face there that's different from new_face_id. */
+ if (!old_face && IT_CHARPOS (*it) > BEG)
+ {
+ int prev_face_id = face_before_it_pos (it);
+
+ old_face = FACE_FROM_ID (it->f, prev_face_id);
+ }
+
+ /* If the new face has a box, but the old face does not,
+ this is the start of a run of characters with box face,
+ i.e. this character has a shadow on the left side. */
+ it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
+ && (old_face == NULL || !old_face->box));
it->face_box_p = new_face->box != FACE_NO_BOX;
}
}
static void
back_to_previous_line_start (struct it *it)
{
- IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
- IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
+ IT_CHARPOS (*it)
+ = find_next_newline_no_quit (IT_CHARPOS (*it) - 1,
+ -1, &IT_BYTEPOS (*it));
}
short-cut. */
if (!newline_found_p)
{
- ptrdiff_t start = IT_CHARPOS (*it);
- ptrdiff_t limit = find_next_newline_no_quit (start, 1);
+ ptrdiff_t bytepos, start = IT_CHARPOS (*it);
+ ptrdiff_t limit = find_next_newline_no_quit (start, 1, &bytepos);
Lisp_Object pos;
eassert (!STRINGP (it->string));
if (!it->bidi_p)
{
IT_CHARPOS (*it) = limit;
- IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit);
+ IT_BYTEPOS (*it) = bytepos;
}
else
{
if (string_p)
it->bidi_it.charpos = it->bidi_it.bytepos = 0;
else
- {
- it->bidi_it.charpos = find_next_newline_no_quit (IT_CHARPOS (*it),
- -1);
- it->bidi_it.bytepos = CHAR_TO_BYTE (it->bidi_it.charpos);
- }
+ it->bidi_it.charpos
+ = find_next_newline_no_quit (IT_CHARPOS (*it), -1,
+ &it->bidi_it.bytepos);
bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1);
do
{
struct it it2, it3;
void *it2data = NULL, *it3data = NULL;
ptrdiff_t start_pos;
+ int nchars_per_row
+ = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
+ ptrdiff_t pos_limit;
move_further_back:
eassert (dy >= 0);
/* Estimate how many newlines we must move back. */
nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
+ if (it->line_wrap == TRUNCATE)
+ pos_limit = BEGV;
+ else
+ pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
- /* Set the iterator's position that many lines back. */
- while (nlines-- && IT_CHARPOS (*it) > BEGV)
+ /* Set the iterator's position that many lines back. But don't go
+ back more than NLINES full screen lines -- this wins a day with
+ buffers which have very long lines. */
+ while (nlines-- && IT_CHARPOS (*it) > pos_limit)
back_to_previous_visible_line_start (it);
/* Reseat the iterator here. When moving backward, we don't want
&& FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
{
ptrdiff_t nl_pos =
- find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
+ find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1, NULL);
move_it_to (it, nl_pos, -1, -1, -1, MOVE_TO_POS);
}
struct it it2;
void *it2data = NULL;
ptrdiff_t start_charpos, i;
+ int nchars_per_row
+ = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
+ ptrdiff_t pos_limit;
/* Start at the beginning of the screen line containing IT's
position. This may actually move vertically backwards,
move_it_vertically_backward (it, 0);
dvpos -= it->vpos;
- /* Go back -DVPOS visible lines and reseat the iterator there. */
+ /* Go back -DVPOS buffer lines, but no farther than -DVPOS full
+ screen lines, and reseat the iterator there. */
start_charpos = IT_CHARPOS (*it);
- for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > BEGV; --i)
+ if (it->line_wrap == TRUNCATE)
+ pos_limit = BEGV;
+ else
+ pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
+ for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
back_to_previous_visible_line_start (it);
reseat (it, it->current.pos, 1);
/* Add a string M of length NBYTES to the message log, optionally
- terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if
- nonzero, means interpret the contents of M as multibyte. This
+ terminated with a newline when NLFLAG is true. MULTIBYTE, if
+ true, means interpret the contents of M as multibyte. This
function calls low-level routines in order to bypass text property
hooks, etc. which might not be safe to run.
so the buffer M must NOT point to a Lisp string. */
void
-message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
+message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
{
const unsigned char *msg = (const unsigned char *) m;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
ptrdiff_t point_at_end = 0;
ptrdiff_t zv_at_end = 0;
- Lisp_Object old_deactivate_mark, tem;
+ Lisp_Object old_deactivate_mark;
+ bool shown;
struct gcpro gcpro1;
old_deactivate_mark = Vdeactivate_mark;
bset_undo_list (current_buffer, Qt);
oldpoint = message_dolog_marker1;
- set_marker_restricted (oldpoint, make_number (PT), Qnil);
+ set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
oldbegv = message_dolog_marker2;
- set_marker_restricted (oldbegv, make_number (BEGV), Qnil);
+ set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
oldzv = message_dolog_marker3;
- set_marker_restricted (oldzv, make_number (ZV), Qnil);
+ set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
GCPRO1 (old_deactivate_mark);
if (PT == Z)
}
}
else if (nbytes)
- insert_1 (m, nbytes, 1, 0, 0);
+ insert_1_both (m, chars_in_text (msg, nbytes), nbytes, 1, 0, 0);
if (nlflag)
{
ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
printmax_t dups;
- insert_1 ("\n", 1, 1, 0, 0);
+
+ insert_1_both ("\n", 1, 1, 1, 0, 0);
scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
this_bol = PT;
change message_log_check_duplicate. */
int duplen = sprintf (dupstr, " [%"pMd" times]", dups);
TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
- insert_1 (dupstr, duplen, 1, 0, 1);
+ insert_1_both (dupstr, duplen, duplen, 1, 0, 1);
}
}
}
del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
}
}
- BEGV = XMARKER (oldbegv)->charpos;
+ BEGV = marker_position (oldbegv);
BEGV_BYTE = marker_byte_position (oldbegv);
if (zv_at_end)
}
else
{
- ZV = XMARKER (oldzv)->charpos;
+ ZV = marker_position (oldzv);
ZV_BYTE = marker_byte_position (oldzv);
}
else
/* We can't do Fgoto_char (oldpoint) because it will run some
Lisp code. */
- TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
- XMARKER (oldpoint)->bytepos);
+ TEMP_SET_PT_BOTH (marker_position (oldpoint),
+ marker_byte_position (oldpoint));
UNGCPRO;
unchain_marker (XMARKER (oldpoint));
unchain_marker (XMARKER (oldbegv));
unchain_marker (XMARKER (oldzv));
- tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
+ shown = buffer_window_count (current_buffer) > 0;
set_buffer_internal (oldbuf);
- if (NILP (tem))
+ if (!shown)
windows_or_buffers_changed = old_windows_or_buffers_changed;
message_log_need_newline = !nlflag;
Vdeactivate_mark = old_deactivate_mark;
for (i = 0; i < len; i++)
{
- if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.')
+ if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
seen_dots = 1;
if (p1[i] != p2[i])
return seen_dots;
char *pend;
intmax_t n = strtoimax ((char *) p1, &pend, 10);
if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
- return n+1;
+ return n + 1;
}
return 0;
}
\f
-/* Display an echo area message M with a specified length of NBYTES
- bytes. The string may include null characters. If M is 0, clear
- out any existing message, and let the mini-buffer text show
- through.
-
- This may GC, so the buffer M must NOT point to a Lisp string. */
-
-void
-message2 (const char *m, ptrdiff_t nbytes, int multibyte)
-{
- /* First flush out any partial line written with print. */
- message_log_maybe_newline ();
- if (m)
- message_dolog (m, nbytes, 1, multibyte);
- message2_nolog (m, nbytes, multibyte);
-}
-
-
-/* The non-logging counterpart of message2. */
-
-void
-message2_nolog (const char *m, ptrdiff_t nbytes, int multibyte)
-{
- struct frame *sf = SELECTED_FRAME ();
- message_enable_multibyte = multibyte;
-
- if (FRAME_INITIAL_P (sf))
- {
- if (noninteractive_need_newline)
- putc ('\n', stderr);
- noninteractive_need_newline = 0;
- if (m)
- fwrite (m, nbytes, 1, stderr);
- if (cursor_in_echo_area == 0)
- fprintf (stderr, "\n");
- fflush (stderr);
- }
- /* A null message buffer means that the frame hasn't really been
- initialized yet. Error messages get reported properly by
- cmd_error, so this must be just an informative message; toss it. */
- else if (INTERACTIVE
- && sf->glyphs_initialized_p
- && FRAME_MESSAGE_BUF (sf))
- {
- Lisp_Object mini_window;
- struct frame *f;
-
- /* Get the frame containing the mini-buffer
- that the selected frame is using. */
- mini_window = FRAME_MINIBUF_WINDOW (sf);
- f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
-
- FRAME_SAMPLE_VISIBILITY (f);
- if (FRAME_VISIBLE_P (sf)
- && ! FRAME_VISIBLE_P (f))
- Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
-
- if (m)
- {
- set_message (m, Qnil, nbytes, multibyte);
- if (minibuffer_auto_raise)
- Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
- }
- else
- clear_message (1, 1);
-
- do_pending_window_change (0);
- echo_area_display (1);
- do_pending_window_change (0);
- if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
- (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
- }
-}
-
-
/* Display an echo area message M with a specified length of NBYTES
bytes. The string may include null characters. If M is not a
string, clear out any existing message, and let the mini-buffer
This function cancels echoing. */
void
-message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
+message3 (Lisp_Object m)
{
struct gcpro gcpro1;
message_log_maybe_newline ();
if (STRINGP (m))
{
+ ptrdiff_t nbytes = SBYTES (m);
+ bool multibyte = STRING_MULTIBYTE (m);
USE_SAFE_ALLOCA;
char *buffer = SAFE_ALLOCA (nbytes);
memcpy (buffer, SDATA (m), nbytes);
message_dolog (buffer, nbytes, 1, multibyte);
SAFE_FREE ();
}
- message3_nolog (m, nbytes, multibyte);
+ message3_nolog (m);
UNGCPRO;
}
and make this cancel echoing. */
void
-message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
+message3_nolog (Lisp_Object m)
{
struct frame *sf = SELECTED_FRAME ();
- message_enable_multibyte = multibyte;
if (FRAME_INITIAL_P (sf))
{
putc ('\n', stderr);
noninteractive_need_newline = 0;
if (STRINGP (m))
- fwrite (SDATA (m), nbytes, 1, stderr);
+ fwrite (SDATA (m), SBYTES (m), 1, stderr);
if (cursor_in_echo_area == 0)
fprintf (stderr, "\n");
fflush (stderr);
}
- /* A null message buffer means that the frame hasn't really been
- initialized yet. Error messages get reported properly by
- cmd_error, so this must be just an informative message; toss it. */
- else if (INTERACTIVE
- && sf->glyphs_initialized_p
- && FRAME_MESSAGE_BUF (sf))
+ /* Error messages get reported properly by cmd_error, so this must be just an
+ informative message; if the frame hasn't really been initialized yet, just
+ toss it. */
+ else if (INTERACTIVE && sf->glyphs_initialized_p)
{
- Lisp_Object mini_window;
- Lisp_Object frame;
- struct frame *f;
-
/* Get the frame containing the mini-buffer
that the selected frame is using. */
- mini_window = FRAME_MINIBUF_WINDOW (sf);
- frame = XWINDOW (mini_window)->frame;
- f = XFRAME (frame);
+ Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
+ Lisp_Object frame = XWINDOW (mini_window)->frame;
+ struct frame *f = XFRAME (frame);
- FRAME_SAMPLE_VISIBILITY (f);
- if (FRAME_VISIBLE_P (sf)
- && !FRAME_VISIBLE_P (f))
+ if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
Fmake_frame_visible (frame);
if (STRINGP (m) && SCHARS (m) > 0)
{
- set_message (NULL, m, nbytes, multibyte);
+ set_message (m);
if (minibuffer_auto_raise)
Fraise_frame (frame);
/* Assume we are not echoing.
void
message1 (const char *m)
{
- message2 (m, (m ? strlen (m) : 0), 0);
+ message3 (m ? make_unibyte_string (m, strlen (m)) : Qnil);
}
void
message1_nolog (const char *m)
{
- message2_nolog (m, (m ? strlen (m) : 0), 0);
+ message3_nolog (m ? make_unibyte_string (m, strlen (m)) : Qnil);
}
/* Display a message M which contains a single %s
mini_window = FRAME_MINIBUF_WINDOW (sf);
f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
- /* A null message buffer means that the frame hasn't really been
- initialized yet. Error messages get reported properly by
- cmd_error, so this must be just an informative message; toss it. */
- if (FRAME_MESSAGE_BUF (f))
+ /* Error messages get reported properly by cmd_error, so this must be
+ just an informative message; if the frame hasn't really been
+ initialized yet, just toss it. */
+ if (f->glyphs_initialized_p)
{
Lisp_Object args[2], msg;
struct gcpro gcpro1, gcpro2;
msg = Fformat (2, args);
if (log)
- message3 (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
+ message3 (msg);
else
- message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
+ message3_nolog (msg);
UNGCPRO;
mini_window = FRAME_MINIBUF_WINDOW (sf);
f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
- /* A null message buffer means that the frame hasn't really been
- initialized yet. Error messages get reported properly by
- cmd_error, so this must be just an informative message; toss
- it. */
- if (FRAME_MESSAGE_BUF (f))
+ /* Error messages get reported properly by cmd_error, so this must be
+ just an informative message; if the frame hasn't really been
+ initialized yet, just toss it. */
+ if (f->glyphs_initialized_p)
{
if (m)
{
ptrdiff_t len;
+ ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
+ char *message_buf = alloca (maxsize + 1);
- len = doprnt (FRAME_MESSAGE_BUF (f),
- FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap);
+ len = doprnt (message_buf, maxsize, m, (char *)0, ap);
- message2 (FRAME_MESSAGE_BUF (f), len, 1);
+ message3 (make_string (message_buf, len));
}
else
message1 (0);
{
Lisp_Object string;
string = Fcurrent_message ();
- message3 (string, SBYTES (string),
- !NILP (BVAR (current_buffer, enable_multibyte_characters)));
+ message3 (string);
}
}
}
-/* Call FN with args A1..A4 with either the current or last displayed
+/* Call FN with args A1..A2 with either the current or last displayed
echo_area_buffer as current buffer.
WHICH zero means use the current message buffer
static int
with_echo_area_buffer (struct window *w, int which,
- int (*fn) (ptrdiff_t, Lisp_Object, ptrdiff_t, ptrdiff_t),
- ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4)
+ int (*fn) (ptrdiff_t, Lisp_Object),
+ ptrdiff_t a1, Lisp_Object a2)
{
Lisp_Object buffer;
int this_one, the_other, clear_buffer_p, rc;
eassert (BEGV >= BEG);
eassert (ZV <= Z && ZV >= BEGV);
- rc = fn (a1, a2, a3, a4);
+ rc = fn (a1, a2);
eassert (BEGV >= BEG);
eassert (ZV <= Z && ZV >= BEGV);
{
XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
ASET (vector, i, w->buffer); ++i;
- ASET (vector, i, make_number (XMARKER (w->pointm)->charpos)); ++i;
- ASET (vector, i, make_number (XMARKER (w->pointm)->bytepos)); ++i;
+ ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
+ ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
}
else
{
window_height_changed_p
= with_echo_area_buffer (w, display_last_displayed_message_p,
display_echo_area_1,
- (intptr_t) w, Qnil, 0, 0);
+ (intptr_t) w, Qnil);
if (no_message_p)
echo_area_buffer[i] = Qnil;
Value is non-zero if height of W was changed. */
static int
-display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4)
+display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2)
{
intptr_t i1 = a1;
struct window *w = (struct window *) i1;
resize_exactly = Qnil;
resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
- (intptr_t) w, resize_exactly,
- 0, 0);
+ (intptr_t) w, resize_exactly);
if (resized_p)
{
++windows_or_buffers_changed;
resize_mini_window returns. */
static int
-resize_mini_window_1 (ptrdiff_t a1, Lisp_Object exactly, ptrdiff_t a3, ptrdiff_t a4)
+resize_mini_window_1 (ptrdiff_t a1, Lisp_Object exactly)
{
intptr_t i1 = a1;
return resize_mini_window ((struct window *) i1, !NILP (exactly));
max_height = total_height / 4;
/* Correct that max. height if it's bogus. */
- max_height = max (1, max_height);
- max_height = min (total_height, max_height);
+ max_height = clip_to_bounds (1, max_height, total_height);
/* Find out the height of the text in the window. */
if (it.line_wrap == TRUNCATE)
else
{
with_echo_area_buffer (0, 0, current_message_1,
- (intptr_t) &msg, Qnil, 0, 0);
+ (intptr_t) &msg, Qnil);
if (NILP (msg))
echo_area_buffer[0] = Qnil;
}
static int
-current_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4)
+current_message_1 (ptrdiff_t a1, Lisp_Object a2)
{
intptr_t i1 = a1;
Lisp_Object *msg = (Lisp_Object *) i1;
void
restore_message (void)
{
- Lisp_Object msg;
-
eassert (CONSP (Vmessage_stack));
- msg = XCAR (Vmessage_stack);
- if (STRINGP (msg))
- message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
- else
- message3_nolog (msg, 0, 0);
+ message3_nolog (XCAR (Vmessage_stack));
}
{
if (nchars == 0)
echo_area_buffer[0] = Qnil;
- /* A null message buffer means that the frame hasn't really been
- initialized yet. Error messages get reported properly by
- cmd_error, so this must be just an informative message; toss it. */
else if (!noninteractive
&& INTERACTIVE
&& !NILP (echo_area_buffer[0]))
{
struct frame *sf = SELECTED_FRAME ();
- if (FRAME_MESSAGE_BUF (sf))
- with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil, 0, 0);
+ /* Error messages get reported properly by cmd_error, so this must be
+ just an informative message; if the frame hasn't really been
+ initialized yet, just toss it. */
+ if (sf->glyphs_initialized_p)
+ with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil);
}
}
message to at most NCHARS characters. */
static int
-truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4)
+truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2)
{
if (BEG + nchars < Z)
del_range (BEG + nchars, Z);
return 0;
}
-/* Set the current message to a substring of S or STRING.
-
- If STRING is a Lisp string, set the message to the first NBYTES
- bytes from STRING. NBYTES zero means use the whole string. If
- STRING is multibyte, the message will be displayed multibyte.
-
- If S is not null, set the message to the first LEN bytes of S. LEN
- zero means use the whole string. MULTIBYTE_P non-zero means S is
- multibyte. Display the message multibyte in that case.
-
- Doesn't GC, as with_echo_area_buffer binds Qinhibit_modification_hooks
- to t before calling set_message_1 (which calls insert).
- */
+/* Set the current message to STRING. */
static void
-set_message (const char *s, Lisp_Object string,
- ptrdiff_t nbytes, int multibyte_p)
+set_message (Lisp_Object string)
{
- message_enable_multibyte
- = ((s && multibyte_p)
- || (STRINGP (string) && STRING_MULTIBYTE (string)));
+ eassert (STRINGP (string));
- with_echo_area_buffer (0, -1, set_message_1,
- (intptr_t) s, string, nbytes, multibyte_p);
+ message_enable_multibyte = STRING_MULTIBYTE (string);
+
+ with_echo_area_buffer (0, -1, set_message_1, 0, string);
message_buf_print = 0;
help_echo_showing_p = 0;
if (STRINGP (Vdebug_on_message)
+ && STRINGP (string)
&& fast_string_match (Vdebug_on_message, string) >= 0)
call_debugger (list2 (Qerror, string));
}
-/* Helper function for set_message. Arguments have the same meaning
- as there, with A1 corresponding to S and A2 corresponding to STRING
- This function is called with the echo area buffer being
- current. */
+/* Helper function for set_message. First argument is ignored and second
+ argument has the same meaning as for set_message.
+ This function is called with the echo area buffer being current. */
static int
-set_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t nbytes, ptrdiff_t multibyte_p)
+set_message_1 (ptrdiff_t a1, Lisp_Object string)
{
- intptr_t i1 = a1;
- const char *s = (const char *) i1;
- const unsigned char *msg = (const unsigned char *) s;
- Lisp_Object string = a2;
+ eassert (STRINGP (string));
/* Change multibyteness of the echo buffer appropriately. */
if (message_enable_multibyte
/* Insert new message at BEG. */
TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
- if (STRINGP (string))
- {
- ptrdiff_t nchars;
-
- if (nbytes == 0)
- nbytes = SBYTES (string);
- nchars = string_byte_to_char (string, nbytes);
-
- /* This function takes care of single/multibyte conversion. We
- just have to ensure that the echo area buffer has the right
- setting of enable_multibyte_characters. */
- insert_from_string (string, 0, 0, nchars, nbytes, 1);
- }
- else if (s)
- {
- if (nbytes == 0)
- nbytes = strlen (s);
-
- if (multibyte_p && NILP (BVAR (current_buffer, enable_multibyte_characters)))
- {
- /* Convert from multi-byte to single-byte. */
- ptrdiff_t i;
- int c, n;
- char work[1];
-
- /* Convert a multibyte string to single-byte. */
- for (i = 0; i < nbytes; i += n)
- {
- c = string_char_and_length (msg + i, &n);
- work[0] = (ASCII_CHAR_P (c)
- ? c
- : multibyte_char_to_unibyte (c));
- insert_1_both (work, 1, 1, 1, 0, 0);
- }
- }
- else if (!multibyte_p
- && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
- {
- /* Convert from single-byte to multi-byte. */
- ptrdiff_t i;
- int c, n;
- unsigned char str[MAX_MULTIBYTE_LENGTH];
-
- /* Convert a single-byte string to multibyte. */
- for (i = 0; i < nbytes; i++)
- {
- c = msg[i];
- MAKE_CHAR_MULTIBYTE (c);
- n = CHAR_STRING (c, str);
- insert_1_both ((char *) str, 1, n, 1, 0, 0);
- }
- }
- else
- insert_1 (s, nbytes, 1, 0, 0);
- }
+ /* This function takes care of single/multibyte conversion.
+ We just have to ensure that the echo area buffer has the right
+ setting of enable_multibyte_characters. */
+ insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), 1);
return 0;
}
static int
buffer_shared_and_changed (void)
{
- /* The variable buffer_shared is set in redisplay_window and
- indicates that we redisplay a buffer in different windows. */
- return (buffer_shared > 1 && UNCHANGED_MODIFIED < MODIFF);
+ return (buffer_window_count (current_buffer) > 1
+ && UNCHANGED_MODIFIED < MODIFF);
}
/* Nonzero if W doesn't reflect the actual state of current buffer due
static int
window_outdated (struct window *w)
{
- return (w->last_modified < MODIFF
+ return (w->last_modified < MODIFF
|| w->last_overlay_modified < OVERLAY_MODIFF);
}
return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star)
|| ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active)))
- != !NILP (w->region_showing)));
+ != (w->region_showing != 0)));
}
/* Nonzero if W has %c in its mode line and mode line should be updated. */
static int
mode_line_update_needed (struct window *w)
{
- return (!NILP (w->column_number_displayed)
+ return (w->column_number_displayed != -1
&& !(PT == w->last_point && !window_outdated (w))
- && (XFASTINT (w->column_number_displayed) != current_column ()));
+ && (w->column_number_displayed != current_column ()));
}
/***********************************************************************
{
/* Show item in pressed state. */
show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
- hlinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
last_tool_bar_item = prop_idx;
}
else
/* Show item in released state. */
show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
- hlinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
&& last_tool_bar_item != prop_idx)
return;
- hlinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
/* If tool-bar item is not enabled, don't highlight it. */
/* Display it as active. */
show_mouse_face (hlinfo, draw);
- hlinfo->mouse_face_image_state = draw;
}
set_help_echo:
if (w == XWINDOW (selected_window))
pt = PT;
else
- {
- pt = marker_position (w->pointm);
- pt = max (BEGV, pt);
- pt = min (ZV, pt);
- }
+ pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
/* Move iterator to pt starting at cursor_row->start in
a line with infinite width. */
reconsider_clip_changes (struct window *w, struct buffer *b)
{
if (b->clip_changed
- && !NILP (w->window_end_valid)
- && w->current_matrix->buffer == b
- && w->current_matrix->zv == BUF_ZV (b)
- && w->current_matrix->begv == BUF_BEGV (b))
+ && w->window_end_valid
+ && w->current_matrix->buffer == b
+ && w->current_matrix->zv == BUF_ZV (b)
+ && w->current_matrix->begv == BUF_BEGV (b))
b->clip_changed = 0;
/* If display wasn't paused, and W is not a tool bar window, see if
we set b->clip_changed to 1 to force updating the screen. If
b->clip_changed has already been set to 1, we can skip this
check. */
- if (!b->clip_changed
- && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
+ if (!b->clip_changed && BUFFERP (w->buffer) && w->window_end_valid)
{
ptrdiff_t pt;
}
\f
-/* Select FRAME to forward the values of frame-local variables into C
- variables so that the redisplay routines can access those values
- directly. */
-
-static void
-select_frame_for_redisplay (Lisp_Object frame)
-{
- Lisp_Object tail, tem;
- Lisp_Object old = selected_frame;
- struct Lisp_Symbol *sym;
-
- eassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame)));
-
- selected_frame = frame;
-
- do {
- for (tail = XFRAME (frame)->param_alist;
- CONSP (tail); tail = XCDR (tail))
- if (CONSP (XCAR (tail))
- && (tem = XCAR (XCAR (tail)),
- SYMBOLP (tem))
- && (sym = indirect_variable (XSYMBOL (tem)),
- sym->redirect == SYMBOL_LOCALIZED)
- && sym->val.blv->frame_local)
- /* Use find_symbol_value rather than Fsymbol_value
- to avoid an error if it is void. */
- find_symbol_value (tem);
- } while (!EQ (frame, old) && (frame = old, 1));
-}
-
-/* Make sure that previously selected OLD_FRAME is selected unless it has been
- deleted (by an X connection failure during redisplay, for example). */
-
-static void
-ensure_selected_frame (Lisp_Object old_frame)
-{
- if (!EQ (old_frame, selected_frame) && FRAME_LIVE_P (XFRAME (old_frame)))
- select_frame_for_redisplay (old_frame);
-}
-
#define STOP_POLLING \
do { if (! polling_stopped_here) stop_polling (); \
polling_stopped_here = 1; } while (0)
ptrdiff_t count, count1;
struct frame *sf;
int polling_stopped_here = 0;
- Lisp_Object tail, frame, old_frame = selected_frame;
+ Lisp_Object tail, frame;
struct backtrace backtrace;
/* Non-zero means redisplay has to consider all windows on all
/* Remember the currently selected window. */
sw = w;
- /* When running redisplay, we play a bit fast-and-loose and allow e.g.
- selected_frame and selected_window to be temporarily out-of-sync so
- when we come back here via `goto retry', we need to resync because we
- may need to run Elisp code (via prepare_menu_bars). */
- ensure_selected_frame (old_frame);
-
pending = 0;
reconsider_clip_changes (w, current_buffer);
last_escape_glyph_frame = NULL;
{
struct frame *f = XFRAME (frame);
- FRAME_SAMPLE_VISIBILITY (f);
if (FRAME_VISIBLE_P (f))
++number_of_visible_frames;
clear_desired_matrices (f);
clear_garbaged_frames ();
}
-
/* If showing the region, and mark has changed, we must redisplay
the whole window. The assignment to this_line_start_pos prevents
the optimization directly below this if-statement. */
if (((!NILP (Vtransient_mark_mode)
&& !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
- != !NILP (w->region_showing))
- || (!NILP (w->region_showing)
- && !EQ (w->region_showing,
- Fmarker_position (BVAR (XBUFFER (w->buffer), mark)))))
+ != (w->region_showing > 0))
+ || (w->region_showing
+ && w->region_showing
+ != XINT (Fmarker_position (BVAR (XBUFFER (w->buffer), mark)))))
CHARPOS (this_line_start_pos) = 0;
/* Optimize the case that only the line containing the cursor in the
else if (XFASTINT (w->window_end_vpos) == this_line_vpos
&& this_line_vpos > 0)
wset_window_end_vpos (w, make_number (this_line_vpos - 1));
- wset_window_end_valid (w, Qnil);
+ w->window_end_valid = 0;
/* Update hint: No need to try to scroll in update_window. */
w->desired_matrix->no_scrolling_p = 1;
&& (EQ (selected_window,
BVAR (current_buffer, last_selected_window))
|| highlight_nonselected_windows)
- && NILP (w->region_showing)
+ && !w->region_showing
&& NILP (Vshow_trailing_whitespace)
&& !cursor_in_echo_area)
{
FOR_EACH_FRAME (tail, frame)
XFRAME (frame)->updated_p = 0;
- /* Recompute # windows showing selected buffer. This will be
- incremented each time such a window is displayed. */
- buffer_shared = 0;
-
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
- if (! EQ (frame, selected_frame))
- /* Select the frame, for the sake of frame-local
- variables. */
- select_frame_for_redisplay (frame);
-
/* Mark all the scroll bars to be removed; we'll redeem
the ones we want when we redisplay their windows. */
if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
}
}
- /* We played a bit fast-and-loose above and allowed selected_frame
- and selected_window to be temporarily out-of-sync but let's make
- sure this stays contained. */
- ensure_selected_frame (old_frame);
eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
if (!pending)
{
int this_is_visible = 0;
- if (XFRAME (frame)->visible)
- this_is_visible = 1;
- FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
if (XFRAME (frame)->visible)
this_is_visible = 1;
unwind_redisplay (Lisp_Object old_frame)
{
redisplaying_p = 0;
- ensure_selected_frame (old_frame);
return Qnil;
}
-/* Mark the display of window W as accurate or inaccurate. If
- ACCURATE_P is non-zero mark display of W as accurate. If
- ACCURATE_P is zero, arrange for W to be redisplayed the next time
- redisplay_internal is called. */
+/* Mark the display of leaf window W as accurate or inaccurate.
+ If ACCURATE_P is non-zero mark display of W as accurate. If
+ ACCURATE_P is zero, arrange for W to be redisplayed the next
+ time redisplay_internal is called. */
static void
mark_window_display_accurate_1 (struct window *w, int accurate_p)
{
- if (BUFFERP (w->buffer))
- {
- struct buffer *b = XBUFFER (w->buffer);
+ struct buffer *b = XBUFFER (w->buffer);
- w->last_modified = accurate_p ? BUF_MODIFF(b) : 0;
- w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF(b) : 0;
- w->last_had_star
- = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
+ w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
+ w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
+ w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
- if (accurate_p)
- {
- b->clip_changed = 0;
- b->prevent_redisplay_optimizations_p = 0;
+ if (accurate_p)
+ {
+ b->clip_changed = 0;
+ b->prevent_redisplay_optimizations_p = 0;
- BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
- BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
- BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
- BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
+ BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
+ BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
+ BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
+ BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
- w->current_matrix->buffer = b;
- w->current_matrix->begv = BUF_BEGV (b);
- w->current_matrix->zv = BUF_ZV (b);
+ w->current_matrix->buffer = b;
+ w->current_matrix->begv = BUF_BEGV (b);
+ w->current_matrix->zv = BUF_ZV (b);
- w->last_cursor = w->cursor;
- w->last_cursor_off_p = w->cursor_off_p;
+ w->last_cursor = w->cursor;
+ w->last_cursor_off_p = w->cursor_off_p;
- if (w == XWINDOW (selected_window))
- w->last_point = BUF_PT (b);
- else
- w->last_point = XMARKER (w->pointm)->charpos;
- }
- }
+ if (w == XWINDOW (selected_window))
+ w->last_point = BUF_PT (b);
+ else
+ w->last_point = marker_position (w->pointm);
- if (accurate_p)
- {
- wset_window_end_valid (w, w->buffer);
+ w->window_end_valid = 1;
w->update_mode_line = 0;
}
}
for (; !NILP (window); window = w->next)
{
w = XWINDOW (window);
- mark_window_display_accurate_1 (w, accurate_p);
-
if (!NILP (w->vchild))
mark_window_display_accurate (w->vchild, accurate_p);
- if (!NILP (w->hchild))
+ else if (!NILP (w->hchild))
mark_window_display_accurate (w->hchild, accurate_p);
+ else if (BUFFERP (w->buffer))
+ mark_window_display_accurate_1 (w, accurate_p);
}
if (accurate_p)
- {
- update_overlay_arrows (1);
- }
+ update_overlay_arrows (1);
else
- {
- /* Force a thorough redisplay the next time by setting
- last_arrow_position and last_arrow_string to t, which is
- unequal to any useful value of Voverlay_arrow_... */
- update_overlay_arrows (-1);
- }
+ /* Force a thorough redisplay the next time by setting
+ last_arrow_position and last_arrow_string to t, which is
+ unequal to any useful value of Voverlay_arrow_... */
+ update_overlay_arrows (-1);
}
CHARPOS is zero or negative. */
int empty_line_p =
(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
- && INTEGERP (glyph->object) && glyph->charpos > 0;
+ && INTEGERP (glyph->object) && glyph->charpos > 0
+ /* On a TTY, continued and truncated rows also have a glyph at
+ their end whose OBJECT is zero and whose CHARPOS is
+ positive (the continuation and truncation glyphs), but such
+ rows are obviously not "empty". */
+ && !(row->continued_p || row->truncated_on_right_p);
if (row->ends_in_ellipsis_p && pos_after == last_pos)
{
else
{
struct text_pos scroll_margin_pos = startp;
+ int y_offset = 0;
/* See if point is inside the scroll margin at the top of the
window. */
if (this_scroll_margin)
{
+ int y_start;
+
start_display (&it, w, startp);
+ y_start = it.current_y;
move_it_vertically (&it, this_scroll_margin);
scroll_margin_pos = it.current.pos;
+ /* If we didn't move enough before hitting ZV, request
+ additional amount of scroll, to move point out of the
+ scroll margin. */
+ if (IT_CHARPOS (it) == ZV
+ && it.current_y - y_start < this_scroll_margin)
+ y_offset = this_scroll_margin - (it.current_y - y_start);
}
if (PT < CHARPOS (scroll_margin_pos))
|| IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
return SCROLLING_FAILED;
+ /* Additional scroll for when ZV was too close to point. */
+ dy += y_offset;
+
/* Compute new window start. */
start_display (&it, w, startp);
if (!just_this_one_p
|| current_buffer->clip_changed
|| BEG_UNCHANGED < CHARPOS (startp))
- wset_base_line_number (w, Qnil);
+ w->base_line_number = 0;
/* If cursor ends up on a partially visible line,
treat that as being off the bottom of the screen. */
SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
/* Find the start of the continued line. This should be fast
- because scan_buffer is fast (newline cache). */
+ because find_newline is fast (newline cache). */
row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
row, DEFAULT_FACE_ID);
/* Can't use this case if highlighting a region. When a
region exists, cursor movement has to do more than just
set the cursor. */
- && !(!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
- && NILP (w->region_showing)
+ && markpos_of_region () < 0
+ && !w->region_showing
&& NILP (Vshow_trailing_whitespace)
/* This code is not used for mini-buffer for the sake of the case
of redisplaying to replace an echo area message; since in
set_buffer_internal_1 (XBUFFER (w->buffer));
current_matrix_up_to_date_p
- = (!NILP (w->window_end_valid)
+ = (w->window_end_valid
&& !current_buffer->clip_changed
&& !current_buffer->prevent_redisplay_optimizations_p
&& !window_outdated (w));
specbind (Qinhibit_point_motion_hooks, Qt);
buffer_unchanged_p
- = (!NILP (w->window_end_valid)
+ = (w->window_end_valid
&& !current_buffer->clip_changed
&& !window_outdated (w));
if (XMARKER (w->start)->buffer == current_buffer)
compute_window_start_on_continuation_line (w);
- wset_window_end_valid (w, Qnil);
+ w->window_end_valid = 0;
}
/* Some sanity checks. */
if (mode_line_update_needed (w))
update_mode_line = 1;
- /* Count number of windows showing the selected buffer. An indirect
- buffer counts as its base buffer. */
- if (!just_this_one_p)
- {
- 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. */
if (!EQ (window, selected_window))
{
- ptrdiff_t new_pt = XMARKER (w->pointm)->charpos;
+ ptrdiff_t new_pt = marker_position (w->pointm);
ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
if (new_pt < BEGV)
{
w->force_start = 0;
w->vscroll = 0;
- wset_window_end_valid (w, Qnil);
+ w->window_end_valid = 0;
/* Forget any recorded base line for line number display. */
if (!buffer_unchanged_p)
- wset_base_line_number (w, Qnil);
+ w->base_line_number = 0;
/* Redisplay the mode line. Select the buffer properly for that.
Also, run the hook window-scroll-functions
/* Some people insist on not letting point enter the scroll
margin, even though this part handles windows that didn't
scroll at all. */
- struct frame *f = XFRAME (w->frame);
int margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
int pixel_margin = margin * FRAME_LINE_HEIGHT (f);
bool header_line = WINDOW_WANTS_HEADER_LINE_P (w);
/* If we are highlighting the region, then we just changed
the region, so redisplay to show it. */
- if (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
+ if (0 <= markpos_of_region ())
{
clear_glyph_matrix (w->desired_matrix);
if (!try_window (window, startp, 0))
|| current_buffer->clip_changed
|| BEG_UNCHANGED < CHARPOS (startp))
/* Forget any recorded base line for line number display. */
- wset_base_line_number (w, Qnil);
+ w->base_line_number = 0;
if (!cursor_row_fully_visible_p (w, 1, 0))
{
debug_method_add (w, "recenter");
#endif
- /* w->vscroll = 0; */
-
/* Forget any previously recorded base line for line number display. */
if (!buffer_unchanged_p)
- wset_base_line_number (w, Qnil);
+ w->base_line_number = 0;
/* Determine the window start relative to point. */
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
line.) */
if (w->cursor.vpos < 0)
{
- if (!NILP (w->window_end_valid)
- && PT >= Z - XFASTINT (w->window_end_pos))
+ if (w->window_end_valid && PT >= Z - XFASTINT (w->window_end_pos))
{
clear_glyph_matrix (w->desired_matrix);
move_it_by_lines (&it, 1);
&& !FRAME_WINDOW_P (f)
&& !WINDOW_FULL_WIDTH_P (w))
/* Line number to display. */
- || INTEGERP (w->base_line_pos)
+ || w->base_line_pos > 0
/* Column number is displayed and different from the one displayed. */
- || (!NILP (w->column_number_displayed)
- && (XFASTINT (w->column_number_displayed) != current_column ())))
+ || (w->column_number_displayed != -1
+ && (w->column_number_displayed != current_column ())))
/* This means that the window has a mode line. */
&& (WINDOW_WANTS_MODELINE_P (w)
|| WINDOW_WANTS_HEADER_LINE_P (w)))
goto need_larger_matrices;
}
- if (!line_number_displayed
- && !BUFFERP (w->base_line_pos))
+ if (!line_number_displayed && w->base_line_pos != -1)
{
- wset_base_line_pos (w, Qnil);
- wset_base_line_number (w, Qnil);
+ w->base_line_pos = 0;
+ w->base_line_number = 0;
}
finish_menu_bars:
}
/* But that is not valid info until redisplay finishes. */
- wset_window_end_valid (w, Qnil);
+ w->window_end_valid = 0;
return 1;
}
return 0;
/* Can't do this if region may have changed. */
- if ((!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
- || !NILP (w->region_showing)
+ if (0 <= markpos_of_region ()
+ || w->region_showing
|| !NILP (Vshow_trailing_whitespace))
return 0;
wset_window_end_pos (w, make_number (Z - ZV));
wset_window_end_vpos (w, make_number (0));
}
- wset_window_end_valid (w, Qnil);
+ w->window_end_valid = 0;
/* Update hint: don't try scrolling again in update_window. */
w->desired_matrix->no_scrolling_p = 1;
(w, make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled));
}
- wset_window_end_valid (w, Qnil);
+ w->window_end_valid = 0;
w->desired_matrix->no_scrolling_p = 1;
#ifdef GLYPH_DEBUG
/* Display must not have been paused, otherwise the current matrix
is not up to date. */
- eassert (!NILP (w->window_end_valid));
+ eassert (w->window_end_valid);
/* A value of window_end_pos >= END_UNCHANGED means that the window
end is in the range of changed text. If so, there is no
/* Try to redisplay window W by reusing its existing display. W's
current matrix must be up to date when this function is called,
- i.e. window_end_valid must not be nil.
+ i.e. window_end_valid must be nonzero.
Value is
GIVE_UP (7);
/* Verify that display wasn't paused. */
- if (NILP (w->window_end_valid))
+ if (!w->window_end_valid)
GIVE_UP (8);
/* Can't use this if highlighting a region because a cursor movement
will do more than just set the cursor. */
- if (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
+ if (0 <= markpos_of_region ())
GIVE_UP (9);
/* Likewise if highlighting trailing whitespace. */
GIVE_UP (11);
/* Likewise if showing a region. */
- if (!NILP (w->region_showing))
+ if (w->region_showing)
GIVE_UP (10);
/* Can't use this if overlay arrow position and/or string have
debug_end_vpos = XFASTINT (w->window_end_vpos));
/* Record that display has not been completed. */
- wset_window_end_valid (w, Qnil);
+ w->window_end_valid = 0;
w->desired_matrix->no_scrolling_p = 1;
return 3;
void
dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
{
- if (glyph->type == CHAR_GLYPH)
+ if (glyph->type == CHAR_GLYPH
+ || glyph->type == GLYPHLESS_GLYPH)
{
fprintf (stderr,
- " %5td %4c %6"pI"d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
+ " %5"pD"d %c %9"pI"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
glyph - row->glyphs[TEXT_AREA],
- 'C',
+ (glyph->type == CHAR_GLYPH
+ ? 'C'
+ : 'G'),
glyph->charpos,
(BUFFERP (glyph->object)
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : '-')),
+ : (INTEGERP (glyph->object)
+ ? '0'
+ : '-'))),
glyph->pixel_width,
glyph->u.ch,
(glyph->u.ch < 0x80 && glyph->u.ch >= ' '
else if (glyph->type == STRETCH_GLYPH)
{
fprintf (stderr,
- " %5td %4c %6"pI"d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
+ " %5"pD"d %c %9"pI"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
glyph - row->glyphs[TEXT_AREA],
'S',
glyph->charpos,
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : '-')),
+ : (INTEGERP (glyph->object)
+ ? '0'
+ : '-'))),
glyph->pixel_width,
0,
- '.',
+ ' ',
glyph->face_id,
glyph->left_box_line_p,
glyph->right_box_line_p);
else if (glyph->type == IMAGE_GLYPH)
{
fprintf (stderr,
- " %5td %4c %6"pI"d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
+ " %5"pD"d %c %9"pI"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
glyph - row->glyphs[TEXT_AREA],
'I',
glyph->charpos,
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : '-')),
+ : (INTEGERP (glyph->object)
+ ? '0'
+ : '-'))),
glyph->pixel_width,
glyph->u.img_id,
'.',
else if (glyph->type == COMPOSITE_GLYPH)
{
fprintf (stderr,
- " %5td %4c %6"pI"d %c %3d 0x%05x",
+ " %5"pD"d %c %9"pI"d %c %3d 0x%06x",
glyph - row->glyphs[TEXT_AREA],
'+',
glyph->charpos,
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : '-')),
+ : (INTEGERP (glyph->object)
+ ? '0'
+ : '-'))),
glyph->pixel_width,
glyph->u.cmp.id);
if (glyph->u.cmp.automatic)
{
if (glyphs != 1)
{
- fprintf (stderr, "Row Start End Used oE><\\CTZFesm X Y W H V A P\n");
- fprintf (stderr, "======================================================================\n");
+ fprintf (stderr, "Row Start End Used oE><\\CTZFesm X Y W H V A P\n");
+ fprintf (stderr, "==============================================================================\n");
- fprintf (stderr, "%3d %5"pI"d %5"pI"d %4d %1.1d%1.1d%1.1d%1.1d\
+ fprintf (stderr, "%3d %9"pI"d %9"pI"d %4d %1.1d%1.1d%1.1d%1.1d\
%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
vpos,
MATRIX_ROW_START_CHARPOS (row),
row->visible_height,
row->ascent,
row->phys_ascent);
- fprintf (stderr, "%9"pD"d %5"pD"d\t%5d\n", row->start.overlay_string_index,
+ /* The next 3 lines should align to "Start" in the header. */
+ fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
row->end.overlay_string_index,
row->continuation_lines_width);
- fprintf (stderr, "%9"pI"d %5"pI"d\n",
+ fprintf (stderr, " %9"pI"d %9"pI"d\n",
CHARPOS (row->start.string_pos),
CHARPOS (row->end.string_pos));
- fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
+ fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
row->end.dpvec_index);
}
++glyph_end;
if (glyph < glyph_end)
- fprintf (stderr, " Glyph Type Pos O W Code C Face LR\n");
+ fprintf (stderr, " Glyph# Type Pos O W Code C Face LR\n");
for (; glyph < glyph_end; ++glyph)
dump_glyph (row, glyph, area);
for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
{
- char *s = alloca (row->used[area] + 1);
+ char *s = alloca (row->used[area] + 4);
int i;
for (i = 0; i < row->used[area]; ++i)
{
struct glyph *glyph = row->glyphs[area] + i;
- if (glyph->type == CHAR_GLYPH
- && glyph->u.ch < 0x80
- && glyph->u.ch >= ' ')
+ if (i == row->used[area] - 1
+ && area == TEXT_AREA
+ && INTEGERP (glyph->object)
+ && glyph->type == CHAR_GLYPH
+ && glyph->u.ch == ' ')
+ {
+ strcpy (&s[i], "[\\n]");
+ i += 4;
+ }
+ else if (glyph->type == CHAR_GLYPH
+ && glyph->u.ch < 0x80
+ && glyph->u.ch >= ' ')
s[i] = glyph->u.ch;
else
s[i] = '.';
const unsigned char *arrow_end = arrow_string + arrow_len;
const unsigned char *p;
struct it it;
- int multibyte_p;
+ bool multibyte_p;
int n_glyphs_before;
set_buffer_temp (buffer);
int saved_char_to_display = it->char_to_display;
int saved_x = it->current_x;
int saved_face_id = it->face_id;
+ int saved_box_end = it->end_of_box_run_p;
struct text_pos saved_pos;
Lisp_Object saved_object;
struct face *face;
it->face_id = it->saved_face_id;
face = FACE_FROM_ID (it->f, it->face_id);
it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
+ /* In R2L rows, we will prepend a stretch glyph that will
+ have the end_of_box_run_p flag set for it, so there's no
+ need for the appended newline glyph to have that flag
+ set. */
+ if (it->glyph_row->reversed_p
+ /* But if the appended newline glyph goes all the way to
+ the end of the row, there will be no stretch glyph,
+ so leave the box flag set. */
+ && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x)
+ it->end_of_box_run_p = 0;
PRODUCE_GLYPHS (it);
it->len = saved_len;
it->c = saved_c;
it->char_to_display = saved_char_to_display;
+ it->end_of_box_run_p = saved_box_end;
return 1;
}
}
struct glyph *g;
int row_width, stretch_ascent, stretch_width;
struct text_pos saved_pos;
- int saved_face_id, saved_avoid_cursor;
+ int saved_face_id, saved_avoid_cursor, saved_box_start;
for (row_width = 0, g = row_start; g < row_end; g++)
row_width += g->pixel_width;
saved_avoid_cursor = it->avoid_cursor_p;
it->avoid_cursor_p = 1;
saved_face_id = it->face_id;
+ saved_box_start = it->start_of_box_run_p;
/* The last row's stretch glyph should get the default
face, to avoid painting the rest of the window with
the region face, if the region ends at ZV. */
it->face_id = default_face->id;
else
it->face_id = face->id;
+ it->start_of_box_run_p = 0;
append_stretch_glyph (it, make_number (0), stretch_width,
it->ascent + it->descent, stretch_ascent);
it->position = saved_pos;
it->avoid_cursor_p = saved_avoid_cursor;
it->face_id = saved_face_id;
+ it->start_of_box_run_p = saved_box_start;
}
}
#endif /* HAVE_WINDOW_SYSTEM */
}
/* Is IT->w showing the region? */
- wset_region_showing (it->w, it->region_beg_charpos > 0 ? Qt : Qnil);
+ it->w->region_showing = it->region_beg_charpos > 0 ? it->region_beg_charpos : 0;
/* Clear the result glyph row and enable it. */
prepare_desired_row (row);
static int
display_mode_lines (struct window *w)
{
- Lisp_Object old_selected_window, old_selected_frame;
+ Lisp_Object old_selected_window = selected_window;
+ Lisp_Object old_selected_frame = selected_frame;
+ Lisp_Object new_frame = w->frame;
+ Lisp_Object old_frame_selected_window = XFRAME (new_frame)->selected_window;
int n = 0;
- old_selected_frame = selected_frame;
- selected_frame = w->frame;
- old_selected_window = selected_window;
+ selected_frame = new_frame;
+ /* FIXME: If we were to allow the mode-line's computation changing the buffer
+ or window's point, then we'd need select_window_1 here as well. */
XSETWINDOW (selected_window, w);
+ XFRAME (new_frame)->selected_window = selected_window;
/* These will be set while the mode line specs are processed. */
line_number_displayed = 0;
- wset_column_number_displayed (w, Qnil);
+ w->column_number_displayed = -1;
if (WINDOW_WANTS_MODELINE_P (w))
{
++n;
}
+ XFRAME (new_frame)->selected_window = old_frame_selected_window;
selected_frame = old_selected_frame;
selected_window = old_selected_window;
return n;
risky);
else if (c != 0)
{
- int multibyte;
+ bool multibyte;
ptrdiff_t bytepos, charpos;
const char *spec;
Lisp_Object string;
decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_flag)
{
Lisp_Object val;
- int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
+ bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
const unsigned char *eol_str;
int eol_str_len;
/* The EOL conversion we are using. */
returned with spaces to that value. Return a Lisp string in
*STRING if the resulting string is taken from that Lisp string.
- Note we operate on the current buffer for most purposes,
- the exception being w->base_line_pos. */
+ Note we operate on the current buffer for most purposes. */
static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
register int i;
/* Let lots_of_dashes be a string of infinite length. */
- if (mode_line_target == MODE_LINE_NOPROP ||
- mode_line_target == MODE_LINE_STRING)
+ if (mode_line_target == MODE_LINE_NOPROP
+ || mode_line_target == MODE_LINE_STRING)
return "--";
if (field_width <= 0
|| field_width > sizeof (lots_of_dashes))
else
{
ptrdiff_t col = current_column ();
- wset_column_number_displayed (w, make_number (col));
+ w->column_number_displayed = col;
pint2str (decode_mode_spec_buf, width, col);
return decode_mode_spec_buf;
}
if (mode_line_target == MODE_LINE_TITLE)
return "";
- startpos = XMARKER (w->start)->charpos;
+ startpos = marker_position (w->start);
startpos_byte = marker_byte_position (w->start);
height = WINDOW_TOTAL_LINES (w);
/* If we decided that this buffer isn't suitable for line numbers,
don't forget that too fast. */
- if (EQ (w->base_line_pos, w->buffer))
+ if (w->base_line_pos == -1)
goto no_value;
- /* But do forget it, if the window shows a different buffer now. */
- else if (BUFFERP (w->base_line_pos))
- wset_base_line_pos (w, Qnil);
/* If the buffer is very big, don't waste time. */
if (INTEGERP (Vline_number_display_limit)
&& BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
{
- wset_base_line_pos (w, Qnil);
- wset_base_line_number (w, Qnil);
+ w->base_line_pos = 0;
+ w->base_line_number = 0;
goto no_value;
}
- if (INTEGERP (w->base_line_number)
- && INTEGERP (w->base_line_pos)
- && XFASTINT (w->base_line_pos) <= startpos)
+ if (w->base_line_number > 0
+ && w->base_line_pos > 0
+ && w->base_line_pos <= startpos)
{
- line = XFASTINT (w->base_line_number);
- linepos = XFASTINT (w->base_line_pos);
+ line = w->base_line_number;
+ linepos = w->base_line_pos;
linepos_byte = buf_charpos_to_bytepos (b, linepos);
}
else
go back past it. */
if (startpos == BUF_BEGV (b))
{
- wset_base_line_number (w, make_number (topline));
- wset_base_line_pos (w, make_number (BUF_BEGV (b)));
+ w->base_line_number = topline;
+ w->base_line_pos = BUF_BEGV (b);
}
else if (nlines < height + 25 || nlines > height * 3 + 50
|| linepos == BUF_BEGV (b))
give up on line numbers for this window. */
if (position == limit_byte && limit == startpos - distance)
{
- wset_base_line_pos (w, w->buffer);
- wset_base_line_number (w, Qnil);
+ w->base_line_pos = -1;
+ w->base_line_number = 0;
goto no_value;
}
- wset_base_line_number (w, make_number (topline - nlines));
- wset_base_line_pos (w, make_number (BYTE_TO_CHAR (position)));
+ w->base_line_number = topline - nlines;
+ w->base_line_pos = BYTE_TO_CHAR (position);
}
/* Now count lines from the start pos to point. */
return "@";
}
- case 't': /* indicate TEXT or BINARY */
- return "T";
-
case 'z':
/* coding-system (not including end-of-line format) */
case 'Z':
}
-/* Count up to COUNT lines starting from START_BYTE.
- But don't go beyond LIMIT_BYTE.
- Return the number of lines thus found (always nonnegative).
+/* Count up to COUNT lines starting from START_BYTE. COUNT negative
+ means count lines back from START_BYTE. But don't go beyond
+ LIMIT_BYTE. Return the number of lines thus found (always
+ nonnegative).
- Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
+ Set *BYTE_POS_PTR to the byte position where we stopped. This is
+ either the position COUNT lines after/before START_BYTE, if we
+ found COUNT lines, or LIMIT_BYTE if we hit the limit before finding
+ COUNT lines. */
static ptrdiff_t
display_count_lines (ptrdiff_t start_byte,
ceiling = min (limit_byte - 1, ceiling);
ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
base = (cursor = BYTE_POS_ADDR (start_byte));
- while (1)
+
+ do
{
if (selective_display)
- while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
- ;
+ {
+ while (*cursor != '\n' && *cursor != 015
+ && ++cursor != ceiling_addr)
+ continue;
+ if (cursor == ceiling_addr)
+ break;
+ }
else
- while (*cursor != '\n' && ++cursor != ceiling_addr)
- ;
+ {
+ cursor = memchr (cursor, '\n', ceiling_addr - cursor);
+ if (! cursor)
+ break;
+ }
- if (cursor != ceiling_addr)
+ cursor++;
+
+ if (--count == 0)
{
- if (--count == 0)
- {
- start_byte += cursor - base + 1;
- *byte_pos_ptr = start_byte;
- return orig_count;
- }
- else
- if (++cursor == ceiling_addr)
- break;
+ start_byte += cursor - base;
+ *byte_pos_ptr = start_byte;
+ return orig_count;
}
- else
- break;
}
- start_byte += cursor - base;
+ while (cursor < ceiling_addr);
+
+ start_byte += ceiling_addr - base;
}
}
else
{
ceiling = BUFFER_FLOOR_OF (start_byte - 1);
ceiling = max (limit_byte, ceiling);
- ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
+ ceiling_addr = BYTE_POS_ADDR (ceiling);
base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
while (1)
{
if (selective_display)
- while (--cursor != ceiling_addr
- && *cursor != '\n' && *cursor != 015)
- ;
+ {
+ while (--cursor >= ceiling_addr
+ && *cursor != '\n' && *cursor != 015)
+ continue;
+ if (cursor < ceiling_addr)
+ break;
+ }
else
- while (--cursor != ceiling_addr && *cursor != '\n')
- ;
+ {
+ cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
+ if (! cursor)
+ break;
+ }
- if (cursor != ceiling_addr)
+ if (++count == 0)
{
- if (++count == 0)
- {
- start_byte += cursor - base + 1;
- *byte_pos_ptr = start_byte;
- /* When scanning backwards, we should
- not count the newline posterior to which we stop. */
- return - orig_count - 1;
- }
+ start_byte += cursor - base + 1;
+ *byte_pos_ptr = start_byte;
+ /* When scanning backwards, we should
+ not count the newline posterior to which we stop. */
+ return - orig_count - 1;
}
- else
- break;
}
- /* Here we add 1 to compensate for the last decrement
- of CURSOR, which took it past the valid range. */
- start_byte += cursor - base + 1;
+ start_byte += ceiling_addr - base;
}
}
/* Let's rather be paranoid than getting a SEGV. */
end = min (end, row->used[area]);
- start = max (0, start);
- start = min (end, start);
+ start = clip_to_bounds (0, start, end);
/* Translate X to frame coordinates. Set last_x to the right
end of the drawing area. */
glyph->type = CHAR_GLYPH;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->glyph_not_available_p = it->glyph_not_available_p;
}
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->padding_p = 0;
glyph->type = IMAGE_GLYPH;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = 0;
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
glyph->type = STRETCH_GLYPH;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = 0;
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
glyph->slice.glyphless.lower_yoff = lower_yoff;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->padding_p = 0;
And verify the buffer's text has not changed. */
b = XBUFFER (w->buffer);
if (part == ON_TEXT
- && EQ (w->window_end_valid, w->buffer)
+ && w->window_end_valid
&& w->last_modified == BUF_MODIFF (b)
&& w->last_overlay_modified == BUF_OVERLAY_MODIFF (b))
{
if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame)))
return;
+ /* Note: It is necessary to redraw both the left and the right
+ borders, for when only this single window W is being
+ redisplayed. */
if (!WINDOW_RIGHTMOST_P (w)
&& !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
{
FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
}
- else if (!WINDOW_LEFTMOST_P (w)
- && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+ if (!WINDOW_LEFTMOST_P (w)
+ && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
{
int x0, x1, y0, y1;