/* Indentation functions.
- Copyright (C) 1985,86,87,88,93,94,95,98,2000,01,02,03,2004
- Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1998, 2000, 2001,
+ 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Emacs.
int current_column_bol_cache;
+extern Lisp_Object Qfontification_functions;
+
/* Get the display table to use for the current buffer. */
struct Lisp_Char_Table *
Lisp_Object window;
{
Lisp_Object prop, position, overlay_limit, proplimit;
- Lisp_Object buffer;
+ Lisp_Object buffer, tmp;
int end, inv_p;
XSETFASTINT (position, pos);
/* No matter what. don't go past next overlay change. */
if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
proplimit = overlay_limit;
- end = XFASTINT (Fnext_single_property_change (position, Qinvisible,
- buffer, proplimit));
+ tmp = Fnext_single_property_change (position, Qinvisible,
+ buffer, proplimit);
+ end = XFASTINT (tmp);
#if 0
/* Don't put the boundary in the middle of multibyte form if
there is no actual property change. */
Ignores finite width of frame, which means that this function may return
values greater than (frame-width).
Whether the line is visible (if `selective-display' is t) has no effect;
-however, ^M is treated as end of line when `selective-display' is t. */)
+however, ^M is treated as end of line when `selective-display' is t.
+Text that has an invisible property is considered as having width 0, unless
+`buffer-invisibility-spec' specifies that it is replaced by an ellipsis. */)
()
{
Lisp_Object temp;
struct position pos;
/* vpos is cumulative vertical position, changed as from is changed */
register int vpos = 0;
- Lisp_Object prevline;
+ int prevline;
register int first;
int from_byte;
int lmargin = hscroll > 0 ? 1 - hscroll : 0;
{
Lisp_Object propval;
- XSETFASTINT (prevline, find_next_newline_no_quit (from - 1, -1));
- while (XFASTINT (prevline) > BEGV
+ prevline = find_next_newline_no_quit (from - 1, -1);
+ while (prevline > BEGV
&& ((selective > 0
- && indented_beyond_p (XFASTINT (prevline),
- CHAR_TO_BYTE (XFASTINT (prevline)),
+ && indented_beyond_p (prevline,
+ CHAR_TO_BYTE (prevline),
(double) selective)) /* iftc */
- /* watch out for newlines with `invisible' property */
- || (propval = Fget_char_property (prevline,
+ /* 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))))
- XSETFASTINT (prevline,
- find_next_newline_no_quit (XFASTINT (prevline) - 1,
- -1));
- pos = *compute_motion (XFASTINT (prevline), 0,
- lmargin + (XFASTINT (prevline) == BEG
- ? start_hpos : 0),
+ prevline = find_next_newline_no_quit (prevline - 1, -1);
+ pos = *compute_motion (prevline, 0,
+ lmargin + (prevline == BEG ? start_hpos : 0),
0,
from,
/* Don't care for VPOS... */
/* This compensates for start_hpos
so that a tab as first character
still occupies 8 columns. */
- (XFASTINT (prevline) == BEG
- ? -start_hpos : 0),
+ (prevline == BEG ? -start_hpos : 0),
w);
vpos -= pos.vpos;
first = 0;
- from = XFASTINT (prevline);
+ from = prevline;
}
/* If we made exactly the desired vertical distance,
{
Lisp_Object propval;
- XSETFASTINT (prevline, find_next_newline_no_quit (from, -1));
- while (XFASTINT (prevline) > BEGV
+ prevline = find_next_newline_no_quit (from, -1);
+ while (prevline > BEGV
&& ((selective > 0
- && indented_beyond_p (XFASTINT (prevline),
- CHAR_TO_BYTE (XFASTINT (prevline)),
+ && indented_beyond_p (prevline,
+ CHAR_TO_BYTE (prevline),
(double) selective)) /* iftc */
- /* watch out for newlines with `invisible' property */
- || (propval = Fget_char_property (prevline, Qinvisible,
+ /* 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))))
- XSETFASTINT (prevline,
- find_next_newline_no_quit (XFASTINT (prevline) - 1,
- -1));
- pos = *compute_motion (XFASTINT (prevline), 0,
- lmargin + (XFASTINT (prevline) == BEG
+ prevline = find_next_newline_no_quit (prevline - 1, -1);
+ pos = *compute_motion (prevline, 0,
+ lmargin + (prevline == BEG
? start_hpos : 0),
0,
from,
/* ... nor HPOS. */
1 << (BITS_PER_SHORT - 1),
-1, hscroll,
- (XFASTINT (prevline) == BEG ? -start_hpos : 0),
+ (prevline == BEG ? -start_hpos : 0),
w);
did_motion = 1;
}
struct window *w;
Lisp_Object old_buffer;
struct gcpro gcpro1;
+ int count = SPECPDL_INDEX ();
CHECK_NUMBER (lines);
if (! NILP (window))
XSETBUFFER (w->buffer, current_buffer);
}
- SET_TEXT_POS (pt, PT, PT_BYTE);
- start_display (&it, w, pt);
-
- /* Move to the start of the display line containing PT. If we don't
- do this, we start moving with IT->current_x == 0, while PT is
- really at some x > 0. The effect is, in continuation lines, that
- we end up with the iterator placed at where it thinks X is 0,
- while the end position is really at some X > 0, the same X that
- PT had. */
- move_it_by_lines (&it, 0, 0);
+ /* Don't fontify text that we just move across. */
+ specbind (Qfontification_functions, Qnil);
- if (XINT (lines) != 0)
- move_it_by_lines (&it, XINT (lines), 0);
-
- SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
+ if (noninteractive)
+ {
+ struct position pos;
+ pos = *vmotion (PT, XINT (lines), w);
+ SET_PT_BOTH (pos.bufpos, pos.bytepos);
+ }
+ else
+ {
+ int it_start;
+ int oselective;
+
+ SET_TEXT_POS (pt, PT, PT_BYTE);
+ start_display (&it, w, pt);
+
+ /* Scan from the start of the line containing PT. If we don't
+ do this, we start moving with IT->current_x == 0, while PT is
+ really at some x > 0. The effect is, in continuation lines, that
+ we end up with the iterator placed at where it thinks X is 0,
+ while the end position is really at some X > 0, the same X that
+ PT had. */
+ it_start = IT_CHARPOS (it);
+ reseat_at_previous_visible_line_start (&it);
+ it.current_x = it.hpos = 0;
+ /* Temporarily disable selective display so we don't move too far */
+ oselective = it.selective;
+ it.selective = 0;
+ move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+ it.selective = oselective;
+
+ /* Move back if we got too far. This may happen if
+ truncate-lines is on and PT is beyond right margin. */
+ if (IT_CHARPOS (it) > it_start && XINT (lines) > 0)
+ move_it_by_lines (&it, -1, 0);
+
+ it.vpos = 0;
+ /* Do this even if LINES is 0, so that we move back
+ to the beginning of the current line as we ought. */
+ move_it_by_lines (&it, XINT (lines), 0);
+
+ SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
+ }
if (BUFFERP (old_buffer))
w->buffer = old_buffer;
+ unbind_to (count, Qnil);
RETURN_UNGCPRO (make_number (it.vpos));
}