Mercurial > emacs
annotate src/indent.c @ 4413:5a00cec8e9b0
(fill-region-as-paragraph): When we take one word
after the fill column, don't stop at period with just one space.
When checking whether at beginning of line, if no fill prefix,
ignore intervening whitespace.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Mon, 02 Aug 1993 05:55:56 +0000 |
parents | edffa4f0c5d9 |
children | 1fc792473491 |
rev | line source |
---|---|
165 | 1 /* Indentation functions. |
2961 | 2 Copyright (C) 1985, 1986, 1987, 1988, 1993 Free Software Foundation, Inc. |
165 | 3 |
4 This file is part of GNU Emacs. | |
5 | |
6 GNU Emacs is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
8 the Free Software Foundation; either version 1, or (at your option) | |
9 any later version. | |
10 | |
11 GNU Emacs is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GNU Emacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | |
20 | |
21 #include "config.h" | |
22 #include "lisp.h" | |
23 #include "buffer.h" | |
24 #include "indent.h" | |
764 | 25 #include "frame.h" |
165 | 26 #include "window.h" |
27 #include "termchar.h" | |
28 #include "termopts.h" | |
29 #include "disptab.h" | |
4385
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
30 #include "intervals.h" |
165 | 31 |
32 /* Indentation can insert tabs if this is non-zero; | |
33 otherwise always uses spaces */ | |
34 int indent_tabs_mode; | |
35 | |
36 #define min(a, b) ((a) < (b) ? (a) : (b)) | |
37 #define max(a, b) ((a) > (b) ? (a) : (b)) | |
38 | |
39 #define CR 015 | |
40 | |
41 /* These three values memoize the current column to avoid recalculation */ | |
42 /* Some things in set last_known_column_point to -1 | |
43 to mark the memoized value as invalid */ | |
44 /* Last value returned by current_column */ | |
45 int last_known_column; | |
46 /* Value of point when current_column was called */ | |
47 int last_known_column_point; | |
48 /* Value of MODIFF when current_column was called */ | |
49 int last_known_column_modified; | |
50 | |
51 /* Get the display table to use for the current buffer. */ | |
52 | |
53 struct Lisp_Vector * | |
54 buffer_display_table () | |
55 { | |
56 Lisp_Object thisbuf; | |
57 | |
58 thisbuf = current_buffer->display_table; | |
59 if (XTYPE (thisbuf) == Lisp_Vector | |
60 && XVECTOR (thisbuf)->size == DISP_TABLE_SIZE) | |
61 return XVECTOR (thisbuf); | |
62 if (XTYPE (Vstandard_display_table) == Lisp_Vector | |
63 && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE) | |
64 return XVECTOR (Vstandard_display_table); | |
65 return 0; | |
66 } | |
67 | |
68 DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0, | |
69 "Return the horizontal position of point. Beginning of line is column 0.\n\ | |
70 This is calculated by adding together the widths of all the displayed\n\ | |
71 representations of the character between the start of the previous line\n\ | |
72 and point. (eg control characters will have a width of 2 or 4, tabs\n\ | |
73 will have a variable width)\n\ | |
764 | 74 Ignores finite width of frame, which means that this function may return\n\ |
75 values greater than (frame-width).\n\ | |
165 | 76 Whether the line is visible (if `selective-display' is t) has no effect;\n\ |
77 however, ^M is treated as end of line when `selective-display' is t.") | |
78 () | |
79 { | |
80 Lisp_Object temp; | |
81 XFASTINT (temp) = current_column (); | |
82 return temp; | |
83 } | |
84 | |
327 | 85 /* Cancel any recorded value of the horizontal position. */ |
86 | |
87 invalidate_current_column () | |
88 { | |
89 last_known_column_point = 0; | |
90 } | |
91 | |
165 | 92 int |
93 current_column () | |
94 { | |
95 register int col; | |
96 register unsigned char *ptr, *stop; | |
97 register int tab_seen; | |
98 int post_tab; | |
99 register int c; | |
100 register int tab_width = XINT (current_buffer->tab_width); | |
488 | 101 int ctl_arrow = !NILP (current_buffer->ctl_arrow); |
165 | 102 register struct Lisp_Vector *dp = buffer_display_table (); |
103 int stopchar; | |
104 | |
105 if (point == last_known_column_point | |
106 && MODIFF == last_known_column_modified) | |
107 return last_known_column; | |
108 | |
109 /* Make a pointer for decrementing through the chars before point. */ | |
110 ptr = &FETCH_CHAR (point - 1) + 1; | |
111 /* Make a pointer to where consecutive chars leave off, | |
112 going backwards from point. */ | |
113 if (point == BEGV) | |
114 stop = ptr; | |
115 else if (point <= GPT || BEGV > GPT) | |
116 stop = BEGV_ADDR; | |
117 else | |
118 stop = GAP_END_ADDR; | |
119 | |
2325
7b5299f3a8fc
(current_column, Findent_to, position_indentation):
Richard M. Stallman <rms@gnu.org>
parents:
2017
diff
changeset
|
120 if (tab_width <= 0 || tab_width > 1000) tab_width = 8; |
165 | 121 |
122 col = 0, tab_seen = 0, post_tab = 0; | |
123 | |
124 while (1) | |
125 { | |
126 if (ptr == stop) | |
127 { | |
128 /* We stopped either for the beginning of the buffer | |
129 or for the gap. */ | |
130 if (ptr == BEGV_ADDR) | |
131 break; | |
132 /* It was the gap. Jump back over it. */ | |
133 stop = BEGV_ADDR; | |
134 ptr = GPT_ADDR; | |
135 /* Check whether that brings us to beginning of buffer. */ | |
136 if (BEGV >= GPT) break; | |
137 } | |
138 | |
139 c = *--ptr; | |
140 if (c >= 040 && c < 0177 | |
2017
ffa43acb7de7
(current_column, Fmove_to_column, compute_motion):
Richard M. Stallman <rms@gnu.org>
parents:
1994
diff
changeset
|
141 && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector)) |
165 | 142 { |
143 col++; | |
144 } | |
145 else if (c == '\n') | |
146 break; | |
147 else if (c == '\r' && EQ (current_buffer->selective_display, Qt)) | |
148 break; | |
149 else if (c == '\t') | |
150 { | |
151 if (tab_seen) | |
152 col = ((col + tab_width) / tab_width) * tab_width; | |
153 | |
154 post_tab += col; | |
155 col = 0; | |
156 tab_seen = 1; | |
157 } | |
2017
ffa43acb7de7
(current_column, Fmove_to_column, compute_motion):
Richard M. Stallman <rms@gnu.org>
parents:
1994
diff
changeset
|
158 else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector) |
ffa43acb7de7
(current_column, Fmove_to_column, compute_motion):
Richard M. Stallman <rms@gnu.org>
parents:
1994
diff
changeset
|
159 col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; |
165 | 160 else |
161 col += (ctl_arrow && c < 0200) ? 2 : 4; | |
162 } | |
163 | |
164 if (tab_seen) | |
165 { | |
166 col = ((col + tab_width) / tab_width) * tab_width; | |
167 col += post_tab; | |
168 } | |
169 | |
170 last_known_column = col; | |
171 last_known_column_point = point; | |
172 last_known_column_modified = MODIFF; | |
173 | |
174 return col; | |
175 } | |
176 | |
177 | |
178 DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ", | |
179 "Indent from point with tabs and spaces until COLUMN is reached.\n\ | |
180 Optional second argument MIN says always do at least MIN spaces\n\ | |
181 even if that goes past COLUMN; by default, MIN is zero.") | |
182 (col, minimum) | |
183 Lisp_Object col, minimum; | |
184 { | |
185 int mincol; | |
186 register int fromcol; | |
187 register int tab_width = XINT (current_buffer->tab_width); | |
188 | |
189 CHECK_NUMBER (col, 0); | |
488 | 190 if (NILP (minimum)) |
165 | 191 XFASTINT (minimum) = 0; |
192 CHECK_NUMBER (minimum, 1); | |
193 | |
194 fromcol = current_column (); | |
195 mincol = fromcol + XINT (minimum); | |
196 if (mincol < XINT (col)) mincol = XINT (col); | |
197 | |
198 if (fromcol == mincol) | |
199 return make_number (mincol); | |
200 | |
2325
7b5299f3a8fc
(current_column, Findent_to, position_indentation):
Richard M. Stallman <rms@gnu.org>
parents:
2017
diff
changeset
|
201 if (tab_width <= 0 || tab_width > 1000) tab_width = 8; |
165 | 202 |
203 if (indent_tabs_mode) | |
204 { | |
205 Lisp_Object n; | |
206 XFASTINT (n) = mincol / tab_width - fromcol / tab_width; | |
207 if (XFASTINT (n) != 0) | |
208 { | |
209 Finsert_char (make_number ('\t'), n); | |
210 | |
211 fromcol = (mincol / tab_width) * tab_width; | |
212 } | |
213 } | |
214 | |
215 XFASTINT (col) = mincol - fromcol; | |
216 Finsert_char (make_number (' '), col); | |
217 | |
218 last_known_column = mincol; | |
219 last_known_column_point = point; | |
220 last_known_column_modified = MODIFF; | |
221 | |
222 XSETINT (col, mincol); | |
223 return col; | |
224 } | |
225 | |
226 DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation, | |
227 0, 0, 0, | |
228 "Return the indentation of the current line.\n\ | |
229 This is the horizontal position of the character\n\ | |
230 following any initial whitespace.") | |
231 () | |
232 { | |
233 Lisp_Object val; | |
234 | |
235 XFASTINT (val) = position_indentation (find_next_newline (point, -1)); | |
236 return val; | |
237 } | |
238 | |
239 position_indentation (pos) | |
240 register int pos; | |
241 { | |
242 register int column = 0; | |
243 register int tab_width = XINT (current_buffer->tab_width); | |
244 register unsigned char *p; | |
245 register unsigned char *stop; | |
246 | |
2325
7b5299f3a8fc
(current_column, Findent_to, position_indentation):
Richard M. Stallman <rms@gnu.org>
parents:
2017
diff
changeset
|
247 if (tab_width <= 0 || tab_width > 1000) tab_width = 8; |
165 | 248 |
249 stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1; | |
250 p = &FETCH_CHAR (pos); | |
251 while (1) | |
252 { | |
253 while (p == stop) | |
254 { | |
255 if (pos == ZV) | |
256 return column; | |
257 pos += p - &FETCH_CHAR (pos); | |
258 p = &FETCH_CHAR (pos); | |
259 stop = &FETCH_CHAR (BUFFER_CEILING_OF (pos)) + 1; | |
260 } | |
261 switch (*p++) | |
262 { | |
263 case ' ': | |
264 column++; | |
265 break; | |
266 case '\t': | |
267 column += tab_width - column % tab_width; | |
268 break; | |
269 default: | |
270 return column; | |
271 } | |
272 } | |
273 } | |
274 | |
275 DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, 0, | |
276 "Move point to column COLUMN in the current line.\n\ | |
277 The column of a character is calculated by adding together the widths\n\ | |
278 as displayed of the previous characters in the line.\n\ | |
279 This function ignores line-continuation;\n\ | |
280 there is no upper limit on the column number a character can have\n\ | |
1208
fa662930e654
* indent.c (Fmove_to_column): Pass the right number of arguments
Jim Blandy <jimb@redhat.com>
parents:
764
diff
changeset
|
281 and horizontal scrolling has no effect.\n\ |
fa662930e654
* indent.c (Fmove_to_column): Pass the right number of arguments
Jim Blandy <jimb@redhat.com>
parents:
764
diff
changeset
|
282 \n\ |
165 | 283 If specified column is within a character, point goes after that character.\n\ |
284 If it's past end of line, point goes to end of line.\n\n\ | |
285 A non-nil second (optional) argument FORCE means, if the line\n\ | |
286 is too short to reach column COLUMN then add spaces/tabs to get there,\n\ | |
287 and if COLUMN is in the middle of a tab character, change it to spaces.") | |
288 (column, force) | |
289 Lisp_Object column, force; | |
290 { | |
291 register int pos; | |
292 register int col = current_column (); | |
293 register int goal; | |
294 register int end; | |
295 register int tab_width = XINT (current_buffer->tab_width); | |
488 | 296 register int ctl_arrow = !NILP (current_buffer->ctl_arrow); |
165 | 297 register struct Lisp_Vector *dp = buffer_display_table (); |
298 | |
299 Lisp_Object val; | |
300 int prev_col; | |
301 int c; | |
302 | |
2325
7b5299f3a8fc
(current_column, Findent_to, position_indentation):
Richard M. Stallman <rms@gnu.org>
parents:
2017
diff
changeset
|
303 if (tab_width <= 0 || tab_width > 1000) tab_width = 8; |
165 | 304 CHECK_NATNUM (column, 0); |
305 goal = XINT (column); | |
306 | |
307 retry: | |
308 pos = point; | |
309 end = ZV; | |
310 | |
311 /* If we're starting past the desired column, | |
312 back up to beginning of line and scan from there. */ | |
313 if (col > goal) | |
314 { | |
315 pos = find_next_newline (pos, -1); | |
316 col = 0; | |
317 } | |
318 | |
319 while (col < goal && pos < end) | |
320 { | |
321 c = FETCH_CHAR (pos); | |
322 if (c == '\n') | |
323 break; | |
324 if (c == '\r' && EQ (current_buffer->selective_display, Qt)) | |
325 break; | |
326 pos++; | |
327 if (c == '\t') | |
328 { | |
329 prev_col = col; | |
330 col += tab_width; | |
331 col = col / tab_width * tab_width; | |
332 } | |
2017
ffa43acb7de7
(current_column, Fmove_to_column, compute_motion):
Richard M. Stallman <rms@gnu.org>
parents:
1994
diff
changeset
|
333 else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector) |
ffa43acb7de7
(current_column, Fmove_to_column, compute_motion):
Richard M. Stallman <rms@gnu.org>
parents:
1994
diff
changeset
|
334 col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; |
165 | 335 else if (ctl_arrow && (c < 040 || c == 0177)) |
336 col++; | |
337 else if (c < 040 || c >= 0177) | |
338 col += 3; | |
339 else | |
340 col++; | |
341 } | |
342 | |
343 SET_PT (pos); | |
344 | |
345 /* If a tab char made us overshoot, change it to spaces | |
346 and scan through it again. */ | |
488 | 347 if (!NILP (force) && col > goal && c == '\t' && prev_col < goal) |
165 | 348 { |
573 | 349 int old_point; |
350 | |
165 | 351 del_range (point - 1, point); |
573 | 352 Findent_to (make_number (goal), Qnil); |
353 old_point = point; | |
354 Findent_to (make_number (col), Qnil); | |
355 SET_PT (old_point); | |
4385
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
356 /* Set the last_known... vars consistently. */ |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
357 col = goal; |
165 | 358 } |
359 | |
360 /* If line ends prematurely, add space to the end. */ | |
488 | 361 if (col < goal && !NILP (force)) |
1208
fa662930e654
* indent.c (Fmove_to_column): Pass the right number of arguments
Jim Blandy <jimb@redhat.com>
parents:
764
diff
changeset
|
362 Findent_to (make_number (col = goal), Qnil); |
165 | 363 |
364 last_known_column = col; | |
365 last_known_column_point = point; | |
366 last_known_column_modified = MODIFF; | |
367 | |
368 XFASTINT (val) = col; | |
369 return val; | |
370 } | |
371 | |
372 struct position val_compute_motion; | |
373 | |
374 /* Scan the current buffer forward from offset FROM, pretending that | |
375 this is at line FROMVPOS, column FROMHPOS, until reaching buffer | |
376 offset TO or line TOVPOS, column TOHPOS (whichever comes first), | |
377 and return the ending buffer position and screen location. | |
378 | |
379 WIDTH is the number of columns available to display text; | |
380 compute_motion uses this to handle continuation lines and such. | |
381 HSCROLL is the number of columns not being displayed at the left | |
382 margin; this is usually taken from a window's hscroll member. | |
543 | 383 TAB_OFFSET is the number of columns of the first tab that aren't |
384 being displayed, perhaps because of a continuation line or | |
385 something. | |
165 | 386 |
387 compute_motion returns a pointer to a struct position. The bufpos | |
388 member gives the buffer position at the end of the scan, and hpos | |
389 and vpos give its cartesian location. I'm not clear on what the | |
390 other members are. | |
391 | |
392 For example, to find the buffer position of column COL of line LINE | |
393 of a certain window, pass the window's starting location as FROM | |
394 and the window's upper-left coordinates as FROMVPOS and FROMHPOS. | |
395 Pass the buffer's ZV as TO, to limit the scan to the end of the | |
396 visible section of the buffer, and pass LINE and COL as TOVPOS and | |
397 TOHPOS. | |
398 | |
399 When displaying in window w, a typical formula for WIDTH is: | |
400 | |
401 window_width - 1 | |
1994
73ce9dd21093
Use the term `scroll bar', instead of `scrollbar'.
Jim Blandy <jimb@redhat.com>
parents:
1777
diff
changeset
|
402 - (has_vertical_scroll_bars |
73ce9dd21093
Use the term `scroll bar', instead of `scrollbar'.
Jim Blandy <jimb@redhat.com>
parents:
1777
diff
changeset
|
403 ? VERTICAL_SCROLL_BAR_WIDTH |
1777
4edfaa19c7a7
* window.c (window_internal_width): New function.
Jim Blandy <jimb@redhat.com>
parents:
1208
diff
changeset
|
404 : (window_width + window_left != frame_width)) |
165 | 405 |
406 where | |
407 window_width is XFASTINT (w->width), | |
408 window_left is XFASTINT (w->left), | |
1994
73ce9dd21093
Use the term `scroll bar', instead of `scrollbar'.
Jim Blandy <jimb@redhat.com>
parents:
1777
diff
changeset
|
409 has_vertical_scroll_bars is |
73ce9dd21093
Use the term `scroll bar', instead of `scrollbar'.
Jim Blandy <jimb@redhat.com>
parents:
1777
diff
changeset
|
410 FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (WINDOW_FRAME (window))) |
1777
4edfaa19c7a7
* window.c (window_internal_width): New function.
Jim Blandy <jimb@redhat.com>
parents:
1208
diff
changeset
|
411 and frame_width = FRAME_WIDTH (XFRAME (window->frame)) |
165 | 412 |
1777
4edfaa19c7a7
* window.c (window_internal_width): New function.
Jim Blandy <jimb@redhat.com>
parents:
1208
diff
changeset
|
413 Or, |
4edfaa19c7a7
* window.c (window_internal_width): New function.
Jim Blandy <jimb@redhat.com>
parents:
1208
diff
changeset
|
414 window_internal_width (w) - 1 |
4edfaa19c7a7
* window.c (window_internal_width): New function.
Jim Blandy <jimb@redhat.com>
parents:
1208
diff
changeset
|
415 |
4edfaa19c7a7
* window.c (window_internal_width): New function.
Jim Blandy <jimb@redhat.com>
parents:
1208
diff
changeset
|
416 The `-1' accounts for the continuation-line backslashes; the rest |
4edfaa19c7a7
* window.c (window_internal_width): New function.
Jim Blandy <jimb@redhat.com>
parents:
1208
diff
changeset
|
417 accounts for window borders if the window is split vertically, and |
1994
73ce9dd21093
Use the term `scroll bar', instead of `scrollbar'.
Jim Blandy <jimb@redhat.com>
parents:
1777
diff
changeset
|
418 the scroll bars if the frame supports them. */ |
165 | 419 |
420 struct position * | |
421 compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, tab_offset) | |
422 int from, fromvpos, fromhpos, to, tovpos, tohpos; | |
423 register int width; | |
424 int hscroll, tab_offset; | |
425 { | |
526 | 426 register int hpos = fromhpos; |
427 register int vpos = fromvpos; | |
165 | 428 |
429 register int pos; | |
430 register int c; | |
431 register int tab_width = XFASTINT (current_buffer->tab_width); | |
488 | 432 register int ctl_arrow = !NILP (current_buffer->ctl_arrow); |
165 | 433 register struct Lisp_Vector *dp = buffer_display_table (); |
434 int selective | |
435 = XTYPE (current_buffer->selective_display) == Lisp_Int | |
436 ? XINT (current_buffer->selective_display) | |
488 | 437 : !NILP (current_buffer->selective_display) ? -1 : 0; |
526 | 438 int prev_vpos, prev_hpos; |
165 | 439 int selective_rlen |
2017
ffa43acb7de7
(current_column, Fmove_to_column, compute_motion):
Richard M. Stallman <rms@gnu.org>
parents:
1994
diff
changeset
|
440 = (selective && dp && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector |
ffa43acb7de7
(current_column, Fmove_to_column, compute_motion):
Richard M. Stallman <rms@gnu.org>
parents:
1994
diff
changeset
|
441 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0); |
4385
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
442 #ifdef USE_TEXT_PROPERTIES |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
443 /* The next location where the `invisible' property changes */ |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
444 int next_invisible = from; |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
445 Lisp_Object prop, position; |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
446 #endif |
165 | 447 |
2325
7b5299f3a8fc
(current_column, Findent_to, position_indentation):
Richard M. Stallman <rms@gnu.org>
parents:
2017
diff
changeset
|
448 if (tab_width <= 0 || tab_width > 1000) tab_width = 8; |
526 | 449 for (pos = from; pos < to; pos++) |
165 | 450 { |
526 | 451 /* Stop if past the target screen position. */ |
452 if (vpos > tovpos | |
453 || (vpos == tovpos && hpos >= tohpos)) | |
454 break; | |
455 | |
456 prev_vpos = vpos; | |
457 prev_hpos = hpos; | |
458 | |
4385
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
459 #ifdef USE_TEXT_PROPERTIES |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
460 /* if the `invisible' property is set, we can skip to |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
461 the next property change */ |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
462 while (pos == next_invisible && pos < to) |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
463 { |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
464 XFASTINT (position) = pos; |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
465 prop = Fget_text_property (position, |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
466 Qinvisible, |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
467 Fcurrent_buffer ()); |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
468 { |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
469 Lisp_Object end; |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
470 |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
471 end = Fnext_single_property_change (position, |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
472 Qinvisible, |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
473 Fcurrent_buffer ()); |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
474 if (INTEGERP (end)) |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
475 next_invisible = XINT (end); |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
476 else |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
477 next_invisible = to; |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
478 if (! NILP (prop)) |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
479 pos = next_invisible; |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
480 } |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
481 } |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
482 if (pos >= to) |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
483 break; |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
484 #endif |
165 | 485 c = FETCH_CHAR (pos); |
486 if (c >= 040 && c < 0177 | |
2017
ffa43acb7de7
(current_column, Fmove_to_column, compute_motion):
Richard M. Stallman <rms@gnu.org>
parents:
1994
diff
changeset
|
487 && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector)) |
526 | 488 hpos++; |
165 | 489 else if (c == '\t') |
490 { | |
526 | 491 hpos += tab_width - ((hpos + tab_offset + hscroll - (hscroll > 0) |
492 /* Add tab_width here to make sure positive. | |
493 hpos can be negative after continuation | |
494 but can't be less than -tab_width. */ | |
495 + tab_width) | |
496 % tab_width); | |
165 | 497 } |
498 else if (c == '\n') | |
499 { | |
500 if (selective > 0 && position_indentation (pos + 1) >= selective) | |
501 { | |
502 /* Skip any number of invisible lines all at once */ | |
503 do | |
504 { | |
526 | 505 while (++pos < to && FETCH_CHAR (pos) != '\n'); |
165 | 506 } |
614
0085dcbad4bd
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
573
diff
changeset
|
507 while (pos < to && position_indentation (pos + 1) >= selective); |
165 | 508 pos--; |
509 /* Allow for the " ..." that is displayed for them. */ | |
510 if (selective_rlen) | |
511 { | |
526 | 512 hpos += selective_rlen; |
513 if (hpos >= width) | |
514 hpos = width; | |
165 | 515 } |
614
0085dcbad4bd
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
573
diff
changeset
|
516 /* We have skipped the invis text, but not the newline after. */ |
165 | 517 } |
518 else | |
526 | 519 { |
520 /* A visible line. */ | |
521 vpos++; | |
522 hpos = 0; | |
617 | 523 hpos -= hscroll; |
524 if (hscroll > 0) hpos++; /* Count the ! on column 0 */ | |
525 tab_offset = 0; | |
526 } | |
165 | 527 } |
528 else if (c == CR && selective < 0) | |
529 { | |
530 /* In selective display mode, | |
531 everything from a ^M to the end of the line is invisible */ | |
526 | 532 while (pos < to && FETCH_CHAR (pos) != '\n') pos++; |
533 /* Stop *before* the real newline. */ | |
165 | 534 pos--; |
535 /* Allow for the " ..." that is displayed for them. */ | |
536 if (selective_rlen) | |
537 { | |
526 | 538 hpos += selective_rlen; |
539 if (hpos >= width) | |
540 hpos = width; | |
165 | 541 } |
542 } | |
2017
ffa43acb7de7
(current_column, Fmove_to_column, compute_motion):
Richard M. Stallman <rms@gnu.org>
parents:
1994
diff
changeset
|
543 else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector) |
ffa43acb7de7
(current_column, Fmove_to_column, compute_motion):
Richard M. Stallman <rms@gnu.org>
parents:
1994
diff
changeset
|
544 hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; |
165 | 545 else |
526 | 546 hpos += (ctl_arrow && c < 0200) ? 2 : 4; |
165 | 547 |
526 | 548 /* Handle right margin. */ |
549 if (hpos >= width | |
550 && (hpos > width | |
551 || (pos < ZV - 1 | |
165 | 552 && FETCH_CHAR (pos + 1) != '\n'))) |
553 { | |
526 | 554 if (vpos > tovpos |
555 || (vpos == tovpos && hpos >= tohpos)) | |
165 | 556 break; |
557 if (hscroll | |
558 || (truncate_partial_width_windows | |
764 | 559 && width + 1 < FRAME_WIDTH (selected_frame)) |
488 | 560 || !NILP (current_buffer->truncate_lines)) |
165 | 561 { |
526 | 562 /* Truncating: skip to newline. */ |
563 while (pos < to && FETCH_CHAR (pos) != '\n') pos++; | |
165 | 564 pos--; |
614
0085dcbad4bd
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
573
diff
changeset
|
565 hpos = width; |
165 | 566 } |
567 else | |
568 { | |
526 | 569 /* Continuing. */ |
570 vpos++; | |
571 hpos -= width; | |
165 | 572 tab_offset += width; |
573 } | |
574 | |
575 } | |
576 } | |
577 | |
578 val_compute_motion.bufpos = pos; | |
526 | 579 val_compute_motion.hpos = hpos; |
580 val_compute_motion.vpos = vpos; | |
581 val_compute_motion.prevhpos = prev_hpos; | |
165 | 582 |
583 /* Nonzero if have just continued a line */ | |
584 val_compute_motion.contin | |
526 | 585 = (pos != from |
586 && (val_compute_motion.vpos != prev_vpos) | |
587 && c != '\n'); | |
165 | 588 |
589 return &val_compute_motion; | |
590 } | |
591 | |
592 | |
593 /* Return the column of position POS in window W's buffer, | |
594 rounded down to a multiple of the internal width of W. | |
595 This is the amount of indentation of position POS | |
596 that is not visible in its horizontal position in the window. */ | |
597 | |
598 int | |
599 pos_tab_offset (w, pos) | |
600 struct window *w; | |
601 register int pos; | |
602 { | |
603 int opoint = point; | |
604 int col; | |
1777
4edfaa19c7a7
* window.c (window_internal_width): New function.
Jim Blandy <jimb@redhat.com>
parents:
1208
diff
changeset
|
605 int width = window_internal_width (w) - 1; |
165 | 606 |
607 if (pos == BEGV || FETCH_CHAR (pos - 1) == '\n') | |
608 return 0; | |
609 SET_PT (pos); | |
610 col = current_column (); | |
611 SET_PT (opoint); | |
612 return col - (col % width); | |
613 } | |
614 | |
615 /* start_hpos is the hpos of the first character of the buffer: | |
616 zero except for the minibuffer window, | |
617 where it is the width of the prompt. */ | |
618 | |
619 struct position val_vmotion; | |
620 | |
621 struct position * | |
622 vmotion (from, vtarget, width, hscroll, window) | |
623 register int from, vtarget, width; | |
624 int hscroll; | |
625 Lisp_Object window; | |
626 { | |
627 struct position pos; | |
628 /* vpos is cumulative vertical position, changed as from is changed */ | |
629 register int vpos = 0; | |
630 register int prevline; | |
631 register int first; | |
632 int lmargin = hscroll > 0 ? 1 - hscroll : 0; | |
633 int selective | |
634 = XTYPE (current_buffer->selective_display) == Lisp_Int | |
635 ? XINT (current_buffer->selective_display) | |
488 | 636 : !NILP (current_buffer->selective_display) ? -1 : 0; |
165 | 637 int start_hpos = (EQ (window, minibuf_window) ? minibuf_prompt_width : 0); |
638 | |
639 retry: | |
640 if (vtarget > vpos) | |
641 { | |
642 /* Moving downward is simple, but must calculate from beg of line | |
643 to determine hpos of starting point */ | |
644 if (from > BEGV && FETCH_CHAR (from - 1) != '\n') | |
645 { | |
646 prevline = find_next_newline (from, -1); | |
4385
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
647 while (prevline > BEGV |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
648 && ((selective > 0 |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
649 && position_indentation (prevline) >= selective) |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
650 #ifdef USE_TEXT_PROPERTIES |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
651 /* watch out for newlines with `invisible' property */ |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
652 || ! NILP (Fget_text_property (XFASTINT (prevline), |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
653 Qinvisible, |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
654 Fcurrent_buffer ())) |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
655 #endif |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
656 )) |
165 | 657 prevline = find_next_newline (prevline - 1, -1); |
658 pos = *compute_motion (prevline, 0, | |
659 lmargin + (prevline == 1 ? start_hpos : 0), | |
526 | 660 from, 1 << (INTBITS - 2), 0, |
165 | 661 width, hscroll, 0); |
662 } | |
663 else | |
664 { | |
665 pos.hpos = lmargin + (from == 1 ? start_hpos : 0); | |
666 pos.vpos = 0; | |
667 } | |
668 return compute_motion (from, vpos, pos.hpos, | |
526 | 669 ZV, vtarget, - (1 << (INTBITS - 2)), |
165 | 670 width, hscroll, pos.vpos * width); |
671 } | |
672 | |
673 /* To move upward, go a line at a time until | |
674 we have gone at least far enough */ | |
675 | |
676 first = 1; | |
677 | |
678 while ((vpos > vtarget || first) && from > BEGV) | |
679 { | |
680 prevline = from; | |
681 while (1) | |
682 { | |
683 prevline = find_next_newline (prevline - 1, -1); | |
684 if (prevline == BEGV | |
4385
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
685 || ((selective <= 0 |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
686 || position_indentation (prevline) < selective) |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
687 #ifdef USE_TEXT_PROPERTIES |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
688 /* watch out for newlines with `invisible' property */ |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
689 && NILP (Fget_text_property (XFASTINT (prevline), |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
690 Qinvisible, |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
691 Fcurrent_buffer ())) |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
692 #endif |
edffa4f0c5d9
(compute_motion): Compute correctly for invisible text.
Richard M. Stallman <rms@gnu.org>
parents:
2961
diff
changeset
|
693 )) |
165 | 694 break; |
695 } | |
696 pos = *compute_motion (prevline, 0, | |
697 lmargin + (prevline == 1 ? start_hpos : 0), | |
526 | 698 from, 1 << (INTBITS - 2), 0, |
165 | 699 width, hscroll, 0); |
700 vpos -= pos.vpos; | |
701 first = 0; | |
702 from = prevline; | |
703 } | |
704 | |
705 /* If we made exactly the desired vertical distance, | |
706 or if we hit beginning of buffer, | |
707 return point found */ | |
708 if (vpos >= vtarget) | |
709 { | |
710 val_vmotion.bufpos = from; | |
711 val_vmotion.vpos = vpos; | |
712 val_vmotion.hpos = lmargin; | |
713 val_vmotion.contin = 0; | |
714 val_vmotion.prevhpos = 0; | |
715 return &val_vmotion; | |
716 } | |
717 | |
718 /* Otherwise find the correct spot by moving down */ | |
719 goto retry; | |
720 } | |
721 | |
722 DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 1, 0, | |
723 "Move to start of screen line LINES lines down.\n\ | |
724 If LINES is negative, this is moving up.\n\ | |
725 Sets point to position found; this may be start of line\n\ | |
726 or just the start of a continuation line.\n\ | |
727 Returns number of lines moved; may be closer to zero than LINES\n\ | |
728 if beginning or end of buffer was reached.") | |
729 (lines) | |
730 Lisp_Object lines; | |
731 { | |
732 struct position pos; | |
733 register struct window *w = XWINDOW (selected_window); | |
1777
4edfaa19c7a7
* window.c (window_internal_width): New function.
Jim Blandy <jimb@redhat.com>
parents:
1208
diff
changeset
|
734 int width = window_internal_width (w) - 1; |
165 | 735 |
736 CHECK_NUMBER (lines, 0); | |
737 | |
738 pos = *vmotion (point, XINT (lines), width, | |
739 /* Not XFASTINT since perhaps could be negative */ | |
740 XINT (w->hscroll), selected_window); | |
741 | |
742 SET_PT (pos.bufpos); | |
743 return make_number (pos.vpos); | |
744 } | |
745 | |
746 syms_of_indent () | |
747 { | |
748 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode, | |
749 "*Indentation can insert tabs if this is non-nil.\n\ | |
750 Setting this variable automatically makes it local to the current buffer."); | |
751 indent_tabs_mode = 1; | |
752 | |
753 defsubr (&Scurrent_indentation); | |
754 defsubr (&Sindent_to); | |
755 defsubr (&Scurrent_column); | |
756 defsubr (&Smove_to_column); | |
757 defsubr (&Svertical_motion); | |
758 } |