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