Avoid calls to CHAR_TO_BYTE if byte position is known.
[bpt/emacs.git] / src / marker.c
CommitLineData
1389ad71 1/* Markers: examining, setting and deleting.
acaf905b 2 Copyright (C) 1985, 1997-1998, 2001-2012 Free Software Foundation, Inc.
dcfdbac7
JB
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
dcfdbac7 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
dcfdbac7
JB
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
dcfdbac7
JB
18
19
18160b98 20#include <config.h>
0328b6de 21
dcfdbac7 22#include "lisp.h"
83be827a 23#include "character.h"
e5560ff7 24#include "buffer.h"
dcfdbac7 25
1389ad71
RS
26/* Record one cached position found recently by
27 buf_charpos_to_bytepos or buf_bytepos_to_charpos. */
28
d311d28c
PE
29static ptrdiff_t cached_charpos;
30static ptrdiff_t cached_bytepos;
1389ad71 31static struct buffer *cached_buffer;
fd2f90cf 32static EMACS_INT cached_modiff;
31f8ab72 33
f1f924b6
DA
34/* Juanma Barranquero <lekktu@gmail.com> reported ~3x increased
35 bootstrap time when byte_char_debug_check is enabled; so this
36 is never turned on by --enable-checking configure option. */
37
38#ifdef MARKER_DEBUG
80d26f99 39
90fc4786 40extern int count_markers (struct buffer *) EXTERNALLY_VISIBLE;
f1f924b6 41extern ptrdiff_t verify_bytepos (ptrdiff_t charpos) EXTERNALLY_VISIBLE;
90fc4786
DA
42
43static void
44byte_char_debug_check (struct buffer *b, ptrdiff_t charpos, ptrdiff_t bytepos)
45{
9d44f8ce
DA
46 ptrdiff_t nchars;
47
48 if (NILP (BVAR (b, enable_multibyte_characters)))
49 return;
90fc4786
DA
50
51 if (bytepos > BUF_GPT_BYTE (b))
9d44f8ce
DA
52 nchars
53 = multibyte_chars_in_text (BUF_BEG_ADDR (b),
54 BUF_GPT_BYTE (b) - BUF_BEG_BYTE (b))
55 + multibyte_chars_in_text (BUF_GAP_END_ADDR (b),
56 bytepos - BUF_GPT_BYTE (b));
90fc4786
DA
57 else
58 nchars = multibyte_chars_in_text (BUF_BEG_ADDR (b),
59 bytepos - BUF_BEG_BYTE (b));
60
61 if (charpos - 1 != nchars)
1088b922 62 emacs_abort ();
90fc4786
DA
63}
64
f1f924b6 65#else /* not MARKER_DEBUG */
90fc4786 66
e2688e4a 67#define byte_char_debug_check(b, charpos, bytepos) do { } while (0)
90fc4786 68
f1f924b6 69#endif /* MARKER_DEBUG */
1088b922 70
dfcf069d 71void
971de7fb 72clear_charpos_cache (struct buffer *b)
31f8ab72
RS
73{
74 if (cached_buffer == b)
75 cached_buffer = 0;
76}
1389ad71
RS
77\f
78/* Converting between character positions and byte positions. */
79
80/* There are several places in the buffer where we know
3f67ae94 81 the correspondence: BEG, BEGV, PT, GPT, ZV and Z,
1389ad71
RS
82 and everywhere there is a marker. So we find the one of these places
83 that is closest to the specified position, and scan from there. */
84
13002885 85/* This macro is a subroutine of buf_charpos_to_bytepos.
1389ad71
RS
86 Note that it is desirable that BYTEPOS is not evaluated
87 except when we really want its value. */
88
89#define CONSIDER(CHARPOS, BYTEPOS) \
90{ \
d311d28c 91 ptrdiff_t this_charpos = (CHARPOS); \
7cded46f 92 bool changed = 0; \
1389ad71
RS
93 \
94 if (this_charpos == charpos) \
6e57421b 95 { \
d311d28c 96 ptrdiff_t value = (BYTEPOS); \
90fc4786
DA
97 \
98 byte_char_debug_check (b, charpos, value); \
6e57421b
RS
99 return value; \
100 } \
1389ad71
RS
101 else if (this_charpos > charpos) \
102 { \
103 if (this_charpos < best_above) \
104 { \
105 best_above = this_charpos; \
106 best_above_byte = (BYTEPOS); \
107 changed = 1; \
108 } \
109 } \
110 else if (this_charpos > best_below) \
111 { \
112 best_below = this_charpos; \
113 best_below_byte = (BYTEPOS); \
114 changed = 1; \
115 } \
116 \
117 if (changed) \
118 { \
119 if (best_above - best_below == best_above_byte - best_below_byte) \
6e57421b 120 { \
d311d28c 121 ptrdiff_t value = best_below_byte + (charpos - best_below); \
90fc4786
DA
122 \
123 byte_char_debug_check (b, charpos, value); \
6e57421b
RS
124 return value; \
125 } \
1389ad71
RS
126 } \
127}
128
13002885 129/* Return the byte position corresponding to CHARPOS in B. */
1389ad71 130
d311d28c
PE
131ptrdiff_t
132buf_charpos_to_bytepos (struct buffer *b, ptrdiff_t charpos)
1389ad71 133{
5e097e00 134 struct Lisp_Marker *tail;
d311d28c
PE
135 ptrdiff_t best_above, best_above_byte;
136 ptrdiff_t best_below, best_below_byte;
1389ad71 137
13002885 138 eassert (BUF_BEG (b) <= charpos && charpos <= BUF_Z (b));
1389ad71
RS
139
140 best_above = BUF_Z (b);
141 best_above_byte = BUF_Z_BYTE (b);
142
143 /* If this buffer has as many characters as bytes,
144 each character must be one byte.
145 This takes care of the case where enable-multibyte-characters is nil. */
146 if (best_above == best_above_byte)
147 return charpos;
148
3ab364ce
SM
149 best_below = BEG;
150 best_below_byte = BEG_BYTE;
1389ad71
RS
151
152 /* We find in best_above and best_above_byte
153 the closest known point above CHARPOS,
154 and in best_below and best_below_byte
155 the closest known point below CHARPOS,
156
157 If at any point we can tell that the space between those
158 two best approximations is all single-byte,
159 we interpolate the result immediately. */
160
161 CONSIDER (BUF_PT (b), BUF_PT_BYTE (b));
162 CONSIDER (BUF_GPT (b), BUF_GPT_BYTE (b));
163 CONSIDER (BUF_BEGV (b), BUF_BEGV_BYTE (b));
164 CONSIDER (BUF_ZV (b), BUF_ZV_BYTE (b));
165
166 if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff)
167 CONSIDER (cached_charpos, cached_bytepos);
168
5e097e00 169 for (tail = BUF_MARKERS (b); tail; tail = tail->next)
1389ad71 170 {
5e097e00 171 CONSIDER (tail->charpos, tail->bytepos);
1389ad71
RS
172
173 /* If we are down to a range of 50 chars,
174 don't bother checking any other markers;
175 scan the intervening chars directly now. */
176 if (best_above - best_below < 50)
177 break;
1389ad71
RS
178 }
179
180 /* We get here if we did not exactly hit one of the known places.
181 We have one known above and one known below.
182 Scan, counting characters, from whichever one is closer. */
183
184 if (charpos - best_below < best_above - charpos)
185 {
7cded46f 186 bool record = charpos - best_below > 5000;
1389ad71
RS
187
188 while (best_below != charpos)
189 {
190 best_below++;
191 BUF_INC_POS (b, best_below_byte);
192 }
193
194 /* If this position is quite far from the nearest known position,
195 cache the correspondence by creating a marker here.
196 It will last until the next GC. */
197 if (record)
657924ff 198 build_marker (b, best_below, best_below_byte);
1389ad71 199
9d44f8ce 200 byte_char_debug_check (b, best_below, best_below_byte);
6e57421b 201
1389ad71
RS
202 cached_buffer = b;
203 cached_modiff = BUF_MODIFF (b);
204 cached_charpos = best_below;
205 cached_bytepos = best_below_byte;
206
207 return best_below_byte;
208 }
209 else
210 {
7cded46f 211 bool record = best_above - charpos > 5000;
1389ad71
RS
212
213 while (best_above != charpos)
214 {
215 best_above--;
216 BUF_DEC_POS (b, best_above_byte);
217 }
218
219 /* If this position is quite far from the nearest known position,
220 cache the correspondence by creating a marker here.
221 It will last until the next GC. */
222 if (record)
657924ff 223 build_marker (b, best_above, best_above_byte);
1389ad71 224
9d44f8ce 225 byte_char_debug_check (b, best_above, best_above_byte);
6e57421b 226
1389ad71
RS
227 cached_buffer = b;
228 cached_modiff = BUF_MODIFF (b);
229 cached_charpos = best_above;
230 cached_bytepos = best_above_byte;
231
232 return best_above_byte;
233 }
234}
235
236#undef CONSIDER
55a91ea3 237
b4c3046a 238/* This macro is a subroutine of buf_bytepos_to_charpos.
1389ad71
RS
239 It is used when BYTEPOS is actually the byte position. */
240
241#define CONSIDER(BYTEPOS, CHARPOS) \
242{ \
d311d28c 243 ptrdiff_t this_bytepos = (BYTEPOS); \
1389ad71
RS
244 int changed = 0; \
245 \
246 if (this_bytepos == bytepos) \
6e57421b 247 { \
d311d28c 248 ptrdiff_t value = (CHARPOS); \
90fc4786
DA
249 \
250 byte_char_debug_check (b, value, bytepos); \
6e57421b
RS
251 return value; \
252 } \
1389ad71
RS
253 else if (this_bytepos > bytepos) \
254 { \
255 if (this_bytepos < best_above_byte) \
256 { \
257 best_above = (CHARPOS); \
258 best_above_byte = this_bytepos; \
259 changed = 1; \
260 } \
261 } \
262 else if (this_bytepos > best_below_byte) \
263 { \
264 best_below = (CHARPOS); \
265 best_below_byte = this_bytepos; \
266 changed = 1; \
267 } \
268 \
269 if (changed) \
270 { \
271 if (best_above - best_below == best_above_byte - best_below_byte) \
6e57421b 272 { \
d311d28c 273 ptrdiff_t value = best_below + (bytepos - best_below_byte); \
90fc4786
DA
274 \
275 byte_char_debug_check (b, value, bytepos); \
6e57421b
RS
276 return value; \
277 } \
1389ad71
RS
278 } \
279}
280
13002885
DA
281/* Return the character position corresponding to BYTEPOS in B. */
282
d311d28c
PE
283ptrdiff_t
284buf_bytepos_to_charpos (struct buffer *b, ptrdiff_t bytepos)
1389ad71 285{
5e097e00 286 struct Lisp_Marker *tail;
d311d28c
PE
287 ptrdiff_t best_above, best_above_byte;
288 ptrdiff_t best_below, best_below_byte;
1389ad71 289
13002885 290 eassert (BUF_BEG_BYTE (b) <= bytepos && bytepos <= BUF_Z_BYTE (b));
1389ad71
RS
291
292 best_above = BUF_Z (b);
293 best_above_byte = BUF_Z_BYTE (b);
294
295 /* If this buffer has as many characters as bytes,
296 each character must be one byte.
297 This takes care of the case where enable-multibyte-characters is nil. */
298 if (best_above == best_above_byte)
299 return bytepos;
300
3ab364ce
SM
301 best_below = BEG;
302 best_below_byte = BEG_BYTE;
1389ad71
RS
303
304 CONSIDER (BUF_PT_BYTE (b), BUF_PT (b));
305 CONSIDER (BUF_GPT_BYTE (b), BUF_GPT (b));
306 CONSIDER (BUF_BEGV_BYTE (b), BUF_BEGV (b));
307 CONSIDER (BUF_ZV_BYTE (b), BUF_ZV (b));
308
309 if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff)
310 CONSIDER (cached_bytepos, cached_charpos);
311
5e097e00 312 for (tail = BUF_MARKERS (b); tail; tail = tail->next)
1389ad71 313 {
5e097e00 314 CONSIDER (tail->bytepos, tail->charpos);
1389ad71
RS
315
316 /* If we are down to a range of 50 chars,
317 don't bother checking any other markers;
318 scan the intervening chars directly now. */
319 if (best_above - best_below < 50)
320 break;
1389ad71
RS
321 }
322
323 /* We get here if we did not exactly hit one of the known places.
324 We have one known above and one known below.
325 Scan, counting characters, from whichever one is closer. */
326
327 if (bytepos - best_below_byte < best_above_byte - bytepos)
328 {
7cded46f 329 bool record = bytepos - best_below_byte > 5000;
1389ad71
RS
330
331 while (best_below_byte < bytepos)
332 {
333 best_below++;
334 BUF_INC_POS (b, best_below_byte);
335 }
336
337 /* If this position is quite far from the nearest known position,
338 cache the correspondence by creating a marker here.
7693a579
RS
339 It will last until the next GC.
340 But don't do it if BUF_MARKERS is nil;
341 that is a signal from Fset_buffer_multibyte. */
5e097e00 342 if (record && BUF_MARKERS (b))
657924ff 343 build_marker (b, best_below, best_below_byte);
1389ad71 344
9d44f8ce 345 byte_char_debug_check (b, best_below, best_below_byte);
6e57421b 346
1389ad71
RS
347 cached_buffer = b;
348 cached_modiff = BUF_MODIFF (b);
349 cached_charpos = best_below;
350 cached_bytepos = best_below_byte;
351
352 return best_below;
353 }
354 else
355 {
7cded46f 356 bool record = best_above_byte - bytepos > 5000;
1389ad71
RS
357
358 while (best_above_byte > bytepos)
359 {
360 best_above--;
361 BUF_DEC_POS (b, best_above_byte);
362 }
363
364 /* If this position is quite far from the nearest known position,
365 cache the correspondence by creating a marker here.
7693a579
RS
366 It will last until the next GC.
367 But don't do it if BUF_MARKERS is nil;
368 that is a signal from Fset_buffer_multibyte. */
5e097e00 369 if (record && BUF_MARKERS (b))
657924ff 370 build_marker (b, best_above, best_above_byte);
1389ad71 371
9d44f8ce 372 byte_char_debug_check (b, best_above, best_above_byte);
6e57421b 373
1389ad71
RS
374 cached_buffer = b;
375 cached_modiff = BUF_MODIFF (b);
376 cached_charpos = best_above;
377 cached_bytepos = best_above_byte;
378
379 return best_above;
380 }
381}
382
383#undef CONSIDER
384\f
dcfdbac7
JB
385/* Operations on markers. */
386
a7ca3326 387DEFUN ("marker-buffer", Fmarker_buffer, Smarker_buffer, 1, 1, 0,
2e1280f8
PJ
388 doc: /* Return the buffer that MARKER points into, or nil if none.
389Returns nil if MARKER points into a dead buffer. */)
5842a27b 390 (register Lisp_Object marker)
dcfdbac7
JB
391{
392 register Lisp_Object buf;
b7826503 393 CHECK_MARKER (marker);
dcfdbac7
JB
394 if (XMARKER (marker)->buffer)
395 {
0e11d869 396 XSETBUFFER (buf, XMARKER (marker)->buffer);
0754c46a
SM
397 /* If the buffer is dead, we're in trouble: the buffer pointer here
398 does not preserve the buffer from being GC'd (it's weak), so
399 markers have to be unlinked from their buffer as soon as the buffer
400 is killed. */
e578f381 401 eassert (BUFFER_LIVE_P (XBUFFER (buf)));
0754c46a 402 return buf;
dcfdbac7
JB
403 }
404 return Qnil;
405}
406
a7ca3326 407DEFUN ("marker-position", Fmarker_position, Smarker_position, 1, 1, 0,
243d70e5
JL
408 doc: /* Return the position MARKER points at, as a character number.
409Returns nil if MARKER points nowhere. */)
5842a27b 410 (Lisp_Object marker)
dcfdbac7 411{
b7826503 412 CHECK_MARKER (marker);
dcfdbac7 413 if (XMARKER (marker)->buffer)
1389ad71 414 return make_number (XMARKER (marker)->charpos);
dcfdbac7 415
dcfdbac7
JB
416 return Qnil;
417}
4e57b342
DA
418
419/* Change M so it points to B at CHARPOS and BYTEPOS. */
420
b0ab8123 421static void
4e57b342
DA
422attach_marker (struct Lisp_Marker *m, struct buffer *b,
423 ptrdiff_t charpos, ptrdiff_t bytepos)
424{
d36d71df
DA
425 /* In a single-byte buffer, two positions must be equal.
426 Otherwise, every character is at least one byte. */
427 if (BUF_Z (b) == BUF_Z_BYTE (b))
428 eassert (charpos == bytepos);
429 else
430 eassert (charpos <= bytepos);
4e57b342
DA
431
432 m->charpos = charpos;
433 m->bytepos = bytepos;
434
435 if (m->buffer != b)
436 {
437 unchain_marker (m);
438 m->buffer = b;
439 m->next = BUF_MARKERS (b);
440 BUF_MARKERS (b) = m;
441 }
442}
443
d36d71df
DA
444/* If BUFFER is nil, return current buffer pointer. Next, check
445 whether BUFFER is a buffer object and return buffer pointer
446 corresponding to BUFFER if BUFFER is live, or NULL otherwise. */
dcfdbac7 447
b0ab8123 448static struct buffer *
d36d71df
DA
449live_buffer (Lisp_Object buffer)
450{
451 struct buffer *b;
5e097e00 452
d36d71df 453 if (NILP (buffer))
dcfdbac7 454 {
d36d71df 455 b = current_buffer;
e578f381 456 eassert (BUFFER_LIVE_P (b));
dcfdbac7 457 }
dcfdbac7
JB
458 else
459 {
b7826503 460 CHECK_BUFFER (buffer);
dcfdbac7 461 b = XBUFFER (buffer);
e578f381 462 if (!BUFFER_LIVE_P (b))
d36d71df 463 b = NULL;
1389ad71 464 }
d36d71df 465 return b;
dcfdbac7
JB
466}
467
d36d71df
DA
468/* Internal function to set MARKER in BUFFER at POSITION. Non-zero
469 RESTRICTED means limit the POSITION by the visible part of BUFFER. */
dcfdbac7 470
b0ab8123 471static Lisp_Object
d36d71df 472set_marker_internal (Lisp_Object marker, Lisp_Object position,
7cded46f 473 Lisp_Object buffer, bool restricted)
dcfdbac7 474{
7cded46f
PE
475 struct Lisp_Marker *m;
476 struct buffer *b = live_buffer (buffer);
dcfdbac7 477
b7826503 478 CHECK_MARKER (marker);
5e097e00
SM
479 m = XMARKER (marker);
480
d36d71df
DA
481 /* Set MARKER to point nowhere if BUFFER is dead, or
482 POSITION is nil or a marker points to nowhere. */
483 if (NILP (position)
484 || (MARKERP (position) && !XMARKER (position)->buffer)
485 || !b)
486 unchain_marker (m);
487
488 /* Optimize the special case where we are copying the position of
489 an existing marker, and MARKER is already in the same buffer. */
490 else if (MARKERP (position) && b == XMARKER (position)->buffer
491 && b == m->buffer)
dcfdbac7 492 {
d36d71df
DA
493 m->bytepos = XMARKER (position)->bytepos;
494 m->charpos = XMARKER (position)->charpos;
dcfdbac7
JB
495 }
496
dcfdbac7
JB
497 else
498 {
d36d71df 499 register ptrdiff_t charpos, bytepos;
1088b922 500
d36d71df
DA
501 CHECK_NUMBER_COERCE_MARKER (position);
502 charpos = clip_to_bounds (restricted ? BUF_BEGV (b) : BUF_BEG (b),
503 XINT (position),
504 restricted ? BUF_ZV (b) : BUF_Z (b));
505 bytepos = buf_charpos_to_bytepos (b, charpos);
506 attach_marker (m, b, charpos, bytepos);
dcfdbac7 507 }
d36d71df
DA
508 return marker;
509}
dcfdbac7 510
d36d71df
DA
511DEFUN ("set-marker", Fset_marker, Sset_marker, 2, 3, 0,
512 doc: /* Position MARKER before character number POSITION in BUFFER,
513which defaults to the current buffer. If POSITION is nil,
514makes marker point nowhere so it no longer slows down
515editing in any buffer. Returns MARKER. */)
516 (Lisp_Object marker, Lisp_Object position, Lisp_Object buffer)
517{
518 return set_marker_internal (marker, position, buffer, 0);
519}
1389ad71 520
d36d71df 521/* Like the above, but won't let the position be outside the visible part. */
177c0ea7 522
d36d71df
DA
523Lisp_Object
524set_marker_restricted (Lisp_Object marker, Lisp_Object position,
525 Lisp_Object buffer)
526{
527 return set_marker_internal (marker, position, buffer, 1);
dcfdbac7 528}
d36d71df 529
1389ad71
RS
530/* Set the position of MARKER, specifying both the
531 character position and the corresponding byte position. */
dcfdbac7 532
177c0ea7 533Lisp_Object
d36d71df
DA
534set_marker_both (Lisp_Object marker, Lisp_Object buffer,
535 ptrdiff_t charpos, ptrdiff_t bytepos)
1389ad71 536{
1389ad71 537 register struct Lisp_Marker *m;
d36d71df 538 register struct buffer *b = live_buffer (buffer);
1389ad71 539
b7826503 540 CHECK_MARKER (marker);
5e097e00 541 m = XMARKER (marker);
1389ad71 542
d36d71df
DA
543 if (b)
544 attach_marker (m, b, charpos, bytepos);
1389ad71 545 else
d36d71df 546 unchain_marker (m);
1389ad71
RS
547 return marker;
548}
549
d36d71df 550/* Like the above, but won't let the position be outside the visible part. */
1389ad71 551
177c0ea7 552Lisp_Object
d36d71df
DA
553set_marker_restricted_both (Lisp_Object marker, Lisp_Object buffer,
554 ptrdiff_t charpos, ptrdiff_t bytepos)
1389ad71 555{
1389ad71 556 register struct Lisp_Marker *m;
d36d71df 557 register struct buffer *b = live_buffer (buffer);
1389ad71 558
b7826503 559 CHECK_MARKER (marker);
5e097e00 560 m = XMARKER (marker);
1389ad71 561
d36d71df 562 if (b)
1389ad71 563 {
1088b922
PE
564 attach_marker
565 (m, b,
d36d71df
DA
566 clip_to_bounds (BUF_BEGV (b), charpos, BUF_ZV (b)),
567 clip_to_bounds (BUF_BEGV_BYTE (b), bytepos, BUF_ZV_BYTE (b)));
1389ad71 568 }
d36d71df
DA
569 else
570 unchain_marker (m);
1389ad71
RS
571 return marker;
572}
d36d71df 573
7b7ae965
DA
574/* Remove MARKER from the chain of whatever buffer it is in,
575 leaving it points to nowhere. This is called during garbage
576 collection, so we must be careful to ignore and preserve
577 mark bits, including those in chain fields of markers. */
dcfdbac7 578
c0323249 579void
971de7fb 580unchain_marker (register struct Lisp_Marker *marker)
dcfdbac7 581{
7b7ae965 582 register struct buffer *b = marker->buffer;
dcfdbac7 583
7b7ae965 584 if (b)
dcfdbac7 585 {
7b7ae965
DA
586 register struct Lisp_Marker *tail, **prev;
587
588 /* No dead buffers here. */
e578f381 589 eassert (BUFFER_LIVE_P (b));
7b7ae965
DA
590
591 marker->buffer = NULL;
592 prev = &BUF_MARKERS (b);
593
594 for (tail = BUF_MARKERS (b); tail; prev = &tail->next, tail = *prev)
595 if (marker == tail)
596 {
597 if (*prev == BUF_MARKERS (b))
598 {
1088b922 599 /* Deleting first marker from the buffer's chain. Crash
7b7ae965
DA
600 if new first marker in chain does not say it belongs
601 to the same buffer, or at least that they have the same
602 base buffer. */
603 if (tail->next && b->text != tail->next->buffer->text)
1088b922 604 emacs_abort ();
7b7ae965
DA
605 }
606 *prev = tail->next;
607 /* We have removed the marker from the chain;
608 no need to scan the rest of the chain. */
609 break;
610 }
611
612 /* Error if marker was not in it's chain. */
613 eassert (tail != NULL);
dcfdbac7 614 }
dcfdbac7
JB
615}
616
1389ad71 617/* Return the char position of marker MARKER, as a C integer. */
d281a86a 618
d311d28c 619ptrdiff_t
971de7fb 620marker_position (Lisp_Object marker)
dcfdbac7
JB
621{
622 register struct Lisp_Marker *m = XMARKER (marker);
623 register struct buffer *buf = m->buffer;
1389ad71
RS
624
625 if (!buf)
626 error ("Marker does not point anywhere");
627
4e57b342
DA
628 eassert (BUF_BEG (buf) <= m->charpos && m->charpos <= BUF_Z (buf));
629
1389ad71
RS
630 return m->charpos;
631}
632
633/* Return the byte position of marker MARKER, as a C integer. */
634
d311d28c 635ptrdiff_t
971de7fb 636marker_byte_position (Lisp_Object marker)
1389ad71
RS
637{
638 register struct Lisp_Marker *m = XMARKER (marker);
639 register struct buffer *buf = m->buffer;
dcfdbac7
JB
640
641 if (!buf)
642 error ("Marker does not point anywhere");
643
4e57b342 644 eassert (BUF_BEG_BYTE (buf) <= m->bytepos && m->bytepos <= BUF_Z_BYTE (buf));
dcfdbac7 645
4e57b342 646 return m->bytepos;
dcfdbac7 647}
fc299663 648\f
a7ca3326 649DEFUN ("copy-marker", Fcopy_marker, Scopy_marker, 0, 2, 0,
2e1280f8
PJ
650 doc: /* Return a new marker pointing at the same place as MARKER.
651If argument is a number, makes a new marker pointing
652at that position in the current buffer.
cd196f12 653If MARKER is not specified, the new marker does not point anywhere.
2e1280f8
PJ
654The optional argument TYPE specifies the insertion type of the new marker;
655see `marker-insertion-type'. */)
5842a27b 656 (register Lisp_Object marker, Lisp_Object type)
dcfdbac7
JB
657{
658 register Lisp_Object new;
659
cd196f12 660 if (!NILP (marker))
0b4331b7 661 CHECK_TYPE (INTEGERP (marker) || MARKERP (marker), Qinteger_or_marker_p, marker);
0469366f
KH
662
663 new = Fmake_marker ();
664 Fset_marker (new, marker,
665 (MARKERP (marker) ? Fmarker_buffer (marker) : Qnil));
666 XMARKER (new)->insertion_type = !NILP (type);
667 return new;
fc299663
RS
668}
669
670DEFUN ("marker-insertion-type", Fmarker_insertion_type,
671 Smarker_insertion_type, 1, 1, 0,
2e1280f8 672 doc: /* Return insertion type of MARKER: t if it stays after inserted text.
1961ac0f 673The value nil means the marker stays before text inserted there. */)
5842a27b 674 (register Lisp_Object marker)
fc299663 675{
b7826503 676 CHECK_MARKER (marker);
fc299663
RS
677 return XMARKER (marker)->insertion_type ? Qt : Qnil;
678}
679
680DEFUN ("set-marker-insertion-type", Fset_marker_insertion_type,
681 Sset_marker_insertion_type, 2, 2, 0,
2e1280f8
PJ
682 doc: /* Set the insertion-type of MARKER to TYPE.
683If TYPE is t, it means the marker advances when you insert text at it.
684If TYPE is nil, it means the marker stays behind when you insert text at it. */)
5842a27b 685 (Lisp_Object marker, Lisp_Object type)
fc299663 686{
b7826503 687 CHECK_MARKER (marker);
fc299663
RS
688
689 XMARKER (marker)->insertion_type = ! NILP (type);
690 return type;
dcfdbac7 691}
9e5896c6
RS
692
693DEFUN ("buffer-has-markers-at", Fbuffer_has_markers_at, Sbuffer_has_markers_at,
2e1280f8
PJ
694 1, 1, 0,
695 doc: /* Return t if there are markers pointing at POSITION in the current buffer. */)
5842a27b 696 (Lisp_Object position)
9e5896c6 697{
5e097e00 698 register struct Lisp_Marker *tail;
4e57b342 699 register ptrdiff_t charpos;
9e5896c6 700
4e57b342 701 charpos = clip_to_bounds (BEG, XINT (position), Z);
9e5896c6 702
5e097e00 703 for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
4e57b342 704 if (tail->charpos == charpos)
9e5896c6
RS
705 return Qt;
706
707 return Qnil;
708}
59d36066 709
f1f924b6 710#ifdef MARKER_DEBUG
90fc4786 711
59d36066
RS
712/* For debugging -- count the markers in buffer BUF. */
713
714int
971de7fb 715count_markers (struct buffer *buf)
59d36066
RS
716{
717 int total = 0;
5e097e00 718 struct Lisp_Marker *tail;
59d36066 719
5e097e00 720 for (tail = BUF_MARKERS (buf); tail; tail = tail->next)
59d36066
RS
721 total++;
722
723 return total;
724}
90fc4786 725
f1f924b6
DA
726/* For debugging -- recompute the bytepos corresponding
727 to CHARPOS in the simplest, most reliable way. */
728
729ptrdiff_t
730verify_bytepos (ptrdiff_t charpos)
731{
732 ptrdiff_t below = 1;
733 ptrdiff_t below_byte = 1;
734
735 while (below != charpos)
736 {
737 below++;
738 BUF_INC_POS (current_buffer, below_byte);
739 }
740
741 return below_byte;
742}
743
744#endif /* MARKER_DEBUG */
dcfdbac7 745\f
c0323249 746void
971de7fb 747syms_of_marker (void)
dcfdbac7
JB
748{
749 defsubr (&Smarker_position);
750 defsubr (&Smarker_buffer);
751 defsubr (&Sset_marker);
752 defsubr (&Scopy_marker);
fc299663
RS
753 defsubr (&Smarker_insertion_type);
754 defsubr (&Sset_marker_insertion_type);
9e5896c6 755 defsubr (&Sbuffer_has_markers_at);
dcfdbac7 756}