1 /* Indentation functions.
2 Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1998, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
27 #include "character.h"
29 #include "composite.h"
37 #include "intervals.h"
38 #include "dispextern.h"
39 #include "region-cache.h"
41 /* Indentation can insert tabs if this is non-zero;
42 otherwise always uses spaces. */
44 static int indent_tabs_mode
;
48 /* These three values memorize the current column to avoid recalculation. */
50 /* Last value returned by current_column.
51 Some things in set last_known_column_point to -1
52 to mark the memorized value as invalid. */
54 static double last_known_column
;
56 /* Value of point when current_column was called. */
58 EMACS_INT last_known_column_point
;
60 /* Value of MODIFF when current_column was called. */
62 static int last_known_column_modified
;
64 static double current_column_1 (void);
65 static double position_indentation (int);
67 /* Cache of beginning of line found by the last call of
70 static EMACS_INT current_column_bol_cache
;
72 /* Get the display table to use for the current buffer. */
74 struct Lisp_Char_Table
*
75 buffer_display_table (void)
79 thisbuf
= current_buffer
->display_table
;
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
);
87 /* Width run cache considerations. */
89 /* Return the width of character C under display table DP. */
92 character_width (int c
, struct Lisp_Char_Table
*dp
)
96 /* These width computations were determined by examining the cases
97 in display_text_line. */
99 /* Everything can be handled by the display table, if it's
100 present and the element is right. */
101 if (dp
&& (elt
= DISP_CHAR_VECTOR (dp
, c
), VECTORP (elt
)))
102 return XVECTOR (elt
)->size
;
104 /* Some characters are special. */
105 if (c
== '\n' || c
== '\t' || c
== '\015')
108 /* Printing characters have width 1. */
109 else if (c
>= 040 && c
< 0177)
112 /* Everybody else (control characters, metacharacters) has other
113 widths. We could return their actual widths here, but they
114 depend on things like ctl_arrow and crud like that, and they're
115 not very common at all. So we'll just claim we don't know their
121 /* Return true if the display table DISPTAB specifies the same widths
122 for characters as WIDTHTAB. We use this to decide when to
123 invalidate the buffer's width_run_cache. */
126 disptab_matches_widthtab (struct Lisp_Char_Table
*disptab
, struct Lisp_Vector
*widthtab
)
130 if (widthtab
->size
!= 256)
133 for (i
= 0; i
< 256; i
++)
134 if (character_width (i
, disptab
)
135 != XFASTINT (widthtab
->contents
[i
]))
141 /* Recompute BUF's width table, using the display table DISPTAB. */
144 recompute_width_table (struct buffer
*buf
, struct Lisp_Char_Table
*disptab
)
147 struct Lisp_Vector
*widthtab
;
149 if (!VECTORP (buf
->width_table
))
150 buf
->width_table
= Fmake_vector (make_number (256), make_number (0));
151 widthtab
= XVECTOR (buf
->width_table
);
152 if (widthtab
->size
!= 256)
155 for (i
= 0; i
< 256; i
++)
156 XSETFASTINT (widthtab
->contents
[i
], character_width (i
, disptab
));
159 /* Allocate or free the width run cache, as requested by the current
160 state of current_buffer's cache_long_line_scans variable. */
163 width_run_cache_on_off (void)
165 if (NILP (current_buffer
->cache_long_line_scans
)
166 /* And, for the moment, this feature doesn't work on multibyte
168 || !NILP (current_buffer
->enable_multibyte_characters
))
170 /* It should be off. */
171 if (current_buffer
->width_run_cache
)
173 free_region_cache (current_buffer
->width_run_cache
);
174 current_buffer
->width_run_cache
= 0;
175 current_buffer
->width_table
= Qnil
;
180 /* It should be on. */
181 if (current_buffer
->width_run_cache
== 0)
183 current_buffer
->width_run_cache
= new_region_cache ();
184 recompute_width_table (current_buffer
, buffer_display_table ());
190 /* Skip some invisible characters starting from POS.
191 This includes characters invisible because of text properties
192 and characters invisible because of overlays.
194 If position POS is followed by invisible characters,
195 skip some of them and return the position after them.
196 Otherwise return POS itself.
198 Set *NEXT_BOUNDARY_P to the next position at which
199 it will be necessary to call this function again.
201 Don't scan past TO, and don't set *NEXT_BOUNDARY_P
202 to a value greater than TO.
204 If WINDOW is non-nil, and this buffer is displayed in WINDOW,
205 take account of overlays that apply only in WINDOW.
207 We don't necessarily skip all the invisible characters after POS
208 because that could take a long time. We skip a reasonable number
209 which can be skipped quickly. If there might be more invisible
210 characters immediately following, then *NEXT_BOUNDARY_P
211 will equal the return value. */
214 skip_invisible (EMACS_INT pos
, EMACS_INT
*next_boundary_p
, EMACS_INT to
, Lisp_Object window
)
216 Lisp_Object prop
, position
, overlay_limit
, proplimit
;
217 Lisp_Object buffer
, tmp
;
221 XSETFASTINT (position
, pos
);
222 XSETBUFFER (buffer
, current_buffer
);
224 /* Give faster response for overlay lookup near POS. */
225 recenter_overlay_lists (current_buffer
, pos
);
227 /* We must not advance farther than the next overlay change.
228 The overlay change might change the invisible property;
229 or there might be overlay strings to be displayed there. */
230 overlay_limit
= Fnext_overlay_change (position
);
231 /* As for text properties, this gives a lower bound
232 for where the invisible text property could change. */
233 proplimit
= Fnext_property_change (position
, buffer
, Qt
);
234 if (XFASTINT (overlay_limit
) < XFASTINT (proplimit
))
235 proplimit
= overlay_limit
;
236 /* PROPLIMIT is now a lower bound for the next change
237 in invisible status. If that is plenty far away,
238 use that lower bound. */
239 if (XFASTINT (proplimit
) > pos
+ 100 || XFASTINT (proplimit
) >= to
)
240 *next_boundary_p
= XFASTINT (proplimit
);
241 /* Otherwise, scan for the next `invisible' property change. */
244 /* Don't scan terribly far. */
245 XSETFASTINT (proplimit
, min (pos
+ 100, to
));
246 /* No matter what, don't go past next overlay change. */
247 if (XFASTINT (overlay_limit
) < XFASTINT (proplimit
))
248 proplimit
= overlay_limit
;
249 tmp
= Fnext_single_property_change (position
, Qinvisible
,
251 end
= XFASTINT (tmp
);
253 /* Don't put the boundary in the middle of multibyte form if
254 there is no actual property change. */
256 && !NILP (current_buffer
->enable_multibyte_characters
)
258 while (pos
< end
&& !CHAR_HEAD_P (POS_ADDR (end
)))
261 *next_boundary_p
= end
;
263 /* if the `invisible' property is set, we can skip to
264 the next property change */
265 prop
= Fget_char_property (position
, Qinvisible
,
267 && EQ (XWINDOW (window
)->buffer
, buffer
))
269 inv_p
= TEXT_PROP_MEANS_INVISIBLE (prop
);
270 /* When counting columns (window == nil), don't skip over ellipsis text. */
271 if (NILP (window
) ? inv_p
== 1 : inv_p
)
272 return *next_boundary_p
;
276 /* Set variables WIDTH and BYTES for a multibyte sequence starting at P.
278 DP is a display table or NULL.
280 This macro is used in current_column_1, Fmove_to_column, and
283 #define MULTIBYTE_BYTES_WIDTH(p, dp) \
288 c = STRING_CHAR_AND_LENGTH (p, bytes); \
289 if (BYTES_BY_CHAR_HEAD (*p) != bytes) \
293 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) \
294 width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; \
296 width = CHAR_WIDTH (c); \
298 wide_column = width; \
303 DEFUN ("current-column", Fcurrent_column
, Scurrent_column
, 0, 0, 0,
304 doc
: /* Return the horizontal position of point. Beginning of line is column 0.
305 This is calculated by adding together the widths of all the displayed
306 representations of the character between the start of the previous line
307 and point (eg. control characters will have a width of 2 or 4, tabs
308 will have a variable width).
309 Ignores finite width of frame, which means that this function may return
310 values greater than (frame-width).
311 Whether the line is visible (if `selective-display' is t) has no effect;
312 however, ^M is treated as end of line when `selective-display' is t.
313 Text that has an invisible property is considered as having width 0, unless
314 `buffer-invisibility-spec' specifies that it is replaced by an ellipsis. */)
318 XSETFASTINT (temp
, (int) current_column ()); /* iftc */
322 /* Cancel any recorded value of the horizontal position. */
325 invalidate_current_column (void)
327 last_known_column_point
= 0;
331 current_column (void)
334 register unsigned char *ptr
, *stop
;
335 register int tab_seen
;
338 register int tab_width
= XINT (current_buffer
->tab_width
);
339 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
340 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
342 if (PT
== last_known_column_point
343 && MODIFF
== last_known_column_modified
)
344 return last_known_column
;
346 /* If the buffer has overlays, text properties,
347 or multibyte characters, use a more general algorithm. */
348 if (BUF_INTERVALS (current_buffer
)
349 || current_buffer
->overlays_before
350 || current_buffer
->overlays_after
352 return current_column_1 ();
354 /* Scan backwards from point to the previous newline,
355 counting width. Tab characters are the only complicated case. */
357 /* Make a pointer for decrementing through the chars before point. */
358 ptr
= BYTE_POS_ADDR (PT_BYTE
- 1) + 1;
359 /* Make a pointer to where consecutive chars leave off,
360 going backwards from point. */
363 else if (PT
<= GPT
|| BEGV
> GPT
)
368 if (tab_width
<= 0 || tab_width
> 1000)
371 col
= 0, tab_seen
= 0, post_tab
= 0;
380 /* We stopped either for the beginning of the buffer
382 if (ptr
== BEGV_ADDR
)
385 /* It was the gap. Jump back over it. */
389 /* Check whether that brings us to beginning of buffer. */
396 if (dp
&& VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
398 charvec
= DISP_CHAR_VECTOR (dp
, c
);
407 for (i
= n
- 1; i
>= 0; --i
)
409 if (VECTORP (charvec
))
411 /* This should be handled the same as
412 next_element_from_display_vector does it. */
413 Lisp_Object entry
= AREF (charvec
, i
);
415 if (GLYPH_CODE_P (entry
)
416 && GLYPH_CODE_CHAR_VALID_P (entry
))
417 c
= GLYPH_CODE_CHAR (entry
);
422 if (c
>= 040 && c
< 0177)
426 && EQ (current_buffer
->selective_display
, Qt
)))
429 goto start_of_line_found
;
434 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
440 else if (VECTORP (charvec
))
441 /* With a display table entry, C is displayed as is, and
442 not displayed as \NNN or as ^N. If C is a single-byte
443 character, it takes one column. If C is multi-byte in
444 an unibyte buffer, it's translated to unibyte, so it
445 also takes one column. */
448 col
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
456 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
460 if (ptr
== BEGV_ADDR
)
461 current_column_bol_cache
= BEGV
;
463 current_column_bol_cache
= BYTE_TO_CHAR (PTR_BYTE_POS (ptr
));
465 last_known_column
= col
;
466 last_known_column_point
= PT
;
467 last_known_column_modified
= MODIFF
;
473 /* Check the presence of a display property and compute its width.
474 If a property was found and its width was found as well, return
475 its width (>= 0) and set the position of the end of the property
477 Otherwise just return -1. */
479 check_display_width (EMACS_INT pos
, EMACS_INT col
, EMACS_INT
*endpos
)
481 Lisp_Object val
, overlay
;
483 if (CONSP (val
= get_char_property_and_overlay
484 (make_number (pos
), Qdisplay
, Qnil
, &overlay
))
485 && EQ (Qspace
, XCAR (val
)))
486 { /* FIXME: Use calc_pixel_width_or_height, as in term.c. */
487 Lisp_Object plist
= XCDR (val
), prop
;
490 if ((prop
= Fplist_get (plist
, QCwidth
), NATNUMP (prop
)))
492 else if (FLOATP (prop
))
493 width
= (int)(XFLOAT_DATA (prop
) + 0.5);
494 else if ((prop
= Fplist_get (plist
, QCalign_to
), NATNUMP (prop
)))
495 width
= XINT (prop
) - col
;
496 else if (FLOATP (prop
))
497 width
= (int)(XFLOAT_DATA (prop
) + 0.5) - col
;
502 if (OVERLAYP (overlay
))
503 *endpos
= OVERLAY_POSITION (OVERLAY_END (overlay
));
505 get_property_and_range (pos
, Qdisplay
, &val
, &start
, endpos
, Qnil
);
512 /* Scanning from the beginning of the current line, stop at the buffer
513 position ENDPOS or at the column GOALCOL or at the end of line, whichever
515 Return the resulting buffer position and column in ENDPOS and GOALCOL.
516 PREVCOL gets set to the column of the previous position (it's always
517 strictly smaller than the goal column). */
519 scan_for_column (EMACS_INT
*endpos
, EMACS_INT
*goalcol
, EMACS_INT
*prevcol
)
521 register EMACS_INT tab_width
= XINT (current_buffer
->tab_width
);
522 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
523 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
524 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
525 struct composition_it cmp_it
;
529 /* Start the scan at the beginning of this line with column number 0. */
530 register EMACS_INT col
= 0, prev_col
= 0;
531 EMACS_INT goal
= goalcol
? *goalcol
: MOST_POSITIVE_FIXNUM
;
532 EMACS_INT end
= endpos
? *endpos
: PT
;
533 EMACS_INT scan
, scan_byte
;
534 EMACS_INT next_boundary
;
536 EMACS_INT opoint
= PT
, opoint_byte
= PT_BYTE
;
537 scan_newline (PT
, PT_BYTE
, BEGV
, BEGV_BYTE
, -1, 1);
538 current_column_bol_cache
= PT
;
539 scan
= PT
, scan_byte
= PT_BYTE
;
540 SET_PT_BOTH (opoint
, opoint_byte
);
541 next_boundary
= scan
;
544 window
= Fget_buffer_window (Fcurrent_buffer (), Qnil
);
545 w
= ! NILP (window
) ? XWINDOW (window
) : NULL
;
547 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
548 memset (&cmp_it
, 0, sizeof cmp_it
);
550 composition_compute_stop_pos (&cmp_it
, scan
, scan_byte
, end
, Qnil
);
552 /* Scan forward to the target position. */
557 /* Occasionally we may need to skip invisible text. */
558 while (scan
== next_boundary
)
560 EMACS_INT old_scan
= scan
;
561 /* This updates NEXT_BOUNDARY to the next place
562 where we might need to skip more invisible text. */
563 scan
= skip_invisible (scan
, &next_boundary
, end
, Qnil
);
564 if (scan
!= old_scan
)
565 scan_byte
= CHAR_TO_BYTE (scan
);
570 /* Test reaching the goal column. We do this after skipping
571 invisible characters, so that we put point before the
572 character on which the cursor will appear. */
577 { /* Check display property. */
579 int width
= check_display_width (scan
, col
, &end
);
583 if (end
> scan
) /* Avoid infinite loops with 0-width overlays. */
585 scan
= end
; scan_byte
= charpos_to_bytepos (scan
);
591 /* Check composition sequence. */
593 || (scan
== cmp_it
.stop_pos
594 && composition_reseat_it (&cmp_it
, scan
, scan_byte
, end
,
596 composition_update_it (&cmp_it
, scan
, scan_byte
, Qnil
);
599 scan
+= cmp_it
.nchars
;
600 scan_byte
+= cmp_it
.nbytes
;
603 if (cmp_it
.to
== cmp_it
.nglyphs
)
606 composition_compute_stop_pos (&cmp_it
, scan
, scan_byte
, end
,
610 cmp_it
.from
= cmp_it
.to
;
614 c
= FETCH_BYTE (scan_byte
);
616 /* See if there is a display table and it relates
617 to this character. */
620 && ! (multibyte
&& LEADING_CODE_P (c
))
621 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
626 /* This character is displayed using a vector of glyphs.
627 Update the column/position based on those glyphs. */
629 charvec
= DISP_CHAR_VECTOR (dp
, c
);
632 for (i
= 0; i
< n
; i
++)
634 /* This should be handled the same as
635 next_element_from_display_vector does it. */
636 Lisp_Object entry
= AREF (charvec
, i
);
638 if (GLYPH_CODE_P (entry
)
639 && GLYPH_CODE_CHAR_VALID_P (entry
))
640 c
= GLYPH_CODE_CHAR (entry
);
646 if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
651 col
= col
/ tab_width
* tab_width
;
659 /* The display table doesn't affect this character;
660 it displays as itself. */
664 if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
669 col
= col
/ tab_width
* tab_width
;
671 else if (multibyte
&& LEADING_CODE_P (c
))
673 /* Start of multi-byte form. */
675 int bytes
, width
, wide_column
;
677 ptr
= BYTE_POS_ADDR (scan_byte
);
678 MULTIBYTE_BYTES_WIDTH (ptr
, dp
);
679 /* Subtract one to compensate for the increment
680 that is going to happen below. */
681 scan_byte
+= bytes
- 1;
684 else if (ctl_arrow
&& (c
< 040 || c
== 0177))
686 else if (c
< 040 || c
>= 0177)
697 last_known_column
= col
;
698 last_known_column_point
= PT
;
699 last_known_column_modified
= MODIFF
;
709 /* Return the column number of position POS
710 by scanning forward from the beginning of the line.
711 This function handles characters that are invisible
712 due to text properties or overlays. */
715 current_column_1 (void)
717 EMACS_INT col
= MOST_POSITIVE_FIXNUM
;
718 EMACS_INT opoint
= PT
;
720 scan_for_column (&opoint
, &col
, NULL
);
725 #if 0 /* Not used. */
727 /* Return the width in columns of the part of STRING from BEG to END.
728 If BEG is nil, that stands for the beginning of STRING.
729 If END is nil, that stands for the end of STRING. */
732 string_display_width (string
, beg
, end
)
733 Lisp_Object string
, beg
, end
;
736 register unsigned char *ptr
, *stop
;
737 register int tab_seen
;
740 register int tab_width
= XINT (current_buffer
->tab_width
);
741 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
742 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
761 /* Make a pointer for decrementing through the chars before point. */
762 ptr
= SDATA (string
) + e
;
763 /* Make a pointer to where consecutive chars leave off,
764 going backwards from point. */
765 stop
= SDATA (string
) + b
;
767 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
769 col
= 0, tab_seen
= 0, post_tab
= 0;
777 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
778 col
+= XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
;
779 else if (c
>= 040 && c
< 0177)
786 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
793 col
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
798 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
808 DEFUN ("indent-to", Findent_to
, Sindent_to
, 1, 2, "NIndent to column: ",
809 doc
: /* Indent from point with tabs and spaces until COLUMN is reached.
810 Optional second argument MINIMUM says always do at least MINIMUM spaces
811 even if that goes past COLUMN; by default, MINIMUM is zero.
813 The return value is COLUMN. */)
814 (Lisp_Object column
, Lisp_Object minimum
)
817 register int fromcol
;
818 register int tab_width
= XINT (current_buffer
->tab_width
);
820 CHECK_NUMBER (column
);
822 XSETFASTINT (minimum
, 0);
823 CHECK_NUMBER (minimum
);
825 fromcol
= current_column ();
826 mincol
= fromcol
+ XINT (minimum
);
827 if (mincol
< XINT (column
)) mincol
= XINT (column
);
829 if (fromcol
== mincol
)
830 return make_number (mincol
);
832 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
834 if (indent_tabs_mode
)
837 XSETFASTINT (n
, mincol
/ tab_width
- fromcol
/ tab_width
);
838 if (XFASTINT (n
) != 0)
840 Finsert_char (make_number ('\t'), n
, Qt
);
842 fromcol
= (mincol
/ tab_width
) * tab_width
;
846 XSETFASTINT (column
, mincol
- fromcol
);
847 Finsert_char (make_number (' '), column
, Qt
);
849 last_known_column
= mincol
;
850 last_known_column_point
= PT
;
851 last_known_column_modified
= MODIFF
;
853 XSETINT (column
, mincol
);
858 static double position_indentation (int);
860 DEFUN ("current-indentation", Fcurrent_indentation
, Scurrent_indentation
,
862 doc
: /* Return the indentation of the current line.
863 This is the horizontal position of the character
864 following any initial whitespace. */)
868 EMACS_INT opoint
= PT
, opoint_byte
= PT_BYTE
;
870 scan_newline (PT
, PT_BYTE
, BEGV
, BEGV_BYTE
, -1, 1);
872 XSETFASTINT (val
, (int) position_indentation (PT_BYTE
)); /* iftc */
873 SET_PT_BOTH (opoint
, opoint_byte
);
878 position_indentation (register int pos_byte
)
880 register EMACS_INT column
= 0;
881 register EMACS_INT tab_width
= XINT (current_buffer
->tab_width
);
882 register unsigned char *p
;
883 register unsigned char *stop
;
884 unsigned char *start
;
885 EMACS_INT next_boundary_byte
= pos_byte
;
886 EMACS_INT ceiling
= next_boundary_byte
;
888 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
890 p
= BYTE_POS_ADDR (pos_byte
);
891 /* STOP records the value of P at which we will need
892 to think about the gap, or about invisible text,
893 or about the end of the buffer. */
895 /* START records the starting value of P. */
901 EMACS_INT stop_pos_byte
;
903 /* If we have updated P, set POS_BYTE to match.
904 The first time we enter the loop, POS_BYTE is already right. */
906 pos_byte
= PTR_BYTE_POS (p
);
907 /* Consider the various reasons STOP might have been set here. */
908 if (pos_byte
== ZV_BYTE
)
910 if (pos_byte
== next_boundary_byte
)
912 EMACS_INT next_boundary
;
913 EMACS_INT pos
= BYTE_TO_CHAR (pos_byte
);
914 pos
= skip_invisible (pos
, &next_boundary
, ZV
, Qnil
);
915 pos_byte
= CHAR_TO_BYTE (pos
);
916 next_boundary_byte
= CHAR_TO_BYTE (next_boundary
);
918 if (pos_byte
>= ceiling
)
919 ceiling
= BUFFER_CEILING_OF (pos_byte
) + 1;
920 /* Compute the next place we need to stop and think,
921 and set STOP accordingly. */
922 stop_pos_byte
= min (ceiling
, next_boundary_byte
);
923 /* The -1 and +1 arrange to point at the first byte of gap
924 (if STOP_POS_BYTE is the position of the gap)
925 rather than at the data after the gap. */
927 stop
= BYTE_POS_ADDR (stop_pos_byte
- 1) + 1;
928 p
= BYTE_POS_ADDR (pos_byte
);
933 if (! NILP (current_buffer
->enable_multibyte_characters
))
939 column
+= tab_width
- column
% tab_width
;
942 if (ASCII_BYTE_P (p
[-1])
943 || NILP (current_buffer
->enable_multibyte_characters
))
947 pos_byte
= PTR_BYTE_POS (p
- 1);
948 c
= FETCH_MULTIBYTE_CHAR (pos_byte
);
949 if (CHAR_HAS_CATEGORY (c
, ' '))
953 p
= BYTE_POS_ADDR (pos_byte
);
962 /* Test whether the line beginning at POS is indented beyond COLUMN.
963 Blank lines are treated as if they had the same indentation as the
967 indented_beyond_p (EMACS_INT pos
, EMACS_INT pos_byte
, double column
)
970 EMACS_INT opoint
= PT
, opoint_byte
= PT_BYTE
;
972 SET_PT_BOTH (pos
, pos_byte
);
973 while (PT
> BEGV
&& FETCH_BYTE (PT_BYTE
) == '\n')
974 scan_newline (PT
- 1, PT_BYTE
- 1, BEGV
, BEGV_BYTE
, -1, 0);
976 val
= position_indentation (PT_BYTE
);
977 SET_PT_BOTH (opoint
, opoint_byte
);
978 return val
>= column
; /* hmm, float comparison */
981 DEFUN ("move-to-column", Fmove_to_column
, Smove_to_column
, 1, 2, "p",
982 doc
: /* Move point to column COLUMN in the current line.
983 Interactively, COLUMN is the value of prefix numeric argument.
984 The column of a character is calculated by adding together the widths
985 as displayed of the previous characters in the line.
986 This function ignores line-continuation;
987 there is no upper limit on the column number a character can have
988 and horizontal scrolling has no effect.
990 If specified column is within a character, point goes after that character.
991 If it's past end of line, point goes to end of line.
993 Optional second argument FORCE non-nil means if COLUMN is in the
994 middle of a tab character, change it to spaces.
995 In addition, if FORCE is t, and the line is too short to reach
996 COLUMN, add spaces/tabs to get there.
998 The return value is the current column. */)
999 (Lisp_Object column
, Lisp_Object force
)
1002 EMACS_INT col
, prev_col
;
1005 CHECK_NATNUM (column
);
1006 goal
= XINT (column
);
1010 scan_for_column (&pos
, &col
, &prev_col
);
1014 /* If a tab char made us overshoot, change it to spaces
1015 and scan through it again. */
1016 if (!NILP (force
) && col
> goal
)
1019 EMACS_INT pos_byte
= PT_BYTE
;
1022 c
= FETCH_CHAR (pos_byte
);
1023 if (c
== '\t' && prev_col
< goal
)
1025 EMACS_INT goal_pt
, goal_pt_byte
;
1027 /* Insert spaces in front of the tab to reach GOAL. Do this
1028 first so that a marker at the end of the tab gets
1030 SET_PT_BOTH (PT
- 1, PT_BYTE
- 1);
1031 Finsert_char (make_number (' '), make_number (goal
- prev_col
), Qt
);
1033 /* Now delete the tab, and indent to COL. */
1034 del_range (PT
, PT
+ 1);
1036 goal_pt_byte
= PT_BYTE
;
1037 Findent_to (make_number (col
), Qnil
);
1038 SET_PT_BOTH (goal_pt
, goal_pt_byte
);
1040 /* Set the last_known... vars consistently. */
1045 /* If line ends prematurely, add space to the end. */
1046 if (col
< goal
&& EQ (force
, Qt
))
1047 Findent_to (make_number (col
= goal
), Qnil
);
1049 last_known_column
= col
;
1050 last_known_column_point
= PT
;
1051 last_known_column_modified
= MODIFF
;
1053 return make_number (col
);
1056 /* compute_motion: compute buffer posn given screen posn and vice versa */
1058 struct position val_compute_motion
;
1060 /* Scan the current buffer forward from offset FROM, pretending that
1061 this is at line FROMVPOS, column FROMHPOS, until reaching buffer
1062 offset TO or line TOVPOS, column TOHPOS (whichever comes first),
1063 and return the ending buffer position and screen location. If we
1064 can't hit the requested column exactly (because of a tab or other
1065 multi-column character), overshoot.
1067 DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
1068 at FROM. This is the case if FROMVPOS and FROMVPOS came from an
1069 earlier call to compute_motion. The other common case is that FROMHPOS
1070 is zero and FROM is a position that "belongs" at column zero, but might
1071 be shifted by overlay strings; in this case DID_MOTION should be 0.
1073 WIDTH is the number of columns available to display text;
1074 compute_motion uses this to handle continuation lines and such.
1075 If WIDTH is -1, use width of window's text area adjusted for
1076 continuation glyph when needed.
1078 HSCROLL is the number of columns not being displayed at the left
1079 margin; this is usually taken from a window's hscroll member.
1080 TAB_OFFSET is the number of columns of the first tab that aren't
1081 being displayed, perhaps because of a continuation line or
1084 compute_motion returns a pointer to a struct position. The bufpos
1085 member gives the buffer position at the end of the scan, and hpos
1086 and vpos give its cartesian location. prevhpos is the column at
1087 which the character before bufpos started, and contin is non-zero
1088 if we reached the current line by continuing the previous.
1090 Note that FROMHPOS and TOHPOS should be expressed in real screen
1091 columns, taking HSCROLL and the truncation glyph at the left margin
1092 into account. That is, beginning-of-line moves you to the hpos
1093 -HSCROLL + (HSCROLL > 0).
1095 For example, to find the buffer position of column COL of line LINE
1096 of a certain window, pass the window's starting location as FROM
1097 and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
1098 Pass the buffer's ZV as TO, to limit the scan to the end of the
1099 visible section of the buffer, and pass LINE and COL as TOVPOS and
1102 When displaying in window w, a typical formula for WIDTH is:
1105 - (has_vertical_scroll_bars
1106 ? WINDOW_CONFIG_SCROLL_BAR_COLS (window)
1107 : (window_width + window_left != frame_cols))
1110 window_width is XFASTINT (w->total_cols),
1111 window_left is XFASTINT (w->left_col),
1112 has_vertical_scroll_bars is
1113 WINDOW_HAS_VERTICAL_SCROLL_BAR (window)
1114 and frame_cols = FRAME_COLS (XFRAME (window->frame))
1116 Or you can let window_box_text_cols do this all for you, and write:
1117 window_box_text_cols (w) - 1
1119 The `-1' accounts for the continuation-line backslashes; the rest
1120 accounts for window borders if the window is split horizontally, and
1121 the scroll bars if they are turned on. */
1124 compute_motion (EMACS_INT from
, EMACS_INT fromvpos
, EMACS_INT fromhpos
, int did_motion
, EMACS_INT to
, EMACS_INT tovpos
, EMACS_INT tohpos
, EMACS_INT width
, EMACS_INT hscroll
, EMACS_INT tab_offset
, struct window
*win
)
1126 register EMACS_INT hpos
= fromhpos
;
1127 register EMACS_INT vpos
= fromvpos
;
1129 register EMACS_INT pos
;
1132 register EMACS_INT tab_width
= XFASTINT (current_buffer
->tab_width
);
1133 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
1134 register struct Lisp_Char_Table
*dp
= window_display_table (win
);
1136 = (INTEGERP (current_buffer
->selective_display
)
1137 ? XINT (current_buffer
->selective_display
)
1138 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1140 = (selective
&& dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
1141 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
: 0);
1142 /* The next location where the `invisible' property changes, or an
1143 overlay starts or ends. */
1144 EMACS_INT next_boundary
= from
;
1146 /* For computing runs of characters with similar widths.
1147 Invariant: width_run_width is zero, or all the characters
1148 from width_run_start to width_run_end have a fixed width of
1150 EMACS_INT width_run_start
= from
;
1151 EMACS_INT width_run_end
= from
;
1152 EMACS_INT width_run_width
= 0;
1153 Lisp_Object
*width_table
;
1156 /* The next buffer pos where we should consult the width run cache. */
1157 EMACS_INT next_width_run
= from
;
1160 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
1161 /* If previous char scanned was a wide character,
1162 this is the column where it ended. Otherwise, this is 0. */
1163 EMACS_INT wide_column_end_hpos
= 0;
1164 EMACS_INT prev_pos
; /* Previous buffer position. */
1165 EMACS_INT prev_pos_byte
; /* Previous buffer position. */
1166 EMACS_INT prev_hpos
= 0;
1167 EMACS_INT prev_vpos
= 0;
1168 EMACS_INT contin_hpos
; /* HPOS of last column of continued line. */
1169 EMACS_INT prev_tab_offset
; /* Previous tab offset. */
1170 EMACS_INT continuation_glyph_width
;
1172 struct composition_it cmp_it
;
1174 XSETBUFFER (buffer
, current_buffer
);
1175 XSETWINDOW (window
, win
);
1177 width_run_cache_on_off ();
1178 if (dp
== buffer_display_table ())
1179 width_table
= (VECTORP (current_buffer
->width_table
)
1180 ? XVECTOR (current_buffer
->width_table
)->contents
1183 /* If the window has its own display table, we can't use the width
1184 run cache, because that's based on the buffer's display table. */
1187 if (tab_width
<= 0 || tab_width
> 1000)
1190 /* Negative width means use all available text columns. */
1193 width
= window_box_text_cols (win
);
1194 /* We must make room for continuation marks if we don't have fringes. */
1195 #ifdef HAVE_WINDOW_SYSTEM
1196 if (!FRAME_WINDOW_P (XFRAME (win
->frame
)))
1201 continuation_glyph_width
= 1;
1202 #ifdef HAVE_WINDOW_SYSTEM
1203 if (FRAME_WINDOW_P (XFRAME (win
->frame
)))
1204 continuation_glyph_width
= 0; /* In the fringe. */
1210 pos
= prev_pos
= from
;
1211 pos_byte
= prev_pos_byte
= CHAR_TO_BYTE (from
);
1213 prev_tab_offset
= tab_offset
;
1214 memset (&cmp_it
, 0, sizeof cmp_it
);
1216 composition_compute_stop_pos (&cmp_it
, pos
, pos_byte
, to
, Qnil
);
1220 while (pos
== next_boundary
)
1222 EMACS_INT pos_here
= pos
;
1225 /* Don't skip invisible if we are already at the margin. */
1226 if (vpos
> tovpos
|| (vpos
== tovpos
&& hpos
>= tohpos
))
1228 if (contin_hpos
&& prev_hpos
== 0
1230 && (contin_hpos
== width
|| wide_column_end_hpos
> width
))
1231 { /* Line breaks because we can't put the character at the
1232 previous line any more. It is not the multi-column
1233 character continued in middle. Go back to previous
1234 buffer position, screen position, and set tab offset
1235 to previous value. It's the beginning of the
1238 pos_byte
= prev_pos_byte
;
1241 tab_offset
= prev_tab_offset
;
1246 /* If the caller says that the screen position came from an earlier
1247 call to compute_motion, then we've already accounted for the
1248 overlay strings at point. This is only true the first time
1249 through, so clear the flag after testing it. */
1251 /* We need to skip past the overlay strings. Currently those
1252 strings must not contain TAB;
1253 if we want to relax that restriction, something will have
1254 to be changed here. */
1256 unsigned char *ovstr
;
1257 EMACS_INT ovlen
= overlay_strings (pos
, win
, &ovstr
);
1258 hpos
+= ((multibyte
&& ovlen
> 0)
1259 ? strwidth (ovstr
, ovlen
) : ovlen
);
1266 /* Advance POS past invisible characters
1267 (but not necessarily all that there are here),
1268 and store in next_boundary the next position where
1269 we need to call skip_invisible. */
1270 newpos
= skip_invisible (pos
, &next_boundary
, to
, window
);
1274 pos
= min (to
, newpos
);
1275 pos_byte
= CHAR_TO_BYTE (pos
);
1279 if (newpos
!= pos_here
)
1282 pos_byte
= CHAR_TO_BYTE (pos
);
1286 /* Handle right margin. */
1287 /* Note on a wide-column character.
1289 Characters are classified into the following three categories
1290 according to the width (columns occupied on screen).
1292 (1) single-column character: ex. `a'
1293 (2) multi-column character: ex. `^A', TAB, `\033'
1294 (3) wide-column character: ex. Japanese character, Chinese character
1295 (In the following example, `W_' stands for them.)
1297 Multi-column characters can be divided around the right margin,
1298 but wide-column characters cannot.
1302 (*) The cursor is placed on the next character after the point.
1306 j ^---- next after the point
1307 ^--- next char. after the point.
1309 In case of sigle-column character
1313 033 ^---- next after the point, next char. after the point.
1315 In case of multi-column character
1319 W_ ^---- next after the point
1320 ^---- next char. after the point.
1322 In case of wide-column character
1324 The problem here is continuation at a wide-column character.
1325 In this case, the line may shorter less than WIDTH.
1326 And we find the continuation AFTER it occurs.
1332 int total_width
= width
+ continuation_glyph_width
;
1335 if (!NILP (Vtruncate_partial_width_windows
)
1336 && (total_width
< FRAME_COLS (XFRAME (WINDOW_FRAME (win
)))))
1338 if (INTEGERP (Vtruncate_partial_width_windows
))
1340 = total_width
< XFASTINT (Vtruncate_partial_width_windows
);
1345 if (hscroll
|| truncate
1346 || !NILP (current_buffer
->truncate_lines
))
1348 /* Truncating: skip to newline, unless we are already past
1349 TO (we need to go back below). */
1352 pos
= find_before_next_newline (pos
, to
, 1);
1353 pos_byte
= CHAR_TO_BYTE (pos
);
1355 /* If we just skipped next_boundary,
1356 loop around in the main while
1358 if (pos
>= next_boundary
)
1359 next_boundary
= pos
+ 1;
1362 prev_tab_offset
= tab_offset
;
1368 /* Remember the previous value. */
1369 prev_tab_offset
= tab_offset
;
1371 if (wide_column_end_hpos
> width
)
1374 tab_offset
+= prev_hpos
;
1378 tab_offset
+= width
;
1382 contin_hpos
= prev_hpos
;
1388 /* Stop if past the target buffer position or screen position. */
1391 /* Go back to the previous position. */
1393 pos_byte
= prev_pos_byte
;
1396 tab_offset
= prev_tab_offset
;
1398 /* NOTE on contin_hpos, hpos, and prev_hpos.
1402 W_ ^---- contin_hpos
1408 if (contin_hpos
&& prev_hpos
== 0
1409 && contin_hpos
< width
&& !wide_column_end_hpos
)
1411 /* Line breaking occurs in the middle of multi-column
1412 character. Go back to previous line. */
1419 if (vpos
> tovpos
|| (vpos
== tovpos
&& hpos
>= tohpos
))
1421 if (contin_hpos
&& prev_hpos
== 0
1423 && (contin_hpos
== width
|| wide_column_end_hpos
> width
))
1424 { /* Line breaks because we can't put the character at the
1425 previous line any more. It is not the multi-column
1426 character continued in middle. Go back to previous
1427 buffer position, screen position, and set tab offset
1428 to previous value. It's the beginning of the
1431 pos_byte
= prev_pos_byte
;
1434 tab_offset
= prev_tab_offset
;
1438 if (pos
== ZV
) /* We cannot go beyond ZV. Stop here. */
1444 prev_pos_byte
= pos_byte
;
1445 wide_column_end_hpos
= 0;
1447 /* Consult the width run cache to see if we can avoid inspecting
1448 the text character-by-character. */
1449 if (current_buffer
->width_run_cache
&& pos
>= next_width_run
)
1453 = region_cache_forward (current_buffer
,
1454 current_buffer
->width_run_cache
,
1457 /* A width of zero means the character's width varies (like
1458 a tab), is meaningless (like a newline), or we just don't
1459 want to skip over it for some other reason. */
1460 if (common_width
!= 0)
1462 EMACS_INT run_end_hpos
;
1464 /* Don't go past the final buffer posn the user
1469 run_end_hpos
= hpos
+ (run_end
- pos
) * common_width
;
1471 /* Don't go past the final horizontal position the user
1473 if (vpos
== tovpos
&& run_end_hpos
> tohpos
)
1475 run_end
= pos
+ (tohpos
- hpos
) / common_width
;
1476 run_end_hpos
= hpos
+ (run_end
- pos
) * common_width
;
1479 /* Don't go past the margin. */
1480 if (run_end_hpos
>= width
)
1482 run_end
= pos
+ (width
- hpos
) / common_width
;
1483 run_end_hpos
= hpos
+ (run_end
- pos
) * common_width
;
1486 hpos
= run_end_hpos
;
1488 prev_hpos
= hpos
- common_width
;
1492 pos_byte
= CHAR_TO_BYTE (pos
);
1496 next_width_run
= run_end
+ 1;
1499 /* We have to scan the text character-by-character. */
1503 Lisp_Object charvec
;
1505 /* Check composition sequence. */
1507 || (pos
== cmp_it
.stop_pos
1508 && composition_reseat_it (&cmp_it
, pos
, pos_byte
, to
, win
,
1510 composition_update_it (&cmp_it
, pos
, pos_byte
, Qnil
);
1513 pos
+= cmp_it
.nchars
;
1514 pos_byte
+= cmp_it
.nbytes
;
1515 hpos
+= cmp_it
.width
;
1516 if (cmp_it
.to
== cmp_it
.nglyphs
)
1519 composition_compute_stop_pos (&cmp_it
, pos
, pos_byte
, to
,
1523 cmp_it
.from
= cmp_it
.to
;
1527 c
= FETCH_BYTE (pos_byte
);
1530 /* Perhaps add some info to the width_run_cache. */
1531 if (current_buffer
->width_run_cache
)
1533 /* Is this character part of the current run? If so, extend
1535 if (pos
- 1 == width_run_end
1536 && XFASTINT (width_table
[c
]) == width_run_width
)
1537 width_run_end
= pos
;
1539 /* The previous run is over, since this is a character at a
1540 different position, or a different width. */
1543 /* Have we accumulated a run to put in the cache?
1544 (Currently, we only cache runs of width == 1). */
1545 if (width_run_start
< width_run_end
1546 && width_run_width
== 1)
1547 know_region_cache (current_buffer
,
1548 current_buffer
->width_run_cache
,
1549 width_run_start
, width_run_end
);
1551 /* Start recording a new width run. */
1552 width_run_width
= XFASTINT (width_table
[c
]);
1553 width_run_start
= pos
- 1;
1554 width_run_end
= pos
;
1559 && ! (multibyte
&& LEADING_CODE_P (c
))
1560 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
1562 charvec
= DISP_CHAR_VECTOR (dp
, c
);
1563 n
= ASIZE (charvec
);
1571 for (i
= n
- 1; i
>= 0; --i
)
1573 if (VECTORP (charvec
))
1575 /* This should be handled the same as
1576 next_element_from_display_vector does it. */
1577 Lisp_Object entry
= AREF (charvec
, i
);
1579 if (GLYPH_CODE_P (entry
)
1580 && GLYPH_CODE_CHAR_VALID_P (entry
))
1581 c
= GLYPH_CODE_CHAR (entry
);
1586 if (c
>= 040 && c
< 0177)
1590 int tem
= ((hpos
+ tab_offset
+ hscroll
- (hscroll
> 0))
1594 hpos
+= tab_width
- tem
;
1599 && indented_beyond_p (pos
, pos_byte
,
1600 (double) selective
)) /* iftc */
1602 /* If (pos == to), we don't have to take care of
1603 selective display. */
1606 /* Skip any number of invisible lines all at once */
1609 pos
= find_before_next_newline (pos
, to
, 1);
1612 pos_byte
= CHAR_TO_BYTE (pos
);
1615 && indented_beyond_p (pos
, pos_byte
,
1616 (double) selective
)); /* iftc */
1617 /* Allow for the " ..." that is displayed for them. */
1620 hpos
+= selective_rlen
;
1624 DEC_BOTH (pos
, pos_byte
);
1625 /* We have skipped the invis text, but not the
1631 /* A visible line. */
1635 /* Count the truncation glyph on column 0 */
1637 hpos
+= continuation_glyph_width
;
1642 else if (c
== CR
&& selective
< 0)
1644 /* In selective display mode,
1645 everything from a ^M to the end of the line is invisible.
1646 Stop *before* the real newline. */
1649 pos
= find_before_next_newline (pos
, to
, 1);
1650 pos_byte
= CHAR_TO_BYTE (pos
);
1652 /* If we just skipped next_boundary,
1653 loop around in the main while
1655 if (pos
> next_boundary
)
1656 next_boundary
= pos
;
1657 /* Allow for the " ..." that is displayed for them. */
1660 hpos
+= selective_rlen
;
1665 else if (multibyte
&& LEADING_CODE_P (c
))
1667 /* Start of multi-byte form. */
1669 int bytes
, width
, wide_column
;
1671 pos_byte
--; /* rewind POS_BYTE */
1672 ptr
= BYTE_POS_ADDR (pos_byte
);
1673 MULTIBYTE_BYTES_WIDTH (ptr
, dp
);
1676 wide_column_end_hpos
= hpos
+ wide_column
;
1679 else if (VECTORP (charvec
))
1682 hpos
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
1689 /* Remember any final width run in the cache. */
1690 if (current_buffer
->width_run_cache
1691 && width_run_width
== 1
1692 && width_run_start
< width_run_end
)
1693 know_region_cache (current_buffer
, current_buffer
->width_run_cache
,
1694 width_run_start
, width_run_end
);
1696 val_compute_motion
.bufpos
= pos
;
1697 val_compute_motion
.bytepos
= pos_byte
;
1698 val_compute_motion
.hpos
= hpos
;
1699 val_compute_motion
.vpos
= vpos
;
1700 if (contin_hpos
&& prev_hpos
== 0)
1701 val_compute_motion
.prevhpos
= contin_hpos
;
1703 val_compute_motion
.prevhpos
= prev_hpos
;
1704 /* We alalways handle all of them here; none of them remain to do. */
1705 val_compute_motion
.ovstring_chars_done
= 0;
1707 /* Nonzero if have just continued a line */
1708 val_compute_motion
.contin
= (contin_hpos
&& prev_hpos
== 0);
1711 return &val_compute_motion
;
1715 DEFUN ("compute-motion", Fcompute_motion
, Scompute_motion
, 7, 7, 0,
1716 doc
: /* Scan through the current buffer, calculating screen position.
1717 Scan the current buffer forward from offset FROM,
1718 assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--
1719 to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--
1720 and return the ending buffer position and screen location.
1722 If TOPOS is nil, the actual width and height of the window's
1725 There are three additional arguments:
1727 WIDTH is the number of columns available to display text;
1728 this affects handling of continuation lines. A value of nil
1729 corresponds to the actual number of available text columns.
1731 OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).
1732 HSCROLL is the number of columns not being displayed at the left
1733 margin; this is usually taken from a window's hscroll member.
1734 TAB-OFFSET is the number of columns of the first tab that aren't
1735 being displayed, perhaps because the line was continued within it.
1736 If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.
1738 WINDOW is the window to operate on. It is used to choose the display table;
1739 if it is showing the current buffer, it is used also for
1740 deciding which overlay properties apply.
1741 Note that `compute-motion' always operates on the current buffer.
1743 The value is a list of five elements:
1744 (POS HPOS VPOS PREVHPOS CONTIN)
1745 POS is the buffer position where the scan stopped.
1746 VPOS is the vertical position where the scan stopped.
1747 HPOS is the horizontal position where the scan stopped.
1749 PREVHPOS is the horizontal position one character back from POS.
1750 CONTIN is t if a line was continued after (or within) the previous character.
1752 For example, to find the buffer position of column COL of line LINE
1753 of a certain window, pass the window's starting location as FROM
1754 and the window's upper-left coordinates as FROMPOS.
1755 Pass the buffer's (point-max) as TO, to limit the scan to the end of the
1756 visible section of the buffer, and pass LINE and COL as TOPOS. */)
1757 (Lisp_Object from
, Lisp_Object frompos
, Lisp_Object to
, Lisp_Object topos
, Lisp_Object width
, Lisp_Object offsets
, Lisp_Object window
)
1760 Lisp_Object bufpos
, hpos
, vpos
, prevhpos
;
1761 struct position
*pos
;
1762 int hscroll
, tab_offset
;
1764 CHECK_NUMBER_COERCE_MARKER (from
);
1765 CHECK_CONS (frompos
);
1766 CHECK_NUMBER_CAR (frompos
);
1767 CHECK_NUMBER_CDR (frompos
);
1768 CHECK_NUMBER_COERCE_MARKER (to
);
1772 CHECK_NUMBER_CAR (topos
);
1773 CHECK_NUMBER_CDR (topos
);
1776 CHECK_NUMBER (width
);
1778 if (!NILP (offsets
))
1780 CHECK_CONS (offsets
);
1781 CHECK_NUMBER_CAR (offsets
);
1782 CHECK_NUMBER_CDR (offsets
);
1783 hscroll
= XINT (XCAR (offsets
));
1784 tab_offset
= XINT (XCDR (offsets
));
1787 hscroll
= tab_offset
= 0;
1790 window
= Fselected_window ();
1792 CHECK_LIVE_WINDOW (window
);
1793 w
= XWINDOW (window
);
1795 if (XINT (from
) < BEGV
|| XINT (from
) > ZV
)
1796 args_out_of_range_3 (from
, make_number (BEGV
), make_number (ZV
));
1797 if (XINT (to
) < BEGV
|| XINT (to
) > ZV
)
1798 args_out_of_range_3 (to
, make_number (BEGV
), make_number (ZV
));
1800 pos
= compute_motion (XINT (from
), XINT (XCDR (frompos
)),
1801 XINT (XCAR (frompos
)), 0,
1804 ? window_internal_height (w
)
1805 : XINT (XCDR (topos
))),
1807 ? (window_box_text_cols (w
)
1809 #ifdef HAVE_WINDOW_SYSTEM
1810 FRAME_WINDOW_P (XFRAME (w
->frame
)) ? 0 :
1813 : XINT (XCAR (topos
))),
1814 (NILP (width
) ? -1 : XINT (width
)),
1815 hscroll
, tab_offset
,
1818 XSETFASTINT (bufpos
, pos
->bufpos
);
1819 XSETINT (hpos
, pos
->hpos
);
1820 XSETINT (vpos
, pos
->vpos
);
1821 XSETINT (prevhpos
, pos
->prevhpos
);
1823 return Fcons (bufpos
,
1827 Fcons (pos
->contin
? Qt
: Qnil
, Qnil
)))));
1831 /* Fvertical_motion and vmotion */
1833 struct position val_vmotion
;
1836 vmotion (register EMACS_INT from
, register EMACS_INT vtarget
, struct window
*w
)
1838 EMACS_INT hscroll
= XINT (w
->hscroll
);
1839 struct position pos
;
1840 /* vpos is cumulative vertical position, changed as from is changed */
1841 register int vpos
= 0;
1843 register EMACS_INT first
;
1844 EMACS_INT from_byte
;
1845 EMACS_INT lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
1847 = (INTEGERP (current_buffer
->selective_display
)
1848 ? XINT (current_buffer
->selective_display
)
1849 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1851 EMACS_INT start_hpos
= 0;
1853 /* This is the object we use for fetching character properties. */
1854 Lisp_Object text_prop_object
;
1856 XSETWINDOW (window
, w
);
1858 /* If the window contains this buffer, use it for getting text properties.
1859 Otherwise use the current buffer as arg for doing that. */
1860 if (EQ (w
->buffer
, Fcurrent_buffer ()))
1861 text_prop_object
= window
;
1863 text_prop_object
= Fcurrent_buffer ();
1865 if (vpos
>= vtarget
)
1867 /* To move upward, go a line at a time until
1868 we have gone at least far enough. */
1872 while ((vpos
> vtarget
|| first
) && from
> BEGV
)
1874 Lisp_Object propval
;
1876 prevline
= find_next_newline_no_quit (from
- 1, -1);
1877 while (prevline
> BEGV
1879 && indented_beyond_p (prevline
,
1880 CHAR_TO_BYTE (prevline
),
1881 (double) selective
)) /* iftc */
1882 /* Watch out for newlines with `invisible' property.
1883 When moving upward, check the newline before. */
1884 || (propval
= Fget_char_property (make_number (prevline
- 1),
1887 TEXT_PROP_MEANS_INVISIBLE (propval
))))
1888 prevline
= find_next_newline_no_quit (prevline
- 1, -1);
1889 pos
= *compute_motion (prevline
, 0,
1890 lmargin
+ (prevline
== BEG
? start_hpos
: 0),
1893 /* Don't care for VPOS... */
1894 1 << (BITS_PER_SHORT
- 1),
1896 1 << (BITS_PER_SHORT
- 1),
1898 /* This compensates for start_hpos
1899 so that a tab as first character
1900 still occupies 8 columns. */
1901 (prevline
== BEG
? -start_hpos
: 0),
1908 /* If we made exactly the desired vertical distance,
1909 or if we hit beginning of buffer,
1910 return point found */
1911 if (vpos
>= vtarget
)
1913 val_vmotion
.bufpos
= from
;
1914 val_vmotion
.bytepos
= CHAR_TO_BYTE (from
);
1915 val_vmotion
.vpos
= vpos
;
1916 val_vmotion
.hpos
= lmargin
;
1917 val_vmotion
.contin
= 0;
1918 val_vmotion
.prevhpos
= 0;
1919 val_vmotion
.ovstring_chars_done
= 0;
1920 val_vmotion
.tab_offset
= 0; /* For accumulating tab offset. */
1921 return &val_vmotion
;
1924 /* Otherwise find the correct spot by moving down */
1926 /* Moving downward is simple, but must calculate from beg of line
1927 to determine hpos of starting point */
1928 from_byte
= CHAR_TO_BYTE (from
);
1929 if (from
> BEGV
&& FETCH_BYTE (from_byte
- 1) != '\n')
1931 Lisp_Object propval
;
1933 prevline
= find_next_newline_no_quit (from
, -1);
1934 while (prevline
> BEGV
1936 && indented_beyond_p (prevline
,
1937 CHAR_TO_BYTE (prevline
),
1938 (double) selective
)) /* iftc */
1939 /* Watch out for newlines with `invisible' property.
1940 When moving downward, check the newline after. */
1941 || (propval
= Fget_char_property (make_number (prevline
),
1944 TEXT_PROP_MEANS_INVISIBLE (propval
))))
1945 prevline
= find_next_newline_no_quit (prevline
- 1, -1);
1946 pos
= *compute_motion (prevline
, 0,
1947 lmargin
+ (prevline
== BEG
1951 /* Don't care for VPOS... */
1952 1 << (BITS_PER_SHORT
- 1),
1954 1 << (BITS_PER_SHORT
- 1),
1956 (prevline
== BEG
? -start_hpos
: 0),
1962 pos
.hpos
= lmargin
+ (from
== BEG
? start_hpos
: 0);
1967 return compute_motion (from
, vpos
, pos
.hpos
, did_motion
,
1968 ZV
, vtarget
, - (1 << (BITS_PER_SHORT
- 1)),
1970 pos
.tab_offset
- (from
== BEG
? start_hpos
: 0),
1974 DEFUN ("vertical-motion", Fvertical_motion
, Svertical_motion
, 1, 2, 0,
1975 doc
: /* Move point to start of the screen line LINES lines down.
1976 If LINES is negative, this means moving up.
1978 This function is an ordinary cursor motion function
1979 which calculates the new position based on how text would be displayed.
1980 The new position may be the start of a line,
1981 or just the start of a continuation line.
1982 The function returns number of screen lines moved over;
1983 that usually equals LINES, but may be closer to zero
1984 if beginning or end of buffer was reached.
1986 The optional second argument WINDOW specifies the window to use for
1987 parameters such as width, horizontal scrolling, and so on.
1988 The default is to use the selected window's parameters.
1990 LINES can optionally take the form (COLS . LINES), in which case
1991 the motion will not stop at the start of a screen line but on
1992 its column COLS (if such exists on that line, that is).
1994 `vertical-motion' always uses the current buffer,
1995 regardless of which buffer is displayed in WINDOW.
1996 This is consistent with other cursor motion functions
1997 and makes it possible to use `vertical-motion' in any buffer,
1998 whether or not it is currently displayed in some window. */)
1999 (Lisp_Object lines
, Lisp_Object window
)
2004 Lisp_Object old_buffer
;
2005 struct gcpro gcpro1
;
2006 Lisp_Object lcols
= Qnil
;
2009 /* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */
2010 if (CONSP (lines
) && (NUMBERP (XCAR (lines
))))
2012 lcols
= XCAR (lines
);
2013 cols
= INTEGERP (lcols
) ? (double) XINT (lcols
) : XFLOAT_DATA (lcols
);
2014 lines
= XCDR (lines
);
2017 CHECK_NUMBER (lines
);
2018 if (! NILP (window
))
2019 CHECK_WINDOW (window
);
2021 window
= selected_window
;
2022 w
= XWINDOW (window
);
2025 GCPRO1 (old_buffer
);
2026 if (XBUFFER (w
->buffer
) != current_buffer
)
2028 /* Set the window's buffer temporarily to the current buffer. */
2029 old_buffer
= w
->buffer
;
2030 XSETBUFFER (w
->buffer
, current_buffer
);
2035 struct position pos
;
2036 pos
= *vmotion (PT
, XINT (lines
), w
);
2037 SET_PT_BOTH (pos
.bufpos
, pos
.bytepos
);
2041 int it_start
, first_x
, it_overshoot_expected
;
2043 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
2044 start_display (&it
, w
, pt
);
2045 first_x
= it
.first_visible_x
;
2046 it_start
= IT_CHARPOS (it
);
2048 /* See comments below for why we calculate this. */
2049 if (XINT (lines
) > 0)
2051 if (it
.cmp_it
.id
>= 0)
2052 it_overshoot_expected
= 1;
2053 else if (it
.method
== GET_FROM_STRING
)
2055 const char *s
= SDATA (it
.string
);
2056 const char *e
= s
+ SBYTES (it
.string
);
2057 while (s
< e
&& *s
!= '\n')
2059 it_overshoot_expected
= (s
== e
) ? -1 : 0;
2062 it_overshoot_expected
= (it
.method
== GET_FROM_IMAGE
2063 || it
.method
== GET_FROM_STRETCH
);
2066 /* Scan from the start of the line containing PT. If we don't
2067 do this, we start moving with IT->current_x == 0, while PT is
2068 really at some x > 0. */
2069 reseat_at_previous_visible_line_start (&it
);
2070 it
.current_x
= it
.hpos
= 0;
2071 if (IT_CHARPOS (it
) != PT
)
2072 /* We used to temporarily disable selective display here; the
2073 comment said this is "so we don't move too far" (2005-01-19
2074 checkin by kfs). But this does nothing useful that I can
2075 tell, and it causes Bug#2694 . -- cyd */
2076 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
2078 if (XINT (lines
) <= 0)
2081 /* Do this even if LINES is 0, so that we move back to the
2082 beginning of the current line as we ought. */
2083 if (XINT (lines
) == 0 || IT_CHARPOS (it
) > 0)
2084 move_it_by_lines (&it
, XINT (lines
), 0);
2088 if (IT_CHARPOS (it
) > it_start
)
2090 /* IT may move too far if truncate-lines is on and PT
2091 lies beyond the right margin. In that case,
2092 backtrack unless the starting point is on an image,
2093 stretch glyph, composition, or Lisp string. */
2094 if (!it_overshoot_expected
2095 /* Also, backtrack if the Lisp string contains no
2096 newline, but there is a newline right after it.
2097 In this case, IT overshoots if there is an
2098 after-string just before the newline. */
2099 || (it_overshoot_expected
< 0
2100 && it
.method
== GET_FROM_BUFFER
2102 move_it_by_lines (&it
, -1, 0);
2104 move_it_by_lines (&it
, XINT (lines
), 0);
2108 /* Otherwise, we are at the first row occupied by PT,
2109 which might span multiple screen lines (e.g., if it's
2110 on a multi-line display string). We want to start
2111 from the last line that it occupies. */
2114 while (IT_CHARPOS (it
) <= it_start
)
2117 move_it_by_lines (&it
, 1, 0);
2119 if (XINT (lines
) > 1)
2120 move_it_by_lines (&it
, XINT (lines
) - 1, 0);
2125 move_it_by_lines (&it
, XINT (lines
), 0);
2130 /* Move to the goal column, if one was specified. */
2133 /* If the window was originally hscrolled, move forward by
2134 the hscrolled amount first. */
2137 move_it_in_display_line (&it
, ZV
, first_x
, MOVE_TO_X
);
2140 move_it_in_display_line
2142 (int)(cols
* FRAME_COLUMN_WIDTH (XFRAME (w
->frame
)) + 0.5),
2146 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
2149 if (BUFFERP (old_buffer
))
2150 w
->buffer
= old_buffer
;
2152 RETURN_UNGCPRO (make_number (it
.vpos
));
2157 /* File's initialization. */
2160 syms_of_indent (void)
2162 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode
,
2163 doc
: /* *Indentation can insert tabs if this is non-nil. */);
2164 indent_tabs_mode
= 1;
2166 defsubr (&Scurrent_indentation
);
2167 defsubr (&Sindent_to
);
2168 defsubr (&Scurrent_column
);
2169 defsubr (&Smove_to_column
);
2170 defsubr (&Svertical_motion
);
2171 defsubr (&Scompute_motion
);
2174 /* arch-tag: 9adfea44-71f7-4988-8ee3-96da15c502cc
2175 (do not change this comment) */