*** empty log message ***
[emacs.git] / src / indent.c
blob50536120d8bc8288fae5236225015d20d4bc4504
1 /* Indentation functions.
2 Copyright (C) 1985, 1986, 1987, 1988, 1992 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)
9 any later version.
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. */
21 #include "config.h"
22 #include "lisp.h"
23 #include "buffer.h"
24 #include "indent.h"
25 #include "screen.h"
26 #include "window.h"
27 #include "termchar.h"
28 #include "termopts.h"
29 #include "disptab.h"
31 /* Indentation can insert tabs if this is non-zero;
32 otherwise always uses spaces */
33 int indent_tabs_mode;
35 #define min(a, b) ((a) < (b) ? (a) : (b))
36 #define max(a, b) ((a) > (b) ? (a) : (b))
38 #define CR 015
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. */
52 struct Lisp_Vector *
53 buffer_display_table ()
55 Lisp_Object thisbuf;
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;
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 screen, which means that this function may return\n\
74 values greater than (screen-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.")
79 Lisp_Object temp;
80 XFASTINT (temp) = current_column ();
81 return temp;
84 /* Cancel any recorded value of the horizontal position. */
86 invalidate_current_column ()
88 last_known_column_point = 0;
91 int
92 current_column ()
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);
100 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
101 register struct Lisp_Vector *dp = buffer_display_table ();
102 int stopchar;
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. */
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;
119 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
121 col = 0, tab_seen = 0, post_tab = 0;
123 while (1)
125 if (ptr == stop)
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;
138 c = *--ptr;
139 if (c >= 040 && c < 0177
140 && (dp == 0 || XTYPE (DISP_CHAR_ROPE (dp, c)) != Lisp_String))
142 col++;
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')
150 if (tab_seen)
151 col = ((col + tab_width) / tab_width) * tab_width;
153 post_tab += col;
154 col = 0;
155 tab_seen = 1;
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;
163 if (tab_seen)
165 col = ((col + tab_width) / tab_width) * tab_width;
166 col += post_tab;
169 last_known_column = col;
170 last_known_column_point = point;
171 last_known_column_modified = MODIFF;
173 return col;
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.")
181 (col, minimum)
182 Lisp_Object col, minimum;
184 int mincol;
185 register int fromcol;
186 register int tab_width = XINT (current_buffer->tab_width);
188 CHECK_NUMBER (col, 0);
189 if (NILP (minimum))
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 > 20) tab_width = 8;
202 if (indent_tabs_mode)
204 Lisp_Object n;
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);
222 return col;
225 DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
226 0, 0, 0,
227 "Return the indentation of the current line.\n\
228 This is the horizontal position of the character\n\
229 following any initial whitespace.")
232 Lisp_Object val;
234 XFASTINT (val) = position_indentation (find_next_newline (point, -1));
235 return val;
238 position_indentation (pos)
239 register int 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 > 20) tab_width = 8;
248 stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1;
249 p = &FETCH_CHAR (pos);
250 while (1)
252 while (p == stop)
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;
260 switch (*p++)
262 case ' ':
263 column++;
264 break;
265 case '\t':
266 column += tab_width - column % tab_width;
267 break;
268 default:
269 return column;
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\n\
281 If specified column is within a character, point goes after that character.\n\
282 If it's past end of line, point goes to end of line.\n\n\
283 A non-nil second (optional) argument FORCE means, if the line\n\
284 is too short to reach column COLUMN then add spaces/tabs to get there,\n\
285 and if COLUMN is in the middle of a tab character, change it to spaces.")
286 (column, force)
287 Lisp_Object column, force;
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);
294 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
295 register struct Lisp_Vector *dp = buffer_display_table ();
297 Lisp_Object val;
298 int prev_col;
299 int c;
301 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
302 CHECK_NATNUM (column, 0);
303 goal = XINT (column);
305 retry:
306 pos = point;
307 end = ZV;
309 /* If we're starting past the desired column,
310 back up to beginning of line and scan from there. */
311 if (col > goal)
313 pos = find_next_newline (pos, -1);
314 col = 0;
317 while (col < goal && pos < end)
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')
327 prev_col = col;
328 col += tab_width;
329 col = col / tab_width * tab_width;
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++;
341 SET_PT (pos);
343 /* If a tab char made us overshoot, change it to spaces
344 and scan through it again. */
345 if (!NILP (force) && col > goal && c == '\t' && prev_col < goal)
347 int old_point;
349 del_range (point - 1, point);
350 Findent_to (make_number (goal), Qnil);
351 old_point = point;
352 Findent_to (make_number (col), Qnil);
353 SET_PT (old_point);
356 /* If line ends prematurely, add space to the end. */
357 if (col < goal && !NILP (force))
358 Findent_to (make_number (col = goal));
360 last_known_column = col;
361 last_known_column_point = point;
362 last_known_column_modified = MODIFF;
364 XFASTINT (val) = col;
365 return val;
368 struct position val_compute_motion;
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.
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.
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.
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.
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.
395 When displaying in window w, a typical formula for WIDTH is:
397 window_width - 1
398 - (window_width + window_left != screen_width)
400 where
401 window_width is XFASTINT (w->width),
402 window_left is XFASTINT (w->left),
403 and screen_width = SCREEN_WIDTH (XSCREEN (window->screen))
405 This accounts for the continuation-line backslashes, and the window
406 borders if the window is split vertically. */
408 struct position *
409 compute_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;
414 register int hpos = fromhpos;
415 register int vpos = fromvpos;
417 register int pos;
418 register int c;
419 register int tab_width = XFASTINT (current_buffer->tab_width);
420 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
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)
425 : !NILP (current_buffer->selective_display) ? -1 : 0;
426 int prev_vpos, prev_hpos;
427 int selective_rlen
428 = (selective && dp && XTYPE (DISP_INVIS_ROPE (dp)) == Lisp_String
429 ? XSTRING (DISP_INVIS_ROPE (dp))->size / sizeof (GLYPH) : 0);
431 if (tab_width <= 0 || tab_width > 20) tab_width = 8;
432 for (pos = from; pos < to; pos++)
434 /* Stop if past the target screen position. */
435 if (vpos > tovpos
436 || (vpos == tovpos && hpos >= tohpos))
437 break;
439 prev_vpos = vpos;
440 prev_hpos = hpos;
442 c = FETCH_CHAR (pos);
443 if (c >= 040 && c < 0177
444 && (dp == 0 || XTYPE (DISP_CHAR_ROPE (dp, c)) != Lisp_String))
445 hpos++;
446 else if (c == '\t')
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);
455 else if (c == '\n')
457 if (selective > 0 && position_indentation (pos + 1) >= selective)
459 /* Skip any number of invisible lines all at once */
462 while (++pos < to && FETCH_CHAR (pos) != '\n');
464 while (pos < to && position_indentation (pos + 1) >= selective);
465 pos--;
466 /* Allow for the " ..." that is displayed for them. */
467 if (selective_rlen)
469 hpos += selective_rlen;
470 if (hpos >= width)
471 hpos = width;
473 /* We have skipped the invis text, but not the newline after. */
475 else
477 /* A visible line. */
478 vpos++;
479 hpos = 0;
480 hpos -= hscroll;
481 if (hscroll > 0) hpos++; /* Count the ! on column 0 */
482 tab_offset = 0;
485 else if (c == CR && selective < 0)
487 /* In selective display mode,
488 everything from a ^M to the end of the line is invisible */
489 while (pos < to && FETCH_CHAR (pos) != '\n') pos++;
490 /* Stop *before* the real newline. */
491 pos--;
492 /* Allow for the " ..." that is displayed for them. */
493 if (selective_rlen)
495 hpos += selective_rlen;
496 if (hpos >= width)
497 hpos = width;
500 else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String)
501 hpos += XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH);
502 else
503 hpos += (ctl_arrow && c < 0200) ? 2 : 4;
505 /* Handle right margin. */
506 if (hpos >= width
507 && (hpos > width
508 || (pos < ZV - 1
509 && FETCH_CHAR (pos + 1) != '\n')))
511 if (vpos > tovpos
512 || (vpos == tovpos && hpos >= tohpos))
513 break;
514 if (hscroll
515 || (truncate_partial_width_windows
516 && width + 1 < SCREEN_WIDTH (selected_screen))
517 || !NILP (current_buffer->truncate_lines))
519 /* Truncating: skip to newline. */
520 while (pos < to && FETCH_CHAR (pos) != '\n') pos++;
521 pos--;
522 hpos = width;
524 else
526 /* Continuing. */
527 vpos++;
528 hpos -= width;
529 tab_offset += width;
535 val_compute_motion.bufpos = pos;
536 val_compute_motion.hpos = hpos;
537 val_compute_motion.vpos = vpos;
538 val_compute_motion.prevhpos = prev_hpos;
540 /* Nonzero if have just continued a line */
541 val_compute_motion.contin
542 = (pos != from
543 && (val_compute_motion.vpos != prev_vpos)
544 && c != '\n');
546 return &val_compute_motion;
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. */
556 pos_tab_offset (w, pos)
557 struct window *w;
558 register int pos;
560 int opoint = point;
561 int col;
562 int width = XFASTINT (w->width) - 1
563 - (XFASTINT (w->width) + XFASTINT (w->left)
564 != SCREEN_WIDTH (XSCREEN (w->screen)));
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);
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. */
578 struct position val_vmotion;
580 struct position *
581 vmotion (from, vtarget, width, hscroll, window)
582 register int from, vtarget, width;
583 int hscroll;
584 Lisp_Object window;
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)
595 : !NILP (current_buffer->selective_display) ? -1 : 0;
596 int start_hpos = (EQ (window, minibuf_window) ? minibuf_prompt_width : 0);
598 retry:
599 if (vtarget > vpos)
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')
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),
612 from, 1 << (INTBITS - 2), 0,
613 width, hscroll, 0);
615 else
617 pos.hpos = lmargin + (from == 1 ? start_hpos : 0);
618 pos.vpos = 0;
620 return compute_motion (from, vpos, pos.hpos,
621 ZV, vtarget, - (1 << (INTBITS - 2)),
622 width, hscroll, pos.vpos * width);
625 /* To move upward, go a line at a time until
626 we have gone at least far enough */
628 first = 1;
630 while ((vpos > vtarget || first) && from > BEGV)
632 prevline = from;
633 while (1)
635 prevline = find_next_newline (prevline - 1, -1);
636 if (prevline == BEGV
637 || selective <= 0
638 || position_indentation (prevline) < selective)
639 break;
641 pos = *compute_motion (prevline, 0,
642 lmargin + (prevline == 1 ? start_hpos : 0),
643 from, 1 << (INTBITS - 2), 0,
644 width, hscroll, 0);
645 vpos -= pos.vpos;
646 first = 0;
647 from = prevline;
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)
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;
663 /* Otherwise find the correct spot by moving down */
664 goto retry;
667 DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 1, 0,
668 "Move to start of screen line LINES lines down.\n\
669 If LINES is negative, this is moving up.\n\
670 Sets point to position found; this may be start of line\n\
671 or just the start of a continuation line.\n\
672 Returns 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;
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)
681 != SCREEN_WIDTH (XSCREEN (w->screen)));
683 CHECK_NUMBER (lines, 0);
685 pos = *vmotion (point, XINT (lines), width,
686 /* Not XFASTINT since perhaps could be negative */
687 XINT (w->hscroll), selected_window);
689 SET_PT (pos.bufpos);
690 return make_number (pos.vpos);
693 syms_of_indent ()
695 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
696 "*Indentation can insert tabs if this is non-nil.\n\
697 Setting this variable automatically makes it local to the current buffer.");
698 indent_tabs_mode = 1;
700 defsubr (&Scurrent_indentation);
701 defsubr (&Sindent_to);
702 defsubr (&Scurrent_column);
703 defsubr (&Smove_to_column);
704 defsubr (&Svertical_motion);