/* Indentation functions.
- Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2012
- Free Software Foundation, Inc.
+ Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2013 Free Software
+ Foundation, Inc.
This file is part of GNU Emacs.
static ptrdiff_t current_column_1 (void);
static ptrdiff_t position_indentation (ptrdiff_t);
-/* Cache of beginning of line found by the last call of
- current_column. */
-
-static ptrdiff_t current_column_bol_cache;
-
/* Get the display table to use for the current buffer. */
struct Lisp_Char_Table *
struct Lisp_Vector *widthtab;
if (!VECTORP (BVAR (buf, width_table)))
- bset_width_table (buf, Fmake_vector (make_number (256), make_number (0)));
+ bset_width_table (buf, make_uninit_vector (256));
widthtab = XVECTOR (BVAR (buf, width_table));
eassert (widthtab->header.size == 256);
XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
}
-/* Allocate or free the width run cache, as requested by the current
- state of current_buffer's cache_long_line_scans variable. */
+/* Allocate or free the width run cache, as requested by the
+ current state of current_buffer's cache_long_scans variable. */
static void
width_run_cache_on_off (void)
{
- if (NILP (BVAR (current_buffer, cache_long_line_scans))
+ if (NILP (BVAR (current_buffer, cache_long_scans))
/* And, for the moment, this feature doesn't work on multibyte
characters. */
|| !NILP (BVAR (current_buffer, enable_multibyte_characters)))
the next property change */
prop = Fget_char_property (position, Qinvisible,
(!NILP (window)
- && EQ (XWINDOW (window)->buffer, buffer))
+ && EQ (XWINDOW (window)->contents, buffer))
? window : buffer);
inv_p = TEXT_PROP_MEANS_INVISIBLE (prop);
/* When counting columns (window == nil), don't skip over ellipsis text. */
doc: /* Return the horizontal position of point. Beginning of line is column 0.
This is calculated by adding together the widths of all the displayed
representations of the character between the start of the previous line
-and point (eg. control characters will have a width of 2 or 4, tabs
+and point (e.g., control characters will have a width of 2 or 4, tabs
will have a variable width).
Ignores finite width of frame, which means that this function may return
values greater than (frame-width).
col += post_tab;
}
- if (ptr == BEGV_ADDR)
- current_column_bol_cache = BEGV;
- else
- current_column_bol_cache = BYTE_TO_CHAR (PTR_BYTE_POS (ptr));
-
last_known_column = col;
last_known_column_point = PT;
last_known_column_modified = MODIFF;
register ptrdiff_t col = 0, prev_col = 0;
EMACS_INT goal = goalcol ? *goalcol : MOST_POSITIVE_FIXNUM;
ptrdiff_t end = endpos ? *endpos : PT;
- ptrdiff_t scan, scan_byte;
- ptrdiff_t next_boundary;
- {
- ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
- scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
- current_column_bol_cache = PT;
- scan = PT, scan_byte = PT_BYTE;
- SET_PT_BOTH (opoint, opoint_byte);
+ ptrdiff_t scan, scan_byte, next_boundary;
+
+ scan = find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, NULL, &scan_byte, 1);
next_boundary = scan;
- }
window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
w = ! NILP (window) ? XWINDOW (window) : NULL;
col += width;
if (endp > scan) /* Avoid infinite loops with 0-width overlays. */
{
- scan = endp; scan_byte = charpos_to_bytepos (scan);
+ scan = endp;
+ scan_byte = CHAR_TO_BYTE (scan);
continue;
}
}
following any initial whitespace. */)
(void)
{
- Lisp_Object val;
- ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
-
- scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
+ ptrdiff_t posbyte;
- XSETFASTINT (val, position_indentation (PT_BYTE));
- SET_PT_BOTH (opoint, opoint_byte);
- return val;
+ find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, NULL, &posbyte, 1);
+ return make_number (position_indentation (posbyte));
}
static ptrdiff_t
bool
indented_beyond_p (ptrdiff_t pos, ptrdiff_t pos_byte, EMACS_INT column)
{
- ptrdiff_t val;
- ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
-
- SET_PT_BOTH (pos, pos_byte);
- while (PT > BEGV && FETCH_BYTE (PT_BYTE) == '\n')
- scan_newline (PT - 1, PT_BYTE - 1, BEGV, BEGV_BYTE, -1, 0);
-
- val = position_indentation (PT_BYTE);
- SET_PT_BOTH (opoint, opoint_byte);
- return val >= column;
+ while (pos > BEGV && FETCH_BYTE (pos_byte) == '\n')
+ {
+ DEC_BOTH (pos, pos_byte);
+ pos = find_newline (pos, pos_byte, BEGV, BEGV_BYTE,
+ -1, NULL, &pos_byte, 0);
+ }
+ return position_indentation (pos_byte) >= column;
}
\f
DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2,
: (window_width + window_left != frame_cols))
where
- window_width is XFASTINT (w->total_cols),
- window_left is XFASTINT (w->left_col),
+ window_width is w->total_cols,
+ window_left is w->left_col,
has_vertical_scroll_bars is
WINDOW_HAS_VERTICAL_SCROLL_BAR (window)
and frame_cols = FRAME_COLS (XFRAME (window->frame))
the scroll bars if they are turned on. */
struct position *
-compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos,
- bool did_motion, ptrdiff_t to,
+compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
+ EMACS_INT fromhpos, bool did_motion, ptrdiff_t to,
EMACS_INT tovpos, EMACS_INT tohpos, EMACS_INT width,
ptrdiff_t hscroll, int tab_offset, struct window *win)
{
/* Negative width means use all available text columns. */
if (width < 0)
{
- width = window_body_cols (win);
+ width = window_body_width (win, 0);
/* We must make room for continuation marks if we don't have fringes. */
#ifdef HAVE_WINDOW_SYSTEM
if (!FRAME_WINDOW_P (XFRAME (win->frame)))
immediate_quit = 1;
QUIT;
+ /* It's just impossible to be too paranoid here. */
+ eassert (from == BYTE_TO_CHAR (frombyte) && frombyte == CHAR_TO_BYTE (from));
+
pos = prev_pos = from;
- pos_byte = prev_pos_byte = CHAR_TO_BYTE (from);
+ pos_byte = prev_pos_byte = frombyte;
contin_hpos = 0;
prev_tab_offset = tab_offset;
memset (&cmp_it, 0, sizeof cmp_it);
TO (we need to go back below). */
if (pos <= to)
{
- pos = find_before_next_newline (pos, to, 1);
- pos_byte = CHAR_TO_BYTE (pos);
+ pos = find_before_next_newline (pos, to, 1, &pos_byte);
hpos = width;
/* If we just skipped next_boundary,
loop around in the main while
/* Skip any number of invisible lines all at once */
do
{
- pos = find_before_next_newline (pos, to, 1);
+ pos = find_before_next_newline (pos, to, 1, &pos_byte);
if (pos < to)
- pos++;
- pos_byte = CHAR_TO_BYTE (pos);
+ INC_BOTH (pos, pos_byte);
}
while (pos < to
&& indented_beyond_p (pos, pos_byte,
everything from a ^M to the end of the line is invisible.
Stop *before* the real newline. */
if (pos < to)
- {
- pos = find_before_next_newline (pos, to, 1);
- pos_byte = CHAR_TO_BYTE (pos);
- }
+ pos = find_before_next_newline (pos, to, 1, &pos_byte);
/* If we just skipped next_boundary,
loop around in the main while
and handle it. */
and the window's upper-left coordinates as FROMPOS.
Pass the buffer's (point-max) as TO, to limit the scan to the end of the
visible section of the buffer, and pass LINE and COL as TOPOS. */)
- (Lisp_Object from, Lisp_Object frompos, Lisp_Object to, Lisp_Object topos, Lisp_Object width, Lisp_Object offsets, Lisp_Object window)
+ (Lisp_Object from, Lisp_Object frompos, Lisp_Object to, Lisp_Object topos,
+ Lisp_Object width, Lisp_Object offsets, Lisp_Object window)
{
struct window *w;
Lisp_Object bufpos, hpos, vpos, prevhpos;
if (XINT (to) < BEGV || XINT (to) > ZV)
args_out_of_range_3 (to, make_number (BEGV), make_number (ZV));
- pos = compute_motion (XINT (from), XINT (XCDR (frompos)),
+ pos = compute_motion (XINT (from), CHAR_TO_BYTE (XINT (from)),
+ XINT (XCDR (frompos)),
XINT (XCAR (frompos)), 0,
XINT (to),
(NILP (topos)
? window_internal_height (w)
: XINT (XCDR (topos))),
(NILP (topos)
- ? (window_body_cols (w)
+ ? (window_body_width (w, 0)
- (
#ifdef HAVE_WINDOW_SYSTEM
FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 :
XSETINT (vpos, pos->vpos);
XSETINT (prevhpos, pos->prevhpos);
- return Fcons (bufpos,
- Fcons (hpos,
- Fcons (vpos,
- Fcons (prevhpos,
- Fcons (pos->contin ? Qt : Qnil, Qnil)))));
-
+ return list5 (bufpos, hpos, vpos, prevhpos, pos->contin ? Qt : Qnil);
}
-\f
-/* Fvertical_motion and vmotion */
+
+/* Fvertical_motion and vmotion. */
static struct position val_vmotion;
struct position *
-vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w)
+vmotion (register ptrdiff_t from, register ptrdiff_t from_byte,
+ register EMACS_INT vtarget, struct window *w)
{
ptrdiff_t hscroll = w->hscroll;
struct position pos;
- /* vpos is cumulative vertical position, changed as from is changed */
+ /* VPOS is cumulative vertical position, changed as from is changed. */
register EMACS_INT vpos = 0;
ptrdiff_t prevline;
register ptrdiff_t first;
- ptrdiff_t from_byte;
ptrdiff_t lmargin = hscroll > 0 ? 1 - hscroll : 0;
ptrdiff_t selective
= (INTEGERP (BVAR (current_buffer, selective_display))
/* If the window contains this buffer, use it for getting text properties.
Otherwise use the current buffer as arg for doing that. */
- if (EQ (w->buffer, Fcurrent_buffer ()))
+ if (EQ (w->contents, Fcurrent_buffer ()))
text_prop_object = window;
else
text_prop_object = Fcurrent_buffer ();
while ((vpos > vtarget || first) && from > BEGV)
{
+ ptrdiff_t bytepos = from_byte;
Lisp_Object propval;
- prevline = find_next_newline_no_quit (from - 1, -1);
+ prevline = from;
+ DEC_BOTH (prevline, bytepos);
+ prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos);
+
while (prevline > BEGV
&& ((selective > 0
- && indented_beyond_p (prevline,
- CHAR_TO_BYTE (prevline),
- selective))
+ && indented_beyond_p (prevline, bytepos, selective))
/* Watch out for newlines with `invisible' property.
When moving upward, check the newline before. */
|| (propval = Fget_char_property (make_number (prevline - 1),
Qinvisible,
text_prop_object),
TEXT_PROP_MEANS_INVISIBLE (propval))))
- prevline = find_next_newline_no_quit (prevline - 1, -1);
- pos = *compute_motion (prevline, 0,
- lmargin,
- 0,
- from,
+ {
+ DEC_BOTH (prevline, bytepos);
+ prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos);
+ }
+ pos = *compute_motion (prevline, bytepos, 0, lmargin, 0, from,
/* Don't care for VPOS... */
1 << (BITS_PER_SHORT - 1),
/* ... nor HPOS. */
1 << (BITS_PER_SHORT - 1),
- -1, hscroll,
- 0,
- w);
+ -1, hscroll, 0, w);
vpos -= pos.vpos;
first = 0;
from = prevline;
+ from_byte = bytepos;
}
- /* If we made exactly the desired vertical distance,
- or if we hit beginning of buffer,
- return point found */
+ /* If we made exactly the desired vertical distance, or
+ if we hit beginning of buffer, return point found. */
if (vpos >= vtarget)
{
val_vmotion.bufpos = from;
- val_vmotion.bytepos = CHAR_TO_BYTE (from);
+ val_vmotion.bytepos = from_byte;
val_vmotion.vpos = vpos;
val_vmotion.hpos = lmargin;
val_vmotion.contin = 0;
return &val_vmotion;
}
- /* Otherwise find the correct spot by moving down */
+ /* Otherwise find the correct spot by moving down. */
}
- /* Moving downward is simple, but must calculate from beg of line
- to determine hpos of starting point */
- from_byte = CHAR_TO_BYTE (from);
+
+ /* Moving downward is simple, but must calculate from
+ beg of line to determine hpos of starting point. */
+
if (from > BEGV && FETCH_BYTE (from_byte - 1) != '\n')
{
+ ptrdiff_t bytepos;
Lisp_Object propval;
- prevline = find_next_newline_no_quit (from, -1);
+ prevline = find_newline_no_quit (from, from_byte, -1, &bytepos);
while (prevline > BEGV
&& ((selective > 0
- && indented_beyond_p (prevline,
- CHAR_TO_BYTE (prevline),
- selective))
+ && indented_beyond_p (prevline, bytepos, selective))
/* Watch out for newlines with `invisible' property.
When moving downward, check the newline after. */
|| (propval = Fget_char_property (make_number (prevline),
Qinvisible,
text_prop_object),
TEXT_PROP_MEANS_INVISIBLE (propval))))
- prevline = find_next_newline_no_quit (prevline - 1, -1);
- pos = *compute_motion (prevline, 0,
- lmargin,
- 0,
- from,
+ {
+ DEC_BOTH (prevline, bytepos);
+ prevline = find_newline_no_quit (prevline, bytepos, -1, &bytepos);
+ }
+ pos = *compute_motion (prevline, bytepos, 0, lmargin, 0, from,
/* Don't care for VPOS... */
1 << (BITS_PER_SHORT - 1),
/* ... nor HPOS. */
1 << (BITS_PER_SHORT - 1),
- -1, hscroll,
- 0,
- w);
+ -1, hscroll, 0, w);
did_motion = 1;
}
else
pos.vpos = 0;
did_motion = 0;
}
- return compute_motion (from, vpos, pos.hpos, did_motion,
+ return compute_motion (from, from_byte, vpos, pos.hpos, did_motion,
ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)),
- -1, hscroll,
- 0,
- w);
+ -1, hscroll, 0, w);
}
DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
struct window *w;
Lisp_Object old_buffer;
EMACS_INT old_charpos IF_LINT (= 0), old_bytepos IF_LINT (= 0);
- struct gcpro gcpro1, gcpro2, gcpro3;
+ struct gcpro gcpro1;
Lisp_Object lcols = Qnil;
double cols IF_LINT (= 0);
void *itdata = NULL;
w = decode_live_window (window);
old_buffer = Qnil;
- GCPRO3 (old_buffer, old_charpos, old_bytepos);
- if (XBUFFER (w->buffer) != current_buffer)
+ GCPRO1 (old_buffer);
+ if (XBUFFER (w->contents) != current_buffer)
{
/* Set the window's buffer temporarily to the current buffer. */
- old_buffer = w->buffer;
- old_charpos = XMARKER (w->pointm)->charpos;
- old_bytepos = XMARKER (w->pointm)->bytepos;
+ old_buffer = w->contents;
+ old_charpos = marker_position (w->pointm);
+ old_bytepos = marker_byte_position (w->pointm);
wset_buffer (w, Fcurrent_buffer ());
- set_marker_both (w->pointm, w->buffer,
+ set_marker_both (w->pointm, w->contents,
BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer));
}
if (noninteractive)
{
struct position pos;
- pos = *vmotion (PT, XINT (lines), w);
+ pos = *vmotion (PT, PT_BYTE, XINT (lines), w);
SET_PT_BOTH (pos.bufpos, pos.bytepos);
}
else
const char *s = SSDATA (it.string);
const char *e = s + SBYTES (it.string);
- disp_string_at_start_p = it.string_from_display_prop_p;
+ disp_string_at_start_p =
+ /* If it.area is anything but TEXT_AREA, we need not bother
+ about the display string, as it doesn't affect cursor
+ positioning. */
+ it.area == TEXT_AREA
+ && it.string_from_display_prop_p
+ /* A display string on anything but buffer text (e.g., on
+ an overlay string) doesn't affect cursor positioning. */
+ && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER);
while (s < e)
{
if (*s++ == '\n')
if (BUFFERP (old_buffer))
{
wset_buffer (w, old_buffer);
- set_marker_both (w->pointm, w->buffer,
+ set_marker_both (w->pointm, w->contents,
old_charpos, old_bytepos);
}