Change doc-string comments to `new style' [w/`doc:' keyword].
[bpt/emacs.git] / src / indent.c
1 /* Indentation functions.
2 Copyright (C) 1985,86,87,88,93,94,95,98, 2000, 2001
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include <config.h>
23 #include "lisp.h"
24 #include "buffer.h"
25 #include "charset.h"
26 #include "category.h"
27 #include "indent.h"
28 #include "keyboard.h"
29 #include "frame.h"
30 #include "window.h"
31 #include "termchar.h"
32 #include "termopts.h"
33 #include "disptab.h"
34 #include "intervals.h"
35 #include "region-cache.h"
36
37 /* Indentation can insert tabs if this is non-zero;
38 otherwise always uses spaces. */
39
40 int indent_tabs_mode;
41
42 #define CR 015
43
44 /* These three values memorize the current column to avoid recalculation. */
45
46 /* Last value returned by current_column.
47 Some things in set last_known_column_point to -1
48 to mark the memorized value as invalid. */
49
50 int last_known_column;
51
52 /* Value of point when current_column was called. */
53
54 int last_known_column_point;
55
56 /* Value of MODIFF when current_column was called. */
57
58 int last_known_column_modified;
59
60 static int current_column_1 P_ ((void));
61 static int position_indentation P_ ((int));
62
63 /* Cache of beginning of line found by the last call of
64 current_column. */
65
66 int current_column_bol_cache;
67
68 /* Get the display table to use for the current buffer. */
69
70 struct Lisp_Char_Table *
71 buffer_display_table ()
72 {
73 Lisp_Object thisbuf;
74
75 thisbuf = current_buffer->display_table;
76 if (DISP_TABLE_P (thisbuf))
77 return XCHAR_TABLE (thisbuf);
78 if (DISP_TABLE_P (Vstandard_display_table))
79 return XCHAR_TABLE (Vstandard_display_table);
80 return 0;
81 }
82 \f
83 /* Width run cache considerations. */
84
85 /* Return the width of character C under display table DP. */
86
87 static int
88 character_width (c, dp)
89 int c;
90 struct Lisp_Char_Table *dp;
91 {
92 Lisp_Object elt;
93
94 /* These width computations were determined by examining the cases
95 in display_text_line. */
96
97 /* Everything can be handled by the display table, if it's
98 present and the element is right. */
99 if (dp && (elt = DISP_CHAR_VECTOR (dp, c), VECTORP (elt)))
100 return XVECTOR (elt)->size;
101
102 /* Some characters are special. */
103 if (c == '\n' || c == '\t' || c == '\015')
104 return 0;
105
106 /* Printing characters have width 1. */
107 else if (c >= 040 && c < 0177)
108 return 1;
109
110 /* Everybody else (control characters, metacharacters) has other
111 widths. We could return their actual widths here, but they
112 depend on things like ctl_arrow and crud like that, and they're
113 not very common at all. So we'll just claim we don't know their
114 widths. */
115 else
116 return 0;
117 }
118
119 /* Return true iff the display table DISPTAB specifies the same widths
120 for characters as WIDTHTAB. We use this to decide when to
121 invalidate the buffer's width_run_cache. */
122
123 int
124 disptab_matches_widthtab (disptab, widthtab)
125 struct Lisp_Char_Table *disptab;
126 struct Lisp_Vector *widthtab;
127 {
128 int i;
129
130 if (widthtab->size != 256)
131 abort ();
132
133 for (i = 0; i < 256; i++)
134 if (character_width (i, disptab)
135 != XFASTINT (widthtab->contents[i]))
136 return 0;
137
138 return 1;
139 }
140
141 /* Recompute BUF's width table, using the display table DISPTAB. */
142
143 void
144 recompute_width_table (buf, disptab)
145 struct buffer *buf;
146 struct Lisp_Char_Table *disptab;
147 {
148 int i;
149 struct Lisp_Vector *widthtab;
150
151 if (!VECTORP (buf->width_table))
152 buf->width_table = Fmake_vector (make_number (256), make_number (0));
153 widthtab = XVECTOR (buf->width_table);
154 if (widthtab->size != 256)
155 abort ();
156
157 for (i = 0; i < 256; i++)
158 XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
159 }
160
161 /* Allocate or free the width run cache, as requested by the current
162 state of current_buffer's cache_long_line_scans variable. */
163
164 static void
165 width_run_cache_on_off ()
166 {
167 if (NILP (current_buffer->cache_long_line_scans)
168 /* And, for the moment, this feature doesn't work on multibyte
169 characters. */
170 || !NILP (current_buffer->enable_multibyte_characters))
171 {
172 /* It should be off. */
173 if (current_buffer->width_run_cache)
174 {
175 free_region_cache (current_buffer->width_run_cache);
176 current_buffer->width_run_cache = 0;
177 current_buffer->width_table = Qnil;
178 }
179 }
180 else
181 {
182 /* It should be on. */
183 if (current_buffer->width_run_cache == 0)
184 {
185 current_buffer->width_run_cache = new_region_cache ();
186 recompute_width_table (current_buffer, buffer_display_table ());
187 }
188 }
189 }
190
191 \f
192 /* Skip some invisible characters starting from POS.
193 This includes characters invisible because of text properties
194 and characters invisible because of overlays.
195
196 If position POS is followed by invisible characters,
197 skip some of them and return the position after them.
198 Otherwise return POS itself.
199
200 Set *NEXT_BOUNDARY_P to the next position at which
201 it will be necessary to call this function again.
202
203 Don't scan past TO, and don't set *NEXT_BOUNDARY_P
204 to a value greater than TO.
205
206 If WINDOW is non-nil, and this buffer is displayed in WINDOW,
207 take account of overlays that apply only in WINDOW.
208
209 We don't necessarily skip all the invisible characters after POS
210 because that could take a long time. We skip a reasonable number
211 which can be skipped quickly. If there might be more invisible
212 characters immediately following, then *NEXT_BOUNDARY_P
213 will equal the return value. */
214
215 int
216 skip_invisible (pos, next_boundary_p, to, window)
217 int pos;
218 int *next_boundary_p;
219 int to;
220 Lisp_Object window;
221 {
222 Lisp_Object prop, position, overlay_limit, proplimit;
223 Lisp_Object buffer;
224 int end;
225
226 XSETFASTINT (position, pos);
227 XSETBUFFER (buffer, current_buffer);
228
229 /* Give faster response for overlay lookup near POS. */
230 recenter_overlay_lists (current_buffer, pos);
231
232 /* We must not advance farther than the next overlay change.
233 The overlay change might change the invisible property;
234 or there might be overlay strings to be displayed there. */
235 overlay_limit = Fnext_overlay_change (position);
236 /* As for text properties, this gives a lower bound
237 for where the invisible text property could change. */
238 proplimit = Fnext_property_change (position, buffer, Qt);
239 if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
240 proplimit = overlay_limit;
241 /* PROPLIMIT is now a lower bound for the next change
242 in invisible status. If that is plenty far away,
243 use that lower bound. */
244 if (XFASTINT (proplimit) > pos + 100 || XFASTINT (proplimit) >= to)
245 *next_boundary_p = XFASTINT (proplimit);
246 /* Otherwise, scan for the next `invisible' property change. */
247 else
248 {
249 /* Don't scan terribly far. */
250 XSETFASTINT (proplimit, min (pos + 100, to));
251 /* No matter what. don't go past next overlay change. */
252 if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
253 proplimit = overlay_limit;
254 end = XFASTINT (Fnext_single_property_change (position, Qinvisible,
255 buffer, proplimit));
256 #if 0
257 /* Don't put the boundary in the middle of multibyte form if
258 there is no actual property change. */
259 if (end == pos + 100
260 && !NILP (current_buffer->enable_multibyte_characters)
261 && end < ZV)
262 while (pos < end && !CHAR_HEAD_P (POS_ADDR (end)))
263 end--;
264 #endif
265 *next_boundary_p = end;
266 }
267 /* if the `invisible' property is set, we can skip to
268 the next property change */
269 if (!NILP (window) && EQ (XWINDOW (window)->buffer, buffer))
270 prop = Fget_char_property (position, Qinvisible, window);
271 else
272 prop = Fget_char_property (position, Qinvisible, buffer);
273 if (TEXT_PROP_MEANS_INVISIBLE (prop) > NILP (window))
274 return *next_boundary_p;
275 return pos;
276 }
277 \f
278 /* If a composition starts at POS/POS_BYTE and it doesn't stride over
279 POINT, set *LEN / *LEN_BYTE to the character and byte lengths, *WIDTH
280 to the width, and return 1. Otherwise, return 0. */
281
282 static int
283 check_composition (pos, pos_byte, point, len, len_byte, width)
284 int pos, pos_byte, point;
285 int *len, *len_byte, *width;
286 {
287 Lisp_Object prop;
288 int start, end;
289 int id;
290
291 if (! find_composition (pos, -1, &start, &end, &prop, Qnil)
292 || pos != start || point < end
293 || !COMPOSITION_VALID_P (start, end, prop))
294 return 0;
295 if ((id = get_composition_id (pos, pos_byte, end - pos, prop, Qnil)) < 0)
296 return 0;
297
298 *len = COMPOSITION_LENGTH (prop);
299 *len_byte = CHAR_TO_BYTE (end) - pos_byte;
300 *width = composition_table[id]->width;
301 return 1;
302 }
303 \f
304 /* Set variables WIDTH and BYTES for a multibyte sequence starting at P.
305
306 DP is a display table or NULL.
307
308 This macro is used in current_column_1, Fmove_to_column, and
309 compute_motion. */
310
311 #define MULTIBYTE_BYTES_WIDTH(p, dp) \
312 do { \
313 int c; \
314 \
315 wide_column = 0; \
316 c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, bytes); \
317 if (BYTES_BY_CHAR_HEAD (*p) != bytes) \
318 width = bytes * 4; \
319 else \
320 { \
321 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) \
322 width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; \
323 else \
324 width = WIDTH_BY_CHAR_HEAD (*p); \
325 if (width > 1) \
326 wide_column = width; \
327 } \
328 } while (0)
329
330 DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
331 doc: /* Return the horizontal position of point. Beginning of line is column 0.
332 This is calculated by adding together the widths of all the displayed
333 representations of the character between the start of the previous line
334 and point. (eg control characters will have a width of 2 or 4, tabs
335 will have a variable width)
336 Ignores finite width of frame, which means that this function may return
337 values greater than (frame-width).
338 Whether the line is visible (if `selective-display' is t) has no effect;
339 however, ^M is treated as end of line when `selective-display' is t. */)
340 ()
341 {
342 Lisp_Object temp;
343 XSETFASTINT (temp, current_column ());
344 return temp;
345 }
346
347 /* Cancel any recorded value of the horizontal position. */
348
349 void
350 invalidate_current_column ()
351 {
352 last_known_column_point = 0;
353 }
354
355 int
356 current_column ()
357 {
358 register int col;
359 register unsigned char *ptr, *stop;
360 register int tab_seen;
361 int post_tab;
362 register int c;
363 register int tab_width = XINT (current_buffer->tab_width);
364 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
365 register struct Lisp_Char_Table *dp = buffer_display_table ();
366
367 if (PT == last_known_column_point
368 && MODIFF == last_known_column_modified)
369 return last_known_column;
370
371 /* If the buffer has overlays, text properties,
372 or multibyte characters, use a more general algorithm. */
373 if (BUF_INTERVALS (current_buffer)
374 || !NILP (current_buffer->overlays_before)
375 || !NILP (current_buffer->overlays_after)
376 || Z != Z_BYTE)
377 return current_column_1 ();
378
379 /* Scan backwards from point to the previous newline,
380 counting width. Tab characters are the only complicated case. */
381
382 /* Make a pointer for decrementing through the chars before point. */
383 ptr = BYTE_POS_ADDR (PT_BYTE - 1) + 1;
384 /* Make a pointer to where consecutive chars leave off,
385 going backwards from point. */
386 if (PT == BEGV)
387 stop = ptr;
388 else if (PT <= GPT || BEGV > GPT)
389 stop = BEGV_ADDR;
390 else
391 stop = GAP_END_ADDR;
392
393 if (tab_width <= 0 || tab_width > 1000)
394 tab_width = 8;
395
396 col = 0, tab_seen = 0, post_tab = 0;
397
398 while (1)
399 {
400 EMACS_INT i, n;
401 Lisp_Object charvec;
402
403 if (ptr == stop)
404 {
405 /* We stopped either for the beginning of the buffer
406 or for the gap. */
407 if (ptr == BEGV_ADDR)
408 break;
409
410 /* It was the gap. Jump back over it. */
411 stop = BEGV_ADDR;
412 ptr = GPT_ADDR;
413
414 /* Check whether that brings us to beginning of buffer. */
415 if (BEGV >= GPT)
416 break;
417 }
418
419 c = *--ptr;
420
421 if (dp && VECTORP (DISP_CHAR_VECTOR (dp, c)))
422 {
423 charvec = DISP_CHAR_VECTOR (dp, c);
424 n = ASIZE (charvec);
425 }
426 else
427 {
428 charvec = Qnil;
429 n = 1;
430 }
431
432 for (i = n - 1; i >= 0; --i)
433 {
434 if (VECTORP (charvec))
435 {
436 /* This should be handled the same as
437 next_element_from_display_vector does it. */
438 Lisp_Object entry = AREF (charvec, i);
439
440 if (INTEGERP (entry)
441 && GLYPH_CHAR_VALID_P (XFASTINT (entry)))
442 c = FAST_GLYPH_CHAR (XFASTINT (entry));
443 else
444 c = ' ';
445 }
446
447 if (c >= 040 && c < 0177)
448 col++;
449 else if (c == '\n'
450 || (c == '\r'
451 && EQ (current_buffer->selective_display, Qt)))
452 {
453 ptr++;
454 goto start_of_line_found;
455 }
456 else if (c == '\t')
457 {
458 if (tab_seen)
459 col = ((col + tab_width) / tab_width) * tab_width;
460
461 post_tab += col;
462 col = 0;
463 tab_seen = 1;
464 }
465 else if (VECTORP (charvec))
466 /* With a display table entry, C is displayed as is, and
467 not displayed as \NNN or as ^N. If C is a single-byte
468 character, it takes one column. If C is multi-byte in
469 an unibyte buffer, it's translated to unibyte, so it
470 also takes one column. */
471 ++col;
472 else
473 col += (ctl_arrow && c < 0200) ? 2 : 4;
474 }
475 }
476
477 start_of_line_found:
478
479 if (tab_seen)
480 {
481 col = ((col + tab_width) / tab_width) * tab_width;
482 col += post_tab;
483 }
484
485 if (ptr == BEGV_ADDR)
486 current_column_bol_cache = BEGV;
487 else
488 current_column_bol_cache = BYTE_TO_CHAR (PTR_BYTE_POS (ptr));
489
490 last_known_column = col;
491 last_known_column_point = PT;
492 last_known_column_modified = MODIFF;
493
494 return col;
495 }
496 \f
497 /* Return the column number of position POS
498 by scanning forward from the beginning of the line.
499 This function handles characters that are invisible
500 due to text properties or overlays. */
501
502 static int
503 current_column_1 ()
504 {
505 register int tab_width = XINT (current_buffer->tab_width);
506 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
507 register struct Lisp_Char_Table *dp = buffer_display_table ();
508 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
509
510 /* Start the scan at the beginning of this line with column number 0. */
511 register int col = 0;
512 int scan, scan_byte;
513 int next_boundary, next_boundary_byte;
514 int opoint = PT, opoint_byte = PT_BYTE;
515
516 scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
517 current_column_bol_cache = PT;
518 scan = PT, scan_byte = PT_BYTE;
519 SET_PT_BOTH (opoint, opoint_byte);
520 next_boundary = scan;
521 next_boundary_byte = scan_byte;
522
523 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
524
525 /* Scan forward to the target position. */
526 while (scan < opoint)
527 {
528 int c;
529 EMACS_INT i, n;
530 Lisp_Object charvec;
531
532 /* Occasionally we may need to skip invisible text. */
533 while (scan == next_boundary)
534 {
535 int old_scan = scan;
536 /* This updates NEXT_BOUNDARY to the next place
537 where we might need to skip more invisible text. */
538 scan = skip_invisible (scan, &next_boundary, opoint, Qnil);
539 if (scan >= opoint)
540 goto endloop;
541 if (scan != old_scan)
542 scan_byte = CHAR_TO_BYTE (scan);
543 next_boundary_byte = CHAR_TO_BYTE (next_boundary);
544 }
545
546 /* Check composition sequence. */
547 {
548 int len, len_byte, width;
549
550 if (check_composition (scan, scan_byte, opoint,
551 &len, &len_byte, &width))
552 {
553 scan += len;
554 scan_byte += len_byte;
555 if (scan <= opoint)
556 col += width;
557 continue;
558 }
559 }
560
561 c = FETCH_BYTE (scan_byte);
562
563 if (dp != 0
564 && ! (multibyte && BASE_LEADING_CODE_P (c))
565 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
566 {
567 charvec = DISP_CHAR_VECTOR (dp, c);
568 n = ASIZE (charvec);
569 }
570 else
571 {
572 charvec = Qnil;
573 n = 1;
574 }
575
576 for (i = n - 1; i >= 0; --i)
577 {
578 if (VECTORP (charvec))
579 {
580 /* This should be handled the same as
581 next_element_from_display_vector does it. */
582 Lisp_Object entry = AREF (charvec, i);
583
584 if (INTEGERP (entry)
585 && GLYPH_CHAR_VALID_P (XFASTINT (entry)))
586 c = FAST_GLYPH_CHAR (XFASTINT (entry));
587 else
588 c = ' ';
589 }
590
591 if (c == '\n')
592 goto endloop;
593 if (c == '\r' && EQ (current_buffer->selective_display, Qt))
594 goto endloop;
595 scan++;
596 scan_byte++;
597 if (c == '\t')
598 {
599 int prev_col = col;
600 col += tab_width;
601 col = col / tab_width * tab_width;
602 }
603 else if (multibyte && BASE_LEADING_CODE_P (c))
604 {
605 unsigned char *ptr;
606 int bytes, width, wide_column;
607
608 scan_byte--;
609 ptr = BYTE_POS_ADDR (scan_byte);
610 MULTIBYTE_BYTES_WIDTH (ptr, dp);
611 scan_byte += bytes;
612 col += width;
613 }
614 else if (VECTORP (charvec))
615 ++col;
616 else if (ctl_arrow && (c < 040 || c == 0177))
617 col += 2;
618 else if (c < 040 || c >= 0177)
619 col += 4;
620 else
621 col++;
622 }
623 }
624 endloop:
625
626 last_known_column = col;
627 last_known_column_point = PT;
628 last_known_column_modified = MODIFF;
629
630 return col;
631 }
632 \f
633
634 #if 0 /* Not used. */
635
636 /* Return the width in columns of the part of STRING from BEG to END.
637 If BEG is nil, that stands for the beginning of STRING.
638 If END is nil, that stands for the end of STRING. */
639
640 static int
641 string_display_width (string, beg, end)
642 Lisp_Object string, beg, end;
643 {
644 register int col;
645 register unsigned char *ptr, *stop;
646 register int tab_seen;
647 int post_tab;
648 register int c;
649 register int tab_width = XINT (current_buffer->tab_width);
650 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
651 register struct Lisp_Char_Table *dp = buffer_display_table ();
652 int b, e;
653
654 if (NILP (end))
655 e = XSTRING (string)->size;
656 else
657 {
658 CHECK_NUMBER (end, 0);
659 e = XINT (end);
660 }
661
662 if (NILP (beg))
663 b = 0;
664 else
665 {
666 CHECK_NUMBER (beg, 0);
667 b = XINT (beg);
668 }
669
670 /* Make a pointer for decrementing through the chars before point. */
671 ptr = XSTRING (string)->data + e;
672 /* Make a pointer to where consecutive chars leave off,
673 going backwards from point. */
674 stop = XSTRING (string)->data + b;
675
676 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
677
678 col = 0, tab_seen = 0, post_tab = 0;
679
680 while (1)
681 {
682 if (ptr == stop)
683 break;
684
685 c = *--ptr;
686 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
687 col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
688 else if (c >= 040 && c < 0177)
689 col++;
690 else if (c == '\n')
691 break;
692 else if (c == '\t')
693 {
694 if (tab_seen)
695 col = ((col + tab_width) / tab_width) * tab_width;
696
697 post_tab += col;
698 col = 0;
699 tab_seen = 1;
700 }
701 else
702 col += (ctl_arrow && c < 0200) ? 2 : 4;
703 }
704
705 if (tab_seen)
706 {
707 col = ((col + tab_width) / tab_width) * tab_width;
708 col += post_tab;
709 }
710
711 return col;
712 }
713
714 #endif /* 0 */
715
716 \f
717 DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
718 doc: /* Indent from point with tabs and spaces until COLUMN is reached.
719 Optional second argument MININUM says always do at least MININUM spaces
720 even if that goes past COLUMN; by default, MININUM is zero. */)
721 (column, minimum)
722 Lisp_Object column, minimum;
723 {
724 int mincol;
725 register int fromcol;
726 register int tab_width = XINT (current_buffer->tab_width);
727
728 CHECK_NUMBER (column, 0);
729 if (NILP (minimum))
730 XSETFASTINT (minimum, 0);
731 CHECK_NUMBER (minimum, 1);
732
733 fromcol = current_column ();
734 mincol = fromcol + XINT (minimum);
735 if (mincol < XINT (column)) mincol = XINT (column);
736
737 if (fromcol == mincol)
738 return make_number (mincol);
739
740 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
741
742 if (indent_tabs_mode)
743 {
744 Lisp_Object n;
745 XSETFASTINT (n, mincol / tab_width - fromcol / tab_width);
746 if (XFASTINT (n) != 0)
747 {
748 Finsert_char (make_number ('\t'), n, Qt);
749
750 fromcol = (mincol / tab_width) * tab_width;
751 }
752 }
753
754 XSETFASTINT (column, mincol - fromcol);
755 Finsert_char (make_number (' '), column, Qt);
756
757 last_known_column = mincol;
758 last_known_column_point = PT;
759 last_known_column_modified = MODIFF;
760
761 XSETINT (column, mincol);
762 return column;
763 }
764
765 \f
766 static int position_indentation P_ ((int));
767
768 DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
769 0, 0, 0,
770 doc: /* Return the indentation of the current line.
771 This is the horizontal position of the character
772 following any initial whitespace. */)
773 ()
774 {
775 Lisp_Object val;
776 int opoint = PT, opoint_byte = PT_BYTE;
777
778 scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
779
780 XSETFASTINT (val, position_indentation (PT_BYTE));
781 SET_PT_BOTH (opoint, opoint_byte);
782 return val;
783 }
784
785 static int
786 position_indentation (pos_byte)
787 register int pos_byte;
788 {
789 register int column = 0;
790 register int tab_width = XINT (current_buffer->tab_width);
791 register unsigned char *p;
792 register unsigned char *stop;
793 unsigned char *start;
794 int next_boundary_byte = pos_byte;
795 int ceiling = next_boundary_byte;
796
797 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
798
799 p = BYTE_POS_ADDR (pos_byte);
800 /* STOP records the value of P at which we will need
801 to think about the gap, or about invisible text,
802 or about the end of the buffer. */
803 stop = p;
804 /* START records the starting value of P. */
805 start = p;
806 while (1)
807 {
808 while (p == stop)
809 {
810 int stop_pos_byte;
811
812 /* If we have updated P, set POS_BYTE to match.
813 The first time we enter the loop, POS_BYTE is already right. */
814 if (p != start)
815 pos_byte = PTR_BYTE_POS (p);
816 /* Consider the various reasons STOP might have been set here. */
817 if (pos_byte == ZV_BYTE)
818 return column;
819 if (pos_byte == next_boundary_byte)
820 {
821 int next_boundary;
822 int pos = BYTE_TO_CHAR (pos_byte);
823 pos = skip_invisible (pos, &next_boundary, ZV, Qnil);
824 pos_byte = CHAR_TO_BYTE (pos);
825 next_boundary_byte = CHAR_TO_BYTE (next_boundary);
826 }
827 if (pos_byte >= ceiling)
828 ceiling = BUFFER_CEILING_OF (pos_byte) + 1;
829 /* Compute the next place we need to stop and think,
830 and set STOP accordingly. */
831 stop_pos_byte = min (ceiling, next_boundary_byte);
832 /* The -1 and +1 arrange to point at the first byte of gap
833 (if STOP_POS_BYTE is the position of the gap)
834 rather than at the data after the gap. */
835
836 stop = BYTE_POS_ADDR (stop_pos_byte - 1) + 1;
837 p = BYTE_POS_ADDR (pos_byte);
838 }
839 switch (*p++)
840 {
841 case 0240:
842 if (! NILP (current_buffer->enable_multibyte_characters))
843 return column;
844 case ' ':
845 column++;
846 break;
847 case '\t':
848 column += tab_width - column % tab_width;
849 break;
850 default:
851 if (ASCII_BYTE_P (p[-1])
852 || NILP (current_buffer->enable_multibyte_characters))
853 return column;
854 {
855 int c;
856 pos_byte = PTR_BYTE_POS (p - 1);
857 c = FETCH_MULTIBYTE_CHAR (pos_byte);
858 if (CHAR_HAS_CATEGORY (c, ' '))
859 {
860 column++;
861 INC_POS (pos_byte);
862 p = BYTE_POS_ADDR (pos_byte);
863 }
864 else
865 return column;
866 }
867 }
868 }
869 }
870
871 /* Test whether the line beginning at POS is indented beyond COLUMN.
872 Blank lines are treated as if they had the same indentation as the
873 preceding line. */
874
875 int
876 indented_beyond_p (pos, pos_byte, column)
877 int pos, pos_byte, column;
878 {
879 int val;
880 int opoint = PT, opoint_byte = PT_BYTE;
881
882 SET_PT_BOTH (pos, pos_byte);
883 while (PT > BEGV && FETCH_BYTE (PT_BYTE) == '\n')
884 scan_newline (PT - 1, PT_BYTE - 1, BEGV, BEGV_BYTE, -1, 0);
885
886 val = position_indentation (PT_BYTE);
887 SET_PT_BOTH (opoint, opoint_byte);
888 return val >= column;
889 }
890 \f
891 DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, "p",
892 doc: /* Move point to column COLUMN in the current line.
893 The column of a character is calculated by adding together the widths
894 as displayed of the previous characters in the line.
895 This function ignores line-continuation;
896 there is no upper limit on the column number a character can have
897 and horizontal scrolling has no effect.
898
899 If specified column is within a character, point goes after that character.
900 If it's past end of line, point goes to end of line.
901
902 A non-nil second (optional) argument FORCE means,
903 if COLUMN is in the middle of a tab character, change it to spaces.
904 In addition, if FORCE is t, and the line is too short
905 to reach column COLUMN, add spaces/tabs to get there.
906
907 The return value is the current column. */)
908 (column, force)
909 Lisp_Object column, force;
910 {
911 register int pos;
912 register int col = current_column ();
913 register int goal;
914 register int end;
915 register int tab_width = XINT (current_buffer->tab_width);
916 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
917 register struct Lisp_Char_Table *dp = buffer_display_table ();
918 register int multibyte = !NILP (current_buffer->enable_multibyte_characters);
919
920 Lisp_Object val;
921 int prev_col = 0;
922 int c = 0;
923 int next_boundary;
924
925 int pos_byte, end_byte, next_boundary_byte;
926
927 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
928 CHECK_NATNUM (column, 0);
929 goal = XINT (column);
930
931 pos = PT;
932 pos_byte = PT_BYTE;
933 end = ZV;
934 end_byte = ZV_BYTE;
935 next_boundary = pos;
936 next_boundary_byte = PT_BYTE;
937
938 /* If we're starting past the desired column,
939 back up to beginning of line and scan from there. */
940 if (col > goal)
941 {
942 end = pos;
943 pos = current_column_bol_cache;
944 pos_byte = CHAR_TO_BYTE (pos);
945 col = 0;
946 }
947
948 while (pos < end)
949 {
950 Lisp_Object charvec;
951 EMACS_INT i, n;
952
953 while (pos == next_boundary)
954 {
955 int prev = pos;
956 pos = skip_invisible (pos, &next_boundary, end, Qnil);
957 if (pos != prev)
958 pos_byte = CHAR_TO_BYTE (pos);
959 next_boundary_byte = CHAR_TO_BYTE (next_boundary);
960 if (pos >= end)
961 goto endloop;
962 }
963
964 /* Test reaching the goal column. We do this after skipping
965 invisible characters, so that we put point before the
966 character on which the cursor will appear. */
967 if (col >= goal)
968 break;
969
970 /* Check composition sequence. */
971 {
972 int len, len_byte, width;
973
974 if (check_composition (pos, pos_byte, Z, &len, &len_byte, &width))
975 {
976 pos += len;
977 pos_byte += len_byte;
978 col += width;
979 continue;
980 }
981 }
982
983 c = FETCH_BYTE (pos_byte);
984
985 if (dp != 0
986 && ! (multibyte && BASE_LEADING_CODE_P (c))
987 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
988 {
989 charvec = DISP_CHAR_VECTOR (dp, c);
990 n = ASIZE (charvec);
991 }
992 else
993 {
994 charvec = Qnil;
995 n = 1;
996 }
997
998 for (i = n - 1; i >= 0; --i)
999 {
1000 if (VECTORP (charvec))
1001 {
1002 /* This should be handled the same as
1003 next_element_from_display_vector does it. */
1004 Lisp_Object entry = AREF (charvec, i);
1005
1006 if (INTEGERP (entry)
1007 && GLYPH_CHAR_VALID_P (XFASTINT (entry)))
1008 c = FAST_GLYPH_CHAR (XFASTINT (entry));
1009 else
1010 c = ' ';
1011 }
1012
1013
1014 if (c == '\n')
1015 goto endloop;
1016 if (c == '\r' && EQ (current_buffer->selective_display, Qt))
1017 goto endloop;
1018 pos++;
1019 pos_byte++;
1020 if (c == '\t')
1021 {
1022 prev_col = col;
1023 col += tab_width;
1024 col = col / tab_width * tab_width;
1025 }
1026 else if (VECTORP (charvec))
1027 ++col;
1028 else if (ctl_arrow && (c < 040 || c == 0177))
1029 col += 2;
1030 else if (c < 040 || c == 0177)
1031 col += 4;
1032 else if (c < 0177)
1033 col++;
1034 else if (multibyte && BASE_LEADING_CODE_P (c))
1035 {
1036 /* Start of multi-byte form. */
1037 unsigned char *ptr;
1038 int bytes, width, wide_column;
1039
1040 pos_byte--;
1041 ptr = BYTE_POS_ADDR (pos_byte);
1042 MULTIBYTE_BYTES_WIDTH (ptr, dp);
1043 pos_byte += bytes;
1044 col += width;
1045 }
1046 else
1047 col += 4;
1048 }
1049 }
1050 endloop:
1051
1052 SET_PT_BOTH (pos, pos_byte);
1053
1054 /* If a tab char made us overshoot, change it to spaces
1055 and scan through it again. */
1056 if (!NILP (force) && col > goal && c == '\t' && prev_col < goal)
1057 {
1058 int goal_pt, goal_pt_byte;
1059
1060 /* Insert spaces in front of the tab to reach GOAL. Do this
1061 first so that a marker at the end of the tab gets
1062 adjusted. */
1063 SET_PT_BOTH (PT - 1, PT_BYTE - 1);
1064 Finsert_char (make_number (' '), make_number (goal - prev_col), Qt);
1065
1066 /* Now delete the tab, and indent to COL. */
1067 del_range (PT, PT + 1);
1068 goal_pt = PT;
1069 goal_pt_byte = PT_BYTE;
1070 Findent_to (make_number (col), Qnil);
1071 SET_PT_BOTH (goal_pt, goal_pt_byte);
1072
1073 /* Set the last_known... vars consistently. */
1074 col = goal;
1075 }
1076
1077 /* If line ends prematurely, add space to the end. */
1078 if (col < goal && EQ (force, Qt))
1079 Findent_to (make_number (col = goal), Qnil);
1080
1081 last_known_column = col;
1082 last_known_column_point = PT;
1083 last_known_column_modified = MODIFF;
1084
1085 XSETFASTINT (val, col);
1086 return val;
1087 }
1088 \f
1089 /* compute_motion: compute buffer posn given screen posn and vice versa */
1090
1091 struct position val_compute_motion;
1092
1093 /* Scan the current buffer forward from offset FROM, pretending that
1094 this is at line FROMVPOS, column FROMHPOS, until reaching buffer
1095 offset TO or line TOVPOS, column TOHPOS (whichever comes first),
1096 and return the ending buffer position and screen location. If we
1097 can't hit the requested column exactly (because of a tab or other
1098 multi-column character), overshoot.
1099
1100 DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
1101 at FROM. This is the case if FROMVPOS and FROMVPOS came from an
1102 earlier call to compute_motion. The other common case is that FROMHPOS
1103 is zero and FROM is a position that "belongs" at column zero, but might
1104 be shifted by overlay strings; in this case DID_MOTION should be 0.
1105
1106 WIDTH is the number of columns available to display text;
1107 compute_motion uses this to handle continuation lines and such.
1108 HSCROLL is the number of columns not being displayed at the left
1109 margin; this is usually taken from a window's hscroll member.
1110 TAB_OFFSET is the number of columns of the first tab that aren't
1111 being displayed, perhaps because of a continuation line or
1112 something.
1113
1114 compute_motion returns a pointer to a struct position. The bufpos
1115 member gives the buffer position at the end of the scan, and hpos
1116 and vpos give its cartesian location. prevhpos is the column at
1117 which the character before bufpos started, and contin is non-zero
1118 if we reached the current line by continuing the previous.
1119
1120 Note that FROMHPOS and TOHPOS should be expressed in real screen
1121 columns, taking HSCROLL and the truncation glyph at the left margin
1122 into account. That is, beginning-of-line moves you to the hpos
1123 -HSCROLL + (HSCROLL > 0).
1124
1125 For example, to find the buffer position of column COL of line LINE
1126 of a certain window, pass the window's starting location as FROM
1127 and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
1128 Pass the buffer's ZV as TO, to limit the scan to the end of the
1129 visible section of the buffer, and pass LINE and COL as TOVPOS and
1130 TOHPOS.
1131
1132 When displaying in window w, a typical formula for WIDTH is:
1133
1134 window_width - 1
1135 - (has_vertical_scroll_bars
1136 ? FRAME_SCROLL_BAR_COLS (XFRAME (window->frame))
1137 : (window_width + window_left != frame_width))
1138
1139 where
1140 window_width is XFASTINT (w->width),
1141 window_left is XFASTINT (w->left),
1142 has_vertical_scroll_bars is
1143 FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (WINDOW_FRAME (window)))
1144 and frame_width = FRAME_WIDTH (XFRAME (window->frame))
1145
1146 Or you can let window_internal_width do this all for you, and write:
1147 window_internal_width (w) - 1
1148
1149 The `-1' accounts for the continuation-line backslashes; the rest
1150 accounts for window borders if the window is split horizontally, and
1151 the scroll bars if they are turned on. */
1152
1153 struct position *
1154 compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, hscroll, tab_offset, win)
1155 int from, fromvpos, fromhpos, to, tovpos, tohpos;
1156 int did_motion;
1157 register int width;
1158 int hscroll, tab_offset;
1159 struct window *win;
1160 {
1161 register int hpos = fromhpos;
1162 register int vpos = fromvpos;
1163
1164 register int pos;
1165 int pos_byte;
1166 register int c = 0;
1167 register int tab_width = XFASTINT (current_buffer->tab_width);
1168 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
1169 register struct Lisp_Char_Table *dp = window_display_table (win);
1170 int selective
1171 = (INTEGERP (current_buffer->selective_display)
1172 ? XINT (current_buffer->selective_display)
1173 : !NILP (current_buffer->selective_display) ? -1 : 0);
1174 int prev_hpos = 0;
1175 int selective_rlen
1176 = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
1177 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0);
1178 /* The next location where the `invisible' property changes, or an
1179 overlay starts or ends. */
1180 int next_boundary = from;
1181
1182 /* For computing runs of characters with similar widths.
1183 Invariant: width_run_width is zero, or all the characters
1184 from width_run_start to width_run_end have a fixed width of
1185 width_run_width. */
1186 int width_run_start = from;
1187 int width_run_end = from;
1188 int width_run_width = 0;
1189 Lisp_Object *width_table;
1190 Lisp_Object buffer;
1191
1192 /* The next buffer pos where we should consult the width run cache. */
1193 int next_width_run = from;
1194 Lisp_Object window;
1195
1196 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
1197 /* If previous char scanned was a wide character,
1198 this is the column where it ended. Otherwise, this is 0. */
1199 int wide_column_end_hpos = 0;
1200 int prev_pos; /* Previous buffer position. */
1201 int prev_pos_byte; /* Previous buffer position. */
1202 int contin_hpos; /* HPOS of last column of continued line. */
1203 int prev_tab_offset; /* Previous tab offset. */
1204
1205 XSETBUFFER (buffer, current_buffer);
1206 XSETWINDOW (window, win);
1207
1208 width_run_cache_on_off ();
1209 if (dp == buffer_display_table ())
1210 width_table = (VECTORP (current_buffer->width_table)
1211 ? XVECTOR (current_buffer->width_table)->contents
1212 : 0);
1213 else
1214 /* If the window has its own display table, we can't use the width
1215 run cache, because that's based on the buffer's display table. */
1216 width_table = 0;
1217
1218 if (tab_width <= 0 || tab_width > 1000)
1219 tab_width = 8;
1220
1221 immediate_quit = 1;
1222 QUIT;
1223
1224 pos = prev_pos = from;
1225 pos_byte = prev_pos_byte = CHAR_TO_BYTE (from);
1226 contin_hpos = 0;
1227 prev_tab_offset = tab_offset;
1228 while (1)
1229 {
1230 while (pos == next_boundary)
1231 {
1232 int pos_here = pos;
1233 int newpos;
1234
1235 /* Don't skip invisible if we are already at the margin. */
1236 if (vpos > tovpos || vpos == tovpos && hpos >= tohpos)
1237 {
1238 if (contin_hpos && prev_hpos == 0
1239 && hpos > tohpos
1240 && (contin_hpos == width || wide_column_end_hpos > width))
1241 { /* Line breaks because we can't put the character at the
1242 previous line any more. It is not the multi-column
1243 character continued in middle. Go back to previous
1244 buffer position, screen position, and set tab offset
1245 to previous value. It's the beginning of the
1246 line. */
1247 pos = prev_pos;
1248 pos_byte = prev_pos_byte;
1249 hpos = prev_hpos;
1250 tab_offset = prev_tab_offset;
1251 }
1252 break;
1253 }
1254
1255 /* If the caller says that the screen position came from an earlier
1256 call to compute_motion, then we've already accounted for the
1257 overlay strings at point. This is only true the first time
1258 through, so clear the flag after testing it. */
1259 if (!did_motion)
1260 /* We need to skip past the overlay strings. Currently those
1261 strings must not contain TAB;
1262 if we want to relax that restriction, something will have
1263 to be changed here. */
1264 {
1265 unsigned char *ovstr;
1266 int ovlen = overlay_strings (pos, win, &ovstr);
1267 hpos += ((multibyte && ovlen > 0)
1268 ? strwidth (ovstr, ovlen) : ovlen);
1269 }
1270 did_motion = 0;
1271
1272 if (pos >= to)
1273 break;
1274
1275 /* Advance POS past invisible characters
1276 (but not necessarily all that there are here),
1277 and store in next_boundary the next position where
1278 we need to call skip_invisible. */
1279 newpos = skip_invisible (pos, &next_boundary, to, window);
1280
1281 if (newpos >= to)
1282 {
1283 pos = min (to, newpos);
1284 pos_byte = CHAR_TO_BYTE (pos);
1285 goto after_loop;
1286 }
1287
1288 if (newpos != pos_here)
1289 {
1290 pos = newpos;
1291 pos_byte = CHAR_TO_BYTE (pos);
1292 }
1293 }
1294
1295 /* Handle right margin. */
1296 /* Note on a wide-column character.
1297
1298 Characters are classified into the following three categories
1299 according to the width (columns occupied on screen).
1300
1301 (1) single-column character: ex. `a'
1302 (2) multi-column character: ex. `^A', TAB, `\033'
1303 (3) wide-column character: ex. Japanese character, Chinese character
1304 (In the following example, `W_' stands for them.)
1305
1306 Multi-column characters can be divided around the right margin,
1307 but wide-column characters cannot.
1308
1309 NOTE:
1310
1311 (*) The cursor is placed on the next character after the point.
1312
1313 ----------
1314 abcdefghi\
1315 j ^---- next after the point
1316 ^--- next char. after the point.
1317 ----------
1318 In case of sigle-column character
1319
1320 ----------
1321 abcdefgh\\
1322 033 ^---- next after the point, next char. after the point.
1323 ----------
1324 In case of multi-column character
1325
1326 ----------
1327 abcdefgh\\
1328 W_ ^---- next after the point
1329 ^---- next char. after the point.
1330 ----------
1331 In case of wide-column character
1332
1333 The problem here is continuation at a wide-column character.
1334 In this case, the line may shorter less than WIDTH.
1335 And we find the continuation AFTER it occurs.
1336
1337 */
1338
1339 if (hpos > width)
1340 {
1341 if (hscroll
1342 || (truncate_partial_width_windows
1343 && width + 1 < FRAME_WIDTH (XFRAME (WINDOW_FRAME (win))))
1344 || !NILP (current_buffer->truncate_lines))
1345 {
1346 /* Truncating: skip to newline, unless we are already past
1347 TO (we need to go back below). */
1348 if (pos <= to)
1349 {
1350 pos = find_before_next_newline (pos, to, 1);
1351 pos_byte = CHAR_TO_BYTE (pos);
1352 hpos = width;
1353 /* If we just skipped next_boundary,
1354 loop around in the main while
1355 and handle it. */
1356 if (pos >= next_boundary)
1357 next_boundary = pos + 1;
1358 prev_hpos = width;
1359 prev_tab_offset = tab_offset;
1360 }
1361 }
1362 else
1363 {
1364 /* Continuing. */
1365 /* Remember the previous value. */
1366 prev_tab_offset = tab_offset;
1367
1368 if (wide_column_end_hpos > width)
1369 {
1370 hpos -= prev_hpos;
1371 tab_offset += prev_hpos;
1372 }
1373 else
1374 {
1375 tab_offset += width;
1376 hpos -= width;
1377 }
1378 vpos++;
1379 contin_hpos = prev_hpos;
1380 prev_hpos = 0;
1381 }
1382 }
1383
1384 /* Stop if past the target buffer position or screen position. */
1385 if (pos > to)
1386 {
1387 /* Go back to the previous position. */
1388 pos = prev_pos;
1389 pos_byte = prev_pos_byte;
1390 hpos = prev_hpos;
1391 tab_offset = prev_tab_offset;
1392
1393 /* NOTE on contin_hpos, hpos, and prev_hpos.
1394
1395 ----------
1396 abcdefgh\\
1397 W_ ^---- contin_hpos
1398 | ^----- hpos
1399 \---- prev_hpos
1400 ----------
1401 */
1402
1403 if (contin_hpos && prev_hpos == 0
1404 && contin_hpos < width && !wide_column_end_hpos)
1405 {
1406 /* Line breaking occurs in the middle of multi-column
1407 character. Go back to previous line. */
1408 hpos = contin_hpos;
1409 vpos = vpos - 1;
1410 }
1411 else if (c == '\n')
1412 /* If previous character is NEWLINE,
1413 set VPOS back to previous line */
1414 vpos = vpos - 1;
1415 break;
1416 }
1417
1418 if (vpos > tovpos || vpos == tovpos && hpos >= tohpos)
1419 {
1420 if (contin_hpos && prev_hpos == 0
1421 && hpos > tohpos
1422 && (contin_hpos == width || wide_column_end_hpos > width))
1423 { /* Line breaks because we can't put the character at the
1424 previous line any more. It is not the multi-column
1425 character continued in middle. Go back to previous
1426 buffer position, screen position, and set tab offset
1427 to previous value. It's the beginning of the
1428 line. */
1429 pos = prev_pos;
1430 pos_byte = prev_pos_byte;
1431 hpos = prev_hpos;
1432 tab_offset = prev_tab_offset;
1433 }
1434 break;
1435 }
1436 if (pos == ZV) /* We cannot go beyond ZV. Stop here. */
1437 break;
1438
1439 prev_hpos = hpos;
1440 prev_pos = pos;
1441 prev_pos_byte = pos_byte;
1442 wide_column_end_hpos = 0;
1443
1444 /* Consult the width run cache to see if we can avoid inspecting
1445 the text character-by-character. */
1446 if (current_buffer->width_run_cache && pos >= next_width_run)
1447 {
1448 int run_end;
1449 int common_width
1450 = region_cache_forward (current_buffer,
1451 current_buffer->width_run_cache,
1452 pos, &run_end);
1453
1454 /* A width of zero means the character's width varies (like
1455 a tab), is meaningless (like a newline), or we just don't
1456 want to skip over it for some other reason. */
1457 if (common_width != 0)
1458 {
1459 int run_end_hpos;
1460
1461 /* Don't go past the final buffer posn the user
1462 requested. */
1463 if (run_end > to)
1464 run_end = to;
1465
1466 run_end_hpos = hpos + (run_end - pos) * common_width;
1467
1468 /* Don't go past the final horizontal position the user
1469 requested. */
1470 if (vpos == tovpos && run_end_hpos > tohpos)
1471 {
1472 run_end = pos + (tohpos - hpos) / common_width;
1473 run_end_hpos = hpos + (run_end - pos) * common_width;
1474 }
1475
1476 /* Don't go past the margin. */
1477 if (run_end_hpos >= width)
1478 {
1479 run_end = pos + (width - hpos) / common_width;
1480 run_end_hpos = hpos + (run_end - pos) * common_width;
1481 }
1482
1483 hpos = run_end_hpos;
1484 if (run_end > pos)
1485 prev_hpos = hpos - common_width;
1486 if (pos != run_end)
1487 {
1488 pos = run_end;
1489 pos_byte = CHAR_TO_BYTE (pos);
1490 }
1491 }
1492
1493 next_width_run = run_end + 1;
1494 }
1495
1496 /* We have to scan the text character-by-character. */
1497 else
1498 {
1499 EMACS_INT i, n;
1500 Lisp_Object charvec;
1501
1502 c = FETCH_BYTE (pos_byte);
1503
1504 /* Check composition sequence. */
1505 {
1506 int len, len_byte, width;
1507
1508 if (check_composition (pos, pos_byte, to, &len, &len_byte, &width))
1509 {
1510 pos += len;
1511 pos_byte += len_byte;
1512 hpos += width;
1513 continue;
1514 }
1515 }
1516
1517 pos++, pos_byte++;
1518
1519 /* Perhaps add some info to the width_run_cache. */
1520 if (current_buffer->width_run_cache)
1521 {
1522 /* Is this character part of the current run? If so, extend
1523 the run. */
1524 if (pos - 1 == width_run_end
1525 && XFASTINT (width_table[c]) == width_run_width)
1526 width_run_end = pos;
1527
1528 /* The previous run is over, since this is a character at a
1529 different position, or a different width. */
1530 else
1531 {
1532 /* Have we accumulated a run to put in the cache?
1533 (Currently, we only cache runs of width == 1). */
1534 if (width_run_start < width_run_end
1535 && width_run_width == 1)
1536 know_region_cache (current_buffer,
1537 current_buffer->width_run_cache,
1538 width_run_start, width_run_end);
1539
1540 /* Start recording a new width run. */
1541 width_run_width = XFASTINT (width_table[c]);
1542 width_run_start = pos - 1;
1543 width_run_end = pos;
1544 }
1545 }
1546
1547 if (dp != 0
1548 && ! (multibyte && BASE_LEADING_CODE_P (c))
1549 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
1550 {
1551 charvec = DISP_CHAR_VECTOR (dp, c);
1552 n = ASIZE (charvec);
1553 }
1554 else
1555 {
1556 charvec = Qnil;
1557 n = 1;
1558 }
1559
1560 for (i = n - 1; i >= 0; --i)
1561 {
1562 if (VECTORP (charvec))
1563 {
1564 /* This should be handled the same as
1565 next_element_from_display_vector does it. */
1566 Lisp_Object entry = AREF (charvec, i);
1567
1568 if (INTEGERP (entry)
1569 && GLYPH_CHAR_VALID_P (XFASTINT (entry)))
1570 c = FAST_GLYPH_CHAR (XFASTINT (entry));
1571 else
1572 c = ' ';
1573 }
1574
1575 if (c >= 040 && c < 0177)
1576 hpos++;
1577 else if (c == '\t')
1578 {
1579 int tem = ((hpos + tab_offset + hscroll - (hscroll > 0))
1580 % tab_width);
1581 if (tem < 0)
1582 tem += tab_width;
1583 hpos += tab_width - tem;
1584 }
1585 else if (c == '\n')
1586 {
1587 if (selective > 0
1588 && indented_beyond_p (pos, pos_byte, selective))
1589 {
1590 /* If (pos == to), we don't have to take care of
1591 selective display. */
1592 if (pos < to)
1593 {
1594 /* Skip any number of invisible lines all at once */
1595 do
1596 {
1597 pos = find_before_next_newline (pos, to, 1);
1598 if (pos < to)
1599 pos++;
1600 pos_byte = CHAR_TO_BYTE (pos);
1601 }
1602 while (pos < to
1603 && indented_beyond_p (pos, pos_byte, selective));
1604 /* Allow for the " ..." that is displayed for them. */
1605 if (selective_rlen)
1606 {
1607 hpos += selective_rlen;
1608 if (hpos >= width)
1609 hpos = width;
1610 }
1611 DEC_BOTH (pos, pos_byte);
1612 /* We have skipped the invis text, but not the
1613 newline after. */
1614 }
1615 }
1616 else
1617 {
1618 /* A visible line. */
1619 vpos++;
1620 hpos = 0;
1621 hpos -= hscroll;
1622 /* Count the truncation glyph on column 0 */
1623 if (hscroll > 0)
1624 hpos++;
1625 tab_offset = 0;
1626 }
1627 contin_hpos = 0;
1628 }
1629 else if (c == CR && selective < 0)
1630 {
1631 /* In selective display mode,
1632 everything from a ^M to the end of the line is invisible.
1633 Stop *before* the real newline. */
1634 if (pos < to)
1635 {
1636 pos = find_before_next_newline (pos, to, 1);
1637 pos_byte = CHAR_TO_BYTE (pos);
1638 }
1639 /* If we just skipped next_boundary,
1640 loop around in the main while
1641 and handle it. */
1642 if (pos > next_boundary)
1643 next_boundary = pos;
1644 /* Allow for the " ..." that is displayed for them. */
1645 if (selective_rlen)
1646 {
1647 hpos += selective_rlen;
1648 if (hpos >= width)
1649 hpos = width;
1650 }
1651 }
1652 else if (multibyte && BASE_LEADING_CODE_P (c))
1653 {
1654 /* Start of multi-byte form. */
1655 unsigned char *ptr;
1656 int bytes, width, wide_column;
1657
1658 pos_byte--; /* rewind POS_BYTE */
1659 ptr = BYTE_POS_ADDR (pos_byte);
1660 MULTIBYTE_BYTES_WIDTH (ptr, dp);
1661 pos_byte += bytes;
1662 if (wide_column)
1663 wide_column_end_hpos = hpos + wide_column;
1664 hpos += width;
1665 }
1666 else if (VECTORP (charvec))
1667 ++hpos;
1668 else
1669 hpos += (ctl_arrow && c < 0200) ? 2 : 4;
1670 }
1671 }
1672 }
1673
1674 after_loop:
1675
1676 /* Remember any final width run in the cache. */
1677 if (current_buffer->width_run_cache
1678 && width_run_width == 1
1679 && width_run_start < width_run_end)
1680 know_region_cache (current_buffer, current_buffer->width_run_cache,
1681 width_run_start, width_run_end);
1682
1683 val_compute_motion.bufpos = pos;
1684 val_compute_motion.bytepos = pos_byte;
1685 val_compute_motion.hpos = hpos;
1686 val_compute_motion.vpos = vpos;
1687 if (contin_hpos && prev_hpos == 0)
1688 val_compute_motion.prevhpos = contin_hpos;
1689 else
1690 val_compute_motion.prevhpos = prev_hpos;
1691 /* We alalways handle all of them here; none of them remain to do. */
1692 val_compute_motion.ovstring_chars_done = 0;
1693
1694 /* Nonzero if have just continued a line */
1695 val_compute_motion.contin = (contin_hpos && prev_hpos == 0);
1696
1697 immediate_quit = 0;
1698 return &val_compute_motion;
1699 }
1700
1701
1702 DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0,
1703 doc: /* Scan through the current buffer, calculating screen position.
1704 Scan the current buffer forward from offset FROM,
1705 assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--
1706 to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--
1707 and return the ending buffer position and screen location.
1708
1709 There are three additional arguments:
1710
1711 WIDTH is the number of columns available to display text;
1712 this affects handling of continuation lines.
1713 This is usually the value returned by `window-width', less one (to allow
1714 for the continuation glyph).
1715
1716 OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).
1717 HSCROLL is the number of columns not being displayed at the left
1718 margin; this is usually taken from a window's hscroll member.
1719 TAB-OFFSET is the number of columns of the first tab that aren't
1720 being displayed, perhaps because the line was continued within it.
1721 If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.
1722
1723 WINDOW is the window to operate on. It is used to choose the display table;
1724 if it is showing the current buffer, it is used also for
1725 deciding which overlay properties apply.
1726 Note that `compute-motion' always operates on the current buffer.
1727
1728 The value is a list of five elements:
1729 (POS HPOS VPOS PREVHPOS CONTIN)
1730 POS is the buffer position where the scan stopped.
1731 VPOS is the vertical position where the scan stopped.
1732 HPOS is the horizontal position where the scan stopped.
1733
1734 PREVHPOS is the horizontal position one character back from POS.
1735 CONTIN is t if a line was continued after (or within) the previous character.
1736
1737 For example, to find the buffer position of column COL of line LINE
1738 of a certain window, pass the window's starting location as FROM
1739 and the window's upper-left coordinates as FROMPOS.
1740 Pass the buffer's (point-max) as TO, to limit the scan to the end of the
1741 visible section of the buffer, and pass LINE and COL as TOPOS. */)
1742 (from, frompos, to, topos, width, offsets, window)
1743 Lisp_Object from, frompos, to, topos;
1744 Lisp_Object width, offsets, window;
1745 {
1746 Lisp_Object bufpos, hpos, vpos, prevhpos;
1747 struct position *pos;
1748 int hscroll, tab_offset;
1749
1750 CHECK_NUMBER_COERCE_MARKER (from, 0);
1751 CHECK_CONS (frompos, 0);
1752 CHECK_NUMBER_CAR (frompos, 0);
1753 CHECK_NUMBER_CDR (frompos, 0);
1754 CHECK_NUMBER_COERCE_MARKER (to, 0);
1755 CHECK_CONS (topos, 0);
1756 CHECK_NUMBER_CAR (topos, 0);
1757 CHECK_NUMBER_CDR (topos, 0);
1758 CHECK_NUMBER (width, 0);
1759 if (!NILP (offsets))
1760 {
1761 CHECK_CONS (offsets, 0);
1762 CHECK_NUMBER_CAR (offsets, 0);
1763 CHECK_NUMBER_CDR (offsets, 0);
1764 hscroll = XINT (XCAR (offsets));
1765 tab_offset = XINT (XCDR (offsets));
1766 }
1767 else
1768 hscroll = tab_offset = 0;
1769
1770 if (NILP (window))
1771 window = Fselected_window ();
1772 else
1773 CHECK_LIVE_WINDOW (window, 0);
1774
1775 if (XINT (from) < BEGV || XINT (from) > ZV)
1776 args_out_of_range_3 (from, make_number (BEGV), make_number (ZV));
1777 if (XINT (to) < BEGV || XINT (to) > ZV)
1778 args_out_of_range_3 (to, make_number (BEGV), make_number (ZV));
1779
1780 pos = compute_motion (XINT (from), XINT (XCDR (frompos)),
1781 XINT (XCAR (frompos)), 0,
1782 XINT (to), XINT (XCDR (topos)),
1783 XINT (XCAR (topos)),
1784 XINT (width), hscroll, tab_offset,
1785 XWINDOW (window));
1786
1787 XSETFASTINT (bufpos, pos->bufpos);
1788 XSETINT (hpos, pos->hpos);
1789 XSETINT (vpos, pos->vpos);
1790 XSETINT (prevhpos, pos->prevhpos);
1791
1792 return Fcons (bufpos,
1793 Fcons (hpos,
1794 Fcons (vpos,
1795 Fcons (prevhpos,
1796 Fcons (pos->contin ? Qt : Qnil, Qnil)))));
1797
1798 }
1799 \f
1800 /* Fvertical_motion and vmotion */
1801
1802 struct position val_vmotion;
1803
1804 struct position *
1805 vmotion (from, vtarget, w)
1806 register int from, vtarget;
1807 struct window *w;
1808 {
1809 int width = window_internal_width (w) - 1;
1810 int hscroll = XINT (w->hscroll);
1811 struct position pos;
1812 /* vpos is cumulative vertical position, changed as from is changed */
1813 register int vpos = 0;
1814 Lisp_Object prevline;
1815 register int first;
1816 int from_byte;
1817 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
1818 int selective
1819 = (INTEGERP (current_buffer->selective_display)
1820 ? XINT (current_buffer->selective_display)
1821 : !NILP (current_buffer->selective_display) ? -1 : 0);
1822 Lisp_Object window;
1823 int start_hpos = 0;
1824 int did_motion;
1825 /* This is the object we use for fetching character properties. */
1826 Lisp_Object text_prop_object;
1827
1828 XSETWINDOW (window, w);
1829
1830 /* If the window contains this buffer, use it for getting text properties.
1831 Otherwise use the current buffer as arg for doing that. */
1832 if (EQ (w->buffer, Fcurrent_buffer ()))
1833 text_prop_object = window;
1834 else
1835 text_prop_object = Fcurrent_buffer ();
1836
1837 if (vpos >= vtarget)
1838 {
1839 /* To move upward, go a line at a time until
1840 we have gone at least far enough. */
1841
1842 first = 1;
1843
1844 while ((vpos > vtarget || first) && from > BEGV)
1845 {
1846 Lisp_Object propval;
1847
1848 XSETFASTINT (prevline, find_next_newline_no_quit (from - 1, -1));
1849 while (XFASTINT (prevline) > BEGV
1850 && ((selective > 0
1851 && indented_beyond_p (XFASTINT (prevline),
1852 CHAR_TO_BYTE (XFASTINT (prevline)),
1853 selective))
1854 /* watch out for newlines with `invisible' property */
1855 || (propval = Fget_char_property (prevline,
1856 Qinvisible,
1857 text_prop_object),
1858 TEXT_PROP_MEANS_INVISIBLE (propval))))
1859 XSETFASTINT (prevline,
1860 find_next_newline_no_quit (XFASTINT (prevline) - 1,
1861 -1));
1862 pos = *compute_motion (XFASTINT (prevline), 0,
1863 lmargin + (XFASTINT (prevline) == BEG
1864 ? start_hpos : 0),
1865 0,
1866 from,
1867 /* Don't care for VPOS... */
1868 1 << (BITS_PER_SHORT - 1),
1869 /* ... nor HPOS. */
1870 1 << (BITS_PER_SHORT - 1),
1871 width, hscroll,
1872 /* This compensates for start_hpos
1873 so that a tab as first character
1874 still occupies 8 columns. */
1875 (XFASTINT (prevline) == BEG
1876 ? -start_hpos : 0),
1877 w);
1878 vpos -= pos.vpos;
1879 first = 0;
1880 from = XFASTINT (prevline);
1881 }
1882
1883 /* If we made exactly the desired vertical distance,
1884 or if we hit beginning of buffer,
1885 return point found */
1886 if (vpos >= vtarget)
1887 {
1888 val_vmotion.bufpos = from;
1889 val_vmotion.bytepos = CHAR_TO_BYTE (from);
1890 val_vmotion.vpos = vpos;
1891 val_vmotion.hpos = lmargin;
1892 val_vmotion.contin = 0;
1893 val_vmotion.prevhpos = 0;
1894 val_vmotion.ovstring_chars_done = 0;
1895 val_vmotion.tab_offset = 0; /* For accumulating tab offset. */
1896 return &val_vmotion;
1897 }
1898
1899 /* Otherwise find the correct spot by moving down */
1900 }
1901 /* Moving downward is simple, but must calculate from beg of line
1902 to determine hpos of starting point */
1903 from_byte = CHAR_TO_BYTE (from);
1904 if (from > BEGV && FETCH_BYTE (from_byte - 1) != '\n')
1905 {
1906 Lisp_Object propval;
1907
1908 XSETFASTINT (prevline, find_next_newline_no_quit (from, -1));
1909 while (XFASTINT (prevline) > BEGV
1910 && ((selective > 0
1911 && indented_beyond_p (XFASTINT (prevline),
1912 CHAR_TO_BYTE (XFASTINT (prevline)),
1913 selective))
1914 /* watch out for newlines with `invisible' property */
1915 || (propval = Fget_char_property (prevline, Qinvisible,
1916 text_prop_object),
1917 TEXT_PROP_MEANS_INVISIBLE (propval))))
1918 XSETFASTINT (prevline,
1919 find_next_newline_no_quit (XFASTINT (prevline) - 1,
1920 -1));
1921 pos = *compute_motion (XFASTINT (prevline), 0,
1922 lmargin + (XFASTINT (prevline) == BEG
1923 ? start_hpos : 0),
1924 0,
1925 from,
1926 /* Don't care for VPOS... */
1927 1 << (BITS_PER_SHORT - 1),
1928 /* ... nor HPOS. */
1929 1 << (BITS_PER_SHORT - 1),
1930 width, hscroll,
1931 (XFASTINT (prevline) == BEG ? -start_hpos : 0),
1932 w);
1933 did_motion = 1;
1934 }
1935 else
1936 {
1937 pos.hpos = lmargin + (from == BEG ? start_hpos : 0);
1938 pos.vpos = 0;
1939 pos.tab_offset = 0;
1940 did_motion = 0;
1941 }
1942 return compute_motion (from, vpos, pos.hpos, did_motion,
1943 ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)),
1944 width, hscroll,
1945 pos.tab_offset - (from == BEG ? start_hpos : 0),
1946 w);
1947 }
1948
1949 DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
1950 doc: /* Move point to start of the screen line LINES lines down.
1951 If LINES is negative, this means moving up.
1952
1953 This function is an ordinary cursor motion function
1954 which calculates the new position based on how text would be displayed.
1955 The new position may be the start of a line,
1956 or just the start of a continuation line.
1957 The function returns number of screen lines moved over;
1958 that usually equals LINES, but may be closer to zero
1959 if beginning or end of buffer was reached.
1960
1961 The optional second argument WINDOW specifies the window to use for
1962 parameters such as width, horizontal scrolling, and so on.
1963 The default is to use the selected window's parameters.
1964
1965 `vertical-motion' always uses the current buffer,
1966 regardless of which buffer is displayed in WINDOW.
1967 This is consistent with other cursor motion functions
1968 and makes it possible to use `vertical-motion' in any buffer,
1969 whether or not it is currently displayed in some window. */)
1970 (lines, window)
1971 Lisp_Object lines, window;
1972 {
1973 struct it it;
1974 struct text_pos pt;
1975 struct window *w;
1976 Lisp_Object old_buffer;
1977 struct gcpro gcpro1;
1978
1979 CHECK_NUMBER (lines, 0);
1980 if (! NILP (window))
1981 CHECK_WINDOW (window, 0);
1982 else
1983 window = selected_window;
1984 w = XWINDOW (window);
1985
1986 old_buffer = Qnil;
1987 GCPRO1 (old_buffer);
1988 if (XBUFFER (w->buffer) != current_buffer)
1989 {
1990 /* Set the window's buffer temporarily to the current buffer. */
1991 old_buffer = w->buffer;
1992 XSETBUFFER (w->buffer, current_buffer);
1993 }
1994
1995 SET_TEXT_POS (pt, PT, PT_BYTE);
1996 start_display (&it, w, pt);
1997 move_it_by_lines (&it, XINT (lines), 0);
1998 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
1999
2000 if (BUFFERP (old_buffer))
2001 w->buffer = old_buffer;
2002
2003 RETURN_UNGCPRO (make_number (it.vpos));
2004 }
2005
2006
2007 \f
2008 /* File's initialization. */
2009
2010 void
2011 syms_of_indent ()
2012 {
2013 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
2014 doc: /* *Indentation can insert tabs if this is non-nil.
2015 Setting this variable automatically makes it local to the current buffer. */);
2016 indent_tabs_mode = 1;
2017
2018 defsubr (&Scurrent_indentation);
2019 defsubr (&Sindent_to);
2020 defsubr (&Scurrent_column);
2021 defsubr (&Smove_to_column);
2022 defsubr (&Svertical_motion);
2023 defsubr (&Scompute_motion);
2024 }