1 /* Indentation functions.
2 Copyright (C) 1985,86,87,88,93,94,95,98, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
34 #include "intervals.h"
35 #include "region-cache.h"
37 /* Indentation can insert tabs if this is non-zero;
38 otherwise always uses spaces. */
44 /* These three values memorize the current column to avoid recalculation. */
46 /* Last value returned by current_column.
47 Some things in set last_known_column_point to -1
48 to mark the memorized value as invalid. */
50 int last_known_column
;
52 /* Value of point when current_column was called. */
54 int last_known_column_point
;
56 /* Value of MODIFF when current_column was called. */
58 int last_known_column_modified
;
60 static int current_column_1
P_ ((void));
61 static int position_indentation
P_ ((int));
63 /* Cache of beginning of line found by the last call of
66 int current_column_bol_cache
;
68 /* Get the display table to use for the current buffer. */
70 struct Lisp_Char_Table
*
71 buffer_display_table ()
75 thisbuf
= current_buffer
->display_table
;
76 if (DISP_TABLE_P (thisbuf
))
77 return XCHAR_TABLE (thisbuf
);
78 if (DISP_TABLE_P (Vstandard_display_table
))
79 return XCHAR_TABLE (Vstandard_display_table
);
83 /* Width run cache considerations. */
85 /* Return the width of character C under display table DP. */
88 character_width (c
, dp
)
90 struct Lisp_Char_Table
*dp
;
94 /* These width computations were determined by examining the cases
95 in display_text_line. */
97 /* Everything can be handled by the display table, if it's
98 present and the element is right. */
99 if (dp
&& (elt
= DISP_CHAR_VECTOR (dp
, c
), VECTORP (elt
)))
100 return XVECTOR (elt
)->size
;
102 /* Some characters are special. */
103 if (c
== '\n' || c
== '\t' || c
== '\015')
106 /* Printing characters have width 1. */
107 else if (c
>= 040 && c
< 0177)
110 /* Everybody else (control characters, metacharacters) has other
111 widths. We could return their actual widths here, but they
112 depend on things like ctl_arrow and crud like that, and they're
113 not very common at all. So we'll just claim we don't know their
119 /* Return true iff the display table DISPTAB specifies the same widths
120 for characters as WIDTHTAB. We use this to decide when to
121 invalidate the buffer's width_run_cache. */
124 disptab_matches_widthtab (disptab
, widthtab
)
125 struct Lisp_Char_Table
*disptab
;
126 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 (buf
, disptab
)
146 struct Lisp_Char_Table
*disptab
;
149 struct Lisp_Vector
*widthtab
;
151 if (!VECTORP (buf
->width_table
))
152 buf
->width_table
= Fmake_vector (make_number (256), make_number (0));
153 widthtab
= XVECTOR (buf
->width_table
);
154 if (widthtab
->size
!= 256)
157 for (i
= 0; i
< 256; i
++)
158 XSETFASTINT (widthtab
->contents
[i
], character_width (i
, disptab
));
161 /* Allocate or free the width run cache, as requested by the current
162 state of current_buffer's cache_long_line_scans variable. */
165 width_run_cache_on_off ()
167 if (NILP (current_buffer
->cache_long_line_scans
)
168 /* And, for the moment, this feature doesn't work on multibyte
170 || !NILP (current_buffer
->enable_multibyte_characters
))
172 /* It should be off. */
173 if (current_buffer
->width_run_cache
)
175 free_region_cache (current_buffer
->width_run_cache
);
176 current_buffer
->width_run_cache
= 0;
177 current_buffer
->width_table
= Qnil
;
182 /* It should be on. */
183 if (current_buffer
->width_run_cache
== 0)
185 current_buffer
->width_run_cache
= new_region_cache ();
186 recompute_width_table (current_buffer
, buffer_display_table ());
192 /* Skip some invisible characters starting from POS.
193 This includes characters invisible because of text properties
194 and characters invisible because of overlays.
196 If position POS is followed by invisible characters,
197 skip some of them and return the position after them.
198 Otherwise return POS itself.
200 Set *NEXT_BOUNDARY_P to the next position at which
201 it will be necessary to call this function again.
203 Don't scan past TO, and don't set *NEXT_BOUNDARY_P
204 to a value greater than TO.
206 If WINDOW is non-nil, and this buffer is displayed in WINDOW,
207 take account of overlays that apply only in WINDOW.
209 We don't necessarily skip all the invisible characters after POS
210 because that could take a long time. We skip a reasonable number
211 which can be skipped quickly. If there might be more invisible
212 characters immediately following, then *NEXT_BOUNDARY_P
213 will equal the return value. */
216 skip_invisible (pos
, next_boundary_p
, to
, window
)
218 int *next_boundary_p
;
222 Lisp_Object prop
, position
, overlay_limit
, proplimit
;
226 XSETFASTINT (position
, pos
);
227 XSETBUFFER (buffer
, current_buffer
);
229 /* Give faster response for overlay lookup near POS. */
230 recenter_overlay_lists (current_buffer
, pos
);
232 /* We must not advance farther than the next overlay change.
233 The overlay change might change the invisible property;
234 or there might be overlay strings to be displayed there. */
235 overlay_limit
= Fnext_overlay_change (position
);
236 /* As for text properties, this gives a lower bound
237 for where the invisible text property could change. */
238 proplimit
= Fnext_property_change (position
, buffer
, Qt
);
239 if (XFASTINT (overlay_limit
) < XFASTINT (proplimit
))
240 proplimit
= overlay_limit
;
241 /* PROPLIMIT is now a lower bound for the next change
242 in invisible status. If that is plenty far away,
243 use that lower bound. */
244 if (XFASTINT (proplimit
) > pos
+ 100 || XFASTINT (proplimit
) >= to
)
245 *next_boundary_p
= XFASTINT (proplimit
);
246 /* Otherwise, scan for the next `invisible' property change. */
249 /* Don't scan terribly far. */
250 XSETFASTINT (proplimit
, min (pos
+ 100, to
));
251 /* No matter what. don't go past next overlay change. */
252 if (XFASTINT (overlay_limit
) < XFASTINT (proplimit
))
253 proplimit
= overlay_limit
;
254 end
= XFASTINT (Fnext_single_property_change (position
, Qinvisible
,
257 /* Don't put the boundary in the middle of multibyte form if
258 there is no actual property change. */
260 && !NILP (current_buffer
->enable_multibyte_characters
)
262 while (pos
< end
&& !CHAR_HEAD_P (POS_ADDR (end
)))
265 *next_boundary_p
= end
;
267 /* if the `invisible' property is set, we can skip to
268 the next property change */
269 if (!NILP (window
) && EQ (XWINDOW (window
)->buffer
, buffer
))
270 prop
= Fget_char_property (position
, Qinvisible
, window
);
272 prop
= Fget_char_property (position
, Qinvisible
, buffer
);
273 if (TEXT_PROP_MEANS_INVISIBLE (prop
) > NILP (window
))
274 return *next_boundary_p
;
278 /* If a composition starts at POS/POS_BYTE and it doesn't stride over
279 POINT, set *LEN / *LEN_BYTE to the character and byte lengths, *WIDTH
280 to the width, and return 1. Otherwise, return 0. */
283 check_composition (pos
, pos_byte
, point
, len
, len_byte
, width
)
284 int pos
, pos_byte
, point
;
285 int *len
, *len_byte
, *width
;
291 if (! find_composition (pos
, -1, &start
, &end
, &prop
, Qnil
)
292 || pos
!= start
|| point
< end
293 || !COMPOSITION_VALID_P (start
, end
, prop
))
295 if ((id
= get_composition_id (pos
, pos_byte
, end
- pos
, prop
, Qnil
)) < 0)
298 *len
= COMPOSITION_LENGTH (prop
);
299 *len_byte
= CHAR_TO_BYTE (end
) - pos_byte
;
300 *width
= composition_table
[id
]->width
;
304 /* Set variables WIDTH and BYTES for a multibyte sequence starting at P.
306 DP is a display table or NULL.
308 This macro is used in current_column_1, Fmove_to_column, and
311 #define MULTIBYTE_BYTES_WIDTH(p, dp) \
316 c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, bytes); \
317 if (BYTES_BY_CHAR_HEAD (*p) != bytes) \
321 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) \
322 width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; \
324 width = WIDTH_BY_CHAR_HEAD (*p); \
326 wide_column = width; \
330 DEFUN ("current-column", Fcurrent_column
, Scurrent_column
, 0, 0, 0,
331 doc
: /* Return the horizontal position of point. Beginning of line is column 0.
332 This is calculated by adding together the widths of all the displayed
333 representations of the character between the start of the previous line
334 and point. (eg control characters will have a width of 2 or 4, tabs
335 will have a variable width)
336 Ignores finite width of frame, which means that this function may return
337 values greater than (frame-width).
338 Whether the line is visible (if `selective-display' is t) has no effect;
339 however, ^M is treated as end of line when `selective-display' is t. */)
343 XSETFASTINT (temp
, current_column ());
347 /* Cancel any recorded value of the horizontal position. */
350 invalidate_current_column ()
352 last_known_column_point
= 0;
359 register unsigned char *ptr
, *stop
;
360 register int tab_seen
;
363 register int tab_width
= XINT (current_buffer
->tab_width
);
364 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
365 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
367 if (PT
== last_known_column_point
368 && MODIFF
== last_known_column_modified
)
369 return last_known_column
;
371 /* If the buffer has overlays, text properties,
372 or multibyte characters, use a more general algorithm. */
373 if (BUF_INTERVALS (current_buffer
)
374 || !NILP (current_buffer
->overlays_before
)
375 || !NILP (current_buffer
->overlays_after
)
377 return current_column_1 ();
379 /* Scan backwards from point to the previous newline,
380 counting width. Tab characters are the only complicated case. */
382 /* Make a pointer for decrementing through the chars before point. */
383 ptr
= BYTE_POS_ADDR (PT_BYTE
- 1) + 1;
384 /* Make a pointer to where consecutive chars leave off,
385 going backwards from point. */
388 else if (PT
<= GPT
|| BEGV
> GPT
)
393 if (tab_width
<= 0 || tab_width
> 1000)
396 col
= 0, tab_seen
= 0, post_tab
= 0;
405 /* We stopped either for the beginning of the buffer
407 if (ptr
== BEGV_ADDR
)
410 /* It was the gap. Jump back over it. */
414 /* Check whether that brings us to beginning of buffer. */
421 if (dp
&& VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
423 charvec
= DISP_CHAR_VECTOR (dp
, c
);
432 for (i
= n
- 1; i
>= 0; --i
)
434 if (VECTORP (charvec
))
436 /* This should be handled the same as
437 next_element_from_display_vector does it. */
438 Lisp_Object entry
= AREF (charvec
, i
);
441 && GLYPH_CHAR_VALID_P (XFASTINT (entry
)))
442 c
= FAST_GLYPH_CHAR (XFASTINT (entry
));
447 if (c
>= 040 && c
< 0177)
451 && EQ (current_buffer
->selective_display
, Qt
)))
454 goto start_of_line_found
;
459 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
465 else if (VECTORP (charvec
))
466 /* With a display table entry, C is displayed as is, and
467 not displayed as \NNN or as ^N. If C is a single-byte
468 character, it takes one column. If C is multi-byte in
469 an unibyte buffer, it's translated to unibyte, so it
470 also takes one column. */
473 col
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
481 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
485 if (ptr
== BEGV_ADDR
)
486 current_column_bol_cache
= BEGV
;
488 current_column_bol_cache
= BYTE_TO_CHAR (PTR_BYTE_POS (ptr
));
490 last_known_column
= col
;
491 last_known_column_point
= PT
;
492 last_known_column_modified
= MODIFF
;
497 /* Return the column number of position POS
498 by scanning forward from the beginning of the line.
499 This function handles characters that are invisible
500 due to text properties or overlays. */
505 register int tab_width
= XINT (current_buffer
->tab_width
);
506 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
507 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
508 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
510 /* Start the scan at the beginning of this line with column number 0. */
511 register int col
= 0;
513 int next_boundary
, next_boundary_byte
;
514 int opoint
= PT
, opoint_byte
= PT_BYTE
;
516 scan_newline (PT
, PT_BYTE
, BEGV
, BEGV_BYTE
, -1, 1);
517 current_column_bol_cache
= PT
;
518 scan
= PT
, scan_byte
= PT_BYTE
;
519 SET_PT_BOTH (opoint
, opoint_byte
);
520 next_boundary
= scan
;
521 next_boundary_byte
= scan_byte
;
523 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
525 /* Scan forward to the target position. */
526 while (scan
< opoint
)
532 /* Occasionally we may need to skip invisible text. */
533 while (scan
== next_boundary
)
536 /* This updates NEXT_BOUNDARY to the next place
537 where we might need to skip more invisible text. */
538 scan
= skip_invisible (scan
, &next_boundary
, opoint
, Qnil
);
541 if (scan
!= old_scan
)
542 scan_byte
= CHAR_TO_BYTE (scan
);
543 next_boundary_byte
= CHAR_TO_BYTE (next_boundary
);
546 /* Check composition sequence. */
548 int len
, len_byte
, width
;
550 if (check_composition (scan
, scan_byte
, opoint
,
551 &len
, &len_byte
, &width
))
554 scan_byte
+= len_byte
;
561 c
= FETCH_BYTE (scan_byte
);
564 && ! (multibyte
&& BASE_LEADING_CODE_P (c
))
565 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
567 charvec
= DISP_CHAR_VECTOR (dp
, c
);
576 for (i
= n
- 1; i
>= 0; --i
)
578 if (VECTORP (charvec
))
580 /* This should be handled the same as
581 next_element_from_display_vector does it. */
582 Lisp_Object entry
= AREF (charvec
, i
);
585 && GLYPH_CHAR_VALID_P (XFASTINT (entry
)))
586 c
= FAST_GLYPH_CHAR (XFASTINT (entry
));
593 if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
601 col
= col
/ tab_width
* tab_width
;
603 else if (multibyte
&& BASE_LEADING_CODE_P (c
))
606 int bytes
, width
, wide_column
;
609 ptr
= BYTE_POS_ADDR (scan_byte
);
610 MULTIBYTE_BYTES_WIDTH (ptr
, dp
);
614 else if (VECTORP (charvec
))
616 else if (ctl_arrow
&& (c
< 040 || c
== 0177))
618 else if (c
< 040 || c
>= 0177)
626 last_known_column
= col
;
627 last_known_column_point
= PT
;
628 last_known_column_modified
= MODIFF
;
634 #if 0 /* Not used. */
636 /* Return the width in columns of the part of STRING from BEG to END.
637 If BEG is nil, that stands for the beginning of STRING.
638 If END is nil, that stands for the end of STRING. */
641 string_display_width (string
, beg
, end
)
642 Lisp_Object string
, beg
, end
;
645 register unsigned char *ptr
, *stop
;
646 register int tab_seen
;
649 register int tab_width
= XINT (current_buffer
->tab_width
);
650 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
651 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
655 e
= XSTRING (string
)->size
;
658 CHECK_NUMBER (end
, 0);
666 CHECK_NUMBER (beg
, 0);
670 /* Make a pointer for decrementing through the chars before point. */
671 ptr
= XSTRING (string
)->data
+ e
;
672 /* Make a pointer to where consecutive chars leave off,
673 going backwards from point. */
674 stop
= XSTRING (string
)->data
+ b
;
676 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
678 col
= 0, tab_seen
= 0, post_tab
= 0;
686 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
687 col
+= XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
;
688 else if (c
>= 040 && c
< 0177)
695 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
702 col
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
707 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
717 DEFUN ("indent-to", Findent_to
, Sindent_to
, 1, 2, "NIndent to column: ",
718 doc
: /* Indent from point with tabs and spaces until COLUMN is reached.
719 Optional second argument MININUM says always do at least MININUM spaces
720 even if that goes past COLUMN; by default, MININUM is zero. */)
722 Lisp_Object column
, minimum
;
725 register int fromcol
;
726 register int tab_width
= XINT (current_buffer
->tab_width
);
728 CHECK_NUMBER (column
, 0);
730 XSETFASTINT (minimum
, 0);
731 CHECK_NUMBER (minimum
, 1);
733 fromcol
= current_column ();
734 mincol
= fromcol
+ XINT (minimum
);
735 if (mincol
< XINT (column
)) mincol
= XINT (column
);
737 if (fromcol
== mincol
)
738 return make_number (mincol
);
740 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
742 if (indent_tabs_mode
)
745 XSETFASTINT (n
, mincol
/ tab_width
- fromcol
/ tab_width
);
746 if (XFASTINT (n
) != 0)
748 Finsert_char (make_number ('\t'), n
, Qt
);
750 fromcol
= (mincol
/ tab_width
) * tab_width
;
754 XSETFASTINT (column
, mincol
- fromcol
);
755 Finsert_char (make_number (' '), column
, Qt
);
757 last_known_column
= mincol
;
758 last_known_column_point
= PT
;
759 last_known_column_modified
= MODIFF
;
761 XSETINT (column
, mincol
);
766 static int position_indentation
P_ ((int));
768 DEFUN ("current-indentation", Fcurrent_indentation
, Scurrent_indentation
,
770 doc
: /* Return the indentation of the current line.
771 This is the horizontal position of the character
772 following any initial whitespace. */)
776 int opoint
= PT
, opoint_byte
= PT_BYTE
;
778 scan_newline (PT
, PT_BYTE
, BEGV
, BEGV_BYTE
, -1, 1);
780 XSETFASTINT (val
, position_indentation (PT_BYTE
));
781 SET_PT_BOTH (opoint
, opoint_byte
);
786 position_indentation (pos_byte
)
787 register int pos_byte
;
789 register int column
= 0;
790 register int tab_width
= XINT (current_buffer
->tab_width
);
791 register unsigned char *p
;
792 register unsigned char *stop
;
793 unsigned char *start
;
794 int next_boundary_byte
= pos_byte
;
795 int ceiling
= next_boundary_byte
;
797 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
799 p
= BYTE_POS_ADDR (pos_byte
);
800 /* STOP records the value of P at which we will need
801 to think about the gap, or about invisible text,
802 or about the end of the buffer. */
804 /* START records the starting value of P. */
812 /* If we have updated P, set POS_BYTE to match.
813 The first time we enter the loop, POS_BYTE is already right. */
815 pos_byte
= PTR_BYTE_POS (p
);
816 /* Consider the various reasons STOP might have been set here. */
817 if (pos_byte
== ZV_BYTE
)
819 if (pos_byte
== next_boundary_byte
)
822 int pos
= BYTE_TO_CHAR (pos_byte
);
823 pos
= skip_invisible (pos
, &next_boundary
, ZV
, Qnil
);
824 pos_byte
= CHAR_TO_BYTE (pos
);
825 next_boundary_byte
= CHAR_TO_BYTE (next_boundary
);
827 if (pos_byte
>= ceiling
)
828 ceiling
= BUFFER_CEILING_OF (pos_byte
) + 1;
829 /* Compute the next place we need to stop and think,
830 and set STOP accordingly. */
831 stop_pos_byte
= min (ceiling
, next_boundary_byte
);
832 /* The -1 and +1 arrange to point at the first byte of gap
833 (if STOP_POS_BYTE is the position of the gap)
834 rather than at the data after the gap. */
836 stop
= BYTE_POS_ADDR (stop_pos_byte
- 1) + 1;
837 p
= BYTE_POS_ADDR (pos_byte
);
842 if (! NILP (current_buffer
->enable_multibyte_characters
))
848 column
+= tab_width
- column
% tab_width
;
851 if (ASCII_BYTE_P (p
[-1])
852 || NILP (current_buffer
->enable_multibyte_characters
))
856 pos_byte
= PTR_BYTE_POS (p
- 1);
857 c
= FETCH_MULTIBYTE_CHAR (pos_byte
);
858 if (CHAR_HAS_CATEGORY (c
, ' '))
862 p
= BYTE_POS_ADDR (pos_byte
);
871 /* Test whether the line beginning at POS is indented beyond COLUMN.
872 Blank lines are treated as if they had the same indentation as the
876 indented_beyond_p (pos
, pos_byte
, column
)
877 int pos
, pos_byte
, column
;
880 int opoint
= PT
, opoint_byte
= PT_BYTE
;
882 SET_PT_BOTH (pos
, pos_byte
);
883 while (PT
> BEGV
&& FETCH_BYTE (PT_BYTE
) == '\n')
884 scan_newline (PT
- 1, PT_BYTE
- 1, BEGV
, BEGV_BYTE
, -1, 0);
886 val
= position_indentation (PT_BYTE
);
887 SET_PT_BOTH (opoint
, opoint_byte
);
888 return val
>= column
;
891 DEFUN ("move-to-column", Fmove_to_column
, Smove_to_column
, 1, 2, "p",
892 doc
: /* Move point to column COLUMN in the current line.
893 The column of a character is calculated by adding together the widths
894 as displayed of the previous characters in the line.
895 This function ignores line-continuation;
896 there is no upper limit on the column number a character can have
897 and horizontal scrolling has no effect.
899 If specified column is within a character, point goes after that character.
900 If it's past end of line, point goes to end of line.
902 A non-nil second (optional) argument FORCE means,
903 if COLUMN is in the middle of a tab character, change it to spaces.
904 In addition, if FORCE is t, and the line is too short
905 to reach column COLUMN, add spaces/tabs to get there.
907 The return value is the current column. */)
909 Lisp_Object column
, force
;
912 register int col
= current_column ();
915 register int tab_width
= XINT (current_buffer
->tab_width
);
916 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
917 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
918 register int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
925 int pos_byte
, end_byte
, next_boundary_byte
;
927 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
928 CHECK_NATNUM (column
, 0);
929 goal
= XINT (column
);
936 next_boundary_byte
= PT_BYTE
;
938 /* If we're starting past the desired column,
939 back up to beginning of line and scan from there. */
943 pos
= current_column_bol_cache
;
944 pos_byte
= CHAR_TO_BYTE (pos
);
953 while (pos
== next_boundary
)
956 pos
= skip_invisible (pos
, &next_boundary
, end
, Qnil
);
958 pos_byte
= CHAR_TO_BYTE (pos
);
959 next_boundary_byte
= CHAR_TO_BYTE (next_boundary
);
964 /* Test reaching the goal column. We do this after skipping
965 invisible characters, so that we put point before the
966 character on which the cursor will appear. */
970 /* Check composition sequence. */
972 int len
, len_byte
, width
;
974 if (check_composition (pos
, pos_byte
, Z
, &len
, &len_byte
, &width
))
977 pos_byte
+= len_byte
;
983 c
= FETCH_BYTE (pos_byte
);
986 && ! (multibyte
&& BASE_LEADING_CODE_P (c
))
987 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
989 charvec
= DISP_CHAR_VECTOR (dp
, c
);
998 for (i
= n
- 1; i
>= 0; --i
)
1000 if (VECTORP (charvec
))
1002 /* This should be handled the same as
1003 next_element_from_display_vector does it. */
1004 Lisp_Object entry
= AREF (charvec
, i
);
1006 if (INTEGERP (entry
)
1007 && GLYPH_CHAR_VALID_P (XFASTINT (entry
)))
1008 c
= FAST_GLYPH_CHAR (XFASTINT (entry
));
1016 if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
1024 col
= col
/ tab_width
* tab_width
;
1026 else if (VECTORP (charvec
))
1028 else if (ctl_arrow
&& (c
< 040 || c
== 0177))
1030 else if (c
< 040 || c
== 0177)
1034 else if (multibyte
&& BASE_LEADING_CODE_P (c
))
1036 /* Start of multi-byte form. */
1038 int bytes
, width
, wide_column
;
1041 ptr
= BYTE_POS_ADDR (pos_byte
);
1042 MULTIBYTE_BYTES_WIDTH (ptr
, dp
);
1052 SET_PT_BOTH (pos
, pos_byte
);
1054 /* If a tab char made us overshoot, change it to spaces
1055 and scan through it again. */
1056 if (!NILP (force
) && col
> goal
&& c
== '\t' && prev_col
< goal
)
1058 int goal_pt
, goal_pt_byte
;
1060 /* Insert spaces in front of the tab to reach GOAL. Do this
1061 first so that a marker at the end of the tab gets
1063 SET_PT_BOTH (PT
- 1, PT_BYTE
- 1);
1064 Finsert_char (make_number (' '), make_number (goal
- prev_col
), Qt
);
1066 /* Now delete the tab, and indent to COL. */
1067 del_range (PT
, PT
+ 1);
1069 goal_pt_byte
= PT_BYTE
;
1070 Findent_to (make_number (col
), Qnil
);
1071 SET_PT_BOTH (goal_pt
, goal_pt_byte
);
1073 /* Set the last_known... vars consistently. */
1077 /* If line ends prematurely, add space to the end. */
1078 if (col
< goal
&& EQ (force
, Qt
))
1079 Findent_to (make_number (col
= goal
), Qnil
);
1081 last_known_column
= col
;
1082 last_known_column_point
= PT
;
1083 last_known_column_modified
= MODIFF
;
1085 XSETFASTINT (val
, col
);
1089 /* compute_motion: compute buffer posn given screen posn and vice versa */
1091 struct position val_compute_motion
;
1093 /* Scan the current buffer forward from offset FROM, pretending that
1094 this is at line FROMVPOS, column FROMHPOS, until reaching buffer
1095 offset TO or line TOVPOS, column TOHPOS (whichever comes first),
1096 and return the ending buffer position and screen location. If we
1097 can't hit the requested column exactly (because of a tab or other
1098 multi-column character), overshoot.
1100 DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
1101 at FROM. This is the case if FROMVPOS and FROMVPOS came from an
1102 earlier call to compute_motion. The other common case is that FROMHPOS
1103 is zero and FROM is a position that "belongs" at column zero, but might
1104 be shifted by overlay strings; in this case DID_MOTION should be 0.
1106 WIDTH is the number of columns available to display text;
1107 compute_motion uses this to handle continuation lines and such.
1108 HSCROLL is the number of columns not being displayed at the left
1109 margin; this is usually taken from a window's hscroll member.
1110 TAB_OFFSET is the number of columns of the first tab that aren't
1111 being displayed, perhaps because of a continuation line or
1114 compute_motion returns a pointer to a struct position. The bufpos
1115 member gives the buffer position at the end of the scan, and hpos
1116 and vpos give its cartesian location. prevhpos is the column at
1117 which the character before bufpos started, and contin is non-zero
1118 if we reached the current line by continuing the previous.
1120 Note that FROMHPOS and TOHPOS should be expressed in real screen
1121 columns, taking HSCROLL and the truncation glyph at the left margin
1122 into account. That is, beginning-of-line moves you to the hpos
1123 -HSCROLL + (HSCROLL > 0).
1125 For example, to find the buffer position of column COL of line LINE
1126 of a certain window, pass the window's starting location as FROM
1127 and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
1128 Pass the buffer's ZV as TO, to limit the scan to the end of the
1129 visible section of the buffer, and pass LINE and COL as TOVPOS and
1132 When displaying in window w, a typical formula for WIDTH is:
1135 - (has_vertical_scroll_bars
1136 ? FRAME_SCROLL_BAR_COLS (XFRAME (window->frame))
1137 : (window_width + window_left != frame_width))
1140 window_width is XFASTINT (w->width),
1141 window_left is XFASTINT (w->left),
1142 has_vertical_scroll_bars is
1143 FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (WINDOW_FRAME (window)))
1144 and frame_width = FRAME_WIDTH (XFRAME (window->frame))
1146 Or you can let window_internal_width do this all for you, and write:
1147 window_internal_width (w) - 1
1149 The `-1' accounts for the continuation-line backslashes; the rest
1150 accounts for window borders if the window is split horizontally, and
1151 the scroll bars if they are turned on. */
1154 compute_motion (from
, fromvpos
, fromhpos
, did_motion
, to
, tovpos
, tohpos
, width
, hscroll
, tab_offset
, win
)
1155 int from
, fromvpos
, fromhpos
, to
, tovpos
, tohpos
;
1158 int hscroll
, tab_offset
;
1161 register int hpos
= fromhpos
;
1162 register int vpos
= fromvpos
;
1167 register int tab_width
= XFASTINT (current_buffer
->tab_width
);
1168 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
1169 register struct Lisp_Char_Table
*dp
= window_display_table (win
);
1171 = (INTEGERP (current_buffer
->selective_display
)
1172 ? XINT (current_buffer
->selective_display
)
1173 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1176 = (selective
&& dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
1177 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
: 0);
1178 /* The next location where the `invisible' property changes, or an
1179 overlay starts or ends. */
1180 int next_boundary
= from
;
1182 /* For computing runs of characters with similar widths.
1183 Invariant: width_run_width is zero, or all the characters
1184 from width_run_start to width_run_end have a fixed width of
1186 int width_run_start
= from
;
1187 int width_run_end
= from
;
1188 int width_run_width
= 0;
1189 Lisp_Object
*width_table
;
1192 /* The next buffer pos where we should consult the width run cache. */
1193 int next_width_run
= from
;
1196 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
1197 /* If previous char scanned was a wide character,
1198 this is the column where it ended. Otherwise, this is 0. */
1199 int wide_column_end_hpos
= 0;
1200 int prev_pos
; /* Previous buffer position. */
1201 int prev_pos_byte
; /* Previous buffer position. */
1202 int contin_hpos
; /* HPOS of last column of continued line. */
1203 int prev_tab_offset
; /* Previous tab offset. */
1205 XSETBUFFER (buffer
, current_buffer
);
1206 XSETWINDOW (window
, win
);
1208 width_run_cache_on_off ();
1209 if (dp
== buffer_display_table ())
1210 width_table
= (VECTORP (current_buffer
->width_table
)
1211 ? XVECTOR (current_buffer
->width_table
)->contents
1214 /* If the window has its own display table, we can't use the width
1215 run cache, because that's based on the buffer's display table. */
1218 if (tab_width
<= 0 || tab_width
> 1000)
1224 pos
= prev_pos
= from
;
1225 pos_byte
= prev_pos_byte
= CHAR_TO_BYTE (from
);
1227 prev_tab_offset
= tab_offset
;
1230 while (pos
== next_boundary
)
1235 /* Don't skip invisible if we are already at the margin. */
1236 if (vpos
> tovpos
|| vpos
== tovpos
&& hpos
>= tohpos
)
1238 if (contin_hpos
&& prev_hpos
== 0
1240 && (contin_hpos
== width
|| wide_column_end_hpos
> width
))
1241 { /* Line breaks because we can't put the character at the
1242 previous line any more. It is not the multi-column
1243 character continued in middle. Go back to previous
1244 buffer position, screen position, and set tab offset
1245 to previous value. It's the beginning of the
1248 pos_byte
= prev_pos_byte
;
1250 tab_offset
= prev_tab_offset
;
1255 /* If the caller says that the screen position came from an earlier
1256 call to compute_motion, then we've already accounted for the
1257 overlay strings at point. This is only true the first time
1258 through, so clear the flag after testing it. */
1260 /* We need to skip past the overlay strings. Currently those
1261 strings must not contain TAB;
1262 if we want to relax that restriction, something will have
1263 to be changed here. */
1265 unsigned char *ovstr
;
1266 int ovlen
= overlay_strings (pos
, win
, &ovstr
);
1267 hpos
+= ((multibyte
&& ovlen
> 0)
1268 ? strwidth (ovstr
, ovlen
) : ovlen
);
1275 /* Advance POS past invisible characters
1276 (but not necessarily all that there are here),
1277 and store in next_boundary the next position where
1278 we need to call skip_invisible. */
1279 newpos
= skip_invisible (pos
, &next_boundary
, to
, window
);
1283 pos
= min (to
, newpos
);
1284 pos_byte
= CHAR_TO_BYTE (pos
);
1288 if (newpos
!= pos_here
)
1291 pos_byte
= CHAR_TO_BYTE (pos
);
1295 /* Handle right margin. */
1296 /* Note on a wide-column character.
1298 Characters are classified into the following three categories
1299 according to the width (columns occupied on screen).
1301 (1) single-column character: ex. `a'
1302 (2) multi-column character: ex. `^A', TAB, `\033'
1303 (3) wide-column character: ex. Japanese character, Chinese character
1304 (In the following example, `W_' stands for them.)
1306 Multi-column characters can be divided around the right margin,
1307 but wide-column characters cannot.
1311 (*) The cursor is placed on the next character after the point.
1315 j ^---- next after the point
1316 ^--- next char. after the point.
1318 In case of sigle-column character
1322 033 ^---- next after the point, next char. after the point.
1324 In case of multi-column character
1328 W_ ^---- next after the point
1329 ^---- next char. after the point.
1331 In case of wide-column character
1333 The problem here is continuation at a wide-column character.
1334 In this case, the line may shorter less than WIDTH.
1335 And we find the continuation AFTER it occurs.
1342 || (truncate_partial_width_windows
1343 && width
+ 1 < FRAME_WIDTH (XFRAME (WINDOW_FRAME (win
))))
1344 || !NILP (current_buffer
->truncate_lines
))
1346 /* Truncating: skip to newline, unless we are already past
1347 TO (we need to go back below). */
1350 pos
= find_before_next_newline (pos
, to
, 1);
1351 pos_byte
= CHAR_TO_BYTE (pos
);
1353 /* If we just skipped next_boundary,
1354 loop around in the main while
1356 if (pos
>= next_boundary
)
1357 next_boundary
= pos
+ 1;
1359 prev_tab_offset
= tab_offset
;
1365 /* Remember the previous value. */
1366 prev_tab_offset
= tab_offset
;
1368 if (wide_column_end_hpos
> width
)
1371 tab_offset
+= prev_hpos
;
1375 tab_offset
+= width
;
1379 contin_hpos
= prev_hpos
;
1384 /* Stop if past the target buffer position or screen position. */
1387 /* Go back to the previous position. */
1389 pos_byte
= prev_pos_byte
;
1391 tab_offset
= prev_tab_offset
;
1393 /* NOTE on contin_hpos, hpos, and prev_hpos.
1397 W_ ^---- contin_hpos
1403 if (contin_hpos
&& prev_hpos
== 0
1404 && contin_hpos
< width
&& !wide_column_end_hpos
)
1406 /* Line breaking occurs in the middle of multi-column
1407 character. Go back to previous line. */
1412 /* If previous character is NEWLINE,
1413 set VPOS back to previous line */
1418 if (vpos
> tovpos
|| vpos
== tovpos
&& hpos
>= tohpos
)
1420 if (contin_hpos
&& prev_hpos
== 0
1422 && (contin_hpos
== width
|| wide_column_end_hpos
> width
))
1423 { /* Line breaks because we can't put the character at the
1424 previous line any more. It is not the multi-column
1425 character continued in middle. Go back to previous
1426 buffer position, screen position, and set tab offset
1427 to previous value. It's the beginning of the
1430 pos_byte
= prev_pos_byte
;
1432 tab_offset
= prev_tab_offset
;
1436 if (pos
== ZV
) /* We cannot go beyond ZV. Stop here. */
1441 prev_pos_byte
= pos_byte
;
1442 wide_column_end_hpos
= 0;
1444 /* Consult the width run cache to see if we can avoid inspecting
1445 the text character-by-character. */
1446 if (current_buffer
->width_run_cache
&& pos
>= next_width_run
)
1450 = region_cache_forward (current_buffer
,
1451 current_buffer
->width_run_cache
,
1454 /* A width of zero means the character's width varies (like
1455 a tab), is meaningless (like a newline), or we just don't
1456 want to skip over it for some other reason. */
1457 if (common_width
!= 0)
1461 /* Don't go past the final buffer posn the user
1466 run_end_hpos
= hpos
+ (run_end
- pos
) * common_width
;
1468 /* Don't go past the final horizontal position the user
1470 if (vpos
== tovpos
&& run_end_hpos
> tohpos
)
1472 run_end
= pos
+ (tohpos
- hpos
) / common_width
;
1473 run_end_hpos
= hpos
+ (run_end
- pos
) * common_width
;
1476 /* Don't go past the margin. */
1477 if (run_end_hpos
>= width
)
1479 run_end
= pos
+ (width
- hpos
) / common_width
;
1480 run_end_hpos
= hpos
+ (run_end
- pos
) * common_width
;
1483 hpos
= run_end_hpos
;
1485 prev_hpos
= hpos
- common_width
;
1489 pos_byte
= CHAR_TO_BYTE (pos
);
1493 next_width_run
= run_end
+ 1;
1496 /* We have to scan the text character-by-character. */
1500 Lisp_Object charvec
;
1502 c
= FETCH_BYTE (pos_byte
);
1504 /* Check composition sequence. */
1506 int len
, len_byte
, width
;
1508 if (check_composition (pos
, pos_byte
, to
, &len
, &len_byte
, &width
))
1511 pos_byte
+= len_byte
;
1519 /* Perhaps add some info to the width_run_cache. */
1520 if (current_buffer
->width_run_cache
)
1522 /* Is this character part of the current run? If so, extend
1524 if (pos
- 1 == width_run_end
1525 && XFASTINT (width_table
[c
]) == width_run_width
)
1526 width_run_end
= pos
;
1528 /* The previous run is over, since this is a character at a
1529 different position, or a different width. */
1532 /* Have we accumulated a run to put in the cache?
1533 (Currently, we only cache runs of width == 1). */
1534 if (width_run_start
< width_run_end
1535 && width_run_width
== 1)
1536 know_region_cache (current_buffer
,
1537 current_buffer
->width_run_cache
,
1538 width_run_start
, width_run_end
);
1540 /* Start recording a new width run. */
1541 width_run_width
= XFASTINT (width_table
[c
]);
1542 width_run_start
= pos
- 1;
1543 width_run_end
= pos
;
1548 && ! (multibyte
&& BASE_LEADING_CODE_P (c
))
1549 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
1551 charvec
= DISP_CHAR_VECTOR (dp
, c
);
1552 n
= ASIZE (charvec
);
1560 for (i
= n
- 1; i
>= 0; --i
)
1562 if (VECTORP (charvec
))
1564 /* This should be handled the same as
1565 next_element_from_display_vector does it. */
1566 Lisp_Object entry
= AREF (charvec
, i
);
1568 if (INTEGERP (entry
)
1569 && GLYPH_CHAR_VALID_P (XFASTINT (entry
)))
1570 c
= FAST_GLYPH_CHAR (XFASTINT (entry
));
1575 if (c
>= 040 && c
< 0177)
1579 int tem
= ((hpos
+ tab_offset
+ hscroll
- (hscroll
> 0))
1583 hpos
+= tab_width
- tem
;
1588 && indented_beyond_p (pos
, pos_byte
, selective
))
1590 /* If (pos == to), we don't have to take care of
1591 selective display. */
1594 /* Skip any number of invisible lines all at once */
1597 pos
= find_before_next_newline (pos
, to
, 1);
1600 pos_byte
= CHAR_TO_BYTE (pos
);
1603 && indented_beyond_p (pos
, pos_byte
, selective
));
1604 /* Allow for the " ..." that is displayed for them. */
1607 hpos
+= selective_rlen
;
1611 DEC_BOTH (pos
, pos_byte
);
1612 /* We have skipped the invis text, but not the
1618 /* A visible line. */
1622 /* Count the truncation glyph on column 0 */
1629 else if (c
== CR
&& selective
< 0)
1631 /* In selective display mode,
1632 everything from a ^M to the end of the line is invisible.
1633 Stop *before* the real newline. */
1636 pos
= find_before_next_newline (pos
, to
, 1);
1637 pos_byte
= CHAR_TO_BYTE (pos
);
1639 /* If we just skipped next_boundary,
1640 loop around in the main while
1642 if (pos
> next_boundary
)
1643 next_boundary
= pos
;
1644 /* Allow for the " ..." that is displayed for them. */
1647 hpos
+= selective_rlen
;
1652 else if (multibyte
&& BASE_LEADING_CODE_P (c
))
1654 /* Start of multi-byte form. */
1656 int bytes
, width
, wide_column
;
1658 pos_byte
--; /* rewind POS_BYTE */
1659 ptr
= BYTE_POS_ADDR (pos_byte
);
1660 MULTIBYTE_BYTES_WIDTH (ptr
, dp
);
1663 wide_column_end_hpos
= hpos
+ wide_column
;
1666 else if (VECTORP (charvec
))
1669 hpos
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
1676 /* Remember any final width run in the cache. */
1677 if (current_buffer
->width_run_cache
1678 && width_run_width
== 1
1679 && width_run_start
< width_run_end
)
1680 know_region_cache (current_buffer
, current_buffer
->width_run_cache
,
1681 width_run_start
, width_run_end
);
1683 val_compute_motion
.bufpos
= pos
;
1684 val_compute_motion
.bytepos
= pos_byte
;
1685 val_compute_motion
.hpos
= hpos
;
1686 val_compute_motion
.vpos
= vpos
;
1687 if (contin_hpos
&& prev_hpos
== 0)
1688 val_compute_motion
.prevhpos
= contin_hpos
;
1690 val_compute_motion
.prevhpos
= prev_hpos
;
1691 /* We alalways handle all of them here; none of them remain to do. */
1692 val_compute_motion
.ovstring_chars_done
= 0;
1694 /* Nonzero if have just continued a line */
1695 val_compute_motion
.contin
= (contin_hpos
&& prev_hpos
== 0);
1698 return &val_compute_motion
;
1702 DEFUN ("compute-motion", Fcompute_motion
, Scompute_motion
, 7, 7, 0,
1703 doc
: /* Scan through the current buffer, calculating screen position.
1704 Scan the current buffer forward from offset FROM,
1705 assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--
1706 to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--
1707 and return the ending buffer position and screen location.
1709 There are three additional arguments:
1711 WIDTH is the number of columns available to display text;
1712 this affects handling of continuation lines.
1713 This is usually the value returned by `window-width', less one (to allow
1714 for the continuation glyph).
1716 OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).
1717 HSCROLL is the number of columns not being displayed at the left
1718 margin; this is usually taken from a window's hscroll member.
1719 TAB-OFFSET is the number of columns of the first tab that aren't
1720 being displayed, perhaps because the line was continued within it.
1721 If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.
1723 WINDOW is the window to operate on. It is used to choose the display table;
1724 if it is showing the current buffer, it is used also for
1725 deciding which overlay properties apply.
1726 Note that `compute-motion' always operates on the current buffer.
1728 The value is a list of five elements:
1729 (POS HPOS VPOS PREVHPOS CONTIN)
1730 POS is the buffer position where the scan stopped.
1731 VPOS is the vertical position where the scan stopped.
1732 HPOS is the horizontal position where the scan stopped.
1734 PREVHPOS is the horizontal position one character back from POS.
1735 CONTIN is t if a line was continued after (or within) the previous character.
1737 For example, to find the buffer position of column COL of line LINE
1738 of a certain window, pass the window's starting location as FROM
1739 and the window's upper-left coordinates as FROMPOS.
1740 Pass the buffer's (point-max) as TO, to limit the scan to the end of the
1741 visible section of the buffer, and pass LINE and COL as TOPOS. */)
1742 (from
, frompos
, to
, topos
, width
, offsets
, window
)
1743 Lisp_Object from
, frompos
, to
, topos
;
1744 Lisp_Object width
, offsets
, window
;
1746 Lisp_Object bufpos
, hpos
, vpos
, prevhpos
;
1747 struct position
*pos
;
1748 int hscroll
, tab_offset
;
1750 CHECK_NUMBER_COERCE_MARKER (from
, 0);
1751 CHECK_CONS (frompos
, 0);
1752 CHECK_NUMBER_CAR (frompos
, 0);
1753 CHECK_NUMBER_CDR (frompos
, 0);
1754 CHECK_NUMBER_COERCE_MARKER (to
, 0);
1755 CHECK_CONS (topos
, 0);
1756 CHECK_NUMBER_CAR (topos
, 0);
1757 CHECK_NUMBER_CDR (topos
, 0);
1758 CHECK_NUMBER (width
, 0);
1759 if (!NILP (offsets
))
1761 CHECK_CONS (offsets
, 0);
1762 CHECK_NUMBER_CAR (offsets
, 0);
1763 CHECK_NUMBER_CDR (offsets
, 0);
1764 hscroll
= XINT (XCAR (offsets
));
1765 tab_offset
= XINT (XCDR (offsets
));
1768 hscroll
= tab_offset
= 0;
1771 window
= Fselected_window ();
1773 CHECK_LIVE_WINDOW (window
, 0);
1775 if (XINT (from
) < BEGV
|| XINT (from
) > ZV
)
1776 args_out_of_range_3 (from
, make_number (BEGV
), make_number (ZV
));
1777 if (XINT (to
) < BEGV
|| XINT (to
) > ZV
)
1778 args_out_of_range_3 (to
, make_number (BEGV
), make_number (ZV
));
1780 pos
= compute_motion (XINT (from
), XINT (XCDR (frompos
)),
1781 XINT (XCAR (frompos
)), 0,
1782 XINT (to
), XINT (XCDR (topos
)),
1783 XINT (XCAR (topos
)),
1784 XINT (width
), hscroll
, tab_offset
,
1787 XSETFASTINT (bufpos
, pos
->bufpos
);
1788 XSETINT (hpos
, pos
->hpos
);
1789 XSETINT (vpos
, pos
->vpos
);
1790 XSETINT (prevhpos
, pos
->prevhpos
);
1792 return Fcons (bufpos
,
1796 Fcons (pos
->contin
? Qt
: Qnil
, Qnil
)))));
1800 /* Fvertical_motion and vmotion */
1802 struct position val_vmotion
;
1805 vmotion (from
, vtarget
, w
)
1806 register int from
, vtarget
;
1809 int width
= window_internal_width (w
) - 1;
1810 int hscroll
= XINT (w
->hscroll
);
1811 struct position pos
;
1812 /* vpos is cumulative vertical position, changed as from is changed */
1813 register int vpos
= 0;
1814 Lisp_Object prevline
;
1817 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
1819 = (INTEGERP (current_buffer
->selective_display
)
1820 ? XINT (current_buffer
->selective_display
)
1821 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1825 /* This is the object we use for fetching character properties. */
1826 Lisp_Object text_prop_object
;
1828 XSETWINDOW (window
, w
);
1830 /* If the window contains this buffer, use it for getting text properties.
1831 Otherwise use the current buffer as arg for doing that. */
1832 if (EQ (w
->buffer
, Fcurrent_buffer ()))
1833 text_prop_object
= window
;
1835 text_prop_object
= Fcurrent_buffer ();
1837 if (vpos
>= vtarget
)
1839 /* To move upward, go a line at a time until
1840 we have gone at least far enough. */
1844 while ((vpos
> vtarget
|| first
) && from
> BEGV
)
1846 Lisp_Object propval
;
1848 XSETFASTINT (prevline
, find_next_newline_no_quit (from
- 1, -1));
1849 while (XFASTINT (prevline
) > BEGV
1851 && indented_beyond_p (XFASTINT (prevline
),
1852 CHAR_TO_BYTE (XFASTINT (prevline
)),
1854 /* watch out for newlines with `invisible' property */
1855 || (propval
= Fget_char_property (prevline
,
1858 TEXT_PROP_MEANS_INVISIBLE (propval
))))
1859 XSETFASTINT (prevline
,
1860 find_next_newline_no_quit (XFASTINT (prevline
) - 1,
1862 pos
= *compute_motion (XFASTINT (prevline
), 0,
1863 lmargin
+ (XFASTINT (prevline
) == BEG
1867 /* Don't care for VPOS... */
1868 1 << (BITS_PER_SHORT
- 1),
1870 1 << (BITS_PER_SHORT
- 1),
1872 /* This compensates for start_hpos
1873 so that a tab as first character
1874 still occupies 8 columns. */
1875 (XFASTINT (prevline
) == BEG
1880 from
= XFASTINT (prevline
);
1883 /* If we made exactly the desired vertical distance,
1884 or if we hit beginning of buffer,
1885 return point found */
1886 if (vpos
>= vtarget
)
1888 val_vmotion
.bufpos
= from
;
1889 val_vmotion
.bytepos
= CHAR_TO_BYTE (from
);
1890 val_vmotion
.vpos
= vpos
;
1891 val_vmotion
.hpos
= lmargin
;
1892 val_vmotion
.contin
= 0;
1893 val_vmotion
.prevhpos
= 0;
1894 val_vmotion
.ovstring_chars_done
= 0;
1895 val_vmotion
.tab_offset
= 0; /* For accumulating tab offset. */
1896 return &val_vmotion
;
1899 /* Otherwise find the correct spot by moving down */
1901 /* Moving downward is simple, but must calculate from beg of line
1902 to determine hpos of starting point */
1903 from_byte
= CHAR_TO_BYTE (from
);
1904 if (from
> BEGV
&& FETCH_BYTE (from_byte
- 1) != '\n')
1906 Lisp_Object propval
;
1908 XSETFASTINT (prevline
, find_next_newline_no_quit (from
, -1));
1909 while (XFASTINT (prevline
) > BEGV
1911 && indented_beyond_p (XFASTINT (prevline
),
1912 CHAR_TO_BYTE (XFASTINT (prevline
)),
1914 /* watch out for newlines with `invisible' property */
1915 || (propval
= Fget_char_property (prevline
, Qinvisible
,
1917 TEXT_PROP_MEANS_INVISIBLE (propval
))))
1918 XSETFASTINT (prevline
,
1919 find_next_newline_no_quit (XFASTINT (prevline
) - 1,
1921 pos
= *compute_motion (XFASTINT (prevline
), 0,
1922 lmargin
+ (XFASTINT (prevline
) == BEG
1926 /* Don't care for VPOS... */
1927 1 << (BITS_PER_SHORT
- 1),
1929 1 << (BITS_PER_SHORT
- 1),
1931 (XFASTINT (prevline
) == BEG
? -start_hpos
: 0),
1937 pos
.hpos
= lmargin
+ (from
== BEG
? start_hpos
: 0);
1942 return compute_motion (from
, vpos
, pos
.hpos
, did_motion
,
1943 ZV
, vtarget
, - (1 << (BITS_PER_SHORT
- 1)),
1945 pos
.tab_offset
- (from
== BEG
? start_hpos
: 0),
1949 DEFUN ("vertical-motion", Fvertical_motion
, Svertical_motion
, 1, 2, 0,
1950 doc
: /* Move point to start of the screen line LINES lines down.
1951 If LINES is negative, this means moving up.
1953 This function is an ordinary cursor motion function
1954 which calculates the new position based on how text would be displayed.
1955 The new position may be the start of a line,
1956 or just the start of a continuation line.
1957 The function returns number of screen lines moved over;
1958 that usually equals LINES, but may be closer to zero
1959 if beginning or end of buffer was reached.
1961 The optional second argument WINDOW specifies the window to use for
1962 parameters such as width, horizontal scrolling, and so on.
1963 The default is to use the selected window's parameters.
1965 `vertical-motion' always uses the current buffer,
1966 regardless of which buffer is displayed in WINDOW.
1967 This is consistent with other cursor motion functions
1968 and makes it possible to use `vertical-motion' in any buffer,
1969 whether or not it is currently displayed in some window. */)
1971 Lisp_Object lines
, window
;
1976 Lisp_Object old_buffer
;
1977 struct gcpro gcpro1
;
1979 CHECK_NUMBER (lines
, 0);
1980 if (! NILP (window
))
1981 CHECK_WINDOW (window
, 0);
1983 window
= selected_window
;
1984 w
= XWINDOW (window
);
1987 GCPRO1 (old_buffer
);
1988 if (XBUFFER (w
->buffer
) != current_buffer
)
1990 /* Set the window's buffer temporarily to the current buffer. */
1991 old_buffer
= w
->buffer
;
1992 XSETBUFFER (w
->buffer
, current_buffer
);
1995 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
1996 start_display (&it
, w
, pt
);
1997 move_it_by_lines (&it
, XINT (lines
), 0);
1998 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
2000 if (BUFFERP (old_buffer
))
2001 w
->buffer
= old_buffer
;
2003 RETURN_UNGCPRO (make_number (it
.vpos
));
2008 /* File's initialization. */
2013 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode
,
2014 doc
: /* *Indentation can insert tabs if this is non-nil.
2015 Setting this variable automatically makes it local to the current buffer. */);
2016 indent_tabs_mode
= 1;
2018 defsubr (&Scurrent_indentation
);
2019 defsubr (&Sindent_to
);
2020 defsubr (&Scurrent_column
);
2021 defsubr (&Smove_to_column
);
2022 defsubr (&Svertical_motion
);
2023 defsubr (&Scompute_motion
);