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