This source file includes following definitions.
- count_markers
- clear_charpos_cache
- CHECK_MARKER
- buf_charpos_to_bytepos
- buf_bytepos_to_charpos
- DEFUN
- DEFUN
- attach_marker
- live_buffer
- set_marker_internal
- set_marker_restricted
- set_marker_both
- set_marker_restricted_both
- detach_marker
- unchain_marker
- marker_position
- marker_byte_position
- DEFUN
- count_markers
- verify_bytepos
- syms_of_marker
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <config.h>
22
23 #include "lisp.h"
24 #include "character.h"
25 #include "buffer.h"
26
27
28
29
30 static ptrdiff_t cached_charpos;
31 static ptrdiff_t cached_bytepos;
32 static struct buffer *cached_buffer;
33 static modiff_count cached_modiff;
34
35
36
37
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
67
68 #define byte_char_debug_check(b, charpos, bytepos) do { } while (0)
69
70 #endif
71
72 void
73 clear_charpos_cache (struct buffer *b)
74 {
75 if (cached_buffer == b)
76 cached_buffer = 0;
77 }
78
79
80
81
82
83
84
85
86
87
88
89
90 #define CONSIDER(CHARPOS, BYTEPOS) \
91 { \
92 ptrdiff_t this_charpos = (CHARPOS); \
93 bool changed = false; \
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 = true; \
109 } \
110 } \
111 else if (this_charpos > best_below) \
112 { \
113 best_below = this_charpos; \
114 best_below_byte = (BYTEPOS); \
115 changed = true; \
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 static void
131 CHECK_MARKER (Lisp_Object x)
132 {
133 CHECK_TYPE (MARKERP (x), Qmarkerp, x);
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 #define BYTECHAR_DISTANCE_INITIAL 50
156 #define BYTECHAR_DISTANCE_INCREMENT 50
157
158
159
160 ptrdiff_t
161 buf_charpos_to_bytepos (struct buffer *b, ptrdiff_t charpos)
162 {
163 struct Lisp_Marker *tail;
164 ptrdiff_t best_above, best_above_byte;
165 ptrdiff_t best_below, best_below_byte;
166 ptrdiff_t distance = BYTECHAR_DISTANCE_INITIAL;
167
168 eassert (BUF_BEG (b) <= charpos && charpos <= BUF_Z (b));
169
170 best_above = BUF_Z (b);
171 best_above_byte = BUF_Z_BYTE (b);
172
173
174
175
176 if (best_above == best_above_byte)
177 return charpos;
178
179 best_below = BEG;
180 best_below_byte = BEG_BYTE;
181
182
183
184
185
186
187
188
189
190
191 CONSIDER (BUF_PT (b), BUF_PT_BYTE (b));
192 CONSIDER (BUF_GPT (b), BUF_GPT_BYTE (b));
193 CONSIDER (BUF_BEGV (b), BUF_BEGV_BYTE (b));
194 CONSIDER (BUF_ZV (b), BUF_ZV_BYTE (b));
195
196 if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff)
197 CONSIDER (cached_charpos, cached_bytepos);
198
199 for (tail = BUF_MARKERS (b); tail; tail = tail->next)
200 {
201 CONSIDER (tail->charpos, tail->bytepos);
202
203
204
205
206 if (best_above - charpos < distance
207 || charpos - best_below < distance)
208 break;
209 else
210 distance += BYTECHAR_DISTANCE_INCREMENT;
211 }
212
213
214
215
216
217 eassert (best_below <= charpos && charpos <= best_above);
218 if (charpos - best_below < best_above - charpos)
219 {
220 bool record = charpos - best_below > 5000;
221
222 while (best_below < charpos)
223 {
224 best_below++;
225 best_below_byte += buf_next_char_len (b, best_below_byte);
226 }
227
228
229
230
231 if (record)
232 build_marker (b, best_below, best_below_byte);
233
234 byte_char_debug_check (b, best_below, best_below_byte);
235
236 cached_buffer = b;
237 cached_modiff = BUF_MODIFF (b);
238 cached_charpos = best_below;
239 cached_bytepos = best_below_byte;
240
241 return best_below_byte;
242 }
243 else
244 {
245 bool record = best_above - charpos > 5000;
246
247 while (best_above > charpos)
248 {
249 best_above--;
250 best_above_byte -= buf_prev_char_len (b, best_above_byte);
251 }
252
253
254
255
256 if (record)
257 build_marker (b, best_above, best_above_byte);
258
259 byte_char_debug_check (b, best_above, best_above_byte);
260
261 cached_buffer = b;
262 cached_modiff = BUF_MODIFF (b);
263 cached_charpos = best_above;
264 cached_bytepos = best_above_byte;
265
266 return best_above_byte;
267 }
268 }
269
270 #undef CONSIDER
271
272
273
274
275 #define CONSIDER(BYTEPOS, CHARPOS) \
276 { \
277 ptrdiff_t this_bytepos = (BYTEPOS); \
278 int changed = false; \
279 \
280 if (this_bytepos == bytepos) \
281 { \
282 ptrdiff_t value = (CHARPOS); \
283 \
284 byte_char_debug_check (b, value, bytepos); \
285 return value; \
286 } \
287 else if (this_bytepos > bytepos) \
288 { \
289 if (this_bytepos < best_above_byte) \
290 { \
291 best_above = (CHARPOS); \
292 best_above_byte = this_bytepos; \
293 changed = true; \
294 } \
295 } \
296 else if (this_bytepos > best_below_byte) \
297 { \
298 best_below = (CHARPOS); \
299 best_below_byte = this_bytepos; \
300 changed = true; \
301 } \
302 \
303 if (changed) \
304 { \
305 if (best_above - best_below == best_above_byte - best_below_byte) \
306 { \
307 ptrdiff_t value = best_below + (bytepos - best_below_byte); \
308 \
309 byte_char_debug_check (b, value, bytepos); \
310 return value; \
311 } \
312 } \
313 }
314
315
316
317 ptrdiff_t
318 buf_bytepos_to_charpos (struct buffer *b, ptrdiff_t bytepos)
319 {
320 struct Lisp_Marker *tail;
321 ptrdiff_t best_above, best_above_byte;
322 ptrdiff_t best_below, best_below_byte;
323 ptrdiff_t distance = BYTECHAR_DISTANCE_INITIAL;
324
325 eassert (BUF_BEG_BYTE (b) <= bytepos && bytepos <= BUF_Z_BYTE (b));
326
327 best_above = BUF_Z (b);
328 best_above_byte = BUF_Z_BYTE (b);
329
330
331
332
333 if (best_above == best_above_byte)
334 return bytepos;
335
336
337 eassert (bytepos >= BUF_Z_BYTE (b)
338 || CHAR_HEAD_P (BUF_FETCH_BYTE (b, bytepos)));
339
340 best_below = BEG;
341 best_below_byte = BEG_BYTE;
342
343 CONSIDER (BUF_PT_BYTE (b), BUF_PT (b));
344 CONSIDER (BUF_GPT_BYTE (b), BUF_GPT (b));
345 CONSIDER (BUF_BEGV_BYTE (b), BUF_BEGV (b));
346 CONSIDER (BUF_ZV_BYTE (b), BUF_ZV (b));
347
348 if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff)
349 CONSIDER (cached_bytepos, cached_charpos);
350
351 for (tail = BUF_MARKERS (b); tail; tail = tail->next)
352 {
353 CONSIDER (tail->bytepos, tail->charpos);
354
355
356
357
358 if (best_above - bytepos < distance
359 || bytepos - best_below < distance)
360 break;
361 else
362 distance += BYTECHAR_DISTANCE_INCREMENT;
363 }
364
365
366
367
368
369 if (bytepos - best_below_byte < best_above_byte - bytepos)
370 {
371 bool record = bytepos - best_below_byte > 5000;
372
373 while (best_below_byte < bytepos)
374 {
375 best_below++;
376 best_below_byte += buf_next_char_len (b, best_below_byte);
377 }
378
379
380
381
382
383
384 if (record && BUF_MARKERS (b))
385 build_marker (b, best_below, best_below_byte);
386
387 byte_char_debug_check (b, best_below, best_below_byte);
388
389 cached_buffer = b;
390 cached_modiff = BUF_MODIFF (b);
391 cached_charpos = best_below;
392 cached_bytepos = best_below_byte;
393
394 return best_below;
395 }
396 else
397 {
398 bool record = best_above_byte - bytepos > 5000;
399
400 while (best_above_byte > bytepos)
401 {
402 best_above--;
403 best_above_byte -= buf_prev_char_len (b, best_above_byte);
404 }
405
406
407
408
409
410
411 if (record && BUF_MARKERS (b))
412 build_marker (b, best_above, best_above_byte);
413
414 byte_char_debug_check (b, best_above, best_above_byte);
415
416 cached_buffer = b;
417 cached_modiff = BUF_MODIFF (b);
418 cached_charpos = best_above;
419 cached_bytepos = best_above_byte;
420
421 return best_above;
422 }
423 }
424
425 #undef CONSIDER
426
427
428
429 DEFUN ("marker-buffer", Fmarker_buffer, Smarker_buffer, 1, 1, 0,
430 doc:
431 )
432 (register Lisp_Object marker)
433 {
434 register Lisp_Object buf;
435 CHECK_MARKER (marker);
436 if (XMARKER (marker)->buffer)
437 {
438 XSETBUFFER (buf, XMARKER (marker)->buffer);
439
440
441
442
443 eassert (BUFFER_LIVE_P (XBUFFER (buf)));
444 return buf;
445 }
446 return Qnil;
447 }
448
449 DEFUN ("marker-position", Fmarker_position, Smarker_position, 1, 1, 0,
450 doc: )
451 (Lisp_Object marker)
452 {
453 CHECK_MARKER (marker);
454 if (XMARKER (marker)->buffer)
455 return make_fixnum (XMARKER (marker)->charpos);
456
457 return Qnil;
458 }
459
460
461
462 static void
463 attach_marker (struct Lisp_Marker *m, struct buffer *b,
464 ptrdiff_t charpos, ptrdiff_t bytepos)
465 {
466
467
468 if (BUF_Z (b) == BUF_Z_BYTE (b))
469 eassert (charpos == bytepos);
470 else
471 eassert (charpos <= bytepos);
472
473 m->charpos = charpos;
474 m->bytepos = bytepos;
475
476 if (m->buffer != b)
477 {
478 unchain_marker (m);
479 m->buffer = b;
480 m->next = BUF_MARKERS (b);
481 BUF_MARKERS (b) = m;
482 }
483 }
484
485
486
487
488
489 static struct buffer *
490 live_buffer (Lisp_Object buffer)
491 {
492 struct buffer *b = decode_buffer (buffer);
493 return BUFFER_LIVE_P (b) ? b : NULL;
494 }
495
496
497
498
499 static Lisp_Object
500 set_marker_internal (Lisp_Object marker, Lisp_Object position,
501 Lisp_Object buffer, bool restricted)
502 {
503 struct Lisp_Marker *m;
504 struct buffer *b = live_buffer (buffer);
505
506 CHECK_MARKER (marker);
507 m = XMARKER (marker);
508
509
510
511 if (NILP (position)
512 || (MARKERP (position) && !XMARKER (position)->buffer)
513 || !b)
514 unchain_marker (m);
515
516
517
518 else if (MARKERP (position) && b == XMARKER (position)->buffer
519 && b == m->buffer)
520 {
521 m->bytepos = XMARKER (position)->bytepos;
522 m->charpos = XMARKER (position)->charpos;
523 }
524
525 else
526 {
527 register ptrdiff_t charpos, bytepos;
528
529
530
531
532 if (FIXNUMP (position))
533 {
534 #if EMACS_INT_MAX > PTRDIFF_MAX
535
536 EMACS_INT cpos = XFIXNUM (position);
537 if (cpos > PTRDIFF_MAX)
538 cpos = PTRDIFF_MAX;
539 charpos = cpos;
540 bytepos = -1;
541 #else
542 charpos = XFIXNUM (position), bytepos = -1;
543 #endif
544 }
545 else if (MARKERP (position))
546 {
547 charpos = XMARKER (position)->charpos;
548 bytepos = XMARKER (position)->bytepos;
549 }
550 else
551 wrong_type_argument (Qinteger_or_marker_p, position);
552
553 charpos = clip_to_bounds
554 (restricted ? BUF_BEGV (b) : BUF_BEG (b), charpos,
555 restricted ? BUF_ZV (b) : BUF_Z (b));
556
557
558
559 if (bytepos == -1
560 || !(MARKERP (position) && XMARKER (position)->buffer == b))
561 bytepos = buf_charpos_to_bytepos (b, charpos);
562 else
563 bytepos = clip_to_bounds
564 (restricted ? BUF_BEGV_BYTE (b) : BUF_BEG_BYTE (b),
565 bytepos, restricted ? BUF_ZV_BYTE (b) : BUF_Z_BYTE (b));
566
567 attach_marker (m, b, charpos, bytepos);
568 }
569 return marker;
570 }
571
572 DEFUN ("set-marker", Fset_marker, Sset_marker, 2, 3, 0,
573 doc:
574
575
576 )
577 (Lisp_Object marker, Lisp_Object position, Lisp_Object buffer)
578 {
579 return set_marker_internal (marker, position, buffer, false);
580 }
581
582
583
584 Lisp_Object
585 set_marker_restricted (Lisp_Object marker, Lisp_Object position,
586 Lisp_Object buffer)
587 {
588 return set_marker_internal (marker, position, buffer, true);
589 }
590
591
592
593
594 Lisp_Object
595 set_marker_both (Lisp_Object marker, Lisp_Object buffer,
596 ptrdiff_t charpos, ptrdiff_t bytepos)
597 {
598 register struct Lisp_Marker *m;
599 register struct buffer *b = live_buffer (buffer);
600
601 CHECK_MARKER (marker);
602 m = XMARKER (marker);
603
604 if (b)
605 attach_marker (m, b, charpos, bytepos);
606 else
607 unchain_marker (m);
608 return marker;
609 }
610
611
612
613 Lisp_Object
614 set_marker_restricted_both (Lisp_Object marker, Lisp_Object buffer,
615 ptrdiff_t charpos, ptrdiff_t bytepos)
616 {
617 register struct Lisp_Marker *m;
618 register struct buffer *b = live_buffer (buffer);
619
620 CHECK_MARKER (marker);
621 m = XMARKER (marker);
622
623 if (b)
624 {
625 attach_marker
626 (m, b,
627 clip_to_bounds (BUF_BEGV (b), charpos, BUF_ZV (b)),
628 clip_to_bounds (BUF_BEGV_BYTE (b), bytepos, BUF_ZV_BYTE (b)));
629 }
630 else
631 unchain_marker (m);
632 return marker;
633 }
634
635
636
637
638
639 void
640 detach_marker (Lisp_Object marker)
641 {
642 Fset_marker (marker, Qnil, Qnil);
643 }
644
645
646
647
648 void
649 unchain_marker (register struct Lisp_Marker *marker)
650 {
651 register struct buffer *b = marker->buffer;
652
653 if (b)
654 {
655 register struct Lisp_Marker *tail, **prev;
656
657
658 eassert (BUFFER_LIVE_P (b));
659
660 marker->buffer = NULL;
661 prev = &BUF_MARKERS (b);
662
663 for (tail = BUF_MARKERS (b); tail; prev = &tail->next, tail = *prev)
664 if (marker == tail)
665 {
666 if (*prev == BUF_MARKERS (b))
667 {
668
669
670
671
672 if (tail->next && b->text != tail->next->buffer->text)
673 emacs_abort ();
674 }
675 *prev = tail->next;
676
677
678 break;
679 }
680
681
682 eassert (tail != NULL);
683 }
684 }
685
686
687
688 ptrdiff_t
689 marker_position (Lisp_Object marker)
690 {
691 register struct Lisp_Marker *m = XMARKER (marker);
692 register struct buffer *buf = m->buffer;
693
694 if (!buf)
695 error ("Marker does not point anywhere");
696
697 eassert (BUF_BEG (buf) <= m->charpos && m->charpos <= BUF_Z (buf));
698
699 return m->charpos;
700 }
701
702
703
704 ptrdiff_t
705 marker_byte_position (Lisp_Object marker)
706 {
707 register struct Lisp_Marker *m = XMARKER (marker);
708 register struct buffer *buf = m->buffer;
709
710 if (!buf)
711 error ("Marker does not point anywhere");
712
713 eassert (BUF_BEG_BYTE (buf) <= m->bytepos && m->bytepos <= BUF_Z_BYTE (buf));
714
715 return m->bytepos;
716 }
717
718 DEFUN ("copy-marker", Fcopy_marker, Scopy_marker, 0, 2, 0,
719 doc:
720
721
722
723
724 )
725 (register Lisp_Object marker, Lisp_Object type)
726 {
727 register Lisp_Object new;
728
729 if (!NILP (marker))
730 CHECK_TYPE (FIXNUMP (marker) || MARKERP (marker), Qinteger_or_marker_p, marker);
731
732 new = Fmake_marker ();
733 Fset_marker (new, marker,
734 (MARKERP (marker) ? Fmarker_buffer (marker) : Qnil));
735 XMARKER (new)->insertion_type = !NILP (type);
736 return new;
737 }
738
739 DEFUN ("marker-insertion-type", Fmarker_insertion_type,
740 Smarker_insertion_type, 1, 1, 0,
741 doc:
742 )
743 (register Lisp_Object marker)
744 {
745 CHECK_MARKER (marker);
746 return XMARKER (marker)->insertion_type ? Qt : Qnil;
747 }
748
749 DEFUN ("set-marker-insertion-type", Fset_marker_insertion_type,
750 Sset_marker_insertion_type, 2, 2, 0,
751 doc:
752
753 )
754 (Lisp_Object marker, Lisp_Object type)
755 {
756 CHECK_MARKER (marker);
757
758 XMARKER (marker)->insertion_type = ! NILP (type);
759 return type;
760 }
761
762 #ifdef MARKER_DEBUG
763
764
765
766 int
767 count_markers (struct buffer *buf)
768 {
769 int total = 0;
770 struct Lisp_Marker *tail;
771
772 for (tail = BUF_MARKERS (buf); tail; tail = tail->next)
773 total++;
774
775 return total;
776 }
777
778
779
780
781 ptrdiff_t
782 verify_bytepos (ptrdiff_t charpos)
783 {
784 ptrdiff_t below = BEG;
785 ptrdiff_t below_byte = BEG_BYTE;
786
787 while (below != charpos)
788 {
789 below++;
790 below_byte += buf_next_char_len (current_buffer, below_byte);
791 }
792
793 return below_byte;
794 }
795
796 #endif
797
798 void
799 syms_of_marker (void)
800 {
801 defsubr (&Smarker_position);
802 defsubr (&Smarker_buffer);
803 defsubr (&Sset_marker);
804 defsubr (&Scopy_marker);
805 defsubr (&Smarker_insertion_type);
806 defsubr (&Sset_marker_insertion_type);
807 }