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