]> code.delx.au - gnu-emacs/blob - src/indent.c
(skip_invisible): Use new retval of TEXT_PROP_MEANS_INVISIBLE.
[gnu-emacs] / 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 "Return the horizontal position of point. Beginning of line is column 0.\n\
332 This is calculated by adding together the widths of all the displayed\n\
333 representations of the character between the start of the previous line\n\
334 and point. (eg control characters will have a width of 2 or 4, tabs\n\
335 will have a variable width)\n\
336 Ignores finite width of frame, which means that this function may return\n\
337 values greater than (frame-width).\n\
338 Whether the line is visible (if `selective-display' is t) has no effect;\n\
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 "Indent from point with tabs and spaces until COLUMN is reached.\n\
719 Optional second argument MININUM says always do at least MININUM spaces\n\
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 "Return the indentation of the current line.\n\
771 This is the horizontal position of the character\n\
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 "Move point to column COLUMN in the current line.\n\
893 The column of a character is calculated by adding together the widths\n\
894 as displayed of the previous characters in the line.\n\
895 This function ignores line-continuation;\n\
896 there is no upper limit on the column number a character can have\n\
897 and horizontal scrolling has no effect.\n\
898 \n\
899 If specified column is within a character, point goes after that character.\n\
900 If it's past end of line, point goes to end of line.\n\n\
901 A non-nil second (optional) argument FORCE means,\n\
902 if COLUMN is in the middle of a tab character, change it to spaces.\n\
903 In addition, if FORCE is t, and the line is too short\n\
904 to reach column COLUMN, add spaces/tabs to get there.\n\
905 \n\
906 The return value is the current column.")
907 (column, force)
908 Lisp_Object column, force;
909 {
910 register int pos;
911 register int col = current_column ();
912 register int goal;
913 register int end;
914 register int tab_width = XINT (current_buffer->tab_width);
915 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
916 register struct Lisp_Char_Table *dp = buffer_display_table ();
917 register int multibyte = !NILP (current_buffer->enable_multibyte_characters);
918
919 Lisp_Object val;
920 int prev_col = 0;
921 int c = 0;
922 int next_boundary;
923
924 int pos_byte, end_byte, next_boundary_byte;
925
926 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
927 CHECK_NATNUM (column, 0);
928 goal = XINT (column);
929
930 pos = PT;
931 pos_byte = PT_BYTE;
932 end = ZV;
933 end_byte = ZV_BYTE;
934 next_boundary = pos;
935 next_boundary_byte = PT_BYTE;
936
937 /* If we're starting past the desired column,
938 back up to beginning of line and scan from there. */
939 if (col > goal)
940 {
941 end = pos;
942 pos = current_column_bol_cache;
943 pos_byte = CHAR_TO_BYTE (pos);
944 col = 0;
945 }
946
947 while (pos < end)
948 {
949 Lisp_Object charvec;
950 EMACS_INT i, n;
951
952 while (pos == next_boundary)
953 {
954 int prev = pos;
955 pos = skip_invisible (pos, &next_boundary, end, Qnil);
956 if (pos != prev)
957 pos_byte = CHAR_TO_BYTE (pos);
958 next_boundary_byte = CHAR_TO_BYTE (next_boundary);
959 if (pos >= end)
960 goto endloop;
961 }
962
963 /* Test reaching the goal column. We do this after skipping
964 invisible characters, so that we put point before the
965 character on which the cursor will appear. */
966 if (col >= goal)
967 break;
968
969 /* Check composition sequence. */
970 {
971 int len, len_byte, width;
972
973 if (check_composition (pos, pos_byte, Z, &len, &len_byte, &width))
974 {
975 pos += len;
976 pos_byte += len_byte;
977 col += width;
978 continue;
979 }
980 }
981
982 c = FETCH_BYTE (pos_byte);
983
984 if (dp != 0
985 && ! (multibyte && BASE_LEADING_CODE_P (c))
986 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
987 {
988 charvec = DISP_CHAR_VECTOR (dp, c);
989 n = ASIZE (charvec);
990 }
991 else
992 {
993 charvec = Qnil;
994 n = 1;
995 }
996
997 for (i = n - 1; i >= 0; --i)
998 {
999 if (VECTORP (charvec))
1000 {
1001 /* This should be handled the same as
1002 next_element_from_display_vector does it. */
1003 Lisp_Object entry = AREF (charvec, i);
1004
1005 if (INTEGERP (entry)
1006 && GLYPH_CHAR_VALID_P (XFASTINT (entry)))
1007 c = FAST_GLYPH_CHAR (XFASTINT (entry));
1008 else
1009 c = ' ';
1010 }
1011
1012
1013 if (c == '\n')
1014 goto endloop;
1015 if (c == '\r' && EQ (current_buffer->selective_display, Qt))
1016 goto endloop;
1017 pos++;
1018 pos_byte++;
1019 if (c == '\t')
1020 {
1021 prev_col = col;
1022 col += tab_width;
1023 col = col / tab_width * tab_width;
1024 }
1025 else if (VECTORP (charvec))
1026 ++col;
1027 else if (ctl_arrow && (c < 040 || c == 0177))
1028 col += 2;
1029 else if (c < 040 || c == 0177)
1030 col += 4;
1031 else if (c < 0177)
1032 col++;
1033 else if (multibyte && BASE_LEADING_CODE_P (c))
1034 {
1035 /* Start of multi-byte form. */
1036 unsigned char *ptr;
1037 int bytes, width, wide_column;
1038
1039 pos_byte--;
1040 ptr = BYTE_POS_ADDR (pos_byte);
1041 MULTIBYTE_BYTES_WIDTH (ptr, dp);
1042 pos_byte += bytes;
1043 col += width;
1044 }
1045 else
1046 col += 4;
1047 }
1048 }
1049 endloop:
1050
1051 SET_PT_BOTH (pos, pos_byte);
1052
1053 /* If a tab char made us overshoot, change it to spaces
1054 and scan through it again. */
1055 if (!NILP (force) && col > goal && c == '\t' && prev_col < goal)
1056 {
1057 int goal_pt, goal_pt_byte;
1058
1059 /* Insert spaces in front of the tab to reach GOAL. Do this
1060 first so that a marker at the end of the tab gets
1061 adjusted. */
1062 SET_PT_BOTH (PT - 1, PT_BYTE - 1);
1063 Finsert_char (make_number (' '), make_number (goal - prev_col), Qt);
1064
1065 /* Now delete the tab, and indent to COL. */
1066 del_range (PT, PT + 1);
1067 goal_pt = PT;
1068 goal_pt_byte = PT_BYTE;
1069 Findent_to (make_number (col), Qnil);
1070 SET_PT_BOTH (goal_pt, goal_pt_byte);
1071
1072 /* Set the last_known... vars consistently. */
1073 col = goal;
1074 }
1075
1076 /* If line ends prematurely, add space to the end. */
1077 if (col < goal && EQ (force, Qt))
1078 Findent_to (make_number (col = goal), Qnil);
1079
1080 last_known_column = col;
1081 last_known_column_point = PT;
1082 last_known_column_modified = MODIFF;
1083
1084 XSETFASTINT (val, col);
1085 return val;
1086 }
1087 \f
1088 /* compute_motion: compute buffer posn given screen posn and vice versa */
1089
1090 struct position val_compute_motion;
1091
1092 /* Scan the current buffer forward from offset FROM, pretending that
1093 this is at line FROMVPOS, column FROMHPOS, until reaching buffer
1094 offset TO or line TOVPOS, column TOHPOS (whichever comes first),
1095 and return the ending buffer position and screen location. If we
1096 can't hit the requested column exactly (because of a tab or other
1097 multi-column character), overshoot.
1098
1099 DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
1100 at FROM. This is the case if FROMVPOS and FROMVPOS came from an
1101 earlier call to compute_motion. The other common case is that FROMHPOS
1102 is zero and FROM is a position that "belongs" at column zero, but might
1103 be shifted by overlay strings; in this case DID_MOTION should be 0.
1104
1105 WIDTH is the number of columns available to display text;
1106 compute_motion uses this to handle continuation lines and such.
1107 HSCROLL is the number of columns not being displayed at the left
1108 margin; this is usually taken from a window's hscroll member.
1109 TAB_OFFSET is the number of columns of the first tab that aren't
1110 being displayed, perhaps because of a continuation line or
1111 something.
1112
1113 compute_motion returns a pointer to a struct position. The bufpos
1114 member gives the buffer position at the end of the scan, and hpos
1115 and vpos give its cartesian location. prevhpos is the column at
1116 which the character before bufpos started, and contin is non-zero
1117 if we reached the current line by continuing the previous.
1118
1119 Note that FROMHPOS and TOHPOS should be expressed in real screen
1120 columns, taking HSCROLL and the truncation glyph at the left margin
1121 into account. That is, beginning-of-line moves you to the hpos
1122 -HSCROLL + (HSCROLL > 0).
1123
1124 For example, to find the buffer position of column COL of line LINE
1125 of a certain window, pass the window's starting location as FROM
1126 and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
1127 Pass the buffer's ZV as TO, to limit the scan to the end of the
1128 visible section of the buffer, and pass LINE and COL as TOVPOS and
1129 TOHPOS.
1130
1131 When displaying in window w, a typical formula for WIDTH is:
1132
1133 window_width - 1
1134 - (has_vertical_scroll_bars
1135 ? FRAME_SCROLL_BAR_COLS (XFRAME (window->frame))
1136 : (window_width + window_left != frame_width))
1137
1138 where
1139 window_width is XFASTINT (w->width),
1140 window_left is XFASTINT (w->left),
1141 has_vertical_scroll_bars is
1142 FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (WINDOW_FRAME (window)))
1143 and frame_width = FRAME_WIDTH (XFRAME (window->frame))
1144
1145 Or you can let window_internal_width do this all for you, and write:
1146 window_internal_width (w) - 1
1147
1148 The `-1' accounts for the continuation-line backslashes; the rest
1149 accounts for window borders if the window is split horizontally, and
1150 the scroll bars if they are turned on. */
1151
1152 struct position *
1153 compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, hscroll, tab_offset, win)
1154 int from, fromvpos, fromhpos, to, tovpos, tohpos;
1155 int did_motion;
1156 register int width;
1157 int hscroll, tab_offset;
1158 struct window *win;
1159 {
1160 register int hpos = fromhpos;
1161 register int vpos = fromvpos;
1162
1163 register int pos;
1164 int pos_byte;
1165 register int c = 0;
1166 register int tab_width = XFASTINT (current_buffer->tab_width);
1167 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
1168 register struct Lisp_Char_Table *dp = window_display_table (win);
1169 int selective
1170 = (INTEGERP (current_buffer->selective_display)
1171 ? XINT (current_buffer->selective_display)
1172 : !NILP (current_buffer->selective_display) ? -1 : 0);
1173 int prev_hpos = 0;
1174 int selective_rlen
1175 = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
1176 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0);
1177 /* The next location where the `invisible' property changes, or an
1178 overlay starts or ends. */
1179 int next_boundary = from;
1180
1181 /* For computing runs of characters with similar widths.
1182 Invariant: width_run_width is zero, or all the characters
1183 from width_run_start to width_run_end have a fixed width of
1184 width_run_width. */
1185 int width_run_start = from;
1186 int width_run_end = from;
1187 int width_run_width = 0;
1188 Lisp_Object *width_table;
1189 Lisp_Object buffer;
1190
1191 /* The next buffer pos where we should consult the width run cache. */
1192 int next_width_run = from;
1193 Lisp_Object window;
1194
1195 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
1196 /* If previous char scanned was a wide character,
1197 this is the column where it ended. Otherwise, this is 0. */
1198 int wide_column_end_hpos = 0;
1199 int prev_pos; /* Previous buffer position. */
1200 int prev_pos_byte; /* Previous buffer position. */
1201 int contin_hpos; /* HPOS of last column of continued line. */
1202 int prev_tab_offset; /* Previous tab offset. */
1203
1204 XSETBUFFER (buffer, current_buffer);
1205 XSETWINDOW (window, win);
1206
1207 width_run_cache_on_off ();
1208 if (dp == buffer_display_table ())
1209 width_table = (VECTORP (current_buffer->width_table)
1210 ? XVECTOR (current_buffer->width_table)->contents
1211 : 0);
1212 else
1213 /* If the window has its own display table, we can't use the width
1214 run cache, because that's based on the buffer's display table. */
1215 width_table = 0;
1216
1217 if (tab_width <= 0 || tab_width > 1000)
1218 tab_width = 8;
1219
1220 immediate_quit = 1;
1221 QUIT;
1222
1223 pos = prev_pos = from;
1224 pos_byte = prev_pos_byte = CHAR_TO_BYTE (from);
1225 contin_hpos = 0;
1226 prev_tab_offset = tab_offset;
1227 while (1)
1228 {
1229 while (pos == next_boundary)
1230 {
1231 int pos_here = pos;
1232 int newpos;
1233
1234 /* Don't skip invisible if we are already at the margin. */
1235 if (vpos > tovpos || vpos == tovpos && hpos >= tohpos)
1236 {
1237 if (contin_hpos && prev_hpos == 0
1238 && hpos > tohpos
1239 && (contin_hpos == width || wide_column_end_hpos > width))
1240 { /* Line breaks because we can't put the character at the
1241 previous line any more. It is not the multi-column
1242 character continued in middle. Go back to previous
1243 buffer position, screen position, and set tab offset
1244 to previous value. It's the beginning of the
1245 line. */
1246 pos = prev_pos;
1247 pos_byte = prev_pos_byte;
1248 hpos = prev_hpos;
1249 tab_offset = prev_tab_offset;
1250 }
1251 break;
1252 }
1253
1254 /* If the caller says that the screen position came from an earlier
1255 call to compute_motion, then we've already accounted for the
1256 overlay strings at point. This is only true the first time
1257 through, so clear the flag after testing it. */
1258 if (!did_motion)
1259 /* We need to skip past the overlay strings. Currently those
1260 strings must not contain TAB;
1261 if we want to relax that restriction, something will have
1262 to be changed here. */
1263 {
1264 unsigned char *ovstr;
1265 int ovlen = overlay_strings (pos, win, &ovstr);
1266 hpos += ((multibyte && ovlen > 0)
1267 ? strwidth (ovstr, ovlen) : ovlen);
1268 }
1269 did_motion = 0;
1270
1271 if (pos >= to)
1272 break;
1273
1274 /* Advance POS past invisible characters
1275 (but not necessarily all that there are here),
1276 and store in next_boundary the next position where
1277 we need to call skip_invisible. */
1278 newpos = skip_invisible (pos, &next_boundary, to, window);
1279
1280 if (newpos >= to)
1281 {
1282 pos = min (to, newpos);
1283 pos_byte = CHAR_TO_BYTE (pos);
1284 goto after_loop;
1285 }
1286
1287 if (newpos != pos_here)
1288 {
1289 pos = newpos;
1290 pos_byte = CHAR_TO_BYTE (pos);
1291 }
1292 }
1293
1294 /* Handle right margin. */
1295 /* Note on a wide-column character.
1296
1297 Characters are classified into the following three categories
1298 according to the width (columns occupied on screen).
1299
1300 (1) single-column character: ex. `a'
1301 (2) multi-column character: ex. `^A', TAB, `\033'
1302 (3) wide-column character: ex. Japanese character, Chinese character
1303 (In the following example, `W_' stands for them.)
1304
1305 Multi-column characters can be divided around the right margin,
1306 but wide-column characters cannot.
1307
1308 NOTE:
1309
1310 (*) The cursor is placed on the next character after the point.
1311
1312 ----------
1313 abcdefghi\
1314 j ^---- next after the point
1315 ^--- next char. after the point.
1316 ----------
1317 In case of sigle-column character
1318
1319 ----------
1320 abcdefgh\\
1321 033 ^---- next after the point, next char. after the point.
1322 ----------
1323 In case of multi-column character
1324
1325 ----------
1326 abcdefgh\\
1327 W_ ^---- next after the point
1328 ^---- next char. after the point.
1329 ----------
1330 In case of wide-column character
1331
1332 The problem here is continuation at a wide-column character.
1333 In this case, the line may shorter less than WIDTH.
1334 And we find the continuation AFTER it occurs.
1335
1336 */
1337
1338 if (hpos > width)
1339 {
1340 if (hscroll
1341 || (truncate_partial_width_windows
1342 && width + 1 < FRAME_WIDTH (XFRAME (WINDOW_FRAME (win))))
1343 || !NILP (current_buffer->truncate_lines))
1344 {
1345 /* Truncating: skip to newline, unless we are already past
1346 TO (we need to go back below). */
1347 if (pos <= to)
1348 {
1349 pos = find_before_next_newline (pos, to, 1);
1350 pos_byte = CHAR_TO_BYTE (pos);
1351 hpos = width;
1352 /* If we just skipped next_boundary,
1353 loop around in the main while
1354 and handle it. */
1355 if (pos >= next_boundary)
1356 next_boundary = pos + 1;
1357 prev_hpos = width;
1358 prev_tab_offset = tab_offset;
1359 }
1360 }
1361 else
1362 {
1363 /* Continuing. */
1364 /* Remember the previous value. */
1365 prev_tab_offset = tab_offset;
1366
1367 if (wide_column_end_hpos > width)
1368 {
1369 hpos -= prev_hpos;
1370 tab_offset += prev_hpos;
1371 }
1372 else
1373 {
1374 tab_offset += width;
1375 hpos -= width;
1376 }
1377 vpos++;
1378 contin_hpos = prev_hpos;
1379 prev_hpos = 0;
1380 }
1381 }
1382
1383 /* Stop if past the target buffer position or screen position. */
1384 if (pos > to)
1385 {
1386 /* Go back to the previous position. */
1387 pos = prev_pos;
1388 pos_byte = prev_pos_byte;
1389 hpos = prev_hpos;
1390 tab_offset = prev_tab_offset;
1391
1392 /* NOTE on contin_hpos, hpos, and prev_hpos.
1393
1394 ----------
1395 abcdefgh\\
1396 W_ ^---- contin_hpos
1397 | ^----- hpos
1398 \---- prev_hpos
1399 ----------
1400 */
1401
1402 if (contin_hpos && prev_hpos == 0
1403 && contin_hpos < width && !wide_column_end_hpos)
1404 {
1405 /* Line breaking occurs in the middle of multi-column
1406 character. Go back to previous line. */
1407 hpos = contin_hpos;
1408 vpos = vpos - 1;
1409 }
1410 else if (c == '\n')
1411 /* If previous character is NEWLINE,
1412 set VPOS back to previous line */
1413 vpos = vpos - 1;
1414 break;
1415 }
1416
1417 if (vpos > tovpos || vpos == tovpos && hpos >= tohpos)
1418 {
1419 if (contin_hpos && prev_hpos == 0
1420 && hpos > tohpos
1421 && (contin_hpos == width || wide_column_end_hpos > width))
1422 { /* Line breaks because we can't put the character at the
1423 previous line any more. It is not the multi-column
1424 character continued in middle. Go back to previous
1425 buffer position, screen position, and set tab offset
1426 to previous value. It's the beginning of the
1427 line. */
1428 pos = prev_pos;
1429 pos_byte = prev_pos_byte;
1430 hpos = prev_hpos;
1431 tab_offset = prev_tab_offset;
1432 }
1433 break;
1434 }
1435 if (pos == ZV) /* We cannot go beyond ZV. Stop here. */
1436 break;
1437
1438 prev_hpos = hpos;
1439 prev_pos = pos;
1440 prev_pos_byte = pos_byte;
1441 wide_column_end_hpos = 0;
1442
1443 /* Consult the width run cache to see if we can avoid inspecting
1444 the text character-by-character. */
1445 if (current_buffer->width_run_cache && pos >= next_width_run)
1446 {
1447 int run_end;
1448 int common_width
1449 = region_cache_forward (current_buffer,
1450 current_buffer->width_run_cache,
1451 pos, &run_end);
1452
1453 /* A width of zero means the character's width varies (like
1454 a tab), is meaningless (like a newline), or we just don't
1455 want to skip over it for some other reason. */
1456 if (common_width != 0)
1457 {
1458 int run_end_hpos;
1459
1460 /* Don't go past the final buffer posn the user
1461 requested. */
1462 if (run_end > to)
1463 run_end = to;
1464
1465 run_end_hpos = hpos + (run_end - pos) * common_width;
1466
1467 /* Don't go past the final horizontal position the user
1468 requested. */
1469 if (vpos == tovpos && run_end_hpos > tohpos)
1470 {
1471 run_end = pos + (tohpos - hpos) / common_width;
1472 run_end_hpos = hpos + (run_end - pos) * common_width;
1473 }
1474
1475 /* Don't go past the margin. */
1476 if (run_end_hpos >= width)
1477 {
1478 run_end = pos + (width - hpos) / common_width;
1479 run_end_hpos = hpos + (run_end - pos) * common_width;
1480 }
1481
1482 hpos = run_end_hpos;
1483 if (run_end > pos)
1484 prev_hpos = hpos - common_width;
1485 if (pos != run_end)
1486 {
1487 pos = run_end;
1488 pos_byte = CHAR_TO_BYTE (pos);
1489 }
1490 }
1491
1492 next_width_run = run_end + 1;
1493 }
1494
1495 /* We have to scan the text character-by-character. */
1496 else
1497 {
1498 EMACS_INT i, n;
1499 Lisp_Object charvec;
1500
1501 c = FETCH_BYTE (pos_byte);
1502
1503 /* Check composition sequence. */
1504 {
1505 int len, len_byte, width;
1506
1507 if (check_composition (pos, pos_byte, to, &len, &len_byte, &width))
1508 {
1509 pos += len;
1510 pos_byte += len_byte;
1511 hpos += width;
1512 continue;
1513 }
1514 }
1515
1516 pos++, pos_byte++;
1517
1518 /* Perhaps add some info to the width_run_cache. */
1519 if (current_buffer->width_run_cache)
1520 {
1521 /* Is this character part of the current run? If so, extend
1522 the run. */
1523 if (pos - 1 == width_run_end
1524 && XFASTINT (width_table[c]) == width_run_width)
1525 width_run_end = pos;
1526
1527 /* The previous run is over, since this is a character at a
1528 different position, or a different width. */
1529 else
1530 {
1531 /* Have we accumulated a run to put in the cache?
1532 (Currently, we only cache runs of width == 1). */
1533 if (width_run_start < width_run_end
1534 && width_run_width == 1)
1535 know_region_cache (current_buffer,
1536 current_buffer->width_run_cache,
1537 width_run_start, width_run_end);
1538
1539 /* Start recording a new width run. */
1540 width_run_width = XFASTINT (width_table[c]);
1541 width_run_start = pos - 1;
1542 width_run_end = pos;
1543 }
1544 }
1545
1546 if (dp != 0
1547 && ! (multibyte && BASE_LEADING_CODE_P (c))
1548 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
1549 {
1550 charvec = DISP_CHAR_VECTOR (dp, c);
1551 n = ASIZE (charvec);
1552 }
1553 else
1554 {
1555 charvec = Qnil;
1556 n = 1;
1557 }
1558
1559 for (i = n - 1; i >= 0; --i)
1560 {
1561 if (VECTORP (charvec))
1562 {
1563 /* This should be handled the same as
1564 next_element_from_display_vector does it. */
1565 Lisp_Object entry = AREF (charvec, i);
1566
1567 if (INTEGERP (entry)
1568 && GLYPH_CHAR_VALID_P (XFASTINT (entry)))
1569 c = FAST_GLYPH_CHAR (XFASTINT (entry));
1570 else
1571 c = ' ';
1572 }
1573
1574 if (c >= 040 && c < 0177)
1575 hpos++;
1576 else if (c == '\t')
1577 {
1578 int tem = ((hpos + tab_offset + hscroll - (hscroll > 0))
1579 % tab_width);
1580 if (tem < 0)
1581 tem += tab_width;
1582 hpos += tab_width - tem;
1583 }
1584 else if (c == '\n')
1585 {
1586 if (selective > 0
1587 && indented_beyond_p (pos, pos_byte, selective))
1588 {
1589 /* If (pos == to), we don't have to take care of
1590 selective display. */
1591 if (pos < to)
1592 {
1593 /* Skip any number of invisible lines all at once */
1594 do
1595 {
1596 pos = find_before_next_newline (pos, to, 1);
1597 if (pos < to)
1598 pos++;
1599 pos_byte = CHAR_TO_BYTE (pos);
1600 }
1601 while (pos < to
1602 && indented_beyond_p (pos, pos_byte, selective));
1603 /* Allow for the " ..." that is displayed for them. */
1604 if (selective_rlen)
1605 {
1606 hpos += selective_rlen;
1607 if (hpos >= width)
1608 hpos = width;
1609 }
1610 DEC_BOTH (pos, pos_byte);
1611 /* We have skipped the invis text, but not the
1612 newline after. */
1613 }
1614 }
1615 else
1616 {
1617 /* A visible line. */
1618 vpos++;
1619 hpos = 0;
1620 hpos -= hscroll;
1621 /* Count the truncation glyph on column 0 */
1622 if (hscroll > 0)
1623 hpos++;
1624 tab_offset = 0;
1625 }
1626 contin_hpos = 0;
1627 }
1628 else if (c == CR && selective < 0)
1629 {
1630 /* In selective display mode,
1631 everything from a ^M to the end of the line is invisible.
1632 Stop *before* the real newline. */
1633 if (pos < to)
1634 {
1635 pos = find_before_next_newline (pos, to, 1);
1636 pos_byte = CHAR_TO_BYTE (pos);
1637 }
1638 /* If we just skipped next_boundary,
1639 loop around in the main while
1640 and handle it. */
1641 if (pos > next_boundary)
1642 next_boundary = pos;
1643 /* Allow for the " ..." that is displayed for them. */
1644 if (selective_rlen)
1645 {
1646 hpos += selective_rlen;
1647 if (hpos >= width)
1648 hpos = width;
1649 }
1650 }
1651 else if (multibyte && BASE_LEADING_CODE_P (c))
1652 {
1653 /* Start of multi-byte form. */
1654 unsigned char *ptr;
1655 int bytes, width, wide_column;
1656
1657 pos_byte--; /* rewind POS_BYTE */
1658 ptr = BYTE_POS_ADDR (pos_byte);
1659 MULTIBYTE_BYTES_WIDTH (ptr, dp);
1660 pos_byte += bytes;
1661 if (wide_column)
1662 wide_column_end_hpos = hpos + wide_column;
1663 hpos += width;
1664 }
1665 else if (VECTORP (charvec))
1666 ++hpos;
1667 else
1668 hpos += (ctl_arrow && c < 0200) ? 2 : 4;
1669 }
1670 }
1671 }
1672
1673 after_loop:
1674
1675 /* Remember any final width run in the cache. */
1676 if (current_buffer->width_run_cache
1677 && width_run_width == 1
1678 && width_run_start < width_run_end)
1679 know_region_cache (current_buffer, current_buffer->width_run_cache,
1680 width_run_start, width_run_end);
1681
1682 val_compute_motion.bufpos = pos;
1683 val_compute_motion.bytepos = pos_byte;
1684 val_compute_motion.hpos = hpos;
1685 val_compute_motion.vpos = vpos;
1686 if (contin_hpos && prev_hpos == 0)
1687 val_compute_motion.prevhpos = contin_hpos;
1688 else
1689 val_compute_motion.prevhpos = prev_hpos;
1690 /* We alalways handle all of them here; none of them remain to do. */
1691 val_compute_motion.ovstring_chars_done = 0;
1692
1693 /* Nonzero if have just continued a line */
1694 val_compute_motion.contin = (contin_hpos && prev_hpos == 0);
1695
1696 immediate_quit = 0;
1697 return &val_compute_motion;
1698 }
1699
1700
1701 #if 0 /* The doc string is too long for some compilers,
1702 but make-docfile can find it in this comment. */
1703 DEFUN ("compute-motion", Ffoo, Sfoo, 7, 7, 0,
1704 "Scan through the current buffer, calculating screen position.\n\
1705 Scan the current buffer forward from offset FROM,\n\
1706 assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--\n\
1707 to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--\n\
1708 and return the ending buffer position and screen location.\n\
1709 \n\
1710 There are three additional arguments:\n\
1711 \n\
1712 WIDTH is the number of columns available to display text;\n\
1713 this affects handling of continuation lines.\n\
1714 This is usually the value returned by `window-width', less one (to allow\n\
1715 for the continuation glyph).\n\
1716 \n\
1717 OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).\n\
1718 HSCROLL is the number of columns not being displayed at the left\n\
1719 margin; this is usually taken from a window's hscroll member.\n\
1720 TAB-OFFSET is the number of columns of the first tab that aren't\n\
1721 being displayed, perhaps because the line was continued within it.\n\
1722 If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.\n\
1723 \n\
1724 WINDOW is the window to operate on. It is used to choose the display table;\n\
1725 if it is showing the current buffer, it is used also for\n\
1726 deciding which overlay properties apply.\n\
1727 Note that `compute-motion' always operates on the current buffer.\n\
1728 \n\
1729 The value is a list of five elements:\n\
1730 (POS HPOS VPOS PREVHPOS CONTIN)\n\
1731 POS is the buffer position where the scan stopped.\n\
1732 VPOS is the vertical position where the scan stopped.\n\
1733 HPOS is the horizontal position where the scan stopped.\n\
1734 \n\
1735 PREVHPOS is the horizontal position one character back from POS.\n\
1736 CONTIN is t if a line was continued after (or within) the previous character.\n\
1737 \n\
1738 For example, to find the buffer position of column COL of line LINE\n\
1739 of a certain window, pass the window's starting location as FROM\n\
1740 and the window's upper-left coordinates as FROMPOS.\n\
1741 Pass the buffer's (point-max) as TO, to limit the scan to the end of the\n\
1742 visible section of the buffer, and pass LINE and COL as TOPOS.")
1743 (from, frompos, to, topos, width, offsets, window)
1744 #endif
1745
1746 DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0,
1747 0)
1748 (from, frompos, to, topos, width, offsets, window)
1749 Lisp_Object from, frompos, to, topos;
1750 Lisp_Object width, offsets, window;
1751 {
1752 Lisp_Object bufpos, hpos, vpos, prevhpos;
1753 struct position *pos;
1754 int hscroll, tab_offset;
1755
1756 CHECK_NUMBER_COERCE_MARKER (from, 0);
1757 CHECK_CONS (frompos, 0);
1758 CHECK_NUMBER (XCAR (frompos), 0);
1759 CHECK_NUMBER (XCDR (frompos), 0);
1760 CHECK_NUMBER_COERCE_MARKER (to, 0);
1761 CHECK_CONS (topos, 0);
1762 CHECK_NUMBER (XCAR (topos), 0);
1763 CHECK_NUMBER (XCDR (topos), 0);
1764 CHECK_NUMBER (width, 0);
1765 if (!NILP (offsets))
1766 {
1767 CHECK_CONS (offsets, 0);
1768 CHECK_NUMBER (XCAR (offsets), 0);
1769 CHECK_NUMBER (XCDR (offsets), 0);
1770 hscroll = XINT (XCAR (offsets));
1771 tab_offset = XINT (XCDR (offsets));
1772 }
1773 else
1774 hscroll = tab_offset = 0;
1775
1776 if (NILP (window))
1777 window = Fselected_window ();
1778 else
1779 CHECK_LIVE_WINDOW (window, 0);
1780
1781 if (XINT (from) < BEGV || XINT (from) > ZV)
1782 args_out_of_range_3 (from, make_number (BEGV), make_number (ZV));
1783 if (XINT (to) < BEGV || XINT (to) > ZV)
1784 args_out_of_range_3 (to, make_number (BEGV), make_number (ZV));
1785
1786 pos = compute_motion (XINT (from), XINT (XCDR (frompos)),
1787 XINT (XCAR (frompos)), 0,
1788 XINT (to), XINT (XCDR (topos)),
1789 XINT (XCAR (topos)),
1790 XINT (width), hscroll, tab_offset,
1791 XWINDOW (window));
1792
1793 XSETFASTINT (bufpos, pos->bufpos);
1794 XSETINT (hpos, pos->hpos);
1795 XSETINT (vpos, pos->vpos);
1796 XSETINT (prevhpos, pos->prevhpos);
1797
1798 return Fcons (bufpos,
1799 Fcons (hpos,
1800 Fcons (vpos,
1801 Fcons (prevhpos,
1802 Fcons (pos->contin ? Qt : Qnil, Qnil)))));
1803
1804 }
1805 \f
1806 /* Fvertical_motion and vmotion */
1807
1808 struct position val_vmotion;
1809
1810 struct position *
1811 vmotion (from, vtarget, w)
1812 register int from, vtarget;
1813 struct window *w;
1814 {
1815 int width = window_internal_width (w) - 1;
1816 int hscroll = XINT (w->hscroll);
1817 struct position pos;
1818 /* vpos is cumulative vertical position, changed as from is changed */
1819 register int vpos = 0;
1820 Lisp_Object prevline;
1821 register int first;
1822 int from_byte;
1823 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
1824 int selective
1825 = (INTEGERP (current_buffer->selective_display)
1826 ? XINT (current_buffer->selective_display)
1827 : !NILP (current_buffer->selective_display) ? -1 : 0);
1828 Lisp_Object window;
1829 int start_hpos = 0;
1830 int did_motion;
1831 /* This is the object we use for fetching character properties. */
1832 Lisp_Object text_prop_object;
1833
1834 XSETWINDOW (window, w);
1835
1836 /* If the window contains this buffer, use it for getting text properties.
1837 Otherwise use the current buffer as arg for doing that. */
1838 if (EQ (w->buffer, Fcurrent_buffer ()))
1839 text_prop_object = window;
1840 else
1841 text_prop_object = Fcurrent_buffer ();
1842
1843 if (vpos >= vtarget)
1844 {
1845 /* To move upward, go a line at a time until
1846 we have gone at least far enough. */
1847
1848 first = 1;
1849
1850 while ((vpos > vtarget || first) && from > BEGV)
1851 {
1852 Lisp_Object propval;
1853
1854 XSETFASTINT (prevline, find_next_newline_no_quit (from - 1, -1));
1855 while (XFASTINT (prevline) > BEGV
1856 && ((selective > 0
1857 && indented_beyond_p (XFASTINT (prevline),
1858 CHAR_TO_BYTE (XFASTINT (prevline)),
1859 selective))
1860 /* watch out for newlines with `invisible' property */
1861 || (propval = Fget_char_property (prevline,
1862 Qinvisible,
1863 text_prop_object),
1864 TEXT_PROP_MEANS_INVISIBLE (propval))))
1865 XSETFASTINT (prevline,
1866 find_next_newline_no_quit (XFASTINT (prevline) - 1,
1867 -1));
1868 pos = *compute_motion (XFASTINT (prevline), 0,
1869 lmargin + (XFASTINT (prevline) == BEG
1870 ? start_hpos : 0),
1871 0,
1872 from,
1873 /* Don't care for VPOS... */
1874 1 << (BITS_PER_SHORT - 1),
1875 /* ... nor HPOS. */
1876 1 << (BITS_PER_SHORT - 1),
1877 width, hscroll,
1878 /* This compensates for start_hpos
1879 so that a tab as first character
1880 still occupies 8 columns. */
1881 (XFASTINT (prevline) == BEG
1882 ? -start_hpos : 0),
1883 w);
1884 vpos -= pos.vpos;
1885 first = 0;
1886 from = XFASTINT (prevline);
1887 }
1888
1889 /* If we made exactly the desired vertical distance,
1890 or if we hit beginning of buffer,
1891 return point found */
1892 if (vpos >= vtarget)
1893 {
1894 val_vmotion.bufpos = from;
1895 val_vmotion.bytepos = CHAR_TO_BYTE (from);
1896 val_vmotion.vpos = vpos;
1897 val_vmotion.hpos = lmargin;
1898 val_vmotion.contin = 0;
1899 val_vmotion.prevhpos = 0;
1900 val_vmotion.ovstring_chars_done = 0;
1901 val_vmotion.tab_offset = 0; /* For accumulating tab offset. */
1902 return &val_vmotion;
1903 }
1904
1905 /* Otherwise find the correct spot by moving down */
1906 }
1907 /* Moving downward is simple, but must calculate from beg of line
1908 to determine hpos of starting point */
1909 from_byte = CHAR_TO_BYTE (from);
1910 if (from > BEGV && FETCH_BYTE (from_byte - 1) != '\n')
1911 {
1912 Lisp_Object propval;
1913
1914 XSETFASTINT (prevline, find_next_newline_no_quit (from, -1));
1915 while (XFASTINT (prevline) > BEGV
1916 && ((selective > 0
1917 && indented_beyond_p (XFASTINT (prevline),
1918 CHAR_TO_BYTE (XFASTINT (prevline)),
1919 selective))
1920 /* watch out for newlines with `invisible' property */
1921 || (propval = Fget_char_property (prevline, Qinvisible,
1922 text_prop_object),
1923 TEXT_PROP_MEANS_INVISIBLE (propval))))
1924 XSETFASTINT (prevline,
1925 find_next_newline_no_quit (XFASTINT (prevline) - 1,
1926 -1));
1927 pos = *compute_motion (XFASTINT (prevline), 0,
1928 lmargin + (XFASTINT (prevline) == BEG
1929 ? start_hpos : 0),
1930 0,
1931 from,
1932 /* Don't care for VPOS... */
1933 1 << (BITS_PER_SHORT - 1),
1934 /* ... nor HPOS. */
1935 1 << (BITS_PER_SHORT - 1),
1936 width, hscroll,
1937 (XFASTINT (prevline) == BEG ? -start_hpos : 0),
1938 w);
1939 did_motion = 1;
1940 }
1941 else
1942 {
1943 pos.hpos = lmargin + (from == BEG ? start_hpos : 0);
1944 pos.vpos = 0;
1945 pos.tab_offset = 0;
1946 did_motion = 0;
1947 }
1948 return compute_motion (from, vpos, pos.hpos, did_motion,
1949 ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)),
1950 width, hscroll,
1951 pos.tab_offset - (from == BEG ? start_hpos : 0),
1952 w);
1953 }
1954
1955 DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
1956 "Move point to start of the screen line LINES lines down.\n\
1957 If LINES is negative, this means moving up.\n\
1958 \n\
1959 This function is an ordinary cursor motion function\n\
1960 which calculates the new position based on how text would be displayed.\n\
1961 The new position may be the start of a line,\n\
1962 or just the start of a continuation line.\n\
1963 The function returns number of screen lines moved over;\n\
1964 that usually equals LINES, but may be closer to zero\n\
1965 if beginning or end of buffer was reached.\n\
1966 \n\
1967 The optional second argument WINDOW specifies the window to use for\n\
1968 parameters such as width, horizontal scrolling, and so on.\n\
1969 The default is to use the selected window's parameters.\n\
1970 \n\
1971 `vertical-motion' always uses the current buffer,\n\
1972 regardless of which buffer is displayed in WINDOW.\n\
1973 This is consistent with other cursor motion functions\n\
1974 and makes it possible to use `vertical-motion' in any buffer,\n\
1975 whether or not it is currently displayed in some window.")
1976 (lines, window)
1977 Lisp_Object lines, window;
1978 {
1979 struct it it;
1980 struct text_pos pt;
1981 struct window *w;
1982 Lisp_Object old_buffer;
1983 struct gcpro gcpro1;
1984
1985 CHECK_NUMBER (lines, 0);
1986 if (! NILP (window))
1987 CHECK_WINDOW (window, 0);
1988 else
1989 window = selected_window;
1990 w = XWINDOW (window);
1991
1992 old_buffer = Qnil;
1993 GCPRO1 (old_buffer);
1994 if (XBUFFER (w->buffer) != current_buffer)
1995 {
1996 /* Set the window's buffer temporarily to the current buffer. */
1997 old_buffer = w->buffer;
1998 XSETBUFFER (w->buffer, current_buffer);
1999 }
2000
2001 SET_TEXT_POS (pt, PT, PT_BYTE);
2002 start_display (&it, w, pt);
2003 move_it_by_lines (&it, XINT (lines), 0);
2004 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
2005
2006 if (BUFFERP (old_buffer))
2007 w->buffer = old_buffer;
2008
2009 RETURN_UNGCPRO (make_number (it.vpos));
2010 }
2011
2012
2013 \f
2014 /* File's initialization. */
2015
2016 void
2017 syms_of_indent ()
2018 {
2019 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
2020 "*Indentation can insert tabs if this is non-nil.\n\
2021 Setting this variable automatically makes it local to the current buffer.");
2022 indent_tabs_mode = 1;
2023
2024 defsubr (&Scurrent_indentation);
2025 defsubr (&Sindent_to);
2026 defsubr (&Scurrent_column);
2027 defsubr (&Smove_to_column);
2028 defsubr (&Svertical_motion);
2029 defsubr (&Scompute_motion);
2030 }