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