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