Mercurial > emacs
comparison src/marker.c @ 20537:cc87b03bad13
(marker_byte_position): Renamed from marker_position.
(marker_position): New function returns the charpos.
(Fbuffer_has_markers_at): Test the marker's charpos.
(set_marker_restricted, Fset_marker): Set both kinds of position.
Optimize case where POSITION is a marker.
(set_marker_both, set_marker_restricted_both): New functions.
(Fmarker_position): Use the charpos.
(charpos_to_bytepos, bytepos_to_charpos): New functions.
(buf_charpos_to_bytepos, buf_bytepos_to_charpos): New functions.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Thu, 01 Jan 1998 02:35:09 +0000 |
parents | 6e2ea54ad704 |
children | d4de7ffb567d |
comparison
equal
deleted
inserted
replaced
20536:8f88438d9f61 | 20537:cc87b03bad13 |
---|---|
1 /* Markers: examining, setting and killing. | 1 /* Markers: examining, setting and deleting. |
2 Copyright (C) 1985 Free Software Foundation, Inc. | 2 Copyright (C) 1985, 1997 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GNU Emacs. | 4 This file is part of GNU Emacs. |
5 | 5 |
6 GNU Emacs is free software; you can redistribute it and/or modify | 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 | 7 it under the terms of the GNU General Public License as published by |
20 | 20 |
21 | 21 |
22 #include <config.h> | 22 #include <config.h> |
23 #include "lisp.h" | 23 #include "lisp.h" |
24 #include "buffer.h" | 24 #include "buffer.h" |
25 | 25 #include "charset.h" |
26 | |
27 /* Record one cached position found recently by | |
28 buf_charpos_to_bytepos or buf_bytepos_to_charpos. */ | |
29 | |
30 static int cached_charpos; | |
31 static int cached_bytepos; | |
32 static struct buffer *cached_buffer; | |
33 static int cached_modiff; | |
34 | |
35 /* Converting between character positions and byte positions. */ | |
36 | |
37 /* There are several places in the buffer where we know | |
38 the corrspondence: BEG, BEGV, PT, GPT, ZV and Z, | |
39 and everywhere there is a marker. So we find the one of these places | |
40 that is closest to the specified position, and scan from there. */ | |
41 | |
42 /* charpos_to_bytepos returns the byte position corresponding to CHARPOS. */ | |
43 | |
44 /* This macro is a subroutine of charpos_to_bytepos. | |
45 Note that it is desirable that BYTEPOS is not evaluated | |
46 except when we really want its value. */ | |
47 | |
48 #define CONSIDER(CHARPOS, BYTEPOS) \ | |
49 { \ | |
50 int this_charpos = (CHARPOS); \ | |
51 int changed = 0; \ | |
52 \ | |
53 if (this_charpos == charpos) \ | |
54 return (BYTEPOS); \ | |
55 else if (this_charpos > charpos) \ | |
56 { \ | |
57 if (this_charpos < best_above) \ | |
58 { \ | |
59 best_above = this_charpos; \ | |
60 best_above_byte = (BYTEPOS); \ | |
61 changed = 1; \ | |
62 } \ | |
63 } \ | |
64 else if (this_charpos > best_below) \ | |
65 { \ | |
66 best_below = this_charpos; \ | |
67 best_below_byte = (BYTEPOS); \ | |
68 changed = 1; \ | |
69 } \ | |
70 \ | |
71 if (changed) \ | |
72 { \ | |
73 if (best_above - best_below == best_above_byte - best_below_byte) \ | |
74 return best_below_byte + (charpos - best_below); \ | |
75 } \ | |
76 } | |
77 | |
78 int | |
79 charpos_to_bytepos (charpos) | |
80 int charpos; | |
81 { | |
82 return buf_charpos_to_bytepos (current_buffer, charpos); | |
83 } | |
84 | |
85 int | |
86 buf_charpos_to_bytepos (b, charpos) | |
87 struct buffer *b; | |
88 int charpos; | |
89 { | |
90 Lisp_Object tail; | |
91 int gapend_byte = BUF_GPT_BYTE (b) + BUF_GAP_SIZE (b); | |
92 int best_above, best_above_byte; | |
93 int best_below, best_below_byte; | |
94 | |
95 if (charpos < BUF_BEG (b) || charpos > BUF_Z (b)) | |
96 abort (); | |
97 | |
98 best_above = BUF_Z (b); | |
99 best_above_byte = BUF_Z_BYTE (b); | |
100 | |
101 /* If this buffer has as many characters as bytes, | |
102 each character must be one byte. | |
103 This takes care of the case where enable-multibyte-characters is nil. */ | |
104 if (best_above == best_above_byte) | |
105 return charpos; | |
106 | |
107 best_below = 1; | |
108 best_below_byte = 1; | |
109 | |
110 /* We find in best_above and best_above_byte | |
111 the closest known point above CHARPOS, | |
112 and in best_below and best_below_byte | |
113 the closest known point below CHARPOS, | |
114 | |
115 If at any point we can tell that the space between those | |
116 two best approximations is all single-byte, | |
117 we interpolate the result immediately. */ | |
118 | |
119 CONSIDER (BUF_PT (b), BUF_PT_BYTE (b)); | |
120 CONSIDER (BUF_GPT (b), BUF_GPT_BYTE (b)); | |
121 CONSIDER (BUF_BEGV (b), BUF_BEGV_BYTE (b)); | |
122 CONSIDER (BUF_ZV (b), BUF_ZV_BYTE (b)); | |
123 | |
124 if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff) | |
125 CONSIDER (cached_charpos, cached_bytepos); | |
126 | |
127 tail = BUF_MARKERS (b); | |
128 while (XSYMBOL (tail) != XSYMBOL (Qnil)) | |
129 { | |
130 int i = XMARKER (tail)->bufpos; | |
131 CONSIDER (XMARKER (tail)->charpos, | |
132 (i > gapend_byte ? i - BUF_GAP_SIZE (b) | |
133 : i > BUF_GPT_BYTE (b) ? BUF_GPT_BYTE (b) | |
134 : i)); | |
135 | |
136 /* If we are down to a range of 50 chars, | |
137 don't bother checking any other markers; | |
138 scan the intervening chars directly now. */ | |
139 if (best_above - best_below < 50) | |
140 break; | |
141 | |
142 tail = XMARKER (tail)->chain; | |
143 } | |
144 | |
145 /* We get here if we did not exactly hit one of the known places. | |
146 We have one known above and one known below. | |
147 Scan, counting characters, from whichever one is closer. */ | |
148 | |
149 if (charpos - best_below < best_above - charpos) | |
150 { | |
151 int record = charpos - best_below > 5000; | |
152 | |
153 while (best_below != charpos) | |
154 { | |
155 best_below++; | |
156 BUF_INC_POS (b, best_below_byte); | |
157 } | |
158 | |
159 /* If this position is quite far from the nearest known position, | |
160 cache the correspondence by creating a marker here. | |
161 It will last until the next GC. */ | |
162 if (record) | |
163 { | |
164 Lisp_Object marker; | |
165 marker = Fmake_marker (); | |
166 set_marker_both (marker, Qnil, best_below, best_below_byte); | |
167 } | |
168 | |
169 cached_buffer = b; | |
170 cached_modiff = BUF_MODIFF (b); | |
171 cached_charpos = best_below; | |
172 cached_bytepos = best_below_byte; | |
173 | |
174 return best_below_byte; | |
175 } | |
176 else | |
177 { | |
178 int record = best_above - charpos > 5000; | |
179 | |
180 while (best_above != charpos) | |
181 { | |
182 best_above--; | |
183 BUF_DEC_POS (b, best_above_byte); | |
184 } | |
185 | |
186 /* If this position is quite far from the nearest known position, | |
187 cache the correspondence by creating a marker here. | |
188 It will last until the next GC. */ | |
189 if (record) | |
190 { | |
191 Lisp_Object marker; | |
192 marker = Fmake_marker (); | |
193 set_marker_both (marker, Qnil, best_above, best_above_byte); | |
194 } | |
195 | |
196 cached_buffer = b; | |
197 cached_modiff = BUF_MODIFF (b); | |
198 cached_charpos = best_above; | |
199 cached_bytepos = best_above_byte; | |
200 | |
201 return best_above_byte; | |
202 } | |
203 } | |
204 | |
205 #undef CONSIDER | |
206 | |
207 /* bytepos_to_charpos returns the char position corresponding to BYTEPOS. */ | |
208 | |
209 /* This macro is a subroutine of bytepos_to_charpos. | |
210 It is used when BYTEPOS is actually the byte position. */ | |
211 | |
212 #define CONSIDER(BYTEPOS, CHARPOS) \ | |
213 { \ | |
214 int this_bytepos = (BYTEPOS); \ | |
215 int changed = 0; \ | |
216 \ | |
217 if (this_bytepos == bytepos) \ | |
218 return (CHARPOS); \ | |
219 else if (this_bytepos > bytepos) \ | |
220 { \ | |
221 if (this_bytepos < best_above_byte) \ | |
222 { \ | |
223 best_above = (CHARPOS); \ | |
224 best_above_byte = this_bytepos; \ | |
225 changed = 1; \ | |
226 } \ | |
227 } \ | |
228 else if (this_bytepos > best_below_byte) \ | |
229 { \ | |
230 best_below = (CHARPOS); \ | |
231 best_below_byte = this_bytepos; \ | |
232 changed = 1; \ | |
233 } \ | |
234 \ | |
235 if (changed) \ | |
236 { \ | |
237 if (best_above - best_below == best_above_byte - best_below_byte) \ | |
238 return best_below + (bytepos - best_below_byte); \ | |
239 } \ | |
240 } | |
241 | |
242 int | |
243 bytepos_to_charpos (bytepos) | |
244 int bytepos; | |
245 { | |
246 return buf_bytepos_to_charpos (current_buffer, bytepos); | |
247 } | |
248 | |
249 int | |
250 buf_bytepos_to_charpos (b, bytepos) | |
251 struct buffer *b; | |
252 int bytepos; | |
253 { | |
254 Lisp_Object tail; | |
255 int best_above, best_above_byte; | |
256 int best_below, best_below_byte; | |
257 | |
258 if (bytepos < BUF_BEG_BYTE (b) || bytepos > BUF_Z_BYTE (b)) | |
259 abort (); | |
260 | |
261 best_above = BUF_Z (b); | |
262 best_above_byte = BUF_Z_BYTE (b); | |
263 | |
264 /* If this buffer has as many characters as bytes, | |
265 each character must be one byte. | |
266 This takes care of the case where enable-multibyte-characters is nil. */ | |
267 if (best_above == best_above_byte) | |
268 return bytepos; | |
269 | |
270 best_below = 1; | |
271 best_below_byte = 1; | |
272 | |
273 CONSIDER (BUF_PT_BYTE (b), BUF_PT (b)); | |
274 CONSIDER (BUF_GPT_BYTE (b), BUF_GPT (b)); | |
275 CONSIDER (BUF_BEGV_BYTE (b), BUF_BEGV (b)); | |
276 CONSIDER (BUF_ZV_BYTE (b), BUF_ZV (b)); | |
277 | |
278 if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff) | |
279 CONSIDER (cached_bytepos, cached_charpos); | |
280 | |
281 tail = BUF_MARKERS (b); | |
282 while (XSYMBOL (tail) != XSYMBOL (Qnil)) | |
283 { | |
284 int marker_bytepos = XMARKER (tail)->bufpos; | |
285 | |
286 if (marker_bytepos > BUF_GPT_BYTE (b) + BUF_GAP_SIZE (b)) | |
287 marker_bytepos -= BUF_GAP_SIZE (b); | |
288 else if (marker_bytepos > BUF_GPT_BYTE (b)) | |
289 marker_bytepos = BUF_GPT_BYTE (b); | |
290 | |
291 CONSIDER (marker_bytepos, XMARKER (tail)->charpos); | |
292 | |
293 /* If we are down to a range of 50 chars, | |
294 don't bother checking any other markers; | |
295 scan the intervening chars directly now. */ | |
296 if (best_above - best_below < 50) | |
297 break; | |
298 | |
299 tail = XMARKER (tail)->chain; | |
300 } | |
301 | |
302 /* We get here if we did not exactly hit one of the known places. | |
303 We have one known above and one known below. | |
304 Scan, counting characters, from whichever one is closer. */ | |
305 | |
306 if (bytepos - best_below_byte < best_above_byte - bytepos) | |
307 { | |
308 int record = best_above_byte - bytepos > 5000; | |
309 | |
310 while (best_below_byte < bytepos) | |
311 { | |
312 best_below++; | |
313 BUF_INC_POS (b, best_below_byte); | |
314 } | |
315 | |
316 /* If this position is quite far from the nearest known position, | |
317 cache the correspondence by creating a marker here. | |
318 It will last until the next GC. */ | |
319 if (record) | |
320 { | |
321 Lisp_Object marker; | |
322 marker = Fmake_marker (); | |
323 set_marker_both (marker, Qnil, best_below, best_below_byte); | |
324 } | |
325 | |
326 cached_buffer = b; | |
327 cached_modiff = BUF_MODIFF (b); | |
328 cached_charpos = best_below; | |
329 cached_bytepos = best_below_byte; | |
330 | |
331 return best_below; | |
332 } | |
333 else | |
334 { | |
335 int record = best_above_byte - bytepos > 5000; | |
336 | |
337 while (best_above_byte > bytepos) | |
338 { | |
339 best_above--; | |
340 BUF_DEC_POS (b, best_above_byte); | |
341 } | |
342 | |
343 /* If this position is quite far from the nearest known position, | |
344 cache the correspondence by creating a marker here. | |
345 It will last until the next GC. */ | |
346 if (record) | |
347 { | |
348 Lisp_Object marker; | |
349 marker = Fmake_marker (); | |
350 set_marker_both (marker, Qnil, best_above, best_above_byte); | |
351 } | |
352 | |
353 cached_buffer = b; | |
354 cached_modiff = BUF_MODIFF (b); | |
355 cached_charpos = best_above; | |
356 cached_bytepos = best_above_byte; | |
357 | |
358 return best_above; | |
359 } | |
360 } | |
361 | |
362 #undef CONSIDER | |
363 | |
26 /* Operations on markers. */ | 364 /* Operations on markers. */ |
27 | 365 |
28 DEFUN ("marker-buffer", Fmarker_buffer, Smarker_buffer, 1, 1, 0, | 366 DEFUN ("marker-buffer", Fmarker_buffer, Smarker_buffer, 1, 1, 0, |
29 "Return the buffer that MARKER points into, or nil if none.\n\ | 367 "Return the buffer that MARKER points into, or nil if none.\n\ |
30 Returns nil if MARKER points into a dead buffer.") | 368 Returns nil if MARKER points into a dead buffer.") |
52 register int i; | 390 register int i; |
53 register struct buffer *buf; | 391 register struct buffer *buf; |
54 | 392 |
55 CHECK_MARKER (marker, 0); | 393 CHECK_MARKER (marker, 0); |
56 if (XMARKER (marker)->buffer) | 394 if (XMARKER (marker)->buffer) |
57 { | 395 return make_number (XMARKER (marker)->charpos); |
58 buf = XMARKER (marker)->buffer; | 396 |
59 i = XMARKER (marker)->bufpos; | |
60 | |
61 if (i > BUF_GPT (buf) + BUF_GAP_SIZE (buf)) | |
62 i -= BUF_GAP_SIZE (buf); | |
63 else if (i > BUF_GPT (buf)) | |
64 i = BUF_GPT (buf); | |
65 | |
66 if (i < BUF_BEG (buf) || i > BUF_Z (buf)) | |
67 abort (); | |
68 | |
69 XSETFASTINT (pos, i); | |
70 return pos; | |
71 } | |
72 return Qnil; | 397 return Qnil; |
73 } | 398 } |
74 | 399 |
75 DEFUN ("set-marker", Fset_marker, Sset_marker, 2, 3, 0, | 400 DEFUN ("set-marker", Fset_marker, Sset_marker, 2, 3, 0, |
76 "Position MARKER before character number POSITION in BUFFER.\n\ | 401 "Position MARKER before character number POSITION in BUFFER.\n\ |
79 Then it no longer slows down editing in any buffer.\n\ | 404 Then it no longer slows down editing in any buffer.\n\ |
80 Returns MARKER.") | 405 Returns MARKER.") |
81 (marker, position, buffer) | 406 (marker, position, buffer) |
82 Lisp_Object marker, position, buffer; | 407 Lisp_Object marker, position, buffer; |
83 { | 408 { |
84 register int charno; | 409 register int charno, bytepos; |
85 register struct buffer *b; | 410 register struct buffer *b; |
86 register struct Lisp_Marker *m; | 411 register struct Lisp_Marker *m; |
87 | 412 |
88 CHECK_MARKER (marker, 0); | 413 CHECK_MARKER (marker, 0); |
89 /* If position is nil or a marker that points nowhere, | 414 /* If position is nil or a marker that points nowhere, |
93 { | 418 { |
94 unchain_marker (marker); | 419 unchain_marker (marker); |
95 return marker; | 420 return marker; |
96 } | 421 } |
97 | 422 |
98 CHECK_NUMBER_COERCE_MARKER (position, 1); | |
99 if (NILP (buffer)) | 423 if (NILP (buffer)) |
100 b = current_buffer; | 424 b = current_buffer; |
101 else | 425 else |
102 { | 426 { |
103 CHECK_BUFFER (buffer, 1); | 427 CHECK_BUFFER (buffer, 1); |
108 unchain_marker (marker); | 432 unchain_marker (marker); |
109 return marker; | 433 return marker; |
110 } | 434 } |
111 } | 435 } |
112 | 436 |
437 m = XMARKER (marker); | |
438 | |
439 /* Optimize the special case where we are copying the position | |
440 of an existing marker, and MARKER is already in the same buffer. */ | |
441 if (MARKERP (position) && b == XMARKER (position)->buffer | |
442 && b == m->buffer) | |
443 { | |
444 m->bufpos = XMARKER (position)->bufpos; | |
445 m->charpos = XMARKER (position)->charpos; | |
446 return marker; | |
447 } | |
448 | |
449 CHECK_NUMBER_COERCE_MARKER (position, 1); | |
450 | |
113 charno = XINT (position); | 451 charno = XINT (position); |
114 m = XMARKER (marker); | |
115 | 452 |
116 if (charno < BUF_BEG (b)) | 453 if (charno < BUF_BEG (b)) |
117 charno = BUF_BEG (b); | 454 charno = BUF_BEG (b); |
118 if (charno > BUF_Z (b)) | 455 if (charno > BUF_Z (b)) |
119 charno = BUF_Z (b); | 456 charno = BUF_Z (b); |
120 if (charno > BUF_GPT (b)) charno += BUF_GAP_SIZE (b); | 457 |
121 m->bufpos = charno; | 458 bytepos = buf_charpos_to_bytepos (b, charno); |
459 | |
460 /* Every character is at least one byte. */ | |
461 if (charno > bytepos) | |
462 abort (); | |
463 | |
464 if (bytepos > BUF_GPT_BYTE (b)) | |
465 bytepos += BUF_GAP_SIZE (b); | |
466 | |
467 m->bufpos = bytepos; | |
468 m->charpos = charno; | |
122 | 469 |
123 if (m->buffer != b) | 470 if (m->buffer != b) |
124 { | 471 { |
125 unchain_marker (marker); | 472 unchain_marker (marker); |
126 m->buffer = b; | 473 m->buffer = b; |
136 | 483 |
137 Lisp_Object | 484 Lisp_Object |
138 set_marker_restricted (marker, pos, buffer) | 485 set_marker_restricted (marker, pos, buffer) |
139 Lisp_Object marker, pos, buffer; | 486 Lisp_Object marker, pos, buffer; |
140 { | 487 { |
141 register int charno; | 488 register int charno, bytepos; |
142 register struct buffer *b; | 489 register struct buffer *b; |
143 register struct Lisp_Marker *m; | 490 register struct Lisp_Marker *m; |
144 | 491 |
145 CHECK_MARKER (marker, 0); | 492 CHECK_MARKER (marker, 0); |
146 /* If position is nil or a marker that points nowhere, | 493 /* If position is nil or a marker that points nowhere, |
147 make this marker point nowhere. */ | 494 make this marker point nowhere. */ |
148 if (NILP (pos) || | 495 if (NILP (pos) |
149 (MARKERP (pos) && !XMARKER (pos)->buffer)) | 496 || (MARKERP (pos) && !XMARKER (pos)->buffer)) |
150 { | 497 { |
151 unchain_marker (marker); | 498 unchain_marker (marker); |
152 return marker; | 499 return marker; |
153 } | 500 } |
154 | 501 |
155 CHECK_NUMBER_COERCE_MARKER (pos, 1); | |
156 if (NILP (buffer)) | 502 if (NILP (buffer)) |
157 b = current_buffer; | 503 b = current_buffer; |
158 else | 504 else |
159 { | 505 { |
160 CHECK_BUFFER (buffer, 1); | 506 CHECK_BUFFER (buffer, 1); |
165 unchain_marker (marker); | 511 unchain_marker (marker); |
166 return marker; | 512 return marker; |
167 } | 513 } |
168 } | 514 } |
169 | 515 |
516 m = XMARKER (marker); | |
517 | |
518 /* Optimize the special case where we are copying the position | |
519 of an existing marker, and MARKER is already in the same buffer. */ | |
520 if (MARKERP (pos) && b == XMARKER (pos)->buffer | |
521 && b == m->buffer) | |
522 { | |
523 m->bufpos = XMARKER (pos)->bufpos; | |
524 m->charpos = XMARKER (pos)->charpos; | |
525 return marker; | |
526 } | |
527 | |
528 CHECK_NUMBER_COERCE_MARKER (pos, 1); | |
529 | |
170 charno = XINT (pos); | 530 charno = XINT (pos); |
171 m = XMARKER (marker); | |
172 | 531 |
173 if (charno < BUF_BEGV (b)) | 532 if (charno < BUF_BEGV (b)) |
174 charno = BUF_BEGV (b); | 533 charno = BUF_BEGV (b); |
175 if (charno > BUF_ZV (b)) | 534 if (charno > BUF_ZV (b)) |
176 charno = BUF_ZV (b); | 535 charno = BUF_ZV (b); |
177 if (charno > BUF_GPT (b)) | 536 |
178 charno += BUF_GAP_SIZE (b); | 537 bytepos = buf_charpos_to_bytepos (b, charno); |
179 m->bufpos = charno; | 538 |
539 /* Every character is at least one byte. */ | |
540 if (charno > bytepos) | |
541 abort (); | |
542 | |
543 if (bytepos > BUF_GPT_BYTE (b)) | |
544 bytepos += BUF_GAP_SIZE (b); | |
545 | |
546 m->bufpos = bytepos; | |
547 m->charpos = charno; | |
180 | 548 |
181 if (m->buffer != b) | 549 if (m->buffer != b) |
182 { | 550 { |
183 unchain_marker (marker); | 551 unchain_marker (marker); |
184 m->buffer = b; | 552 m->buffer = b; |
186 BUF_MARKERS (b) = marker; | 554 BUF_MARKERS (b) = marker; |
187 } | 555 } |
188 | 556 |
189 return marker; | 557 return marker; |
190 } | 558 } |
191 | 559 |
560 /* Set the position of MARKER, specifying both the | |
561 character position and the corresponding byte position. */ | |
562 | |
563 Lisp_Object | |
564 set_marker_both (marker, buffer, charpos, bytepos) | |
565 Lisp_Object marker, buffer; | |
566 int charpos, bytepos; | |
567 { | |
568 register struct buffer *b; | |
569 register struct Lisp_Marker *m; | |
570 | |
571 CHECK_MARKER (marker, 0); | |
572 /* If position is nil or a marker that points nowhere, | |
573 make this marker point nowhere. */ | |
574 if (NILP (charpos) | |
575 || (MARKERP (charpos) && !XMARKER (charpos)->buffer)) | |
576 { | |
577 unchain_marker (marker); | |
578 return marker; | |
579 } | |
580 | |
581 CHECK_NUMBER_COERCE_MARKER (charpos, 1); | |
582 if (NILP (buffer)) | |
583 b = current_buffer; | |
584 else | |
585 { | |
586 CHECK_BUFFER (buffer, 1); | |
587 b = XBUFFER (buffer); | |
588 /* If buffer is dead, set marker to point nowhere. */ | |
589 if (EQ (b->name, Qnil)) | |
590 { | |
591 unchain_marker (marker); | |
592 return marker; | |
593 } | |
594 } | |
595 | |
596 m = XMARKER (marker); | |
597 | |
598 /* In a single-byte buffer, the two positions must be equal. */ | |
599 if (BUF_Z (b) == BUF_Z_BYTE (b) | |
600 && charpos != bytepos) | |
601 abort (); | |
602 /* Every character is at least one byte. */ | |
603 if (charpos > bytepos) | |
604 abort (); | |
605 | |
606 if (bytepos > BUF_GPT_BYTE (b)) | |
607 bytepos += BUF_GAP_SIZE (b); | |
608 | |
609 m->bufpos = bytepos; | |
610 m->charpos = charpos; | |
611 | |
612 if (m->buffer != b) | |
613 { | |
614 unchain_marker (marker); | |
615 m->buffer = b; | |
616 m->chain = BUF_MARKERS (b); | |
617 BUF_MARKERS (b) = marker; | |
618 } | |
619 | |
620 return marker; | |
621 } | |
622 | |
623 /* This version of set_marker_both won't let the position | |
624 be outside the visible part. */ | |
625 | |
626 Lisp_Object | |
627 set_marker_restricted_both (marker, buffer, charpos, bytepos) | |
628 Lisp_Object marker, buffer; | |
629 int charpos, bytepos; | |
630 { | |
631 register struct buffer *b; | |
632 register struct Lisp_Marker *m; | |
633 | |
634 CHECK_MARKER (marker, 0); | |
635 | |
636 if (NILP (buffer)) | |
637 b = current_buffer; | |
638 else | |
639 { | |
640 CHECK_BUFFER (buffer, 1); | |
641 b = XBUFFER (buffer); | |
642 /* If buffer is dead, set marker to point nowhere. */ | |
643 if (EQ (b->name, Qnil)) | |
644 { | |
645 unchain_marker (marker); | |
646 return marker; | |
647 } | |
648 } | |
649 | |
650 m = XMARKER (marker); | |
651 | |
652 if (charpos < BUF_BEGV (b)) | |
653 charpos = BUF_BEGV (b); | |
654 if (charpos > BUF_ZV (b)) | |
655 charpos = BUF_ZV (b); | |
656 if (bytepos < BUF_BEGV_BYTE (b)) | |
657 bytepos = BUF_BEGV_BYTE (b); | |
658 if (bytepos > BUF_ZV_BYTE (b)) | |
659 bytepos = BUF_ZV_BYTE (b); | |
660 | |
661 /* In a single-byte buffer, the two positions must be equal. */ | |
662 if (BUF_Z (b) == BUF_Z_BYTE (b) | |
663 && charpos != bytepos) | |
664 abort (); | |
665 /* Every character is at least one byte. */ | |
666 if (charpos > bytepos) | |
667 abort (); | |
668 | |
669 if (bytepos > BUF_GPT_BYTE (b)) | |
670 bytepos += BUF_GAP_SIZE (b); | |
671 | |
672 m->bufpos = bytepos; | |
673 m->charpos = charpos; | |
674 | |
675 if (m->buffer != b) | |
676 { | |
677 unchain_marker (marker); | |
678 m->buffer = b; | |
679 m->chain = BUF_MARKERS (b); | |
680 BUF_MARKERS (b) = marker; | |
681 } | |
682 | |
683 return marker; | |
684 } | |
685 | |
192 /* This is called during garbage collection, | 686 /* This is called during garbage collection, |
193 so we must be careful to ignore and preserve mark bits, | 687 so we must be careful to ignore and preserve mark bits, |
194 including those in chain fields of markers. */ | 688 including those in chain fields of markers. */ |
195 | 689 |
196 void | 690 void |
240 tail = next; | 734 tail = next; |
241 } | 735 } |
242 XMARKER (marker)->buffer = 0; | 736 XMARKER (marker)->buffer = 0; |
243 } | 737 } |
244 | 738 |
245 /* Return the buffer position of marker MARKER, as a C integer. */ | 739 /* Return the char position of marker MARKER, as a C integer. */ |
246 | 740 |
247 int | 741 int |
248 marker_position (marker) | 742 marker_position (marker) |
249 Lisp_Object marker; | 743 Lisp_Object marker; |
250 { | 744 { |
251 register struct Lisp_Marker *m = XMARKER (marker); | 745 register struct Lisp_Marker *m = XMARKER (marker); |
252 register struct buffer *buf = m->buffer; | 746 register struct buffer *buf = m->buffer; |
253 register int i = m->bufpos; | |
254 | 747 |
255 if (!buf) | 748 if (!buf) |
256 error ("Marker does not point anywhere"); | 749 error ("Marker does not point anywhere"); |
257 | 750 |
258 if (i > BUF_GPT (buf) + BUF_GAP_SIZE (buf)) | 751 return m->charpos; |
752 } | |
753 | |
754 /* Return the byte position of marker MARKER, as a C integer. */ | |
755 | |
756 int | |
757 marker_byte_position (marker) | |
758 Lisp_Object marker; | |
759 { | |
760 register struct Lisp_Marker *m = XMARKER (marker); | |
761 register struct buffer *buf = m->buffer; | |
762 register int i = m->bufpos; | |
763 | |
764 if (!buf) | |
765 error ("Marker does not point anywhere"); | |
766 | |
767 if (i > BUF_GPT_BYTE (buf) + BUF_GAP_SIZE (buf)) | |
259 i -= BUF_GAP_SIZE (buf); | 768 i -= BUF_GAP_SIZE (buf); |
260 else if (i > BUF_GPT (buf)) | 769 else if (i > BUF_GPT_BYTE (buf)) |
261 i = BUF_GPT (buf); | 770 i = BUF_GPT_BYTE (buf); |
262 | 771 |
263 if (i < BUF_BEG (buf) || i > BUF_Z (buf)) | 772 if (i < BUF_BEG_BYTE (buf) || i > BUF_Z_BYTE (buf)) |
264 abort (); | 773 abort (); |
265 | 774 |
266 return i; | 775 return i; |
267 } | 776 } |
268 | 777 |
315 return type; | 824 return type; |
316 } | 825 } |
317 | 826 |
318 DEFUN ("buffer-has-markers-at", Fbuffer_has_markers_at, Sbuffer_has_markers_at, | 827 DEFUN ("buffer-has-markers-at", Fbuffer_has_markers_at, Sbuffer_has_markers_at, |
319 1, 1, 0, | 828 1, 1, 0, |
320 "Return t if there are markers pointing at POSITION in the currentbuffer.") | 829 "Return t if there are markers pointing at POSITION in the current buffer.") |
321 (position) | 830 (position) |
322 Lisp_Object position; | 831 Lisp_Object position; |
323 { | 832 { |
324 register Lisp_Object tail; | 833 register Lisp_Object tail; |
325 register int charno; | 834 register int charno; |
328 | 837 |
329 if (charno < BEG) | 838 if (charno < BEG) |
330 charno = BEG; | 839 charno = BEG; |
331 if (charno > Z) | 840 if (charno > Z) |
332 charno = Z; | 841 charno = Z; |
333 if (charno > GPT) charno += GAP_SIZE; | |
334 | 842 |
335 for (tail = BUF_MARKERS (current_buffer); | 843 for (tail = BUF_MARKERS (current_buffer); |
336 XSYMBOL (tail) != XSYMBOL (Qnil); | 844 XSYMBOL (tail) != XSYMBOL (Qnil); |
337 tail = XMARKER (tail)->chain) | 845 tail = XMARKER (tail)->chain) |
338 if (XMARKER (tail)->bufpos == charno) | 846 if (XMARKER (tail)->charpos == charno) |
339 return Qt; | 847 return Qt; |
340 | 848 |
341 return Qnil; | 849 return Qnil; |
342 } | 850 } |
343 | 851 |