(Fhandle_switch_frame, Fset_frame_height): Harmonize arguments with
[bpt/emacs.git] / src / indent.c
CommitLineData
993b6404 1/* Indentation functions.
2ff4775b 2 Copyright (C) 1985,86,87,88,93,94,95 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
7c938215 8the Free Software Foundation; either version 2, or (at your option)
993b6404
JB
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
18160b98 21#include <config.h>
993b6404
JB
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"
5a05d3d2 30#include "intervals.h"
0aa01123 31#include "region-cache.h"
993b6404
JB
32
33/* Indentation can insert tabs if this is non-zero;
34 otherwise always uses spaces */
35int indent_tabs_mode;
36
37#define min(a, b) ((a) < (b) ? (a) : (b))
38#define max(a, b) ((a) > (b) ? (a) : (b))
39
40#define CR 015
41
42/* These three values memoize the current column to avoid recalculation */
43/* Some things in set last_known_column_point to -1
44 to mark the memoized value as invalid */
45/* Last value returned by current_column */
46int last_known_column;
47/* Value of point when current_column was called */
48int last_known_column_point;
49/* Value of MODIFF when current_column was called */
50int last_known_column_modified;
51
993b6404
JB
52/* Get the display table to use for the current buffer. */
53
d44f12b4 54struct Lisp_Char_Table *
993b6404
JB
55buffer_display_table ()
56{
57 Lisp_Object thisbuf;
58
59 thisbuf = current_buffer->display_table;
d44f12b4
RS
60 if (DISP_TABLE_P (thisbuf))
61 return XCHAR_TABLE (thisbuf);
62 if (DISP_TABLE_P (Vstandard_display_table))
63 return XCHAR_TABLE (Vstandard_display_table);
993b6404
JB
64 return 0;
65}
66\f
0aa01123
JB
67/* Width run cache considerations. */
68
69/* Return the width of character C under display table DP. */
f845b8b2 70
0aa01123
JB
71static int
72character_width (c, dp)
73 int c;
d44f12b4 74 struct Lisp_Char_Table *dp;
0aa01123
JB
75{
76 Lisp_Object elt;
77
78 /* These width computations were determined by examining the cases
79 in display_text_line. */
80
f845b8b2 81 /* Everything can be handled by the display table, if it's
0aa01123 82 present and the element is right. */
f845b8b2 83 if (dp && (elt = DISP_CHAR_VECTOR (dp, c), VECTORP (elt)))
0aa01123
JB
84 return XVECTOR (elt)->size;
85
f845b8b2
RS
86 /* Some characters are special. */
87 if (c == '\n' || c == '\t' || c == '\015')
88 return 0;
89
90 /* Printing characters have width 1. */
0aa01123
JB
91 else if (c >= 040 && c < 0177)
92 return 1;
93
94 /* Everybody else (control characters, metacharacters) has other
95 widths. We could return their actual widths here, but they
96 depend on things like ctl_arrow and crud like that, and they're
97 not very common at all. So we'll just claim we don't know their
98 widths. */
99 else
100 return 0;
101}
102
103/* Return true iff the display table DISPTAB specifies the same widths
104 for characters as WIDTHTAB. We use this to decide when to
105 invalidate the buffer's width_run_cache. */
106int
107disptab_matches_widthtab (disptab, widthtab)
d44f12b4 108 struct Lisp_Char_Table *disptab;
0aa01123
JB
109 struct Lisp_Vector *widthtab;
110{
111 int i;
112
113 if (widthtab->size != 256)
114 abort ();
115
116 for (i = 0; i < 256; i++)
117 if (character_width (i, disptab)
118 != XFASTINT (widthtab->contents[i]))
119 return 0;
120
121 return 1;
2ff4775b 122}
0aa01123
JB
123
124/* Recompute BUF's width table, using the display table DISPTAB. */
125void
126recompute_width_table (buf, disptab)
127 struct buffer *buf;
d44f12b4 128 struct Lisp_Char_Table *disptab;
0aa01123
JB
129{
130 int i;
228a2e1a 131 struct Lisp_Vector *widthtab;
0aa01123 132
228a2e1a
KH
133 if (!VECTORP (buf->width_table))
134 buf->width_table = Fmake_vector (make_number (256), make_number (0));
135 widthtab = XVECTOR (buf->width_table);
0aa01123
JB
136 if (widthtab->size != 256)
137 abort ();
138
139 for (i = 0; i < 256; i++)
228a2e1a 140 XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
0aa01123
JB
141}
142
143/* Allocate or free the width run cache, as requested by the current
144 state of current_buffer's cache_long_line_scans variable. */
145static void
146width_run_cache_on_off ()
147{
148 if (NILP (current_buffer->cache_long_line_scans))
149 {
150 /* It should be off. */
151 if (current_buffer->width_run_cache)
152 {
153 free_region_cache (current_buffer->width_run_cache);
154 current_buffer->width_run_cache = 0;
155 current_buffer->width_table = Qnil;
156 }
157 }
158 else
159 {
160 /* It should be on. */
161 if (current_buffer->width_run_cache == 0)
2ff4775b 162 {
0aa01123 163 current_buffer->width_run_cache = new_region_cache ();
0aa01123
JB
164 recompute_width_table (current_buffer, buffer_display_table ());
165 }
166 }
167}
168
169\f
993b6404
JB
170DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
171 "Return the horizontal position of point. Beginning of line is column 0.\n\
172This is calculated by adding together the widths of all the displayed\n\
173representations of the character between the start of the previous line\n\
174and point. (eg control characters will have a width of 2 or 4, tabs\n\
175will have a variable width)\n\
502b9b64
JB
176Ignores finite width of frame, which means that this function may return\n\
177values greater than (frame-width).\n\
993b6404
JB
178Whether the line is visible (if `selective-display' is t) has no effect;\n\
179however, ^M is treated as end of line when `selective-display' is t.")
180 ()
181{
182 Lisp_Object temp;
94d92e9c 183 XSETFASTINT (temp, current_column ());
993b6404
JB
184 return temp;
185}
186
e74928fc
JB
187/* Cancel any recorded value of the horizontal position. */
188
189invalidate_current_column ()
190{
191 last_known_column_point = 0;
192}
193
993b6404
JB
194int
195current_column ()
196{
197 register int col;
198 register unsigned char *ptr, *stop;
199 register int tab_seen;
200 int post_tab;
201 register int c;
202 register int tab_width = XINT (current_buffer->tab_width);
56a98455 203 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
d44f12b4 204 register struct Lisp_Char_Table *dp = buffer_display_table ();
993b6404
JB
205 int stopchar;
206
207 if (point == last_known_column_point
208 && MODIFF == last_known_column_modified)
209 return last_known_column;
210
211 /* Make a pointer for decrementing through the chars before point. */
212 ptr = &FETCH_CHAR (point - 1) + 1;
213 /* Make a pointer to where consecutive chars leave off,
214 going backwards from point. */
215 if (point == BEGV)
216 stop = ptr;
217 else if (point <= GPT || BEGV > GPT)
218 stop = BEGV_ADDR;
219 else
220 stop = GAP_END_ADDR;
221
ccdcf1f5 222 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
993b6404
JB
223
224 col = 0, tab_seen = 0, post_tab = 0;
225
226 while (1)
227 {
228 if (ptr == stop)
229 {
230 /* We stopped either for the beginning of the buffer
231 or for the gap. */
232 if (ptr == BEGV_ADDR)
233 break;
234 /* It was the gap. Jump back over it. */
235 stop = BEGV_ADDR;
236 ptr = GPT_ADDR;
237 /* Check whether that brings us to beginning of buffer. */
238 if (BEGV >= GPT) break;
239 }
240
241 c = *--ptr;
f845b8b2
RS
242 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
243 col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
244 else if (c >= 040 && c < 0177)
245 col++;
993b6404
JB
246 else if (c == '\n')
247 break;
248 else if (c == '\r' && EQ (current_buffer->selective_display, Qt))
249 break;
250 else if (c == '\t')
251 {
252 if (tab_seen)
253 col = ((col + tab_width) / tab_width) * tab_width;
254
255 post_tab += col;
256 col = 0;
257 tab_seen = 1;
258 }
993b6404
JB
259 else
260 col += (ctl_arrow && c < 0200) ? 2 : 4;
261 }
262
263 if (tab_seen)
264 {
265 col = ((col + tab_width) / tab_width) * tab_width;
266 col += post_tab;
267 }
268
269 last_known_column = col;
270 last_known_column_point = point;
271 last_known_column_modified = MODIFF;
272
273 return col;
274}
275\f
c412c808
RS
276/* Return the width in columns of the part of STRING from BEG to END.
277 If BEG is nil, that stands for the beginning of STRING.
278 If END is nil, that stands for the end of STRING. */
279
280static int
382ac0bd 281string_display_width (string, beg, end)
c412c808
RS
282 Lisp_Object string, beg, end;
283{
284 register int col;
285 register unsigned char *ptr, *stop;
286 register int tab_seen;
287 int post_tab;
288 register int c;
289 register int tab_width = XINT (current_buffer->tab_width);
290 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
d44f12b4 291 register struct Lisp_Char_Table *dp = buffer_display_table ();
c412c808
RS
292 int b, e;
293
294 if (NILP (end))
295 e = XSTRING (string)->size;
296 else
297 {
298 CHECK_NUMBER (end, 0);
299 e = XINT (end);
300 }
301
302 if (NILP (beg))
303 b = 0;
304 else
305 {
306 CHECK_NUMBER (beg, 0);
307 b = XINT (beg);
308 }
309
310 /* Make a pointer for decrementing through the chars before point. */
311 ptr = XSTRING (string)->data + e;
312 /* Make a pointer to where consecutive chars leave off,
313 going backwards from point. */
314 stop = XSTRING (string)->data + b;
315
316 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
317
318 col = 0, tab_seen = 0, post_tab = 0;
319
320 while (1)
321 {
322 if (ptr == stop)
323 break;
324
325 c = *--ptr;
326 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
327 col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
328 else if (c >= 040 && c < 0177)
329 col++;
330 else if (c == '\n')
331 break;
332 else if (c == '\t')
333 {
334 if (tab_seen)
335 col = ((col + tab_width) / tab_width) * tab_width;
336
337 post_tab += col;
338 col = 0;
339 tab_seen = 1;
340 }
341 else
342 col += (ctl_arrow && c < 0200) ? 2 : 4;
343 }
344
345 if (tab_seen)
346 {
347 col = ((col + tab_width) / tab_width) * tab_width;
348 col += post_tab;
349 }
350
351 return col;
352}
353\f
993b6404
JB
354DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
355 "Indent from point with tabs and spaces until COLUMN is reached.\n\
356Optional second argument MIN says always do at least MIN spaces\n\
357even if that goes past COLUMN; by default, MIN is zero.")
358 (col, minimum)
359 Lisp_Object col, minimum;
360{
361 int mincol;
362 register int fromcol;
363 register int tab_width = XINT (current_buffer->tab_width);
364
365 CHECK_NUMBER (col, 0);
56a98455 366 if (NILP (minimum))
94d92e9c 367 XSETFASTINT (minimum, 0);
993b6404
JB
368 CHECK_NUMBER (minimum, 1);
369
370 fromcol = current_column ();
371 mincol = fromcol + XINT (minimum);
372 if (mincol < XINT (col)) mincol = XINT (col);
373
374 if (fromcol == mincol)
375 return make_number (mincol);
376
ccdcf1f5 377 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
993b6404
JB
378
379 if (indent_tabs_mode)
380 {
381 Lisp_Object n;
94d92e9c 382 XSETFASTINT (n, mincol / tab_width - fromcol / tab_width);
993b6404
JB
383 if (XFASTINT (n) != 0)
384 {
6d1bd1a5 385 Finsert_char (make_number ('\t'), n, Qt);
993b6404
JB
386
387 fromcol = (mincol / tab_width) * tab_width;
388 }
389 }
390
94d92e9c 391 XSETFASTINT (col, mincol - fromcol);
6d1bd1a5 392 Finsert_char (make_number (' '), col, Qt);
993b6404
JB
393
394 last_known_column = mincol;
395 last_known_column_point = point;
396 last_known_column_modified = MODIFF;
397
398 XSETINT (col, mincol);
399 return col;
400}
0aa01123 401
993b6404
JB
402\f
403DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
404 0, 0, 0,
405 "Return the indentation of the current line.\n\
406This is the horizontal position of the character\n\
407following any initial whitespace.")
408 ()
409{
410 Lisp_Object val;
411
94d92e9c 412 XSETFASTINT (val, position_indentation (find_next_newline (point, -1)));
993b6404
JB
413 return val;
414}
415
416position_indentation (pos)
417 register int pos;
418{
419 register int column = 0;
420 register int tab_width = XINT (current_buffer->tab_width);
421 register unsigned char *p;
422 register unsigned char *stop;
2ff4775b 423
ccdcf1f5 424 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
2ff4775b 425
993b6404
JB
426 stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1;
427 p = &FETCH_CHAR (pos);
428 while (1)
429 {
430 while (p == stop)
431 {
432 if (pos == ZV)
433 return column;
434 pos += p - &FETCH_CHAR (pos);
435 p = &FETCH_CHAR (pos);
436 stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1;
437 }
438 switch (*p++)
439 {
440 case ' ':
441 column++;
442 break;
443 case '\t':
444 column += tab_width - column % tab_width;
445 break;
446 default:
447 return column;
448 }
449 }
450}
1b15e576
KH
451
452/* Test whether the line beginning at POS is indented beyond COLUMN.
453 Blank lines are treated as if they had the same indentation as the
454 preceding line. */
455int
456indented_beyond_p (pos, column)
457 int pos, column;
458{
459 while (pos > BEGV && FETCH_CHAR (pos) == '\n')
04d25c3d 460 pos = find_next_newline_no_quit (pos - 1, -1);
1b15e576
KH
461 return (position_indentation (pos) >= column);
462}
0aa01123 463
993b6404 464\f
782d260e 465DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, "p",
993b6404
JB
466 "Move point to column COLUMN in the current line.\n\
467The column of a character is calculated by adding together the widths\n\
468as displayed of the previous characters in the line.\n\
469This function ignores line-continuation;\n\
470there is no upper limit on the column number a character can have\n\
230a4cbd
JB
471and horizontal scrolling has no effect.\n\
472\n\
993b6404
JB
473If specified column is within a character, point goes after that character.\n\
474If it's past end of line, point goes to end of line.\n\n\
475A non-nil second (optional) argument FORCE means, if the line\n\
476is too short to reach column COLUMN then add spaces/tabs to get there,\n\
55f7a32b
RS
477and if COLUMN is in the middle of a tab character, change it to spaces.\n\
478\n\
479The return value is the current column.")
993b6404
JB
480 (column, force)
481 Lisp_Object column, force;
482{
483 register int pos;
484 register int col = current_column ();
485 register int goal;
486 register int end;
487 register int tab_width = XINT (current_buffer->tab_width);
56a98455 488 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
d44f12b4 489 register struct Lisp_Char_Table *dp = buffer_display_table ();
993b6404
JB
490
491 Lisp_Object val;
492 int prev_col;
493 int c;
494
ccdcf1f5 495 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
993b6404
JB
496 CHECK_NATNUM (column, 0);
497 goal = XINT (column);
498
499 retry:
500 pos = point;
501 end = ZV;
502
503 /* If we're starting past the desired column,
504 back up to beginning of line and scan from there. */
505 if (col > goal)
506 {
507 pos = find_next_newline (pos, -1);
508 col = 0;
509 }
510
511 while (col < goal && pos < end)
512 {
513 c = FETCH_CHAR (pos);
f845b8b2
RS
514 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
515 {
516 col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
517 pos++;
0088a46e 518 continue;
f845b8b2 519 }
993b6404
JB
520 if (c == '\n')
521 break;
522 if (c == '\r' && EQ (current_buffer->selective_display, Qt))
523 break;
524 pos++;
525 if (c == '\t')
526 {
527 prev_col = col;
528 col += tab_width;
529 col = col / tab_width * tab_width;
530 }
993b6404 531 else if (ctl_arrow && (c < 040 || c == 0177))
bbc2998f 532 col += 2;
993b6404 533 else if (c < 040 || c >= 0177)
bbc2998f 534 col += 4;
993b6404
JB
535 else
536 col++;
537 }
538
539 SET_PT (pos);
540
541 /* If a tab char made us overshoot, change it to spaces
542 and scan through it again. */
56a98455 543 if (!NILP (force) && col > goal && c == '\t' && prev_col < goal)
993b6404 544 {
70ee42f7
JB
545 int old_point;
546
993b6404 547 del_range (point - 1, point);
70ee42f7
JB
548 Findent_to (make_number (goal), Qnil);
549 old_point = point;
550 Findent_to (make_number (col), Qnil);
551 SET_PT (old_point);
5a05d3d2
RS
552 /* Set the last_known... vars consistently. */
553 col = goal;
993b6404
JB
554 }
555
556 /* If line ends prematurely, add space to the end. */
56a98455 557 if (col < goal && !NILP (force))
230a4cbd 558 Findent_to (make_number (col = goal), Qnil);
993b6404
JB
559
560 last_known_column = col;
561 last_known_column_point = point;
562 last_known_column_modified = MODIFF;
563
94d92e9c 564 XSETFASTINT (val, col);
993b6404
JB
565 return val;
566}
0aa01123 567
993b6404 568\f
0aa01123
JB
569/* compute_motion: compute buffer posn given screen posn and vice versa */
570
993b6404
JB
571struct position val_compute_motion;
572
573/* Scan the current buffer forward from offset FROM, pretending that
574 this is at line FROMVPOS, column FROMHPOS, until reaching buffer
575 offset TO or line TOVPOS, column TOHPOS (whichever comes first),
0aa01123
JB
576 and return the ending buffer position and screen location. If we
577 can't hit the requested column exactly (because of a tab or other
578 multi-column character), overshoot.
993b6404 579
2ab90d49
KH
580 DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
581 at FROM. This is the case if FROMVPOS and FROMVPOS came from an
582 earlier call to compute_motion. The other common case is that FROMHPOS
583 is zero and FROM is a position that "belongs" at column zero, but might
584 be shifted by overlay strings; in this case DID_MOTION should be 0.
585
993b6404
JB
586 WIDTH is the number of columns available to display text;
587 compute_motion uses this to handle continuation lines and such.
588 HSCROLL is the number of columns not being displayed at the left
589 margin; this is usually taken from a window's hscroll member.
a9764248
JB
590 TAB_OFFSET is the number of columns of the first tab that aren't
591 being displayed, perhaps because of a continuation line or
592 something.
993b6404
JB
593
594 compute_motion returns a pointer to a struct position. The bufpos
595 member gives the buffer position at the end of the scan, and hpos
0aa01123
JB
596 and vpos give its cartesian location. prevhpos is the column at
597 which the character before bufpos started, and contin is non-zero
598 if we reached the current line by continuing the previous.
599
600 Note that FROMHPOS and TOHPOS should be expressed in real screen
601 columns, taking HSCROLL and the truncation glyph at the left margin
602 into account. That is, beginning-of-line moves you to the hpos
603 -HSCROLL + (HSCROLL > 0).
993b6404 604
1827d036
KH
605 Note that FROMHPOS and TOHPOS should be expressed in real screen
606 columns, taking HSCROLL and the truncation glyph at the left margin
607 into account. That is, beginning-of-line moves you to the hpos
608 -HSCROLL + (HSCROLL > 0).
609
993b6404
JB
610 For example, to find the buffer position of column COL of line LINE
611 of a certain window, pass the window's starting location as FROM
612 and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
613 Pass the buffer's ZV as TO, to limit the scan to the end of the
614 visible section of the buffer, and pass LINE and COL as TOVPOS and
2ff4775b 615 TOHPOS.
993b6404
JB
616
617 When displaying in window w, a typical formula for WIDTH is:
618
619 window_width - 1
a3c87d4e 620 - (has_vertical_scroll_bars
40284d6b 621 ? FRAME_SCROLL_BAR_COLS (XFRAME (window->frame))
fa61c701 622 : (window_width + window_left != frame_width))
993b6404
JB
623
624 where
625 window_width is XFASTINT (w->width),
626 window_left is XFASTINT (w->left),
a3c87d4e
JB
627 has_vertical_scroll_bars is
628 FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (WINDOW_FRAME (window)))
fa61c701 629 and frame_width = FRAME_WIDTH (XFRAME (window->frame))
993b6404 630
1827d036
KH
631 Or you can let window_internal_width do this all for you, and write:
632 window_internal_width (w) - 1
fa61c701
JB
633
634 The `-1' accounts for the continuation-line backslashes; the rest
7e7a76b5 635 accounts for window borders if the window is split horizontally, and
1827d036 636 the scroll bars if they are turned on. */
993b6404
JB
637
638struct position *
2ab90d49 639compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, hscroll, tab_offset, win)
993b6404 640 int from, fromvpos, fromhpos, to, tovpos, tohpos;
2ab90d49 641 int did_motion;
993b6404
JB
642 register int width;
643 int hscroll, tab_offset;
88af3af4 644 struct window *win;
993b6404 645{
cde9337b
JB
646 register int hpos = fromhpos;
647 register int vpos = fromvpos;
648
993b6404
JB
649 register int pos;
650 register int c;
651 register int tab_width = XFASTINT (current_buffer->tab_width);
56a98455 652 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
d44f12b4 653 register struct Lisp_Char_Table *dp = window_display_table (win);
993b6404 654 int selective
eeaafd4f 655 = (INTEGERP (current_buffer->selective_display)
69eaf10d
RS
656 ? XINT (current_buffer->selective_display)
657 : !NILP (current_buffer->selective_display) ? -1 : 0);
0aa01123 658 int prev_vpos = vpos, prev_hpos = 0;
993b6404 659 int selective_rlen
eeaafd4f 660 = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
dea4d2e6 661 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0);
2ab90d49
KH
662 /* The next location where the `invisible' property changes, or an
663 overlay starts or ends. */
664 int next_boundary = from;
993b6404 665
0aa01123
JB
666 /* For computing runs of characters with similar widths.
667 Invariant: width_run_width is zero, or all the characters
2ff4775b 668 from width_run_start to width_run_end have a fixed width of
0aa01123
JB
669 width_run_width. */
670 int width_run_start = from;
671 int width_run_end = from;
672 int width_run_width = 0;
673 Lisp_Object *width_table;
66c75ca5 674 Lisp_Object buffer;
0aa01123
JB
675
676 /* The next buffer pos where we should consult the width run cache. */
677 int next_width_run = from;
678
66c75ca5
RS
679 XSETBUFFER (buffer, current_buffer);
680
0aa01123
JB
681 width_run_cache_on_off ();
682 if (dp == buffer_display_table ())
683 width_table = (VECTORP (current_buffer->width_table)
684 ? XVECTOR (current_buffer->width_table)->contents
685 : 0);
686 else
687 /* If the window has its own display table, we can't use the width
688 run cache, because that's based on the buffer's display table. */
689 width_table = 0;
690
ccdcf1f5 691 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
cde9337b 692
2ab90d49
KH
693 pos = from;
694 while (1)
695 {
696 while (pos == next_boundary)
f75c0f8a 697 {
2ab90d49
KH
698 /* If the caller says that the screen position came from an earlier
699 call to compute_motion, then we've already accounted for the
700 overlay strings at point. This is only true the first time
701 through, so clear the flag after testing it. */
702 if (!did_motion)
703 /* We need to skip past the overlay strings. Currently those
704 strings must contain single-column printing characters;
705 if we want to relax that restriction, something will have
706 to be changed here. */
707 hpos += overlay_strings (pos, win, (char **)0);
708 did_motion = 0;
709
710 if (pos >= to)
711 break;
66c75ca5 712
f75c0f8a 713 {
2ab90d49
KH
714 Lisp_Object prop, position, end, limit, proplimit;
715
716 XSETFASTINT (position, pos);
717
718 /* Give faster response for overlay lookup near POS. */
719 recenter_overlay_lists (current_buffer, pos);
f75c0f8a 720
f845b8b2
RS
721 /* We must not advance farther than the next overlay change.
722 The overlay change might change the invisible property;
2ab90d49 723 or there might be overlay strings to be displayed there. */
7ea9c020 724 limit = Fnext_overlay_change (position);
f845b8b2
RS
725 /* As for text properties, this gives a lower bound
726 for where the invisible text property could change. */
66c75ca5 727 proplimit = Fnext_property_change (position, buffer, Qt);
f845b8b2
RS
728 if (XFASTINT (limit) < XFASTINT (proplimit))
729 proplimit = limit;
730 /* PROPLIMIT is now a lower bound for the next change
66c75ca5
RS
731 in invisible status. If that is plenty far away,
732 use that lower bound. */
f845b8b2 733 if (XFASTINT (proplimit) > pos + 100 || XFASTINT (proplimit) >= to)
2ab90d49 734 next_boundary = XFASTINT (proplimit);
66c75ca5 735 /* Otherwise, scan for the next `invisible' property change. */
f75c0f8a 736 else
66c75ca5
RS
737 {
738 /* Don't scan terribly far. */
f845b8b2
RS
739 XSETFASTINT (proplimit, min (pos + 100, to));
740 /* No matter what. don't go past next overlay change. */
741 if (XFASTINT (limit) < XFASTINT (proplimit))
742 proplimit = limit;
66c75ca5 743 end = Fnext_single_property_change (position, Qinvisible,
f845b8b2 744 buffer, proplimit);
2ab90d49 745 next_boundary = XFASTINT (end);
66c75ca5 746 }
2ab90d49
KH
747 /* if the `invisible' property is set, we can skip to
748 the next property change */
749 prop = Fget_char_property (position, Qinvisible,
750 Fcurrent_buffer ());
66c75ca5 751 if (TEXT_PROP_MEANS_INVISIBLE (prop))
2ab90d49 752 pos = next_boundary;
f75c0f8a
RS
753 }
754 }
2ab90d49
KH
755
756 /* Handle right margin. */
757 if (hpos >= width
758 && (hpos > width
759 || (pos < ZV && FETCH_CHAR (pos) != '\n')))
760 {
761 if (hscroll
762 || (truncate_partial_width_windows
763 && width + 1 < FRAME_WIDTH (XFRAME (WINDOW_FRAME (win))))
764 || !NILP (current_buffer->truncate_lines))
765 {
766 /* Truncating: skip to newline. */
767 pos = find_before_next_newline (pos, to, 1);
768 hpos = width;
55f7a32b
RS
769 /* If we just skipped next_boundary,
770 loop around in the main while
771 and handle it. */
772 if (pos >= next_boundary)
773 next_boundary = pos + 1;
2ab90d49
KH
774 }
775 else
776 {
777 /* Continuing. */
778 vpos += hpos / width;
779 tab_offset += hpos - hpos % width;
780 hpos %= width;
781 }
782 }
783
784 /* Stop if past the target buffer position or screen position. */
5a05d3d2
RS
785 if (pos >= to)
786 break;
2ab90d49
KH
787 if (vpos > tovpos || (vpos == tovpos && hpos >= tohpos))
788 break;
789
790 prev_vpos = vpos;
791 prev_hpos = hpos;
0aa01123
JB
792
793 /* Consult the width run cache to see if we can avoid inspecting
794 the text character-by-character. */
795 if (current_buffer->width_run_cache && pos >= next_width_run)
796 {
797 int run_end;
798 int common_width
799 = region_cache_forward (current_buffer,
800 current_buffer->width_run_cache,
801 pos, &run_end);
802
803 /* A width of zero means the character's width varies (like
804 a tab), is meaningless (like a newline), or we just don't
805 want to skip over it for some other reason. */
806 if (common_width != 0)
807 {
808 int run_end_hpos;
809
810 /* Don't go past the final buffer posn the user
811 requested. */
812 if (run_end > to)
813 run_end = to;
814
815 run_end_hpos = hpos + (run_end - pos) * common_width;
816
817 /* Don't go past the final horizontal position the user
818 requested. */
819 if (vpos == tovpos && run_end_hpos > tohpos)
820 {
821 run_end = pos + (tohpos - hpos) / common_width;
822 run_end_hpos = hpos + (run_end - pos) * common_width;
823 }
2ff4775b 824
0aa01123
JB
825 /* Don't go past the margin. */
826 if (run_end_hpos >= width)
827 {
828 run_end = pos + (width - hpos) / common_width;
829 run_end_hpos = hpos + (run_end - pos) * common_width;
830 }
831
832 hpos = run_end_hpos;
833 if (run_end > pos)
834 prev_hpos = hpos - common_width;
835 pos = run_end;
836 }
837
838 next_width_run = run_end + 1;
839 }
840
841 /* We have to scan the text character-by-character. */
993b6404 842 else
2ab90d49
KH
843 {
844 c = FETCH_CHAR (pos);
845 pos++;
0aa01123 846
2ab90d49
KH
847 /* Perhaps add some info to the width_run_cache. */
848 if (current_buffer->width_run_cache)
849 {
850 /* Is this character part of the current run? If so, extend
851 the run. */
852 if (pos - 1 == width_run_end
853 && width_table[c] == width_run_width)
854 width_run_end = pos;
855
856 /* The previous run is over, since this is a character at a
857 different position, or a different width. */
858 else
859 {
860 /* Have we accumulated a run to put in the cache?
861 (Currently, we only cache runs of width == 1). */
862 if (width_run_start < width_run_end
863 && width_run_width == 1)
864 know_region_cache (current_buffer,
865 current_buffer->width_run_cache,
866 width_run_start, width_run_end);
867
868 /* Start recording a new width run. */
869 width_run_width = width_table[c];
870 width_run_start = pos - 1;
871 width_run_end = pos;
872 }
873 }
993b6404 874
2ab90d49
KH
875 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
876 hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
877 else if (c >= 040 && c < 0177)
878 hpos++;
879 else if (c == '\t')
993b6404 880 {
2ab90d49
KH
881 int tem = (hpos + tab_offset + hscroll - (hscroll > 0)) % tab_width;
882 if (tem < 0)
883 tem += tab_width;
884 hpos += tab_width - tem;
993b6404 885 }
2ab90d49 886 else if (c == '\n')
993b6404 887 {
2ab90d49
KH
888 if (selective > 0 && indented_beyond_p (pos, selective))
889 {
890 /* Skip any number of invisible lines all at once */
891 do
892 pos = find_before_next_newline (pos, to, 1) + 1;
893 while (pos < to
894 && indented_beyond_p (pos, selective));
895 /* Allow for the " ..." that is displayed for them. */
896 if (selective_rlen)
897 {
898 hpos += selective_rlen;
899 if (hpos >= width)
900 hpos = width;
901 }
902 --pos;
903 /* We have skipped the invis text, but not the
904 newline after. */
905 }
906 else
907 {
908 /* A visible line. */
909 vpos++;
910 hpos = 0;
911 hpos -= hscroll;
912 /* Count the truncation glyph on column 0 */
913 if (hscroll > 0)
914 hpos++;
915 tab_offset = 0;
916 }
993b6404 917 }
2ab90d49
KH
918 else if (c == CR && selective < 0)
919 {
920 /* In selective display mode,
921 everything from a ^M to the end of the line is invisible.
922 Stop *before* the real newline. */
923 pos = find_before_next_newline (pos, to, 1);
55f7a32b
RS
924 /* If we just skipped next_boundary,
925 loop around in the main while
926 and handle it. */
927 if (pos > next_boundary)
928 next_boundary = pos;
2ab90d49
KH
929 /* Allow for the " ..." that is displayed for them. */
930 if (selective_rlen)
931 {
932 hpos += selective_rlen;
933 if (hpos >= width)
934 hpos = width;
935 }
936 }
937 else
938 hpos += (ctl_arrow && c < 0200) ? 2 : 4;
993b6404
JB
939 }
940 }
941
0aa01123
JB
942 /* Remember any final width run in the cache. */
943 if (current_buffer->width_run_cache
944 && width_run_width == 1
945 && width_run_start < width_run_end)
946 know_region_cache (current_buffer, current_buffer->width_run_cache,
947 width_run_start, width_run_end);
948
993b6404 949 val_compute_motion.bufpos = pos;
cde9337b
JB
950 val_compute_motion.hpos = hpos;
951 val_compute_motion.vpos = vpos;
952 val_compute_motion.prevhpos = prev_hpos;
993b6404
JB
953
954 /* Nonzero if have just continued a line */
955 val_compute_motion.contin
cde9337b
JB
956 = (pos != from
957 && (val_compute_motion.vpos != prev_vpos)
958 && c != '\n');
993b6404
JB
959
960 return &val_compute_motion;
961}
993b6404 962
992371ca
KH
963#if 0 /* The doc string is too long for some compilers,
964 but make-docfile can find it in this comment. */
88af3af4 965DEFUN ("compute-motion", Ffoo, Sfoo, 7, 7, 0,
42918ba5
RS
966 "Scan through the current buffer, calculating screen position.\n\
967Scan the current buffer forward from offset FROM,\n\
968assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--\n\
969to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--\n\
970and return the ending buffer position and screen location.\n\
971\n\
88af3af4 972There are three additional arguments:\n\
42918ba5
RS
973\n\
974WIDTH is the number of columns available to display text;\n\
975this affects handling of continuation lines.\n\
992371ca
KH
976This is usually the value returned by `window-width', less one (to allow\n\
977for the continuation glyph).\n\
42918ba5
RS
978\n\
979OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).\n\
980HSCROLL is the number of columns not being displayed at the left\n\
981margin; this is usually taken from a window's hscroll member.\n\
982TAB-OFFSET is the number of columns of the first tab that aren't\n\
983being displayed, perhaps because the line was continued within it.\n\
4fb76787 984If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.\n\
69eaf10d 985\n\
88af3af4 986WINDOW is the window to operate on. Currently this is used only to\n\
69eaf10d
RS
987find the display table. It does not matter what buffer WINDOW displays;\n\
988`compute-motion' always operates on the current buffer.\n\
42918ba5
RS
989\n\
990The value is a list of five elements:\n\
faa5c515 991 (POS HPOS VPOS PREVHPOS CONTIN)\n\
42918ba5
RS
992POS is the buffer position where the scan stopped.\n\
993VPOS is the vertical position where the scan stopped.\n\
994HPOS is the horizontal position where the scan stopped.\n\
995\n\
996PREVHPOS is the horizontal position one character back from POS.\n\
997CONTIN is t if a line was continued after (or within) the previous character.\n\
998\n\
999For example, to find the buffer position of column COL of line LINE\n\
1000of a certain window, pass the window's starting location as FROM\n\
1001and the window's upper-left coordinates as FROMPOS.\n\
1002Pass the buffer's (point-max) as TO, to limit the scan to the end of the\n\
1003visible section of the buffer, and pass LINE and COL as TOPOS.")
5844e1c4 1004 (from, frompos, to, topos, width, offsets, window)
992371ca
KH
1005#endif
1006
88af3af4 1007DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0,
992371ca 1008 0)
88af3af4 1009 (from, frompos, to, topos, width, offsets, window)
42918ba5 1010 Lisp_Object from, frompos, to, topos;
88af3af4 1011 Lisp_Object width, offsets, window;
42918ba5
RS
1012{
1013 Lisp_Object bufpos, hpos, vpos, prevhpos, contin;
1014 struct position *pos;
1015 int hscroll, tab_offset;
1016
26a8d14b 1017 CHECK_NUMBER_COERCE_MARKER (from, 0);
42918ba5 1018 CHECK_CONS (frompos, 0);
26a8d14b
KH
1019 CHECK_NUMBER (XCONS (frompos)->car, 0);
1020 CHECK_NUMBER (XCONS (frompos)->cdr, 0);
1021 CHECK_NUMBER_COERCE_MARKER (to, 0);
42918ba5 1022 CHECK_CONS (topos, 0);
26a8d14b
KH
1023 CHECK_NUMBER (XCONS (topos)->car, 0);
1024 CHECK_NUMBER (XCONS (topos)->cdr, 0);
1025 CHECK_NUMBER (width, 0);
42918ba5
RS
1026 if (!NILP (offsets))
1027 {
1028 CHECK_CONS (offsets, 0);
26a8d14b
KH
1029 CHECK_NUMBER (XCONS (offsets)->car, 0);
1030 CHECK_NUMBER (XCONS (offsets)->cdr, 0);
42918ba5
RS
1031 hscroll = XINT (XCONS (offsets)->car);
1032 tab_offset = XINT (XCONS (offsets)->cdr);
1033 }
1034 else
1035 hscroll = tab_offset = 0;
1036
88af3af4
KH
1037 if (NILP (window))
1038 window = Fselected_window ();
1039 else
1040 CHECK_LIVE_WINDOW (window, 0);
1041
42918ba5 1042 pos = compute_motion (XINT (from), XINT (XCONS (frompos)->cdr),
2ab90d49 1043 XINT (XCONS (frompos)->car), 0,
42918ba5
RS
1044 XINT (to), XINT (XCONS (topos)->cdr),
1045 XINT (XCONS (topos)->car),
88af3af4
KH
1046 XINT (width), hscroll, tab_offset,
1047 XWINDOW (window));
42918ba5 1048
94d92e9c 1049 XSETFASTINT (bufpos, pos->bufpos);
f8f645a1
KH
1050 XSETINT (hpos, pos->hpos);
1051 XSETINT (vpos, pos->vpos);
1052 XSETINT (prevhpos, pos->prevhpos);
42918ba5
RS
1053
1054 return Fcons (bufpos,
1055 Fcons (hpos,
1056 Fcons (vpos,
1057 Fcons (prevhpos,
1058 Fcons (pos->contin ? Qt : Qnil, Qnil)))));
1059
1060}
993b6404 1061\f
0aa01123
JB
1062/* Return the column of position POS in window W's buffer.
1063 The result is rounded down to a multiple of the internal width of W.
993b6404
JB
1064 This is the amount of indentation of position POS
1065 that is not visible in its horizontal position in the window. */
1066
1067int
1068pos_tab_offset (w, pos)
1069 struct window *w;
1070 register int pos;
1071{
3d94e943 1072 int opoint = PT;
993b6404 1073 int col;
fa61c701 1074 int width = window_internal_width (w) - 1;
993b6404
JB
1075
1076 if (pos == BEGV || FETCH_CHAR (pos - 1) == '\n')
1077 return 0;
3d94e943 1078 TEMP_SET_PT (pos);
993b6404 1079 col = current_column ();
3d94e943 1080 TEMP_SET_PT (opoint);
993b6404
JB
1081 return col - (col % width);
1082}
1083
0aa01123
JB
1084\f
1085/* Fvertical_motion and vmotion */
993b6404
JB
1086struct position val_vmotion;
1087
1088struct position *
99ce22d5
KH
1089vmotion (from, vtarget, w)
1090 register int from, vtarget;
1091 struct window *w;
993b6404 1092{
99ce22d5
KH
1093 int width = window_internal_width (w) - 1;
1094 int hscroll = XINT (w->hscroll);
993b6404
JB
1095 struct position pos;
1096 /* vpos is cumulative vertical position, changed as from is changed */
1097 register int vpos = 0;
92992c7e 1098 Lisp_Object prevline;
993b6404
JB
1099 register int first;
1100 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
1101 int selective
eeaafd4f
KH
1102 = (INTEGERP (current_buffer->selective_display)
1103 ? XINT (current_buffer->selective_display)
1104 : !NILP (current_buffer->selective_display) ? -1 : 0);
99ce22d5
KH
1105 Lisp_Object window;
1106 int start_hpos = 0;
2ab90d49 1107 int did_motion;
99ce22d5
KH
1108
1109 XSETWINDOW (window, w);
1110
cb1068e5 1111 /* The omission of the clause
99ce22d5 1112 && marker_position (w->start) == BEG
cb1068e5
KH
1113 here is deliberate; I think we want to measure from the prompt
1114 position even if the minibuffer window has scrolled. */
c412c808
RS
1115 if (EQ (window, minibuf_window))
1116 {
39fc6077 1117 if (minibuf_prompt_width == 0 && STRINGP (minibuf_prompt))
382ac0bd
RS
1118 minibuf_prompt_width
1119 = string_display_width (minibuf_prompt, Qnil, Qnil);
c412c808
RS
1120
1121 start_hpos = minibuf_prompt_width;
1122 }
993b6404 1123
99ce22d5 1124 if (vpos >= vtarget)
993b6404 1125 {
99ce22d5
KH
1126 /* To move upward, go a line at a time until
1127 we have gone at least far enough */
1128
1129 first = 1;
1130
1131 while ((vpos > vtarget || first) && from > BEGV)
993b6404 1132 {
66c75ca5
RS
1133 Lisp_Object propval;
1134
99ce22d5 1135 XSETFASTINT (prevline, find_next_newline_no_quit (from - 1, -1));
92992c7e 1136 while (XFASTINT (prevline) > BEGV
5a05d3d2 1137 && ((selective > 0
92992c7e 1138 && indented_beyond_p (XFASTINT (prevline), selective))
5a05d3d2
RS
1139#ifdef USE_TEXT_PROPERTIES
1140 /* watch out for newlines with `invisible' property */
66c75ca5
RS
1141 || (propval = Fget_char_property (prevline,
1142 Qinvisible,
1143 window),
1144 TEXT_PROP_MEANS_INVISIBLE (propval))
5a05d3d2 1145#endif
99ce22d5 1146 ))
94d92e9c
KH
1147 XSETFASTINT (prevline,
1148 find_next_newline_no_quit (XFASTINT (prevline) - 1,
1149 -1));
92992c7e 1150 pos = *compute_motion (XFASTINT (prevline), 0,
99ce22d5 1151 lmargin + (XFASTINT (prevline) == BEG
92992c7e 1152 ? start_hpos : 0),
2ab90d49 1153 0,
68be917d 1154 from, 1 << (BITS_PER_INT - 2), 0,
99ce22d5
KH
1155 width, hscroll, 0, w);
1156 vpos -= pos.vpos;
1157 first = 0;
1158 from = XFASTINT (prevline);
993b6404 1159 }
99ce22d5
KH
1160
1161 /* If we made exactly the desired vertical distance,
1162 or if we hit beginning of buffer,
1163 return point found */
1164 if (vpos >= vtarget)
993b6404 1165 {
99ce22d5
KH
1166 val_vmotion.bufpos = from;
1167 val_vmotion.vpos = vpos;
1168 val_vmotion.hpos = lmargin;
1169 val_vmotion.contin = 0;
1170 val_vmotion.prevhpos = 0;
1171 return &val_vmotion;
993b6404 1172 }
993b6404 1173
99ce22d5
KH
1174 /* Otherwise find the correct spot by moving down */
1175 }
1176 /* Moving downward is simple, but must calculate from beg of line
1177 to determine hpos of starting point */
1178 if (from > BEGV && FETCH_CHAR (from - 1) != '\n')
993b6404 1179 {
2ab90d49 1180 Lisp_Object propval;
66c75ca5 1181
99ce22d5
KH
1182 XSETFASTINT (prevline, find_next_newline_no_quit (from, -1));
1183 while (XFASTINT (prevline) > BEGV
1184 && ((selective > 0
1185 && indented_beyond_p (XFASTINT (prevline), selective))
5a05d3d2 1186#ifdef USE_TEXT_PROPERTIES
99ce22d5
KH
1187 /* watch out for newlines with `invisible' property */
1188 || (propval = Fget_char_property (prevline, Qinvisible,
1189 window),
1190 TEXT_PROP_MEANS_INVISIBLE (propval))
5a05d3d2 1191#endif
99ce22d5
KH
1192 ))
1193 XSETFASTINT (prevline,
1194 find_next_newline_no_quit (XFASTINT (prevline) - 1,
1195 -1));
92992c7e 1196 pos = *compute_motion (XFASTINT (prevline), 0,
99ce22d5 1197 lmargin + (XFASTINT (prevline) == BEG
92992c7e 1198 ? start_hpos : 0),
2ab90d49 1199 0,
68be917d 1200 from, 1 << (BITS_PER_INT - 2), 0,
99ce22d5 1201 width, hscroll, 0, w);
2ab90d49 1202 did_motion = 1;
993b6404 1203 }
99ce22d5 1204 else
993b6404 1205 {
99ce22d5
KH
1206 pos.hpos = lmargin + (from == BEG ? start_hpos : 0);
1207 pos.vpos = 0;
2ab90d49 1208 did_motion = 0;
993b6404 1209 }
2ab90d49 1210 return compute_motion (from, vpos, pos.hpos, did_motion,
68be917d 1211 ZV, vtarget, - (1 << (BITS_PER_INT - 2)),
99ce22d5 1212 width, hscroll, pos.vpos * width, w);
993b6404
JB
1213}
1214
f1ecfe9b 1215DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
993b6404
JB
1216 "Move to start of screen line LINES lines down.\n\
1217If LINES is negative, this is moving up.\n\
69eaf10d
RS
1218\n\
1219The optional second argument WINDOW specifies the window to use for\n\
1220parameters such as width, horizontal scrolling, and so on.\n\
1221the default is the selected window.\n\
1222It does not matter what buffer is displayed in WINDOW.\n\
1223`vertical-motion' always uses the current buffer.\n\
1224\n\
993b6404 1225Sets point to position found; this may be start of line\n\
69eaf10d 1226or just the start of a continuation line.\n\
993b6404 1227Returns number of lines moved; may be closer to zero than LINES\n\
69eaf10d 1228if beginning or end of buffer was reached.")
f1ecfe9b
RS
1229 (lines, window)
1230 Lisp_Object lines, window;
993b6404
JB
1231{
1232 struct position pos;
993b6404
JB
1233
1234 CHECK_NUMBER (lines, 0);
f1ecfe9b
RS
1235 if (! NILP (window))
1236 CHECK_WINDOW (window, 0);
1237 else
92992c7e 1238 window = selected_window;
993b6404 1239
ef423eac 1240 pos = *vmotion (point, (int) XINT (lines), XWINDOW (window));
993b6404
JB
1241
1242 SET_PT (pos.bufpos);
1243 return make_number (pos.vpos);
1244}
1245\f
0aa01123
JB
1246/* file's initialization. */
1247
993b6404
JB
1248syms_of_indent ()
1249{
1250 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
1251 "*Indentation can insert tabs if this is non-nil.\n\
1252Setting this variable automatically makes it local to the current buffer.");
1253 indent_tabs_mode = 1;
1254
1255 defsubr (&Scurrent_indentation);
1256 defsubr (&Sindent_to);
1257 defsubr (&Scurrent_column);
1258 defsubr (&Smove_to_column);
1259 defsubr (&Svertical_motion);
42918ba5 1260 defsubr (&Scompute_motion);
993b6404 1261}