1 /* Indentation functions.
2 Copyright (C) 1985, 1986, 1987, 1988, 1993 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. */
31 /* Indentation can insert tabs if this is non-zero;
32 otherwise always uses spaces */
35 #define min(a, b) ((a) < (b) ? (a) : (b))
36 #define max(a, b) ((a) > (b) ? (a) : (b))
40 /* These three values memoize the current column to avoid recalculation */
41 /* Some things in set last_known_column_point to -1
42 to mark the memoized value as invalid */
43 /* Last value returned by current_column */
44 int last_known_column
;
45 /* Value of point when current_column was called */
46 int last_known_column_point
;
47 /* Value of MODIFF when current_column was called */
48 int last_known_column_modified
;
50 /* Get the display table to use for the current buffer. */
53 buffer_display_table ()
57 thisbuf
= current_buffer
->display_table
;
58 if (XTYPE (thisbuf
) == Lisp_Vector
59 && XVECTOR (thisbuf
)->size
== DISP_TABLE_SIZE
)
60 return XVECTOR (thisbuf
);
61 if (XTYPE (Vstandard_display_table
) == Lisp_Vector
62 && XVECTOR (Vstandard_display_table
)->size
== DISP_TABLE_SIZE
)
63 return XVECTOR (Vstandard_display_table
);
67 DEFUN ("current-column", Fcurrent_column
, Scurrent_column
, 0, 0, 0,
68 "Return the horizontal position of point. Beginning of line is column 0.\n\
69 This is calculated by adding together the widths of all the displayed\n\
70 representations of the character between the start of the previous line\n\
71 and point. (eg control characters will have a width of 2 or 4, tabs\n\
72 will have a variable width)\n\
73 Ignores finite width of frame, which means that this function may return\n\
74 values greater than (frame-width).\n\
75 Whether the line is visible (if `selective-display' is t) has no effect;\n\
76 however, ^M is treated as end of line when `selective-display' is t.")
80 XFASTINT (temp
) = current_column ();
84 /* Cancel any recorded value of the horizontal position. */
86 invalidate_current_column ()
88 last_known_column_point
= 0;
95 register unsigned char *ptr
, *stop
;
96 register int tab_seen
;
99 register int tab_width
= XINT (current_buffer
->tab_width
);
100 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
101 register struct Lisp_Vector
*dp
= buffer_display_table ();
104 if (point
== last_known_column_point
105 && MODIFF
== last_known_column_modified
)
106 return last_known_column
;
108 /* Make a pointer for decrementing through the chars before point. */
109 ptr
= &FETCH_CHAR (point
- 1) + 1;
110 /* Make a pointer to where consecutive chars leave off,
111 going backwards from point. */
114 else if (point
<= GPT
|| BEGV
> GPT
)
119 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
121 col
= 0, tab_seen
= 0, post_tab
= 0;
127 /* We stopped either for the beginning of the buffer
129 if (ptr
== BEGV_ADDR
)
131 /* It was the gap. Jump back over it. */
134 /* Check whether that brings us to beginning of buffer. */
135 if (BEGV
>= GPT
) break;
139 if (c
>= 040 && c
< 0177
140 && (dp
== 0 || XTYPE (DISP_CHAR_VECTOR (dp
, c
)) != Lisp_Vector
))
146 else if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
151 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
157 else if (dp
!= 0 && XTYPE (DISP_CHAR_VECTOR (dp
, c
)) == Lisp_Vector
)
158 col
+= XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
;
160 col
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
165 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
169 last_known_column
= col
;
170 last_known_column_point
= point
;
171 last_known_column_modified
= MODIFF
;
177 DEFUN ("indent-to", Findent_to
, Sindent_to
, 1, 2, "NIndent to column: ",
178 "Indent from point with tabs and spaces until COLUMN is reached.\n\
179 Optional second argument MIN says always do at least MIN spaces\n\
180 even if that goes past COLUMN; by default, MIN is zero.")
182 Lisp_Object col
, minimum
;
185 register int fromcol
;
186 register int tab_width
= XINT (current_buffer
->tab_width
);
188 CHECK_NUMBER (col
, 0);
190 XFASTINT (minimum
) = 0;
191 CHECK_NUMBER (minimum
, 1);
193 fromcol
= current_column ();
194 mincol
= fromcol
+ XINT (minimum
);
195 if (mincol
< XINT (col
)) mincol
= XINT (col
);
197 if (fromcol
== mincol
)
198 return make_number (mincol
);
200 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
202 if (indent_tabs_mode
)
205 XFASTINT (n
) = mincol
/ tab_width
- fromcol
/ tab_width
;
206 if (XFASTINT (n
) != 0)
208 Finsert_char (make_number ('\t'), n
);
210 fromcol
= (mincol
/ tab_width
) * tab_width
;
214 XFASTINT (col
) = mincol
- fromcol
;
215 Finsert_char (make_number (' '), col
);
217 last_known_column
= mincol
;
218 last_known_column_point
= point
;
219 last_known_column_modified
= MODIFF
;
221 XSETINT (col
, mincol
);
225 DEFUN ("current-indentation", Fcurrent_indentation
, Scurrent_indentation
,
227 "Return the indentation of the current line.\n\
228 This is the horizontal position of the character\n\
229 following any initial whitespace.")
234 XFASTINT (val
) = position_indentation (find_next_newline (point
, -1));
238 position_indentation (pos
)
241 register int column
= 0;
242 register int tab_width
= XINT (current_buffer
->tab_width
);
243 register unsigned char *p
;
244 register unsigned char *stop
;
246 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
248 stop
= &FETCH_CHAR (BUFFER_CEILING_OF (pos
)) + 1;
249 p
= &FETCH_CHAR (pos
);
256 pos
+= p
- &FETCH_CHAR (pos
);
257 p
= &FETCH_CHAR (pos
);
258 stop
= &FETCH_CHAR (BUFFER_CEILING_OF (pos
)) + 1;
266 column
+= tab_width
- column
% tab_width
;
274 DEFUN ("move-to-column", Fmove_to_column
, Smove_to_column
, 1, 2, 0,
275 "Move point to column COLUMN in the current line.\n\
276 The column of a character is calculated by adding together the widths\n\
277 as displayed of the previous characters in the line.\n\
278 This function ignores line-continuation;\n\
279 there is no upper limit on the column number a character can have\n\
280 and horizontal scrolling has no effect.\n\
282 If specified column is within a character, point goes after that character.\n\
283 If it's past end of line, point goes to end of line.\n\n\
284 A non-nil second (optional) argument FORCE means, if the line\n\
285 is too short to reach column COLUMN then add spaces/tabs to get there,\n\
286 and if COLUMN is in the middle of a tab character, change it to spaces.")
288 Lisp_Object column
, force
;
291 register int col
= current_column ();
294 register int tab_width
= XINT (current_buffer
->tab_width
);
295 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
296 register struct Lisp_Vector
*dp
= buffer_display_table ();
302 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
303 CHECK_NATNUM (column
, 0);
304 goal
= XINT (column
);
310 /* If we're starting past the desired column,
311 back up to beginning of line and scan from there. */
314 pos
= find_next_newline (pos
, -1);
318 while (col
< goal
&& pos
< end
)
320 c
= FETCH_CHAR (pos
);
323 if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
330 col
= col
/ tab_width
* tab_width
;
332 else if (dp
!= 0 && XTYPE (DISP_CHAR_VECTOR (dp
, c
)) == Lisp_Vector
)
333 col
+= XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
;
334 else if (ctl_arrow
&& (c
< 040 || c
== 0177))
336 else if (c
< 040 || c
>= 0177)
344 /* If a tab char made us overshoot, change it to spaces
345 and scan through it again. */
346 if (!NILP (force
) && col
> goal
&& c
== '\t' && prev_col
< goal
)
350 del_range (point
- 1, point
);
351 Findent_to (make_number (goal
), Qnil
);
353 Findent_to (make_number (col
), Qnil
);
357 /* If line ends prematurely, add space to the end. */
358 if (col
< goal
&& !NILP (force
))
359 Findent_to (make_number (col
= goal
), Qnil
);
361 last_known_column
= col
;
362 last_known_column_point
= point
;
363 last_known_column_modified
= MODIFF
;
365 XFASTINT (val
) = col
;
369 struct position val_compute_motion
;
371 /* Scan the current buffer forward from offset FROM, pretending that
372 this is at line FROMVPOS, column FROMHPOS, until reaching buffer
373 offset TO or line TOVPOS, column TOHPOS (whichever comes first),
374 and return the ending buffer position and screen location.
376 WIDTH is the number of columns available to display text;
377 compute_motion uses this to handle continuation lines and such.
378 HSCROLL is the number of columns not being displayed at the left
379 margin; this is usually taken from a window's hscroll member.
380 TAB_OFFSET is the number of columns of the first tab that aren't
381 being displayed, perhaps because of a continuation line or
384 compute_motion returns a pointer to a struct position. The bufpos
385 member gives the buffer position at the end of the scan, and hpos
386 and vpos give its cartesian location. I'm not clear on what the
389 For example, to find the buffer position of column COL of line LINE
390 of a certain window, pass the window's starting location as FROM
391 and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
392 Pass the buffer's ZV as TO, to limit the scan to the end of the
393 visible section of the buffer, and pass LINE and COL as TOVPOS and
396 When displaying in window w, a typical formula for WIDTH is:
399 - (has_vertical_scroll_bars
400 ? VERTICAL_SCROLL_BAR_WIDTH
401 : (window_width + window_left != frame_width))
404 window_width is XFASTINT (w->width),
405 window_left is XFASTINT (w->left),
406 has_vertical_scroll_bars is
407 FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (WINDOW_FRAME (window)))
408 and frame_width = FRAME_WIDTH (XFRAME (window->frame))
411 window_internal_width (w) - 1
413 The `-1' accounts for the continuation-line backslashes; the rest
414 accounts for window borders if the window is split vertically, and
415 the scroll bars if the frame supports them. */
418 compute_motion (from
, fromvpos
, fromhpos
, to
, tovpos
, tohpos
, width
, hscroll
, tab_offset
)
419 int from
, fromvpos
, fromhpos
, to
, tovpos
, tohpos
;
421 int hscroll
, tab_offset
;
423 register int hpos
= fromhpos
;
424 register int vpos
= fromvpos
;
428 register int tab_width
= XFASTINT (current_buffer
->tab_width
);
429 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
430 register struct Lisp_Vector
*dp
= buffer_display_table ();
432 = XTYPE (current_buffer
->selective_display
) == Lisp_Int
433 ? XINT (current_buffer
->selective_display
)
434 : !NILP (current_buffer
->selective_display
) ? -1 : 0;
435 int prev_vpos
, prev_hpos
;
437 = (selective
&& dp
&& XTYPE (DISP_INVIS_VECTOR (dp
)) == Lisp_Vector
438 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
: 0);
440 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
441 for (pos
= from
; pos
< to
; pos
++)
443 /* Stop if past the target screen position. */
445 || (vpos
== tovpos
&& hpos
>= tohpos
))
451 c
= FETCH_CHAR (pos
);
452 if (c
>= 040 && c
< 0177
453 && (dp
== 0 || XTYPE (DISP_CHAR_VECTOR (dp
, c
)) != Lisp_Vector
))
457 hpos
+= tab_width
- ((hpos
+ tab_offset
+ hscroll
- (hscroll
> 0)
458 /* Add tab_width here to make sure positive.
459 hpos can be negative after continuation
460 but can't be less than -tab_width. */
466 if (selective
> 0 && position_indentation (pos
+ 1) >= selective
)
468 /* Skip any number of invisible lines all at once */
471 while (++pos
< to
&& FETCH_CHAR (pos
) != '\n');
473 while (pos
< to
&& position_indentation (pos
+ 1) >= selective
);
475 /* Allow for the " ..." that is displayed for them. */
478 hpos
+= selective_rlen
;
482 /* We have skipped the invis text, but not the newline after. */
486 /* A visible line. */
490 if (hscroll
> 0) hpos
++; /* Count the ! on column 0 */
494 else if (c
== CR
&& selective
< 0)
496 /* In selective display mode,
497 everything from a ^M to the end of the line is invisible */
498 while (pos
< to
&& FETCH_CHAR (pos
) != '\n') pos
++;
499 /* Stop *before* the real newline. */
501 /* Allow for the " ..." that is displayed for them. */
504 hpos
+= selective_rlen
;
509 else if (dp
!= 0 && XTYPE (DISP_CHAR_VECTOR (dp
, c
)) == Lisp_Vector
)
510 hpos
+= XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
;
512 hpos
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
514 /* Handle right margin. */
518 && FETCH_CHAR (pos
+ 1) != '\n')))
521 || (vpos
== tovpos
&& hpos
>= tohpos
))
524 || (truncate_partial_width_windows
525 && width
+ 1 < FRAME_WIDTH (selected_frame
))
526 || !NILP (current_buffer
->truncate_lines
))
528 /* Truncating: skip to newline. */
529 while (pos
< to
&& FETCH_CHAR (pos
) != '\n') pos
++;
544 val_compute_motion
.bufpos
= pos
;
545 val_compute_motion
.hpos
= hpos
;
546 val_compute_motion
.vpos
= vpos
;
547 val_compute_motion
.prevhpos
= prev_hpos
;
549 /* Nonzero if have just continued a line */
550 val_compute_motion
.contin
552 && (val_compute_motion
.vpos
!= prev_vpos
)
555 return &val_compute_motion
;
559 /* Return the column of position POS in window W's buffer,
560 rounded down to a multiple of the internal width of W.
561 This is the amount of indentation of position POS
562 that is not visible in its horizontal position in the window. */
565 pos_tab_offset (w
, pos
)
571 int width
= window_internal_width (w
) - 1;
573 if (pos
== BEGV
|| FETCH_CHAR (pos
- 1) == '\n')
576 col
= current_column ();
578 return col
- (col
% width
);
581 /* start_hpos is the hpos of the first character of the buffer:
582 zero except for the minibuffer window,
583 where it is the width of the prompt. */
585 struct position val_vmotion
;
588 vmotion (from
, vtarget
, width
, hscroll
, window
)
589 register int from
, vtarget
, width
;
594 /* vpos is cumulative vertical position, changed as from is changed */
595 register int vpos
= 0;
596 register int prevline
;
598 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
600 = XTYPE (current_buffer
->selective_display
) == Lisp_Int
601 ? XINT (current_buffer
->selective_display
)
602 : !NILP (current_buffer
->selective_display
) ? -1 : 0;
603 int start_hpos
= (EQ (window
, minibuf_window
) ? minibuf_prompt_width
: 0);
608 /* Moving downward is simple, but must calculate from beg of line
609 to determine hpos of starting point */
610 if (from
> BEGV
&& FETCH_CHAR (from
- 1) != '\n')
612 prevline
= find_next_newline (from
, -1);
615 && position_indentation (prevline
) >= selective
)
616 prevline
= find_next_newline (prevline
- 1, -1);
617 pos
= *compute_motion (prevline
, 0,
618 lmargin
+ (prevline
== 1 ? start_hpos
: 0),
619 from
, 1 << (INTBITS
- 2), 0,
624 pos
.hpos
= lmargin
+ (from
== 1 ? start_hpos
: 0);
627 return compute_motion (from
, vpos
, pos
.hpos
,
628 ZV
, vtarget
, - (1 << (INTBITS
- 2)),
629 width
, hscroll
, pos
.vpos
* width
);
632 /* To move upward, go a line at a time until
633 we have gone at least far enough */
637 while ((vpos
> vtarget
|| first
) && from
> BEGV
)
642 prevline
= find_next_newline (prevline
- 1, -1);
645 || position_indentation (prevline
) < selective
)
648 pos
= *compute_motion (prevline
, 0,
649 lmargin
+ (prevline
== 1 ? start_hpos
: 0),
650 from
, 1 << (INTBITS
- 2), 0,
657 /* If we made exactly the desired vertical distance,
658 or if we hit beginning of buffer,
659 return point found */
662 val_vmotion
.bufpos
= from
;
663 val_vmotion
.vpos
= vpos
;
664 val_vmotion
.hpos
= lmargin
;
665 val_vmotion
.contin
= 0;
666 val_vmotion
.prevhpos
= 0;
670 /* Otherwise find the correct spot by moving down */
674 DEFUN ("vertical-motion", Fvertical_motion
, Svertical_motion
, 1, 1, 0,
675 "Move to start of screen line LINES lines down.\n\
676 If LINES is negative, this is moving up.\n\
677 Sets point to position found; this may be start of line\n\
678 or just the start of a continuation line.\n\
679 Returns number of lines moved; may be closer to zero than LINES\n\
680 if beginning or end of buffer was reached.")
685 register struct window
*w
= XWINDOW (selected_window
);
686 int width
= window_internal_width (w
) - 1;
688 CHECK_NUMBER (lines
, 0);
690 pos
= *vmotion (point
, XINT (lines
), width
,
691 /* Not XFASTINT since perhaps could be negative */
692 XINT (w
->hscroll
), selected_window
);
695 return make_number (pos
.vpos
);
700 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode
,
701 "*Indentation can insert tabs if this is non-nil.\n\
702 Setting this variable automatically makes it local to the current buffer.");
703 indent_tabs_mode
= 1;
705 defsubr (&Scurrent_indentation
);
706 defsubr (&Sindent_to
);
707 defsubr (&Scurrent_column
);
708 defsubr (&Smove_to_column
);
709 defsubr (&Svertical_motion
);