*** empty log message ***
[bpt/emacs.git] / src / indent.c
CommitLineData
993b6404 1/* Indentation functions.
70ee42f7 2 Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc.
993b6404
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config.h"
22#include "lisp.h"
23#include "buffer.h"
24#include "indent.h"
502b9b64 25#include "frame.h"
993b6404
JB
26#include "window.h"
27#include "termchar.h"
28#include "termopts.h"
29#include "disptab.h"
30
31/* Indentation can insert tabs if this is non-zero;
32 otherwise always uses spaces */
33int indent_tabs_mode;
34
35#define min(a, b) ((a) < (b) ? (a) : (b))
36#define max(a, b) ((a) > (b) ? (a) : (b))
37
38#define CR 015
39
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 */
44int last_known_column;
45/* Value of point when current_column was called */
46int last_known_column_point;
47/* Value of MODIFF when current_column was called */
48int last_known_column_modified;
49
993b6404
JB
50/* Get the display table to use for the current buffer. */
51
52struct Lisp_Vector *
53buffer_display_table ()
54{
55 Lisp_Object thisbuf;
56
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);
64 return 0;
65}
66\f
67DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
68 "Return the horizontal position of point. Beginning of line is column 0.\n\
69This is calculated by adding together the widths of all the displayed\n\
70representations of the character between the start of the previous line\n\
71and point. (eg control characters will have a width of 2 or 4, tabs\n\
72will have a variable width)\n\
502b9b64
JB
73Ignores finite width of frame, which means that this function may return\n\
74values greater than (frame-width).\n\
993b6404
JB
75Whether the line is visible (if `selective-display' is t) has no effect;\n\
76however, ^M is treated as end of line when `selective-display' is t.")
77 ()
78{
79 Lisp_Object temp;
80 XFASTINT (temp) = current_column ();
81 return temp;
82}
83
e74928fc
JB
84/* Cancel any recorded value of the horizontal position. */
85
86invalidate_current_column ()
87{
88 last_known_column_point = 0;
89}
90
993b6404
JB
91int
92current_column ()
93{
94 register int col;
95 register unsigned char *ptr, *stop;
96 register int tab_seen;
97 int post_tab;
98 register int c;
99 register int tab_width = XINT (current_buffer->tab_width);
56a98455 100 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
993b6404
JB
101 register struct Lisp_Vector *dp = buffer_display_table ();
102 int stopchar;
103
104 if (point == last_known_column_point
105 && MODIFF == last_known_column_modified)
106 return last_known_column;
107
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. */
112 if (point == BEGV)
113 stop = ptr;
114 else if (point <= GPT || BEGV > GPT)
115 stop = BEGV_ADDR;
116 else
117 stop = GAP_END_ADDR;
118
119 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
120
121 col = 0, tab_seen = 0, post_tab = 0;
122
123 while (1)
124 {
125 if (ptr == stop)
126 {
127 /* We stopped either for the beginning of the buffer
128 or for the gap. */
129 if (ptr == BEGV_ADDR)
130 break;
131 /* It was the gap. Jump back over it. */
132 stop = BEGV_ADDR;
133 ptr = GPT_ADDR;
134 /* Check whether that brings us to beginning of buffer. */
135 if (BEGV >= GPT) break;
136 }
137
138 c = *--ptr;
139 if (c >= 040 && c < 0177
140 && (dp == 0 || XTYPE (DISP_CHAR_ROPE (dp, c)) != Lisp_String))
141 {
142 col++;
143 }
144 else if (c == '\n')
145 break;
146 else if (c == '\r' && EQ (current_buffer->selective_display, Qt))
147 break;
148 else if (c == '\t')
149 {
150 if (tab_seen)
151 col = ((col + tab_width) / tab_width) * tab_width;
152
153 post_tab += col;
154 col = 0;
155 tab_seen = 1;
156 }
157 else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String)
158 col += XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH);
159 else
160 col += (ctl_arrow && c < 0200) ? 2 : 4;
161 }
162
163 if (tab_seen)
164 {
165 col = ((col + tab_width) / tab_width) * tab_width;
166 col += post_tab;
167 }
168
169 last_known_column = col;
170 last_known_column_point = point;
171 last_known_column_modified = MODIFF;
172
173 return col;
174}
175\f
176
177DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
178 "Indent from point with tabs and spaces until COLUMN is reached.\n\
179Optional second argument MIN says always do at least MIN spaces\n\
180even if that goes past COLUMN; by default, MIN is zero.")
181 (col, minimum)
182 Lisp_Object col, minimum;
183{
184 int mincol;
185 register int fromcol;
186 register int tab_width = XINT (current_buffer->tab_width);
187
188 CHECK_NUMBER (col, 0);
56a98455 189 if (NILP (minimum))
993b6404
JB
190 XFASTINT (minimum) = 0;
191 CHECK_NUMBER (minimum, 1);
192
193 fromcol = current_column ();
194 mincol = fromcol + XINT (minimum);
195 if (mincol < XINT (col)) mincol = XINT (col);
196
197 if (fromcol == mincol)
198 return make_number (mincol);
199
200 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
201
202 if (indent_tabs_mode)
203 {
204 Lisp_Object n;
205 XFASTINT (n) = mincol / tab_width - fromcol / tab_width;
206 if (XFASTINT (n) != 0)
207 {
208 Finsert_char (make_number ('\t'), n);
209
210 fromcol = (mincol / tab_width) * tab_width;
211 }
212 }
213
214 XFASTINT (col) = mincol - fromcol;
215 Finsert_char (make_number (' '), col);
216
217 last_known_column = mincol;
218 last_known_column_point = point;
219 last_known_column_modified = MODIFF;
220
221 XSETINT (col, mincol);
222 return col;
223}
224\f
225DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
226 0, 0, 0,
227 "Return the indentation of the current line.\n\
228This is the horizontal position of the character\n\
229following any initial whitespace.")
230 ()
231{
232 Lisp_Object val;
233
234 XFASTINT (val) = position_indentation (find_next_newline (point, -1));
235 return val;
236}
237
238position_indentation (pos)
239 register int pos;
240{
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;
245
246 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
247
248 stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1;
249 p = &FETCH_CHAR (pos);
250 while (1)
251 {
252 while (p == stop)
253 {
254 if (pos == ZV)
255 return column;
256 pos += p - &FETCH_CHAR (pos);
257 p = &FETCH_CHAR (pos);
258 stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1;
259 }
260 switch (*p++)
261 {
262 case ' ':
263 column++;
264 break;
265 case '\t':
266 column += tab_width - column % tab_width;
267 break;
268 default:
269 return column;
270 }
271 }
272}
273\f
274DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, 0,
275 "Move point to column COLUMN in the current line.\n\
276The column of a character is calculated by adding together the widths\n\
277as displayed of the previous characters in the line.\n\
278This function ignores line-continuation;\n\
279there is no upper limit on the column number a character can have\n\
280and horizontal scrolling has no effect.\n\n\
281If specified column is within a character, point goes after that character.\n\
282If it's past end of line, point goes to end of line.\n\n\
283A non-nil second (optional) argument FORCE means, if the line\n\
284is too short to reach column COLUMN then add spaces/tabs to get there,\n\
285and if COLUMN is in the middle of a tab character, change it to spaces.")
286 (column, force)
287 Lisp_Object column, force;
288{
289 register int pos;
290 register int col = current_column ();
291 register int goal;
292 register int end;
293 register int tab_width = XINT (current_buffer->tab_width);
56a98455 294 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
993b6404
JB
295 register struct Lisp_Vector *dp = buffer_display_table ();
296
297 Lisp_Object val;
298 int prev_col;
299 int c;
300
301 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
302 CHECK_NATNUM (column, 0);
303 goal = XINT (column);
304
305 retry:
306 pos = point;
307 end = ZV;
308
309 /* If we're starting past the desired column,
310 back up to beginning of line and scan from there. */
311 if (col > goal)
312 {
313 pos = find_next_newline (pos, -1);
314 col = 0;
315 }
316
317 while (col < goal && pos < end)
318 {
319 c = FETCH_CHAR (pos);
320 if (c == '\n')
321 break;
322 if (c == '\r' && EQ (current_buffer->selective_display, Qt))
323 break;
324 pos++;
325 if (c == '\t')
326 {
327 prev_col = col;
328 col += tab_width;
329 col = col / tab_width * tab_width;
330 }
331 else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String)
332 col += XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH);
333 else if (ctl_arrow && (c < 040 || c == 0177))
334 col++;
335 else if (c < 040 || c >= 0177)
336 col += 3;
337 else
338 col++;
339 }
340
341 SET_PT (pos);
342
343 /* If a tab char made us overshoot, change it to spaces
344 and scan through it again. */
56a98455 345 if (!NILP (force) && col > goal && c == '\t' && prev_col < goal)
993b6404 346 {
70ee42f7
JB
347 int old_point;
348
993b6404 349 del_range (point - 1, point);
70ee42f7
JB
350 Findent_to (make_number (goal), Qnil);
351 old_point = point;
352 Findent_to (make_number (col), Qnil);
353 SET_PT (old_point);
993b6404
JB
354 }
355
356 /* If line ends prematurely, add space to the end. */
56a98455 357 if (col < goal && !NILP (force))
993b6404
JB
358 Findent_to (make_number (col = goal));
359
360 last_known_column = col;
361 last_known_column_point = point;
362 last_known_column_modified = MODIFF;
363
364 XFASTINT (val) = col;
365 return val;
366}
367\f
368struct position val_compute_motion;
369
370/* Scan the current buffer forward from offset FROM, pretending that
371 this is at line FROMVPOS, column FROMHPOS, until reaching buffer
372 offset TO or line TOVPOS, column TOHPOS (whichever comes first),
373 and return the ending buffer position and screen location.
374
375 WIDTH is the number of columns available to display text;
376 compute_motion uses this to handle continuation lines and such.
377 HSCROLL is the number of columns not being displayed at the left
378 margin; this is usually taken from a window's hscroll member.
a9764248
JB
379 TAB_OFFSET is the number of columns of the first tab that aren't
380 being displayed, perhaps because of a continuation line or
381 something.
993b6404
JB
382
383 compute_motion returns a pointer to a struct position. The bufpos
384 member gives the buffer position at the end of the scan, and hpos
385 and vpos give its cartesian location. I'm not clear on what the
386 other members are.
387
388 For example, to find the buffer position of column COL of line LINE
389 of a certain window, pass the window's starting location as FROM
390 and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
391 Pass the buffer's ZV as TO, to limit the scan to the end of the
392 visible section of the buffer, and pass LINE and COL as TOVPOS and
393 TOHPOS.
394
395 When displaying in window w, a typical formula for WIDTH is:
396
397 window_width - 1
502b9b64 398 - (window_width + window_left != frame_width)
993b6404
JB
399
400 where
401 window_width is XFASTINT (w->width),
402 window_left is XFASTINT (w->left),
502b9b64 403 and frame_width = FRAME_WIDTH (XFRAME (window->frame))
993b6404
JB
404
405 This accounts for the continuation-line backslashes, and the window
406 borders if the window is split vertically. */
407
408struct position *
409compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, tab_offset)
410 int from, fromvpos, fromhpos, to, tovpos, tohpos;
411 register int width;
412 int hscroll, tab_offset;
413{
cde9337b
JB
414 register int hpos = fromhpos;
415 register int vpos = fromvpos;
416
993b6404
JB
417 register int pos;
418 register int c;
419 register int tab_width = XFASTINT (current_buffer->tab_width);
56a98455 420 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
993b6404
JB
421 register struct Lisp_Vector *dp = buffer_display_table ();
422 int selective
423 = XTYPE (current_buffer->selective_display) == Lisp_Int
424 ? XINT (current_buffer->selective_display)
56a98455 425 : !NILP (current_buffer->selective_display) ? -1 : 0;
cde9337b 426 int prev_vpos, prev_hpos;
993b6404
JB
427 int selective_rlen
428 = (selective && dp && XTYPE (DISP_INVIS_ROPE (dp)) == Lisp_String
429 ? XSTRING (DISP_INVIS_ROPE (dp))->size / sizeof (GLYPH) : 0);
430
431 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
cde9337b 432 for (pos = from; pos < to; pos++)
993b6404 433 {
cde9337b
JB
434 /* Stop if past the target screen position. */
435 if (vpos > tovpos
436 || (vpos == tovpos && hpos >= tohpos))
437 break;
438
439 prev_vpos = vpos;
440 prev_hpos = hpos;
441
993b6404
JB
442 c = FETCH_CHAR (pos);
443 if (c >= 040 && c < 0177
444 && (dp == 0 || XTYPE (DISP_CHAR_ROPE (dp, c)) != Lisp_String))
cde9337b 445 hpos++;
993b6404
JB
446 else if (c == '\t')
447 {
cde9337b
JB
448 hpos += tab_width - ((hpos + tab_offset + hscroll - (hscroll > 0)
449 /* Add tab_width here to make sure positive.
450 hpos can be negative after continuation
451 but can't be less than -tab_width. */
452 + tab_width)
453 % tab_width);
993b6404
JB
454 }
455 else if (c == '\n')
456 {
457 if (selective > 0 && position_indentation (pos + 1) >= selective)
458 {
459 /* Skip any number of invisible lines all at once */
460 do
461 {
cde9337b 462 while (++pos < to && FETCH_CHAR (pos) != '\n');
993b6404 463 }
e51eab7c 464 while (pos < to && position_indentation (pos + 1) >= selective);
993b6404
JB
465 pos--;
466 /* Allow for the " ..." that is displayed for them. */
467 if (selective_rlen)
468 {
cde9337b
JB
469 hpos += selective_rlen;
470 if (hpos >= width)
471 hpos = width;
993b6404 472 }
e51eab7c 473 /* We have skipped the invis text, but not the newline after. */
993b6404
JB
474 }
475 else
cde9337b
JB
476 {
477 /* A visible line. */
478 vpos++;
479 hpos = 0;
46947372
JB
480 hpos -= hscroll;
481 if (hscroll > 0) hpos++; /* Count the ! on column 0 */
482 tab_offset = 0;
483 }
993b6404
JB
484 }
485 else if (c == CR && selective < 0)
486 {
487 /* In selective display mode,
488 everything from a ^M to the end of the line is invisible */
cde9337b
JB
489 while (pos < to && FETCH_CHAR (pos) != '\n') pos++;
490 /* Stop *before* the real newline. */
993b6404
JB
491 pos--;
492 /* Allow for the " ..." that is displayed for them. */
493 if (selective_rlen)
494 {
cde9337b
JB
495 hpos += selective_rlen;
496 if (hpos >= width)
497 hpos = width;
993b6404
JB
498 }
499 }
500 else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String)
cde9337b 501 hpos += XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH);
993b6404 502 else
cde9337b 503 hpos += (ctl_arrow && c < 0200) ? 2 : 4;
993b6404 504
cde9337b
JB
505 /* Handle right margin. */
506 if (hpos >= width
507 && (hpos > width
508 || (pos < ZV - 1
993b6404
JB
509 && FETCH_CHAR (pos + 1) != '\n')))
510 {
cde9337b
JB
511 if (vpos > tovpos
512 || (vpos == tovpos && hpos >= tohpos))
993b6404
JB
513 break;
514 if (hscroll
515 || (truncate_partial_width_windows
502b9b64 516 && width + 1 < FRAME_WIDTH (selected_frame))
56a98455 517 || !NILP (current_buffer->truncate_lines))
993b6404 518 {
cde9337b
JB
519 /* Truncating: skip to newline. */
520 while (pos < to && FETCH_CHAR (pos) != '\n') pos++;
993b6404 521 pos--;
e51eab7c 522 hpos = width;
993b6404
JB
523 }
524 else
525 {
cde9337b
JB
526 /* Continuing. */
527 vpos++;
528 hpos -= width;
993b6404
JB
529 tab_offset += width;
530 }
531
532 }
533 }
534
535 val_compute_motion.bufpos = pos;
cde9337b
JB
536 val_compute_motion.hpos = hpos;
537 val_compute_motion.vpos = vpos;
538 val_compute_motion.prevhpos = prev_hpos;
993b6404
JB
539
540 /* Nonzero if have just continued a line */
541 val_compute_motion.contin
cde9337b
JB
542 = (pos != from
543 && (val_compute_motion.vpos != prev_vpos)
544 && c != '\n');
993b6404
JB
545
546 return &val_compute_motion;
547}
993b6404
JB
548
549\f
550/* Return the column of position POS in window W's buffer,
551 rounded down to a multiple of the internal width of W.
552 This is the amount of indentation of position POS
553 that is not visible in its horizontal position in the window. */
554
555int
556pos_tab_offset (w, pos)
557 struct window *w;
558 register int pos;
559{
560 int opoint = point;
561 int col;
562 int width = XFASTINT (w->width) - 1
563 - (XFASTINT (w->width) + XFASTINT (w->left)
502b9b64 564 != FRAME_WIDTH (XFRAME (w->frame)));
993b6404
JB
565
566 if (pos == BEGV || FETCH_CHAR (pos - 1) == '\n')
567 return 0;
568 SET_PT (pos);
569 col = current_column ();
570 SET_PT (opoint);
571 return col - (col % width);
572}
573
574/* start_hpos is the hpos of the first character of the buffer:
575 zero except for the minibuffer window,
576 where it is the width of the prompt. */
577
578struct position val_vmotion;
579
580struct position *
581vmotion (from, vtarget, width, hscroll, window)
582 register int from, vtarget, width;
583 int hscroll;
584 Lisp_Object window;
585{
586 struct position pos;
587 /* vpos is cumulative vertical position, changed as from is changed */
588 register int vpos = 0;
589 register int prevline;
590 register int first;
591 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
592 int selective
593 = XTYPE (current_buffer->selective_display) == Lisp_Int
594 ? XINT (current_buffer->selective_display)
56a98455 595 : !NILP (current_buffer->selective_display) ? -1 : 0;
993b6404
JB
596 int start_hpos = (EQ (window, minibuf_window) ? minibuf_prompt_width : 0);
597
598 retry:
599 if (vtarget > vpos)
600 {
601 /* Moving downward is simple, but must calculate from beg of line
602 to determine hpos of starting point */
603 if (from > BEGV && FETCH_CHAR (from - 1) != '\n')
604 {
605 prevline = find_next_newline (from, -1);
606 while (selective > 0
607 && prevline > BEGV
608 && position_indentation (prevline) >= selective)
609 prevline = find_next_newline (prevline - 1, -1);
610 pos = *compute_motion (prevline, 0,
611 lmargin + (prevline == 1 ? start_hpos : 0),
cde9337b 612 from, 1 << (INTBITS - 2), 0,
993b6404
JB
613 width, hscroll, 0);
614 }
615 else
616 {
617 pos.hpos = lmargin + (from == 1 ? start_hpos : 0);
618 pos.vpos = 0;
619 }
620 return compute_motion (from, vpos, pos.hpos,
cde9337b 621 ZV, vtarget, - (1 << (INTBITS - 2)),
993b6404
JB
622 width, hscroll, pos.vpos * width);
623 }
624
625 /* To move upward, go a line at a time until
626 we have gone at least far enough */
627
628 first = 1;
629
630 while ((vpos > vtarget || first) && from > BEGV)
631 {
632 prevline = from;
633 while (1)
634 {
635 prevline = find_next_newline (prevline - 1, -1);
636 if (prevline == BEGV
637 || selective <= 0
638 || position_indentation (prevline) < selective)
639 break;
640 }
641 pos = *compute_motion (prevline, 0,
642 lmargin + (prevline == 1 ? start_hpos : 0),
cde9337b 643 from, 1 << (INTBITS - 2), 0,
993b6404
JB
644 width, hscroll, 0);
645 vpos -= pos.vpos;
646 first = 0;
647 from = prevline;
648 }
649
650 /* If we made exactly the desired vertical distance,
651 or if we hit beginning of buffer,
652 return point found */
653 if (vpos >= vtarget)
654 {
655 val_vmotion.bufpos = from;
656 val_vmotion.vpos = vpos;
657 val_vmotion.hpos = lmargin;
658 val_vmotion.contin = 0;
659 val_vmotion.prevhpos = 0;
660 return &val_vmotion;
661 }
662
663 /* Otherwise find the correct spot by moving down */
664 goto retry;
665}
666
667DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 1, 0,
668 "Move to start of screen line LINES lines down.\n\
669If LINES is negative, this is moving up.\n\
670Sets point to position found; this may be start of line\n\
671 or just the start of a continuation line.\n\
672Returns number of lines moved; may be closer to zero than LINES\n\
673 if beginning or end of buffer was reached.")
674 (lines)
675 Lisp_Object lines;
676{
677 struct position pos;
678 register struct window *w = XWINDOW (selected_window);
679 int width = XFASTINT (w->width) - 1
680 - (XFASTINT (w->width) + XFASTINT (w->left)
502b9b64 681 != FRAME_WIDTH (XFRAME (w->frame)));
993b6404
JB
682
683 CHECK_NUMBER (lines, 0);
684
685 pos = *vmotion (point, XINT (lines), width,
686 /* Not XFASTINT since perhaps could be negative */
687 XINT (w->hscroll), selected_window);
688
689 SET_PT (pos.bufpos);
690 return make_number (pos.vpos);
691}
692\f
693syms_of_indent ()
694{
695 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
696 "*Indentation can insert tabs if this is non-nil.\n\
697Setting this variable automatically makes it local to the current buffer.");
698 indent_tabs_mode = 1;
699
700 defsubr (&Scurrent_indentation);
701 defsubr (&Sindent_to);
702 defsubr (&Scurrent_column);
703 defsubr (&Smove_to_column);
704 defsubr (&Svertical_motion);
705}