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
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
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
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);
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);
}
}
}
/* 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)
+ else if (INTERACTIVE && sf->glyphs_initialized_p)
{
/* Get the frame containing the mini-buffer
that the selected frame is using. */
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)
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 ()));
}
/***********************************************************************
{
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
&& (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)
{
{
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;
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);
region exists, cursor movement has to do more than just
set the cursor. */
&& markpos_of_region () < 0
- && NILP (w->region_showing)
+ && !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
/* 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
|| 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);
&& !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:
/* Can't do this if region may have changed. */
if (0 <= markpos_of_region ()
- || !NILP (w->region_showing)
+ || w->region_showing
|| !NILP (Vshow_trailing_whitespace))
return 0;
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
}
/* 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);
/* 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))
{
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[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
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 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;
+ }
+
+ cursor++;
- if (cursor != ceiling_addr)
+ 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;
}
}