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 prop
= Fget_char_property (position
, Qinvisible
,
271 && EQ (XWINDOW (window
)->buffer
, buffer
))
273 inv_p
= TEXT_PROP_MEANS_INVISIBLE (prop
);
274 /* When counting columns (window == nil), don't skip over ellipsis text. */
275 if (NILP (window
) ? inv_p
== 1 : inv_p
)
276 return *next_boundary_p
;
280 /* If a composition starts at POS/POS_BYTE and it doesn't stride over
281 POINT, set *LEN / *LEN_BYTE to the character and byte lengths, *WIDTH
282 to the width, and return 1. Otherwise, return 0. */
285 check_composition (pos
, pos_byte
, point
, len
, len_byte
, width
)
286 int pos
, pos_byte
, point
;
287 int *len
, *len_byte
, *width
;
293 if (! find_composition (pos
, -1, &start
, &end
, &prop
, Qnil
)
294 || pos
!= start
|| point
< end
295 || !COMPOSITION_VALID_P (start
, end
, prop
))
297 if ((id
= get_composition_id (pos
, pos_byte
, end
- pos
, prop
, Qnil
)) < 0)
300 *len
= COMPOSITION_LENGTH (prop
);
301 *len_byte
= CHAR_TO_BYTE (end
) - pos_byte
;
302 *width
= composition_table
[id
]->width
;
306 /* Set variables WIDTH and BYTES for a multibyte sequence starting at P.
308 DP is a display table or NULL.
310 This macro is used in current_column_1, Fmove_to_column, and
313 #define MULTIBYTE_BYTES_WIDTH(p, dp) \
318 c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, bytes); \
319 if (BYTES_BY_CHAR_HEAD (*p) != bytes) \
323 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) \
324 width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; \
326 width = WIDTH_BY_CHAR_HEAD (*p); \
328 wide_column = width; \
332 DEFUN ("current-column", Fcurrent_column
, Scurrent_column
, 0, 0, 0,
333 doc
: /* Return the horizontal position of point. Beginning of line is column 0.
334 This is calculated by adding together the widths of all the displayed
335 representations of the character between the start of the previous line
336 and point. (eg control characters will have a width of 2 or 4, tabs
337 will have a variable width)
338 Ignores finite width of frame, which means that this function may return
339 values greater than (frame-width).
340 Whether the line is visible (if `selective-display' is t) has no effect;
341 however, ^M is treated as end of line when `selective-display' is t. */)
345 XSETFASTINT (temp
, current_column ());
349 /* Cancel any recorded value of the horizontal position. */
352 invalidate_current_column ()
354 last_known_column_point
= 0;
361 register unsigned char *ptr
, *stop
;
362 register int tab_seen
;
365 register int tab_width
= XINT (current_buffer
->tab_width
);
366 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
367 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
369 if (PT
== last_known_column_point
370 && MODIFF
== last_known_column_modified
)
371 return last_known_column
;
373 /* If the buffer has overlays, text properties,
374 or multibyte characters, use a more general algorithm. */
375 if (BUF_INTERVALS (current_buffer
)
376 || !NILP (current_buffer
->overlays_before
)
377 || !NILP (current_buffer
->overlays_after
)
379 return current_column_1 ();
381 /* Scan backwards from point to the previous newline,
382 counting width. Tab characters are the only complicated case. */
384 /* Make a pointer for decrementing through the chars before point. */
385 ptr
= BYTE_POS_ADDR (PT_BYTE
- 1) + 1;
386 /* Make a pointer to where consecutive chars leave off,
387 going backwards from point. */
390 else if (PT
<= GPT
|| BEGV
> GPT
)
395 if (tab_width
<= 0 || tab_width
> 1000)
398 col
= 0, tab_seen
= 0, post_tab
= 0;
407 /* We stopped either for the beginning of the buffer
409 if (ptr
== BEGV_ADDR
)
412 /* It was the gap. Jump back over it. */
416 /* Check whether that brings us to beginning of buffer. */
423 if (dp
&& VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
425 charvec
= DISP_CHAR_VECTOR (dp
, c
);
434 for (i
= n
- 1; i
>= 0; --i
)
436 if (VECTORP (charvec
))
438 /* This should be handled the same as
439 next_element_from_display_vector does it. */
440 Lisp_Object entry
= AREF (charvec
, i
);
443 && GLYPH_CHAR_VALID_P (XFASTINT (entry
)))
444 c
= FAST_GLYPH_CHAR (XFASTINT (entry
));
449 if (c
>= 040 && c
< 0177)
453 && EQ (current_buffer
->selective_display
, Qt
)))
456 goto start_of_line_found
;
461 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
467 else if (VECTORP (charvec
))
468 /* With a display table entry, C is displayed as is, and
469 not displayed as \NNN or as ^N. If C is a single-byte
470 character, it takes one column. If C is multi-byte in
471 an unibyte buffer, it's translated to unibyte, so it
472 also takes one column. */
475 col
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
483 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
487 if (ptr
== BEGV_ADDR
)
488 current_column_bol_cache
= BEGV
;
490 current_column_bol_cache
= BYTE_TO_CHAR (PTR_BYTE_POS (ptr
));
492 last_known_column
= col
;
493 last_known_column_point
= PT
;
494 last_known_column_modified
= MODIFF
;
499 /* Return the column number of position POS
500 by scanning forward from the beginning of the line.
501 This function handles characters that are invisible
502 due to text properties or overlays. */
507 register int tab_width
= XINT (current_buffer
->tab_width
);
508 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
509 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
510 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
512 /* Start the scan at the beginning of this line with column number 0. */
513 register int col
= 0;
515 int next_boundary
, next_boundary_byte
;
516 int opoint
= PT
, opoint_byte
= PT_BYTE
;
518 scan_newline (PT
, PT_BYTE
, BEGV
, BEGV_BYTE
, -1, 1);
519 current_column_bol_cache
= PT
;
520 scan
= PT
, scan_byte
= PT_BYTE
;
521 SET_PT_BOTH (opoint
, opoint_byte
);
522 next_boundary
= scan
;
523 next_boundary_byte
= scan_byte
;
525 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
527 /* Scan forward to the target position. */
528 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
)))
570 /* This character is displayed using a vector of glyphs.
571 Update the column based on those glyphs. */
573 charvec
= DISP_CHAR_VECTOR (dp
, c
);
576 for (i
= 0; i
< n
; i
++)
578 /* This should be handled the same as
579 next_element_from_display_vector does it. */
581 entry
= AREF (charvec
, i
);
584 && GLYPH_CHAR_VALID_P (XFASTINT (entry
)))
585 c
= FAST_GLYPH_CHAR (XFASTINT (entry
));
591 if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
596 col
= col
/ tab_width
* tab_width
;
604 /* The display table says nothing for this character.
605 Display it as itself. */
609 if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
614 col
= col
/ tab_width
* tab_width
;
616 else if (multibyte
&& BASE_LEADING_CODE_P (c
))
619 int bytes
, width
, wide_column
;
621 ptr
= BYTE_POS_ADDR (scan_byte
);
622 MULTIBYTE_BYTES_WIDTH (ptr
, dp
);
624 /* Subtract one to compensate for the increment
625 that is going to happen below. */
629 else if (ctl_arrow
&& (c
< 040 || c
== 0177))
631 else if (c
< 040 || c
>= 0177)
642 last_known_column
= col
;
643 last_known_column_point
= PT
;
644 last_known_column_modified
= MODIFF
;
650 #if 0 /* Not used. */
652 /* Return the width in columns of the part of STRING from BEG to END.
653 If BEG is nil, that stands for the beginning of STRING.
654 If END is nil, that stands for the end of STRING. */
657 string_display_width (string
, beg
, end
)
658 Lisp_Object string
, beg
, end
;
661 register unsigned char *ptr
, *stop
;
662 register int tab_seen
;
665 register int tab_width
= XINT (current_buffer
->tab_width
);
666 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
667 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
671 e
= XSTRING (string
)->size
;
686 /* Make a pointer for decrementing through the chars before point. */
687 ptr
= XSTRING (string
)->data
+ e
;
688 /* Make a pointer to where consecutive chars leave off,
689 going backwards from point. */
690 stop
= XSTRING (string
)->data
+ b
;
692 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
694 col
= 0, tab_seen
= 0, post_tab
= 0;
702 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
703 col
+= XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
;
704 else if (c
>= 040 && c
< 0177)
711 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
718 col
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
723 col
= ((col
+ tab_width
) / tab_width
) * tab_width
;
733 DEFUN ("indent-to", Findent_to
, Sindent_to
, 1, 2, "NIndent to column: ",
734 doc
: /* Indent from point with tabs and spaces until COLUMN is reached.
735 Optional second argument MININUM says always do at least MININUM spaces
736 even if that goes past COLUMN; by default, MININUM is zero. */)
738 Lisp_Object column
, minimum
;
741 register int fromcol
;
742 register int tab_width
= XINT (current_buffer
->tab_width
);
744 CHECK_NUMBER (column
);
746 XSETFASTINT (minimum
, 0);
747 CHECK_NUMBER (minimum
);
749 fromcol
= current_column ();
750 mincol
= fromcol
+ XINT (minimum
);
751 if (mincol
< XINT (column
)) mincol
= XINT (column
);
753 if (fromcol
== mincol
)
754 return make_number (mincol
);
756 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
758 if (indent_tabs_mode
)
761 XSETFASTINT (n
, mincol
/ tab_width
- fromcol
/ tab_width
);
762 if (XFASTINT (n
) != 0)
764 Finsert_char (make_number ('\t'), n
, Qt
);
766 fromcol
= (mincol
/ tab_width
) * tab_width
;
770 XSETFASTINT (column
, mincol
- fromcol
);
771 Finsert_char (make_number (' '), column
, Qt
);
773 last_known_column
= mincol
;
774 last_known_column_point
= PT
;
775 last_known_column_modified
= MODIFF
;
777 XSETINT (column
, mincol
);
782 static int position_indentation
P_ ((int));
784 DEFUN ("current-indentation", Fcurrent_indentation
, Scurrent_indentation
,
786 doc
: /* Return the indentation of the current line.
787 This is the horizontal position of the character
788 following any initial whitespace. */)
792 int opoint
= PT
, opoint_byte
= PT_BYTE
;
794 scan_newline (PT
, PT_BYTE
, BEGV
, BEGV_BYTE
, -1, 1);
796 XSETFASTINT (val
, position_indentation (PT_BYTE
));
797 SET_PT_BOTH (opoint
, opoint_byte
);
802 position_indentation (pos_byte
)
803 register int pos_byte
;
805 register int column
= 0;
806 register int tab_width
= XINT (current_buffer
->tab_width
);
807 register unsigned char *p
;
808 register unsigned char *stop
;
809 unsigned char *start
;
810 int next_boundary_byte
= pos_byte
;
811 int ceiling
= next_boundary_byte
;
813 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
815 p
= BYTE_POS_ADDR (pos_byte
);
816 /* STOP records the value of P at which we will need
817 to think about the gap, or about invisible text,
818 or about the end of the buffer. */
820 /* START records the starting value of P. */
828 /* If we have updated P, set POS_BYTE to match.
829 The first time we enter the loop, POS_BYTE is already right. */
831 pos_byte
= PTR_BYTE_POS (p
);
832 /* Consider the various reasons STOP might have been set here. */
833 if (pos_byte
== ZV_BYTE
)
835 if (pos_byte
== next_boundary_byte
)
838 int pos
= BYTE_TO_CHAR (pos_byte
);
839 pos
= skip_invisible (pos
, &next_boundary
, ZV
, Qnil
);
840 pos_byte
= CHAR_TO_BYTE (pos
);
841 next_boundary_byte
= CHAR_TO_BYTE (next_boundary
);
843 if (pos_byte
>= ceiling
)
844 ceiling
= BUFFER_CEILING_OF (pos_byte
) + 1;
845 /* Compute the next place we need to stop and think,
846 and set STOP accordingly. */
847 stop_pos_byte
= min (ceiling
, next_boundary_byte
);
848 /* The -1 and +1 arrange to point at the first byte of gap
849 (if STOP_POS_BYTE is the position of the gap)
850 rather than at the data after the gap. */
852 stop
= BYTE_POS_ADDR (stop_pos_byte
- 1) + 1;
853 p
= BYTE_POS_ADDR (pos_byte
);
858 if (! NILP (current_buffer
->enable_multibyte_characters
))
864 column
+= tab_width
- column
% tab_width
;
867 if (ASCII_BYTE_P (p
[-1])
868 || NILP (current_buffer
->enable_multibyte_characters
))
872 pos_byte
= PTR_BYTE_POS (p
- 1);
873 c
= FETCH_MULTIBYTE_CHAR (pos_byte
);
874 if (CHAR_HAS_CATEGORY (c
, ' '))
878 p
= BYTE_POS_ADDR (pos_byte
);
887 /* Test whether the line beginning at POS is indented beyond COLUMN.
888 Blank lines are treated as if they had the same indentation as the
892 indented_beyond_p (pos
, pos_byte
, column
)
893 int pos
, pos_byte
, column
;
896 int opoint
= PT
, opoint_byte
= PT_BYTE
;
898 SET_PT_BOTH (pos
, pos_byte
);
899 while (PT
> BEGV
&& FETCH_BYTE (PT_BYTE
) == '\n')
900 scan_newline (PT
- 1, PT_BYTE
- 1, BEGV
, BEGV_BYTE
, -1, 0);
902 val
= position_indentation (PT_BYTE
);
903 SET_PT_BOTH (opoint
, opoint_byte
);
904 return val
>= column
;
907 DEFUN ("move-to-column", Fmove_to_column
, Smove_to_column
, 1, 2, "p",
908 doc
: /* Move point to column COLUMN in the current line.
909 The column of a character is calculated by adding together the widths
910 as displayed of the previous characters in the line.
911 This function ignores line-continuation;
912 there is no upper limit on the column number a character can have
913 and horizontal scrolling has no effect.
915 If specified column is within a character, point goes after that character.
916 If it's past end of line, point goes to end of line.
918 A non-nil second (optional) argument FORCE means,
919 if COLUMN is in the middle of a tab character, change it to spaces.
920 In addition, if FORCE is t, and the line is too short
921 to reach column COLUMN, add spaces/tabs to get there.
923 The return value is the current column. */)
925 Lisp_Object column
, force
;
928 register int col
= current_column ();
931 register int tab_width
= XINT (current_buffer
->tab_width
);
932 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
933 register struct Lisp_Char_Table
*dp
= buffer_display_table ();
934 register int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
941 int pos_byte
, end_byte
, next_boundary_byte
;
943 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
944 CHECK_NATNUM (column
);
945 goal
= XINT (column
);
952 next_boundary_byte
= PT_BYTE
;
954 /* If we're starting past the desired column,
955 back up to beginning of line and scan from there. */
959 pos
= current_column_bol_cache
;
960 pos_byte
= CHAR_TO_BYTE (pos
);
966 while (pos
== next_boundary
)
969 pos
= skip_invisible (pos
, &next_boundary
, end
, Qnil
);
971 pos_byte
= CHAR_TO_BYTE (pos
);
972 next_boundary_byte
= CHAR_TO_BYTE (next_boundary
);
977 /* Test reaching the goal column. We do this after skipping
978 invisible characters, so that we put point before the
979 character on which the cursor will appear. */
983 /* Check composition sequence. */
985 int len
, len_byte
, width
;
987 if (check_composition (pos
, pos_byte
, Z
, &len
, &len_byte
, &width
))
990 pos_byte
+= len_byte
;
996 c
= FETCH_BYTE (pos_byte
);
998 /* See if there is a display table and it relates
999 to this character. */
1002 && ! (multibyte
&& BASE_LEADING_CODE_P (c
))
1003 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
1005 Lisp_Object charvec
;
1008 /* This character is displayed using a vector of glyphs.
1009 Update the position based on those glyphs. */
1011 charvec
= DISP_CHAR_VECTOR (dp
, c
);
1012 n
= ASIZE (charvec
);
1014 for (i
= 0; i
< n
; i
++)
1016 /* This should be handled the same as
1017 next_element_from_display_vector does it. */
1020 entry
= AREF (charvec
, i
);
1022 if (INTEGERP (entry
)
1023 && GLYPH_CHAR_VALID_P (XFASTINT (entry
)))
1024 c
= FAST_GLYPH_CHAR (XFASTINT (entry
));
1030 if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
1036 col
= col
/ tab_width
* tab_width
;
1044 /* The display table doesn't affect this character;
1045 it displays as itself. */
1049 if (c
== '\r' && EQ (current_buffer
->selective_display
, Qt
))
1055 col
= col
/ tab_width
* tab_width
;
1057 else if (ctl_arrow
&& (c
< 040 || c
== 0177))
1059 else if (c
< 040 || c
== 0177)
1063 else if (multibyte
&& BASE_LEADING_CODE_P (c
))
1065 /* Start of multi-byte form. */
1067 int bytes
, width
, wide_column
;
1069 ptr
= BYTE_POS_ADDR (pos_byte
);
1070 MULTIBYTE_BYTES_WIDTH (ptr
, dp
);
1071 pos_byte
+= bytes
- 1;
1083 SET_PT_BOTH (pos
, pos_byte
);
1085 /* If a tab char made us overshoot, change it to spaces
1086 and scan through it again. */
1087 if (!NILP (force
) && col
> goal
&& c
== '\t' && prev_col
< goal
)
1089 int goal_pt
, goal_pt_byte
;
1091 /* Insert spaces in front of the tab to reach GOAL. Do this
1092 first so that a marker at the end of the tab gets
1094 SET_PT_BOTH (PT
- 1, PT_BYTE
- 1);
1095 Finsert_char (make_number (' '), make_number (goal
- prev_col
), Qt
);
1097 /* Now delete the tab, and indent to COL. */
1098 del_range (PT
, PT
+ 1);
1100 goal_pt_byte
= PT_BYTE
;
1101 Findent_to (make_number (col
), Qnil
);
1102 SET_PT_BOTH (goal_pt
, goal_pt_byte
);
1104 /* Set the last_known... vars consistently. */
1108 /* If line ends prematurely, add space to the end. */
1109 if (col
< goal
&& EQ (force
, Qt
))
1110 Findent_to (make_number (col
= goal
), Qnil
);
1112 last_known_column
= col
;
1113 last_known_column_point
= PT
;
1114 last_known_column_modified
= MODIFF
;
1116 XSETFASTINT (val
, col
);
1120 /* compute_motion: compute buffer posn given screen posn and vice versa */
1122 struct position val_compute_motion
;
1124 /* Scan the current buffer forward from offset FROM, pretending that
1125 this is at line FROMVPOS, column FROMHPOS, until reaching buffer
1126 offset TO or line TOVPOS, column TOHPOS (whichever comes first),
1127 and return the ending buffer position and screen location. If we
1128 can't hit the requested column exactly (because of a tab or other
1129 multi-column character), overshoot.
1131 DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
1132 at FROM. This is the case if FROMVPOS and FROMVPOS came from an
1133 earlier call to compute_motion. The other common case is that FROMHPOS
1134 is zero and FROM is a position that "belongs" at column zero, but might
1135 be shifted by overlay strings; in this case DID_MOTION should be 0.
1137 WIDTH is the number of columns available to display text;
1138 compute_motion uses this to handle continuation lines and such.
1139 HSCROLL is the number of columns not being displayed at the left
1140 margin; this is usually taken from a window's hscroll member.
1141 TAB_OFFSET is the number of columns of the first tab that aren't
1142 being displayed, perhaps because of a continuation line or
1145 compute_motion returns a pointer to a struct position. The bufpos
1146 member gives the buffer position at the end of the scan, and hpos
1147 and vpos give its cartesian location. prevhpos is the column at
1148 which the character before bufpos started, and contin is non-zero
1149 if we reached the current line by continuing the previous.
1151 Note that FROMHPOS and TOHPOS should be expressed in real screen
1152 columns, taking HSCROLL and the truncation glyph at the left margin
1153 into account. That is, beginning-of-line moves you to the hpos
1154 -HSCROLL + (HSCROLL > 0).
1156 For example, to find the buffer position of column COL of line LINE
1157 of a certain window, pass the window's starting location as FROM
1158 and the window's upper-left coordinates as FROMVPOS and FROMHPOS.
1159 Pass the buffer's ZV as TO, to limit the scan to the end of the
1160 visible section of the buffer, and pass LINE and COL as TOVPOS and
1163 When displaying in window w, a typical formula for WIDTH is:
1166 - (has_vertical_scroll_bars
1167 ? FRAME_SCROLL_BAR_COLS (XFRAME (window->frame))
1168 : (window_width + window_left != frame_width))
1171 window_width is XFASTINT (w->width),
1172 window_left is XFASTINT (w->left),
1173 has_vertical_scroll_bars is
1174 FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (WINDOW_FRAME (window)))
1175 and frame_width = FRAME_WIDTH (XFRAME (window->frame))
1177 Or you can let window_internal_width do this all for you, and write:
1178 window_internal_width (w) - 1
1180 The `-1' accounts for the continuation-line backslashes; the rest
1181 accounts for window borders if the window is split horizontally, and
1182 the scroll bars if they are turned on. */
1185 compute_motion (from
, fromvpos
, fromhpos
, did_motion
, to
, tovpos
, tohpos
, width
, hscroll
, tab_offset
, win
)
1186 int from
, fromvpos
, fromhpos
, to
, tovpos
, tohpos
;
1189 int hscroll
, tab_offset
;
1192 register int hpos
= fromhpos
;
1193 register int vpos
= fromvpos
;
1198 register int tab_width
= XFASTINT (current_buffer
->tab_width
);
1199 register int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
1200 register struct Lisp_Char_Table
*dp
= window_display_table (win
);
1202 = (INTEGERP (current_buffer
->selective_display
)
1203 ? XINT (current_buffer
->selective_display
)
1204 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1207 = (selective
&& dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
1208 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
: 0);
1209 /* The next location where the `invisible' property changes, or an
1210 overlay starts or ends. */
1211 int next_boundary
= from
;
1213 /* For computing runs of characters with similar widths.
1214 Invariant: width_run_width is zero, or all the characters
1215 from width_run_start to width_run_end have a fixed width of
1217 int width_run_start
= from
;
1218 int width_run_end
= from
;
1219 int width_run_width
= 0;
1220 Lisp_Object
*width_table
;
1223 /* The next buffer pos where we should consult the width run cache. */
1224 int next_width_run
= from
;
1227 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
1228 /* If previous char scanned was a wide character,
1229 this is the column where it ended. Otherwise, this is 0. */
1230 int wide_column_end_hpos
= 0;
1231 int prev_pos
; /* Previous buffer position. */
1232 int prev_pos_byte
; /* Previous buffer position. */
1233 int contin_hpos
; /* HPOS of last column of continued line. */
1234 int prev_tab_offset
; /* Previous tab offset. */
1236 XSETBUFFER (buffer
, current_buffer
);
1237 XSETWINDOW (window
, win
);
1239 width_run_cache_on_off ();
1240 if (dp
== buffer_display_table ())
1241 width_table
= (VECTORP (current_buffer
->width_table
)
1242 ? XVECTOR (current_buffer
->width_table
)->contents
1245 /* If the window has its own display table, we can't use the width
1246 run cache, because that's based on the buffer's display table. */
1249 if (tab_width
<= 0 || tab_width
> 1000)
1255 pos
= prev_pos
= from
;
1256 pos_byte
= prev_pos_byte
= CHAR_TO_BYTE (from
);
1258 prev_tab_offset
= tab_offset
;
1261 while (pos
== next_boundary
)
1266 /* Don't skip invisible if we are already at the margin. */
1267 if (vpos
> tovpos
|| (vpos
== tovpos
&& hpos
>= tohpos
))
1269 if (contin_hpos
&& prev_hpos
== 0
1271 && (contin_hpos
== width
|| wide_column_end_hpos
> width
))
1272 { /* Line breaks because we can't put the character at the
1273 previous line any more. It is not the multi-column
1274 character continued in middle. Go back to previous
1275 buffer position, screen position, and set tab offset
1276 to previous value. It's the beginning of the
1279 pos_byte
= prev_pos_byte
;
1281 tab_offset
= prev_tab_offset
;
1286 /* If the caller says that the screen position came from an earlier
1287 call to compute_motion, then we've already accounted for the
1288 overlay strings at point. This is only true the first time
1289 through, so clear the flag after testing it. */
1291 /* We need to skip past the overlay strings. Currently those
1292 strings must not contain TAB;
1293 if we want to relax that restriction, something will have
1294 to be changed here. */
1296 unsigned char *ovstr
;
1297 int ovlen
= overlay_strings (pos
, win
, &ovstr
);
1298 hpos
+= ((multibyte
&& ovlen
> 0)
1299 ? strwidth (ovstr
, ovlen
) : ovlen
);
1306 /* Advance POS past invisible characters
1307 (but not necessarily all that there are here),
1308 and store in next_boundary the next position where
1309 we need to call skip_invisible. */
1310 newpos
= skip_invisible (pos
, &next_boundary
, to
, window
);
1314 pos
= min (to
, newpos
);
1315 pos_byte
= CHAR_TO_BYTE (pos
);
1319 if (newpos
!= pos_here
)
1322 pos_byte
= CHAR_TO_BYTE (pos
);
1326 /* Handle right margin. */
1327 /* Note on a wide-column character.
1329 Characters are classified into the following three categories
1330 according to the width (columns occupied on screen).
1332 (1) single-column character: ex. `a'
1333 (2) multi-column character: ex. `^A', TAB, `\033'
1334 (3) wide-column character: ex. Japanese character, Chinese character
1335 (In the following example, `W_' stands for them.)
1337 Multi-column characters can be divided around the right margin,
1338 but wide-column characters cannot.
1342 (*) The cursor is placed on the next character after the point.
1346 j ^---- next after the point
1347 ^--- next char. after the point.
1349 In case of sigle-column character
1353 033 ^---- next after the point, next char. after the point.
1355 In case of multi-column character
1359 W_ ^---- next after the point
1360 ^---- next char. after the point.
1362 In case of wide-column character
1364 The problem here is continuation at a wide-column character.
1365 In this case, the line may shorter less than WIDTH.
1366 And we find the continuation AFTER it occurs.
1373 || (truncate_partial_width_windows
1374 && width
+ 1 < FRAME_WIDTH (XFRAME (WINDOW_FRAME (win
))))
1375 || !NILP (current_buffer
->truncate_lines
))
1377 /* Truncating: skip to newline, unless we are already past
1378 TO (we need to go back below). */
1381 pos
= find_before_next_newline (pos
, to
, 1);
1382 pos_byte
= CHAR_TO_BYTE (pos
);
1384 /* If we just skipped next_boundary,
1385 loop around in the main while
1387 if (pos
>= next_boundary
)
1388 next_boundary
= pos
+ 1;
1390 prev_tab_offset
= tab_offset
;
1396 /* Remember the previous value. */
1397 prev_tab_offset
= tab_offset
;
1399 if (wide_column_end_hpos
> width
)
1402 tab_offset
+= prev_hpos
;
1406 tab_offset
+= width
;
1410 contin_hpos
= prev_hpos
;
1415 /* Stop if past the target buffer position or screen position. */
1418 /* Go back to the previous position. */
1420 pos_byte
= prev_pos_byte
;
1422 tab_offset
= prev_tab_offset
;
1424 /* NOTE on contin_hpos, hpos, and prev_hpos.
1428 W_ ^---- contin_hpos
1434 if (contin_hpos
&& prev_hpos
== 0
1435 && contin_hpos
< width
&& !wide_column_end_hpos
)
1437 /* Line breaking occurs in the middle of multi-column
1438 character. Go back to previous line. */
1443 /* If previous character is NEWLINE,
1444 set VPOS back to previous line */
1449 if (vpos
> tovpos
|| (vpos
== tovpos
&& hpos
>= tohpos
))
1451 if (contin_hpos
&& prev_hpos
== 0
1453 && (contin_hpos
== width
|| wide_column_end_hpos
> width
))
1454 { /* Line breaks because we can't put the character at the
1455 previous line any more. It is not the multi-column
1456 character continued in middle. Go back to previous
1457 buffer position, screen position, and set tab offset
1458 to previous value. It's the beginning of the
1461 pos_byte
= prev_pos_byte
;
1463 tab_offset
= prev_tab_offset
;
1467 if (pos
== ZV
) /* We cannot go beyond ZV. Stop here. */
1472 prev_pos_byte
= pos_byte
;
1473 wide_column_end_hpos
= 0;
1475 /* Consult the width run cache to see if we can avoid inspecting
1476 the text character-by-character. */
1477 if (current_buffer
->width_run_cache
&& pos
>= next_width_run
)
1481 = region_cache_forward (current_buffer
,
1482 current_buffer
->width_run_cache
,
1485 /* A width of zero means the character's width varies (like
1486 a tab), is meaningless (like a newline), or we just don't
1487 want to skip over it for some other reason. */
1488 if (common_width
!= 0)
1492 /* Don't go past the final buffer posn the user
1497 run_end_hpos
= hpos
+ (run_end
- pos
) * common_width
;
1499 /* Don't go past the final horizontal position the user
1501 if (vpos
== tovpos
&& run_end_hpos
> tohpos
)
1503 run_end
= pos
+ (tohpos
- hpos
) / common_width
;
1504 run_end_hpos
= hpos
+ (run_end
- pos
) * common_width
;
1507 /* Don't go past the margin. */
1508 if (run_end_hpos
>= width
)
1510 run_end
= pos
+ (width
- hpos
) / common_width
;
1511 run_end_hpos
= hpos
+ (run_end
- pos
) * common_width
;
1514 hpos
= run_end_hpos
;
1516 prev_hpos
= hpos
- common_width
;
1520 pos_byte
= CHAR_TO_BYTE (pos
);
1524 next_width_run
= run_end
+ 1;
1527 /* We have to scan the text character-by-character. */
1531 Lisp_Object charvec
;
1533 c
= FETCH_BYTE (pos_byte
);
1535 /* Check composition sequence. */
1537 int len
, len_byte
, width
;
1539 if (check_composition (pos
, pos_byte
, to
, &len
, &len_byte
, &width
))
1542 pos_byte
+= len_byte
;
1550 /* Perhaps add some info to the width_run_cache. */
1551 if (current_buffer
->width_run_cache
)
1553 /* Is this character part of the current run? If so, extend
1555 if (pos
- 1 == width_run_end
1556 && XFASTINT (width_table
[c
]) == width_run_width
)
1557 width_run_end
= pos
;
1559 /* The previous run is over, since this is a character at a
1560 different position, or a different width. */
1563 /* Have we accumulated a run to put in the cache?
1564 (Currently, we only cache runs of width == 1). */
1565 if (width_run_start
< width_run_end
1566 && width_run_width
== 1)
1567 know_region_cache (current_buffer
,
1568 current_buffer
->width_run_cache
,
1569 width_run_start
, width_run_end
);
1571 /* Start recording a new width run. */
1572 width_run_width
= XFASTINT (width_table
[c
]);
1573 width_run_start
= pos
- 1;
1574 width_run_end
= pos
;
1579 && ! (multibyte
&& BASE_LEADING_CODE_P (c
))
1580 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
1582 charvec
= DISP_CHAR_VECTOR (dp
, c
);
1583 n
= ASIZE (charvec
);
1591 for (i
= n
- 1; i
>= 0; --i
)
1593 if (VECTORP (charvec
))
1595 /* This should be handled the same as
1596 next_element_from_display_vector does it. */
1597 Lisp_Object entry
= AREF (charvec
, i
);
1599 if (INTEGERP (entry
)
1600 && GLYPH_CHAR_VALID_P (XFASTINT (entry
)))
1601 c
= FAST_GLYPH_CHAR (XFASTINT (entry
));
1606 if (c
>= 040 && c
< 0177)
1610 int tem
= ((hpos
+ tab_offset
+ hscroll
- (hscroll
> 0))
1614 hpos
+= tab_width
- tem
;
1619 && indented_beyond_p (pos
, pos_byte
, selective
))
1621 /* If (pos == to), we don't have to take care of
1622 selective display. */
1625 /* Skip any number of invisible lines all at once */
1628 pos
= find_before_next_newline (pos
, to
, 1);
1631 pos_byte
= CHAR_TO_BYTE (pos
);
1634 && indented_beyond_p (pos
, pos_byte
, selective
));
1635 /* Allow for the " ..." that is displayed for them. */
1638 hpos
+= selective_rlen
;
1642 DEC_BOTH (pos
, pos_byte
);
1643 /* We have skipped the invis text, but not the
1649 /* A visible line. */
1653 /* Count the truncation glyph on column 0 */
1660 else if (c
== CR
&& selective
< 0)
1662 /* In selective display mode,
1663 everything from a ^M to the end of the line is invisible.
1664 Stop *before* the real newline. */
1667 pos
= find_before_next_newline (pos
, to
, 1);
1668 pos_byte
= CHAR_TO_BYTE (pos
);
1670 /* If we just skipped next_boundary,
1671 loop around in the main while
1673 if (pos
> next_boundary
)
1674 next_boundary
= pos
;
1675 /* Allow for the " ..." that is displayed for them. */
1678 hpos
+= selective_rlen
;
1683 else if (multibyte
&& BASE_LEADING_CODE_P (c
))
1685 /* Start of multi-byte form. */
1687 int bytes
, width
, wide_column
;
1689 pos_byte
--; /* rewind POS_BYTE */
1690 ptr
= BYTE_POS_ADDR (pos_byte
);
1691 MULTIBYTE_BYTES_WIDTH (ptr
, dp
);
1694 wide_column_end_hpos
= hpos
+ wide_column
;
1697 else if (VECTORP (charvec
))
1700 hpos
+= (ctl_arrow
&& c
< 0200) ? 2 : 4;
1707 /* Remember any final width run in the cache. */
1708 if (current_buffer
->width_run_cache
1709 && width_run_width
== 1
1710 && width_run_start
< width_run_end
)
1711 know_region_cache (current_buffer
, current_buffer
->width_run_cache
,
1712 width_run_start
, width_run_end
);
1714 val_compute_motion
.bufpos
= pos
;
1715 val_compute_motion
.bytepos
= pos_byte
;
1716 val_compute_motion
.hpos
= hpos
;
1717 val_compute_motion
.vpos
= vpos
;
1718 if (contin_hpos
&& prev_hpos
== 0)
1719 val_compute_motion
.prevhpos
= contin_hpos
;
1721 val_compute_motion
.prevhpos
= prev_hpos
;
1722 /* We alalways handle all of them here; none of them remain to do. */
1723 val_compute_motion
.ovstring_chars_done
= 0;
1725 /* Nonzero if have just continued a line */
1726 val_compute_motion
.contin
= (contin_hpos
&& prev_hpos
== 0);
1729 return &val_compute_motion
;
1733 DEFUN ("compute-motion", Fcompute_motion
, Scompute_motion
, 7, 7, 0,
1734 doc
: /* Scan through the current buffer, calculating screen position.
1735 Scan the current buffer forward from offset FROM,
1736 assuming it is at position FROMPOS--a cons of the form (HPOS . VPOS)--
1737 to position TO or position TOPOS--another cons of the form (HPOS . VPOS)--
1738 and return the ending buffer position and screen location.
1740 There are three additional arguments:
1742 WIDTH is the number of columns available to display text;
1743 this affects handling of continuation lines.
1744 This is usually the value returned by `window-width', less one (to allow
1745 for the continuation glyph).
1747 OFFSETS is either nil or a cons cell (HSCROLL . TAB-OFFSET).
1748 HSCROLL is the number of columns not being displayed at the left
1749 margin; this is usually taken from a window's hscroll member.
1750 TAB-OFFSET is the number of columns of the first tab that aren't
1751 being displayed, perhaps because the line was continued within it.
1752 If OFFSETS is nil, HSCROLL and TAB-OFFSET are assumed to be zero.
1754 WINDOW is the window to operate on. It is used to choose the display table;
1755 if it is showing the current buffer, it is used also for
1756 deciding which overlay properties apply.
1757 Note that `compute-motion' always operates on the current buffer.
1759 The value is a list of five elements:
1760 (POS HPOS VPOS PREVHPOS CONTIN)
1761 POS is the buffer position where the scan stopped.
1762 VPOS is the vertical position where the scan stopped.
1763 HPOS is the horizontal position where the scan stopped.
1765 PREVHPOS is the horizontal position one character back from POS.
1766 CONTIN is t if a line was continued after (or within) the previous character.
1768 For example, to find the buffer position of column COL of line LINE
1769 of a certain window, pass the window's starting location as FROM
1770 and the window's upper-left coordinates as FROMPOS.
1771 Pass the buffer's (point-max) as TO, to limit the scan to the end of the
1772 visible section of the buffer, and pass LINE and COL as TOPOS. */)
1773 (from
, frompos
, to
, topos
, width
, offsets
, window
)
1774 Lisp_Object from
, frompos
, to
, topos
;
1775 Lisp_Object width
, offsets
, window
;
1777 Lisp_Object bufpos
, hpos
, vpos
, prevhpos
;
1778 struct position
*pos
;
1779 int hscroll
, tab_offset
;
1781 CHECK_NUMBER_COERCE_MARKER (from
);
1782 CHECK_CONS (frompos
);
1783 CHECK_NUMBER_CAR (frompos
);
1784 CHECK_NUMBER_CDR (frompos
);
1785 CHECK_NUMBER_COERCE_MARKER (to
);
1787 CHECK_NUMBER_CAR (topos
);
1788 CHECK_NUMBER_CDR (topos
);
1789 CHECK_NUMBER (width
);
1790 if (!NILP (offsets
))
1792 CHECK_CONS (offsets
);
1793 CHECK_NUMBER_CAR (offsets
);
1794 CHECK_NUMBER_CDR (offsets
);
1795 hscroll
= XINT (XCAR (offsets
));
1796 tab_offset
= XINT (XCDR (offsets
));
1799 hscroll
= tab_offset
= 0;
1802 window
= Fselected_window ();
1804 CHECK_LIVE_WINDOW (window
);
1806 if (XINT (from
) < BEGV
|| XINT (from
) > ZV
)
1807 args_out_of_range_3 (from
, make_number (BEGV
), make_number (ZV
));
1808 if (XINT (to
) < BEGV
|| XINT (to
) > ZV
)
1809 args_out_of_range_3 (to
, make_number (BEGV
), make_number (ZV
));
1811 pos
= compute_motion (XINT (from
), XINT (XCDR (frompos
)),
1812 XINT (XCAR (frompos
)), 0,
1813 XINT (to
), XINT (XCDR (topos
)),
1814 XINT (XCAR (topos
)),
1815 XINT (width
), 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 (from
, vtarget
, w
)
1837 register int from
, vtarget
;
1840 int width
= window_internal_width (w
) - 1;
1841 int hscroll
= XINT (w
->hscroll
);
1842 struct position pos
;
1843 /* vpos is cumulative vertical position, changed as from is changed */
1844 register int vpos
= 0;
1845 Lisp_Object prevline
;
1848 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
1850 = (INTEGERP (current_buffer
->selective_display
)
1851 ? XINT (current_buffer
->selective_display
)
1852 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1856 /* This is the object we use for fetching character properties. */
1857 Lisp_Object text_prop_object
;
1859 XSETWINDOW (window
, w
);
1861 /* If the window contains this buffer, use it for getting text properties.
1862 Otherwise use the current buffer as arg for doing that. */
1863 if (EQ (w
->buffer
, Fcurrent_buffer ()))
1864 text_prop_object
= window
;
1866 text_prop_object
= Fcurrent_buffer ();
1868 if (vpos
>= vtarget
)
1870 /* To move upward, go a line at a time until
1871 we have gone at least far enough. */
1875 while ((vpos
> vtarget
|| first
) && from
> BEGV
)
1877 Lisp_Object propval
;
1879 XSETFASTINT (prevline
, find_next_newline_no_quit (from
- 1, -1));
1880 while (XFASTINT (prevline
) > BEGV
1882 && indented_beyond_p (XFASTINT (prevline
),
1883 CHAR_TO_BYTE (XFASTINT (prevline
)),
1885 /* watch out for newlines with `invisible' property */
1886 || (propval
= Fget_char_property (prevline
,
1889 TEXT_PROP_MEANS_INVISIBLE (propval
))))
1890 XSETFASTINT (prevline
,
1891 find_next_newline_no_quit (XFASTINT (prevline
) - 1,
1893 pos
= *compute_motion (XFASTINT (prevline
), 0,
1894 lmargin
+ (XFASTINT (prevline
) == BEG
1898 /* Don't care for VPOS... */
1899 1 << (BITS_PER_SHORT
- 1),
1901 1 << (BITS_PER_SHORT
- 1),
1903 /* This compensates for start_hpos
1904 so that a tab as first character
1905 still occupies 8 columns. */
1906 (XFASTINT (prevline
) == BEG
1911 from
= XFASTINT (prevline
);
1914 /* If we made exactly the desired vertical distance,
1915 or if we hit beginning of buffer,
1916 return point found */
1917 if (vpos
>= vtarget
)
1919 val_vmotion
.bufpos
= from
;
1920 val_vmotion
.bytepos
= CHAR_TO_BYTE (from
);
1921 val_vmotion
.vpos
= vpos
;
1922 val_vmotion
.hpos
= lmargin
;
1923 val_vmotion
.contin
= 0;
1924 val_vmotion
.prevhpos
= 0;
1925 val_vmotion
.ovstring_chars_done
= 0;
1926 val_vmotion
.tab_offset
= 0; /* For accumulating tab offset. */
1927 return &val_vmotion
;
1930 /* Otherwise find the correct spot by moving down */
1932 /* Moving downward is simple, but must calculate from beg of line
1933 to determine hpos of starting point */
1934 from_byte
= CHAR_TO_BYTE (from
);
1935 if (from
> BEGV
&& FETCH_BYTE (from_byte
- 1) != '\n')
1937 Lisp_Object propval
;
1939 XSETFASTINT (prevline
, find_next_newline_no_quit (from
, -1));
1940 while (XFASTINT (prevline
) > BEGV
1942 && indented_beyond_p (XFASTINT (prevline
),
1943 CHAR_TO_BYTE (XFASTINT (prevline
)),
1945 /* watch out for newlines with `invisible' property */
1946 || (propval
= Fget_char_property (prevline
, Qinvisible
,
1948 TEXT_PROP_MEANS_INVISIBLE (propval
))))
1949 XSETFASTINT (prevline
,
1950 find_next_newline_no_quit (XFASTINT (prevline
) - 1,
1952 pos
= *compute_motion (XFASTINT (prevline
), 0,
1953 lmargin
+ (XFASTINT (prevline
) == BEG
1957 /* Don't care for VPOS... */
1958 1 << (BITS_PER_SHORT
- 1),
1960 1 << (BITS_PER_SHORT
- 1),
1962 (XFASTINT (prevline
) == BEG
? -start_hpos
: 0),
1968 pos
.hpos
= lmargin
+ (from
== BEG
? start_hpos
: 0);
1973 return compute_motion (from
, vpos
, pos
.hpos
, did_motion
,
1974 ZV
, vtarget
, - (1 << (BITS_PER_SHORT
- 1)),
1976 pos
.tab_offset
- (from
== BEG
? start_hpos
: 0),
1980 DEFUN ("vertical-motion", Fvertical_motion
, Svertical_motion
, 1, 2, 0,
1981 doc
: /* Move point to start of the screen line LINES lines down.
1982 If LINES is negative, this means moving up.
1984 This function is an ordinary cursor motion function
1985 which calculates the new position based on how text would be displayed.
1986 The new position may be the start of a line,
1987 or just the start of a continuation line.
1988 The function returns number of screen lines moved over;
1989 that usually equals LINES, but may be closer to zero
1990 if beginning or end of buffer was reached.
1992 The optional second argument WINDOW specifies the window to use for
1993 parameters such as width, horizontal scrolling, and so on.
1994 The default is to use the selected window's parameters.
1996 `vertical-motion' always uses the current buffer,
1997 regardless of which buffer is displayed in WINDOW.
1998 This is consistent with other cursor motion functions
1999 and makes it possible to use `vertical-motion' in any buffer,
2000 whether or not it is currently displayed in some window. */)
2002 Lisp_Object lines
, window
;
2007 Lisp_Object old_buffer
;
2008 struct gcpro gcpro1
;
2010 CHECK_NUMBER (lines
);
2011 if (! NILP (window
))
2012 CHECK_WINDOW (window
);
2014 window
= selected_window
;
2015 w
= XWINDOW (window
);
2018 GCPRO1 (old_buffer
);
2019 if (XBUFFER (w
->buffer
) != current_buffer
)
2021 /* Set the window's buffer temporarily to the current buffer. */
2022 old_buffer
= w
->buffer
;
2023 XSETBUFFER (w
->buffer
, current_buffer
);
2026 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
2027 start_display (&it
, w
, pt
);
2028 move_it_by_lines (&it
, XINT (lines
), 0);
2029 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
2031 if (BUFFERP (old_buffer
))
2032 w
->buffer
= old_buffer
;
2034 RETURN_UNGCPRO (make_number (it
.vpos
));
2039 /* File's initialization. */
2044 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode
,
2045 doc
: /* *Indentation can insert tabs if this is non-nil.
2046 Setting this variable automatically makes it local to the current buffer. */);
2047 indent_tabs_mode
= 1;
2049 defsubr (&Scurrent_indentation
);
2050 defsubr (&Sindent_to
);
2051 defsubr (&Scurrent_column
);
2052 defsubr (&Smove_to_column
);
2053 defsubr (&Svertical_motion
);
2054 defsubr (&Scompute_motion
);