1 /* Indentation functions.
2 Copyright (C) 1985,86,87,88,93,94 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
30 #include "intervals.h"
32 /* Indentation can insert tabs if this is non-zero;
33 otherwise always uses spaces */
36 #define min(a, b) ((a) < (b) ? (a) : (b))
37 #define max(a, b) ((a) > (b) ? (a) : (b))
41 /* These three values memoize the current column to avoid recalculation */
42 /* Some things in set last_known_column_point to -1
43 to mark the memoized value as invalid */
44 /* Last value returned by current_column */
45 int last_known_column
;
46 /* Value of point when current_column was called */
47 int last_known_column_point
;
48 /* Value of MODIFF when current_column was called */
49 int last_known_column_modified
;
51 /* Get the display table to use for the current buffer. */
54 buffer_display_table ()
58 thisbuf
= current_buffer
->display_table
;
59 if (XTYPE (thisbuf
) == Lisp_Vector
60 && XVECTOR (thisbuf
)->size
== DISP_TABLE_SIZE
)
61 return XVECTOR (thisbuf
);
62 if (XTYPE (Vstandard_display_table
) == Lisp_Vector
63 && XVECTOR (Vstandard_display_table
)->size
== DISP_TABLE_SIZE
)
64 return XVECTOR (Vstandard_display_table
);
68 DEFUN ("current-column", Fcurrent_column
, Scurrent_column
, 0, 0, 0,
69 "Return the horizontal position of point. Beginning of line is column 0.\n\
70 This is calculated by adding together the widths of all the displayed\n\
71 representations of the character between the start of the previous line\n\
72 and point. (eg control characters will have a width of 2 or 4, tabs\n\
73 will have a variable width)\n\
74 Ignores finite width of frame, which means that this function may return\n\
75 values greater than (frame-width).\n\
76 Whether the line is visible (if `selective-display' is t) has no effect;\n\
77 however, ^M is treated as end of line when `selective-display' is t.")
81 XFASTINT (temp
) = current_column ();
85 /* Cancel any recorded value of the horizontal position. */
87 invalidate_current_column ()
89 last_known_column_point
= 0;
96 register unsigned char *ptr
, *stop
;
97 register int tab_seen
;
100 register int tab_width
= XINT (current_buffer
->tab_width
);
101 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
102 register struct Lisp_Vector
*dp
= buffer_display_table ();
105 if (point
== last_known_column_point
106 && MODIFF
== last_known_column_modified
)
107 return last_known_column
;
109 /* Make a pointer for decrementing through the chars before point. */
110 ptr
= &FETCH_CHAR (point
- 1) + 1;
111 /* Make a pointer to where consecutive chars leave off,
112 going backwards from point. */
115 else if (point
<= GPT
|| BEGV
> GPT
)
120 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
122 col
= 0, tab_seen
= 0, post_tab
= 0;
128 /* We stopped either for the beginning of the buffer
130 if (ptr
== BEGV_ADDR
)
132 /* It was the gap. Jump back over it. */
135 /* Check whether that brings us to beginning of buffer. */
136 if (BEGV
>= GPT
) break;
140 if (c
>= 040 && c
< 0177
141 && (dp
== 0 || XTYPE (DISP_CHAR_VECTOR (dp
, c
)) != Lisp_Vector
))
147 else if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
152 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
158 else if (dp
!= 0 && XTYPE (DISP_CHAR_VECTOR (dp
, c
)) == Lisp_Vector
)
159 col
+= XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
;
161 col
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
166 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
170 last_known_column
= col
;
171 last_known_column_point
= point
;
172 last_known_column_modified
= MODIFF
;
178 DEFUN ("indent-to", Findent_to
, Sindent_to
, 1, 2, "NIndent to column: ",
179 "Indent from point with tabs and spaces until COLUMN is reached.\n\
180 Optional second argument MIN says always do at least MIN spaces\n\
181 even if that goes past COLUMN; by default, MIN is zero.")
183 Lisp_Object col
, minimum
;
186 register int fromcol
;
187 register int tab_width
= XINT (current_buffer
->tab_width
);
189 CHECK_NUMBER (col
, 0);
191 XFASTINT (minimum
) = 0;
192 CHECK_NUMBER (minimum
, 1);
194 fromcol
= current_column ();
195 mincol
= fromcol
+ XINT (minimum
);
196 if (mincol
< XINT (col
)) mincol
= XINT (col
);
198 if (fromcol
== mincol
)
199 return make_number (mincol
);
201 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
203 if (indent_tabs_mode
)
206 XFASTINT (n
) = mincol
/ tab_width
- fromcol
/ tab_width
;
207 if (XFASTINT (n
) != 0)
209 Finsert_char (make_number ('\t'), n
, Qt
);
211 fromcol
= (mincol
/ tab_width
) * tab_width
;
215 XFASTINT (col
) = mincol
- fromcol
;
216 Finsert_char (make_number (' '), col
, Qt
);
218 last_known_column
= mincol
;
219 last_known_column_point
= point
;
220 last_known_column_modified
= MODIFF
;
222 XSETINT (col
, mincol
);
226 DEFUN ("current-indentation", Fcurrent_indentation
, Scurrent_indentation
,
228 "Return the indentation of the current line.\n\
229 This is the horizontal position of the character\n\
230 following any initial whitespace.")
235 XFASTINT (val
) = position_indentation (find_next_newline (point
, -1));
239 position_indentation (pos
)
242 register int column
= 0;
243 register int tab_width
= XINT (current_buffer
->tab_width
);
244 register unsigned char *p
;
245 register unsigned char *stop
;
247 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
249 stop
= &FETCH_CHAR (BUFFER_CEILING_OF (pos
)) + 1;
250 p
= &FETCH_CHAR (pos
);
257 pos
+= p
- &FETCH_CHAR (pos
);
258 p
= &FETCH_CHAR (pos
);
259 stop
= &FETCH_CHAR (BUFFER_CEILING_OF (pos
)) + 1;
267 column
+= tab_width
- column
% tab_width
;
275 /* Test whether the line beginning at POS is indented beyond COLUMN.
276 Blank lines are treated as if they had the same indentation as the
279 indented_beyond_p (pos
, column
)
282 while (pos
> BEGV
&& FETCH_CHAR (pos
) == '\n')
283 pos
= find_next_newline_no_quit (pos
- 1, -1);
284 return (position_indentation (pos
) >= column
);
287 DEFUN ("move-to-column", Fmove_to_column
, Smove_to_column
, 1, 2, 0,
288 "Move point to column COLUMN in the current line.\n\
289 The column of a character is calculated by adding together the widths\n\
290 as displayed of the previous characters in the line.\n\
291 This function ignores line-continuation;\n\
292 there is no upper limit on the column number a character can have\n\
293 and horizontal scrolling has no effect.\n\
295 If specified column is within a character, point goes after that character.\n\
296 If it's past end of line, point goes to end of line.\n\n\
297 A non-nil second (optional) argument FORCE means, if the line\n\
298 is too short to reach column COLUMN then add spaces/tabs to get there,\n\
299 and if COLUMN is in the middle of a tab character, change it to spaces.")
301 Lisp_Object column
, force
;
304 register int col
= current_column ();
307 register int tab_width
= XINT (current_buffer
->tab_width
);
308 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
309 register struct Lisp_Vector
*dp
= buffer_display_table ();
315 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
316 CHECK_NATNUM (column
, 0);
317 goal
= XINT (column
);
323 /* If we're starting past the desired column,
324 back up to beginning of line and scan from there. */
327 pos
= find_next_newline (pos
, -1);
331 while (col
< goal
&& pos
< end
)
333 c
= FETCH_CHAR (pos
);
336 if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
343 col
= col
/ tab_width
* tab_width
;
345 else if (dp
!= 0 && XTYPE (DISP_CHAR_VECTOR (dp
, c
)) == Lisp_Vector
)
346 col
+= XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
;
347 else if (ctl_arrow
&& (c
< 040 || c
== 0177))
349 else if (c
< 040 || c
>= 0177)
357 /* If a tab char made us overshoot, change it to spaces
358 and scan through it again. */
359 if (!NILP (force
) && col
> goal
&& c
== '\t' && prev_col
< goal
)
363 del_range (point
- 1, point
);
364 Findent_to (make_number (goal
), Qnil
);
366 Findent_to (make_number (col
), Qnil
);
368 /* Set the last_known... vars consistently. */
372 /* If line ends prematurely, add space to the end. */
373 if (col
< goal
&& !NILP (force
))
374 Findent_to (make_number (col
= goal
), Qnil
);
376 last_known_column
= col
;
377 last_known_column_point
= point
;
378 last_known_column_modified
= MODIFF
;
380 XFASTINT (val
) = col
;
384 struct position val_compute_motion
;
386 /* Scan the current buffer forward from offset FROM, pretending that
387 this is at line FROMVPOS, column FROMHPOS, until reaching buffer
388 offset TO or line TOVPOS, column TOHPOS (whichever comes first),
389 and return the ending buffer position and screen location.
391 WIDTH is the number of columns available to display text;
392 compute_motion uses this to handle continuation lines and such.
393 HSCROLL is the number of columns not being displayed at the left
394 margin; this is usually taken from a window's hscroll member.
395 TAB_OFFSET is the number of columns of the first tab that aren't
396 being displayed, perhaps because of a continuation line or
399 compute_motion returns a pointer to a struct position. The bufpos
400 member gives the buffer position at the end of the scan, and hpos
401 and vpos give its cartesian location. I'm not clear on what the
404 Note that FROMHPOS and TOHPOS should be expressed in real screen
405 columns, taking HSCROLL and the truncation glyph at the left margin
406 into account. That is, beginning-of-line moves you to the hpos
407 -HSCROLL + (HSCROLL > 0).
409 For example, to find the buffer position of column COL of line LINE
410 of a certain window, pass the window's starting location as FROM
411 and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
412 Pass the buffer's ZV as TO, to limit the scan to the end of the
413 visible section of the buffer, and pass LINE and COL as TOVPOS and
416 When displaying in window w, a typical formula for WIDTH is:
419 - (has_vertical_scroll_bars
420 ? FRAME_SCROLL_BAR_COLS (XFRAME (window->frame))
421 : (window_width + window_left != frame_width))
424 window_width is XFASTINT (w->width),
425 window_left is XFASTINT (w->left),
426 has_vertical_scroll_bars is
427 FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (WINDOW_FRAME (window)))
428 and frame_width = FRAME_WIDTH (XFRAME (window->frame))
430 Or you can let window_internal_width do this all for you, and write:
431 window_internal_width (w) - 1
433 The `-1' accounts for the continuation-line backslashes; the rest
434 accounts for window borders if the window is split horizontally, and
435 the scroll bars if they are turned on. */
438 compute_motion (from
, fromvpos
, fromhpos
, to
, tovpos
, tohpos
, width
, hscroll
, tab_offset
, win
)
439 int from
, fromvpos
, fromhpos
, to
, tovpos
, tohpos
;
441 int hscroll
, tab_offset
;
444 register int hpos
= fromhpos
;
445 register int vpos
= fromvpos
;
449 register int tab_width
= XFASTINT (current_buffer
->tab_width
);
450 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
451 register struct Lisp_Vector
*dp
= window_display_table (win
);
453 = (XTYPE (current_buffer
->selective_display
) == Lisp_Int
454 ? XINT (current_buffer
->selective_display
)
455 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
456 int prev_vpos
, prev_hpos
= 0;
458 = (selective
&& dp
&& XTYPE (DISP_INVIS_VECTOR (dp
)) == Lisp_Vector
459 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
: 0);
460 #ifdef USE_TEXT_PROPERTIES
461 /* The next location where the `invisible' property changes */
462 int next_invisible
= from
;
463 Lisp_Object prop
, position
;
466 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
467 for (pos
= from
; pos
< to
; pos
++)
469 /* Stop if past the target screen position. */
471 || (vpos
== tovpos
&& hpos
>= tohpos
))
477 #ifdef USE_TEXT_PROPERTIES
478 /* if the `invisible' property is set, we can skip to
479 the next property change */
480 while (pos
== next_invisible
&& pos
< to
)
482 XFASTINT (position
) = pos
;
483 prop
= Fget_char_property (position
,
487 Lisp_Object end
, limit
;
489 recenter_overlay_lists (current_buffer
, pos
);
490 /* This is just an estimate to give reasonable
491 performance; nothing should go wrong if it is too small. */
492 limit
= Fnext_overlay_change (position
);
493 if (XFASTINT (limit
) > pos
+ 100)
494 XFASTINT (limit
) = pos
+ 100;
495 end
= Fnext_single_property_change (position
, Qinvisible
,
496 Fcurrent_buffer (), limit
);
498 next_invisible
= XINT (end
);
502 pos
= next_invisible
;
508 c
= FETCH_CHAR (pos
);
509 if (c
>= 040 && c
< 0177
510 && (dp
== 0 || XTYPE (DISP_CHAR_VECTOR (dp
, c
)) != Lisp_Vector
))
514 hpos
+= tab_width
- ((hpos
+ tab_offset
+ hscroll
- (hscroll
> 0)
515 /* Add tab_width here to make sure positive.
516 hpos can be negative after continuation
517 but can't be less than -tab_width. */
523 if (selective
> 0 && indented_beyond_p (pos
+ 1, selective
))
525 /* Skip any number of invisible lines all at once */
528 while (++pos
< to
&& FETCH_CHAR (pos
) != '\n');
530 while (pos
< to
&& indented_beyond_p (pos
+ 1, selective
));
531 pos
--; /* Reread the newline on the next pass. */
532 /* Allow for the " ..." that is displayed for them. */
535 hpos
+= selective_rlen
;
539 /* We have skipped the invis text, but not the newline after. */
543 /* A visible line. */
547 if (hscroll
> 0) hpos
++; /* Truncation glyph on column 0 */
551 else if (c
== CR
&& selective
< 0)
553 /* In selective display mode,
554 everything from a ^M to the end of the line is invisible */
555 while (pos
< to
&& FETCH_CHAR (pos
) != '\n') pos
++;
556 /* Stop *before* the real newline. */
558 /* Allow for the " ..." that is displayed for them. */
561 hpos
+= selective_rlen
;
566 else if (dp
!= 0 && XTYPE (DISP_CHAR_VECTOR (dp
, c
)) == Lisp_Vector
)
567 hpos
+= XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
;
569 hpos
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
571 /* Handle right margin. */
575 && FETCH_CHAR (pos
+ 1) != '\n')))
578 || (vpos
== tovpos
&& hpos
>= tohpos
))
581 || (truncate_partial_width_windows
582 && width
+ 1 < FRAME_WIDTH (XFRAME (WINDOW_FRAME (win
))))
583 || !NILP (current_buffer
->truncate_lines
))
585 /* Truncating: skip to newline. */
586 while (pos
< to
&& FETCH_CHAR (pos
) != '\n') pos
++;
601 val_compute_motion
.bufpos
= pos
;
602 val_compute_motion
.hpos
= hpos
;
603 val_compute_motion
.vpos
= vpos
;
604 val_compute_motion
.prevhpos
= prev_hpos
;
606 /* Nonzero if have just continued a line */
607 val_compute_motion
.contin
609 && (val_compute_motion
.vpos
!= prev_vpos
)
612 return &val_compute_motion
;
615 #if 0 /* The doc string is too long for some compilers,
616 but make-docfile can find it in this comment. */
617 DEFUN ("compute-motion", Ffoo
, Sfoo
, 7, 7, 0,
618 "Scan through the current buffer, calculating screen position.\n\
619 Scan the current buffer forward from offset FROM,\n\
620 assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--\n\
621 to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--\n\
622 and return the ending buffer position and screen location.\n\
624 There are three additional arguments:\n\
626 WIDTH is the number of columns available to display text;\n\
627 this affects handling of continuation lines.\n\
628 This is usually the value returned by `window-width', less one (to allow\n\
629 for the continuation glyph).\n\
631 OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).\n\
632 HSCROLL is the number of columns not being displayed at the left\n\
633 margin; this is usually taken from a window's hscroll member.\n\
634 TAB-OFFSET is the number of columns of the first tab that aren't\n\
635 being displayed, perhaps because the line was continued within it.\n\
636 If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.\n\
638 WINDOW is the window to operate on. Currently this is used only to\n\
639 find the display table. It does not matter what buffer WINDOW displays;\n\
640 `compute-motion' always operates on the current buffer.\n\
642 The value is a list of five elements:\n\
643 (POS HPOS VPOS PREVHPOS CONTIN)\n\
644 POS is the buffer position where the scan stopped.\n\
645 VPOS is the vertical position where the scan stopped.\n\
646 HPOS is the horizontal position where the scan stopped.\n\
648 PREVHPOS is the horizontal position one character back from POS.\n\
649 CONTIN is t if a line was continued after (or within) the previous character.\n\
651 For example, to find the buffer position of column COL of line LINE\n\
652 of a certain window, pass the window's starting location as FROM\n\
653 and the window's upper-left coordinates as FROMPOS.\n\
654 Pass the buffer's (point-max) as TO, to limit the scan to the end of the\n\
655 visible section of the buffer, and pass LINE and COL as TOPOS.")
656 (from
, frompos
, to
, topos
, width
, offsets
, window
)
659 DEFUN ("compute-motion", Fcompute_motion
, Scompute_motion
, 7, 7, 0,
661 (from
, frompos
, to
, topos
, width
, offsets
, window
)
662 Lisp_Object from
, frompos
, to
, topos
;
663 Lisp_Object width
, offsets
, window
;
665 Lisp_Object bufpos
, hpos
, vpos
, prevhpos
, contin
;
666 struct position
*pos
;
667 int hscroll
, tab_offset
;
669 CHECK_NUMBER_COERCE_MARKER (from
, 0);
670 CHECK_CONS (frompos
, 0);
671 CHECK_NUMBER (XCONS (frompos
)->car
, 0);
672 CHECK_NUMBER (XCONS (frompos
)->cdr
, 0);
673 CHECK_NUMBER_COERCE_MARKER (to
, 0);
674 CHECK_CONS (topos
, 0);
675 CHECK_NUMBER (XCONS (topos
)->car
, 0);
676 CHECK_NUMBER (XCONS (topos
)->cdr
, 0);
677 CHECK_NUMBER (width
, 0);
680 CHECK_CONS (offsets
, 0);
681 CHECK_NUMBER (XCONS (offsets
)->car
, 0);
682 CHECK_NUMBER (XCONS (offsets
)->cdr
, 0);
683 hscroll
= XINT (XCONS (offsets
)->car
);
684 tab_offset
= XINT (XCONS (offsets
)->cdr
);
687 hscroll
= tab_offset
= 0;
690 window
= Fselected_window ();
692 CHECK_LIVE_WINDOW (window
, 0);
694 pos
= compute_motion (XINT (from
), XINT (XCONS (frompos
)->cdr
),
695 XINT (XCONS (frompos
)->car
),
696 XINT (to
), XINT (XCONS (topos
)->cdr
),
697 XINT (XCONS (topos
)->car
),
698 XINT (width
), hscroll
, tab_offset
,
701 XFASTINT (bufpos
) = pos
->bufpos
;
702 XSET (hpos
, Lisp_Int
, pos
->hpos
);
703 XSET (vpos
, Lisp_Int
, pos
->vpos
);
704 XSET (prevhpos
, Lisp_Int
, pos
->prevhpos
);
706 return Fcons (bufpos
,
710 Fcons (pos
->contin
? Qt
: Qnil
, Qnil
)))));
714 /* Return the column of position POS in window W's buffer,
715 rounded down to a multiple of the internal width of W.
716 This is the amount of indentation of position POS
717 that is not visible in its horizontal position in the window. */
720 pos_tab_offset (w
, pos
)
726 int width
= window_internal_width (w
) - 1;
728 if (pos
== BEGV
|| FETCH_CHAR (pos
- 1) == '\n')
731 col
= current_column ();
732 TEMP_SET_PT (opoint
);
733 return col
- (col
% width
);
736 /* start_hpos is the hpos of the first character of the buffer:
737 zero except for the minibuffer window,
738 where it is the width of the prompt. */
740 struct position val_vmotion
;
743 vmotion (from
, vtarget
, width
, hscroll
, window
)
744 register int from
, vtarget
, width
;
749 /* vpos is cumulative vertical position, changed as from is changed */
750 register int vpos
= 0;
751 Lisp_Object prevline
;
753 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
755 = XTYPE (current_buffer
->selective_display
) == Lisp_Int
756 ? XINT (current_buffer
->selective_display
)
757 : !NILP (current_buffer
->selective_display
) ? -1 : 0;
758 /* The omission of the clause
759 && marker_position (XWINDOW (window)->start) == BEG
760 here is deliberate; I think we want to measure from the prompt
761 position even if the minibuffer window has scrolled. */
762 int start_hpos
= (EQ (window
, minibuf_window
) ? minibuf_prompt_width
: 0);
767 /* Moving downward is simple, but must calculate from beg of line
768 to determine hpos of starting point */
769 if (from
> BEGV
&& FETCH_CHAR (from
- 1) != '\n')
771 XFASTINT (prevline
) = find_next_newline_no_quit (from
, -1);
772 while (XFASTINT (prevline
) > BEGV
774 && indented_beyond_p (XFASTINT (prevline
), selective
))
775 #ifdef USE_TEXT_PROPERTIES
776 /* watch out for newlines with `invisible' property */
777 || ! NILP (Fget_char_property (prevline
,
783 = find_next_newline_no_quit (XFASTINT (prevline
) - 1, -1);
784 pos
= *compute_motion (XFASTINT (prevline
), 0,
785 lmargin
+ (XFASTINT (prevline
) == 1
787 from
, 1 << (INTBITS
- 2), 0,
788 width
, hscroll
, 0, XWINDOW (window
));
792 pos
.hpos
= lmargin
+ (from
== 1 ? start_hpos
: 0);
795 return compute_motion (from
, vpos
, pos
.hpos
,
796 ZV
, vtarget
, - (1 << (INTBITS
- 2)),
797 width
, hscroll
, pos
.vpos
* width
,
801 /* To move upward, go a line at a time until
802 we have gone at least far enough */
806 while ((vpos
> vtarget
|| first
) && from
> BEGV
)
808 XFASTINT (prevline
) = from
;
812 = find_next_newline_no_quit (XFASTINT (prevline
) - 1, -1);
813 if (XFASTINT (prevline
) == BEGV
815 || ! indented_beyond_p (XFASTINT (prevline
), selective
))
816 #ifdef USE_TEXT_PROPERTIES
817 /* watch out for newlines with `invisible' property */
818 && NILP (Fget_char_property (prevline
, Qinvisible
, window
))
823 pos
= *compute_motion (XFASTINT (prevline
), 0,
824 lmargin
+ (XFASTINT (prevline
) == 1
826 from
, 1 << (INTBITS
- 2), 0,
827 width
, hscroll
, 0, XWINDOW (window
));
830 from
= XFASTINT (prevline
);
833 /* If we made exactly the desired vertical distance,
834 or if we hit beginning of buffer,
835 return point found */
838 val_vmotion
.bufpos
= from
;
839 val_vmotion
.vpos
= vpos
;
840 val_vmotion
.hpos
= lmargin
;
841 val_vmotion
.contin
= 0;
842 val_vmotion
.prevhpos
= 0;
846 /* Otherwise find the correct spot by moving down */
850 DEFUN ("vertical-motion", Fvertical_motion
, Svertical_motion
, 1, 2, 0,
851 "Move to start of screen line LINES lines down.\n\
852 If LINES is negative, this is moving up.\n\
854 The optional second argument WINDOW specifies the window to use for\n\
855 parameters such as width, horizontal scrolling, and so on.\n\
856 the default is the selected window.\n\
857 It does not matter what buffer is displayed in WINDOW.\n\
858 `vertical-motion' always uses the current buffer.\n\
860 Sets point to position found; this may be start of line\n\
861 or just the start of a continuation line.\n\
862 Returns number of lines moved; may be closer to zero than LINES\n\
863 if beginning or end of buffer was reached.")
865 Lisp_Object lines
, window
;
868 register struct window
*w
;
870 CHECK_NUMBER (lines
, 0);
872 CHECK_WINDOW (window
, 0);
874 window
= selected_window
;
876 w
= XWINDOW (window
);
878 pos
= *vmotion (point
, XINT (lines
), window_internal_width (w
) - 1,
879 /* Not XFASTINT since perhaps could be negative */
880 XINT (w
->hscroll
), window
);
883 return make_number (pos
.vpos
);
888 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode
,
889 "*Indentation can insert tabs if this is non-nil.\n\
890 Setting this variable automatically makes it local to the current buffer.");
891 indent_tabs_mode
= 1;
893 defsubr (&Scurrent_indentation
);
894 defsubr (&Sindent_to
);
895 defsubr (&Scurrent_column
);
896 defsubr (&Smove_to_column
);
897 defsubr (&Svertical_motion
);
898 defsubr (&Scompute_motion
);