aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDmitry Antipov2012-07-22 09:37:24 +0400
committerDmitry Antipov2012-07-22 09:37:24 +0400
commitd36d71df9c550e69d8a469139714a188f221aea8 (patch)
tree0e8aaf407ee05e20925765a434bbbcc99d8a9aa9 /src
parent894bd8732db202ab5a2dd43cd0e949289b20c3f5 (diff)
downloademacs-d36d71df9c550e69d8a469139714a188f221aea8.tar.gz
emacs-d36d71df9c550e69d8a469139714a188f221aea8.zip
Simplify and cleanup markers positioning code.
* marker.c (attach_marker): More useful eassert. (live_buffer, set_marker_internal): New function. (Fset_marker, set_marker_restricted): Use set_marker_internal. (set_marker_both, set_marker_restricted_both): Use live_buffer.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog8
-rw-r--r--src/marker.c215
2 files changed, 90 insertions, 133 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 6392044ed62..f0937856559 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
12012-07-22 Dmitry Antipov <dmantipov@yandex.ru>
2
3 Simplify and cleanup markers positioning code.
4 * marker.c (attach_marker): More useful eassert.
5 (live_buffer, set_marker_internal): New function.
6 (Fset_marker, set_marker_restricted): Use set_marker_internal.
7 (set_marker_both, set_marker_restricted_both): Use live_buffer.
8
12012-07-22 Paul Eggert <eggert@cs.ucla.edu> 92012-07-22 Paul Eggert <eggert@cs.ucla.edu>
2 10
3 * buffer.h (struct buffer.indirections): Now ptrdiff_t, not int, 11 * buffer.h (struct buffer.indirections): Now ptrdiff_t, not int,
diff --git a/src/marker.c b/src/marker.c
index 72f48a2d7b9..0a93f4c180f 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -431,8 +431,12 @@ static inline void
431attach_marker (struct Lisp_Marker *m, struct buffer *b, 431attach_marker (struct Lisp_Marker *m, struct buffer *b,
432 ptrdiff_t charpos, ptrdiff_t bytepos) 432 ptrdiff_t charpos, ptrdiff_t bytepos)
433{ 433{
434 /* Every character is at least one byte. */ 434 /* In a single-byte buffer, two positions must be equal.
435 eassert (charpos <= bytepos); 435 Otherwise, every character is at least one byte. */
436 if (BUF_Z (b) == BUF_Z_BYTE (b))
437 eassert (charpos == bytepos);
438 else
439 eassert (charpos <= bytepos);
436 440
437 m->charpos = charpos; 441 m->charpos = charpos;
438 m->bytepos = bytepos; 442 m->bytepos = bytepos;
@@ -446,191 +450,136 @@ attach_marker (struct Lisp_Marker *m, struct buffer *b,
446 } 450 }
447} 451}
448 452
449DEFUN ("set-marker", Fset_marker, Sset_marker, 2, 3, 0, 453/* If BUFFER is nil, return current buffer pointer. Next, check
450 doc: /* Position MARKER before character number POSITION in BUFFER. 454 whether BUFFER is a buffer object and return buffer pointer
451BUFFER defaults to the current buffer. 455 corresponding to BUFFER if BUFFER is live, or NULL otherwise. */
452If POSITION is nil, makes marker point nowhere.
453Then it no longer slows down editing in any buffer.
454Returns MARKER. */)
455 (Lisp_Object marker, Lisp_Object position, Lisp_Object buffer)
456{
457 register ptrdiff_t charpos;
458 register ptrdiff_t bytepos;
459 register struct buffer *b;
460 register struct Lisp_Marker *m;
461 456
462 CHECK_MARKER (marker); 457static inline struct buffer *
463 m = XMARKER (marker); 458live_buffer (Lisp_Object buffer)
459{
460 struct buffer *b;
464 461
465 /* If position is nil or a marker that points nowhere, 462 if (NILP (buffer))
466 make this marker point nowhere. */
467 if (NILP (position)
468 || (MARKERP (position) && !XMARKER (position)->buffer))
469 { 463 {
470 unchain_marker (m); 464 b = current_buffer;
471 return marker; 465 eassert (!NILP (BVAR (b, name)));
472 } 466 }
473
474 if (NILP (buffer))
475 b = current_buffer;
476 else 467 else
477 { 468 {
478 CHECK_BUFFER (buffer); 469 CHECK_BUFFER (buffer);
479 b = XBUFFER (buffer); 470 b = XBUFFER (buffer);
480 /* If buffer is dead, set marker to point nowhere. */ 471 if (NILP (BVAR (b, name)))
481 if (EQ (BVAR (b, name), Qnil)) 472 b = NULL;
482 {
483 unchain_marker (m);
484 return marker;
485 }
486 } 473 }
487 474 return b;
488 /* Optimize the special case where we are copying the position
489 of an existing marker, and MARKER is already in the same buffer. */
490 if (MARKERP (position) && b == XMARKER (position)->buffer
491 && b == m->buffer)
492 {
493 m->bytepos = XMARKER (position)->bytepos;
494 m->charpos = XMARKER (position)->charpos;
495 return marker;
496 }
497
498 CHECK_NUMBER_COERCE_MARKER (position);
499 charpos = clip_to_bounds (BUF_BEG (b), XINT (position), BUF_Z (b));
500 bytepos = buf_charpos_to_bytepos (b, charpos);
501
502 attach_marker (m, b, charpos, bytepos);
503 return marker;
504} 475}
505 476
506/* This version of Fset_marker won't let the position 477/* Internal function to set MARKER in BUFFER at POSITION. Non-zero
507 be outside the visible part. */ 478 RESTRICTED means limit the POSITION by the visible part of BUFFER. */
508 479
509Lisp_Object 480static inline Lisp_Object
510set_marker_restricted (Lisp_Object marker, Lisp_Object pos, Lisp_Object buffer) 481set_marker_internal (Lisp_Object marker, Lisp_Object position,
482 Lisp_Object buffer, int restricted)
511{ 483{
512 register ptrdiff_t charpos;
513 register ptrdiff_t bytepos;
514 register struct buffer *b;
515 register struct Lisp_Marker *m; 484 register struct Lisp_Marker *m;
485 register struct buffer *b = live_buffer (buffer);
516 486
517 CHECK_MARKER (marker); 487 CHECK_MARKER (marker);
518 m = XMARKER (marker); 488 m = XMARKER (marker);
519 489
520 /* If position is nil or a marker that points nowhere, 490 /* Set MARKER to point nowhere if BUFFER is dead, or
521 make this marker point nowhere. */ 491 POSITION is nil or a marker points to nowhere. */
522 if (NILP (pos) 492 if (NILP (position)
523 || (MARKERP (pos) && !XMARKER (pos)->buffer)) 493 || (MARKERP (position) && !XMARKER (position)->buffer)
494 || !b)
495 unchain_marker (m);
496
497 /* Optimize the special case where we are copying the position of
498 an existing marker, and MARKER is already in the same buffer. */
499 else if (MARKERP (position) && b == XMARKER (position)->buffer
500 && b == m->buffer)
524 { 501 {
525 unchain_marker (m); 502 m->bytepos = XMARKER (position)->bytepos;
526 return marker; 503 m->charpos = XMARKER (position)->charpos;
527 } 504 }
528 505
529 if (NILP (buffer))
530 b = current_buffer;
531 else 506 else
532 { 507 {
533 CHECK_BUFFER (buffer); 508 register ptrdiff_t charpos, bytepos;
534 b = XBUFFER (buffer); 509
535 /* If buffer is dead, set marker to point nowhere. */ 510 CHECK_NUMBER_COERCE_MARKER (position);
536 if (EQ (BVAR (b, name), Qnil)) 511 charpos = clip_to_bounds (restricted ? BUF_BEGV (b) : BUF_BEG (b),
537 { 512 XINT (position),
538 unchain_marker (m); 513 restricted ? BUF_ZV (b) : BUF_Z (b));
539 return marker; 514 bytepos = buf_charpos_to_bytepos (b, charpos);
540 } 515 attach_marker (m, b, charpos, bytepos);
541 } 516 }
517 return marker;
518}
542 519
543 /* Optimize the special case where we are copying the position 520DEFUN ("set-marker", Fset_marker, Sset_marker, 2, 3, 0,
544 of an existing marker, and MARKER is already in the same buffer. */ 521 doc: /* Position MARKER before character number POSITION in BUFFER,
545 if (MARKERP (pos) && b == XMARKER (pos)->buffer 522which defaults to the current buffer. If POSITION is nil,
546 && b == m->buffer) 523makes marker point nowhere so it no longer slows down
547 { 524editing in any buffer. Returns MARKER. */)
548 m->bytepos = XMARKER (pos)->bytepos; 525 (Lisp_Object marker, Lisp_Object position, Lisp_Object buffer)
549 m->charpos = XMARKER (pos)->charpos; 526{
550 return marker; 527 return set_marker_internal (marker, position, buffer, 0);
551 } 528}
552 529
553 CHECK_NUMBER_COERCE_MARKER (pos); 530/* Like the above, but won't let the position be outside the visible part. */
554 charpos = clip_to_bounds (BUF_BEGV (b), XINT (pos), BUF_ZV (b));
555 bytepos = buf_charpos_to_bytepos (b, charpos);
556 531
557 attach_marker (m, b, charpos, bytepos); 532Lisp_Object
558 return marker; 533set_marker_restricted (Lisp_Object marker, Lisp_Object position,
534 Lisp_Object buffer)
535{
536 return set_marker_internal (marker, position, buffer, 1);
559} 537}
560 538
561/* Set the position of MARKER, specifying both the 539/* Set the position of MARKER, specifying both the
562 character position and the corresponding byte position. */ 540 character position and the corresponding byte position. */
563 541
564Lisp_Object 542Lisp_Object
565set_marker_both (Lisp_Object marker, Lisp_Object buffer, ptrdiff_t charpos, ptrdiff_t bytepos) 543set_marker_both (Lisp_Object marker, Lisp_Object buffer,
544 ptrdiff_t charpos, ptrdiff_t bytepos)
566{ 545{
567 register struct buffer *b;
568 register struct Lisp_Marker *m; 546 register struct Lisp_Marker *m;
547 register struct buffer *b = live_buffer (buffer);
569 548
570 CHECK_MARKER (marker); 549 CHECK_MARKER (marker);
571 m = XMARKER (marker); 550 m = XMARKER (marker);
572 551
573 if (NILP (buffer)) 552 if (b)
574 b = current_buffer; 553 attach_marker (m, b, charpos, bytepos);
575 else 554 else
576 { 555 unchain_marker (m);
577 CHECK_BUFFER (buffer);
578 b = XBUFFER (buffer);
579 /* If buffer is dead, set marker to point nowhere. */
580 if (EQ (BVAR (b, name), Qnil))
581 {
582 unchain_marker (m);
583 return marker;
584 }
585 }
586
587 /* In a single-byte buffer, the two positions must be equal. */
588 if (BUF_Z (b) == BUF_Z_BYTE (b)
589 && charpos != bytepos)
590 abort ();
591
592 attach_marker (m, b, charpos, bytepos);
593 return marker; 556 return marker;
594} 557}
595 558
596/* This version of set_marker_both won't let the position 559/* Like the above, but won't let the position be outside the visible part. */
597 be outside the visible part. */
598 560
599Lisp_Object 561Lisp_Object
600set_marker_restricted_both (Lisp_Object marker, Lisp_Object buffer, ptrdiff_t charpos, ptrdiff_t bytepos) 562set_marker_restricted_both (Lisp_Object marker, Lisp_Object buffer,
563 ptrdiff_t charpos, ptrdiff_t bytepos)
601{ 564{
602 register struct buffer *b;
603 register struct Lisp_Marker *m; 565 register struct Lisp_Marker *m;
566 register struct buffer *b = live_buffer (buffer);
604 567
605 CHECK_MARKER (marker); 568 CHECK_MARKER (marker);
606 m = XMARKER (marker); 569 m = XMARKER (marker);
607 570
608 if (NILP (buffer)) 571 if (b)
609 b = current_buffer;
610 else
611 { 572 {
612 CHECK_BUFFER (buffer); 573 attach_marker
613 b = XBUFFER (buffer); 574 (m, b,
614 /* If buffer is dead, set marker to point nowhere. */ 575 clip_to_bounds (BUF_BEGV (b), charpos, BUF_ZV (b)),
615 if (EQ (BVAR (b, name), Qnil)) 576 clip_to_bounds (BUF_BEGV_BYTE (b), bytepos, BUF_ZV_BYTE (b)));
616 {
617 unchain_marker (m);
618 return marker;
619 }
620 } 577 }
621 578 else
622 charpos = clip_to_bounds (BUF_BEGV (b), charpos, BUF_ZV (b)); 579 unchain_marker (m);
623 bytepos = clip_to_bounds (BUF_BEGV_BYTE (b), bytepos, BUF_ZV_BYTE (b));
624
625 /* In a single-byte buffer, the two positions must be equal. */
626 if (BUF_Z (b) == BUF_Z_BYTE (b)
627 && charpos != bytepos)
628 abort ();
629
630 attach_marker (m, b, charpos, bytepos);
631 return marker; 580 return marker;
632} 581}
633 582
634/* Remove MARKER from the chain of whatever buffer it is in, 583/* Remove MARKER from the chain of whatever buffer it is in,
635 leaving it points to nowhere. This is called during garbage 584 leaving it points to nowhere. This is called during garbage
636 collection, so we must be careful to ignore and preserve 585 collection, so we must be careful to ignore and preserve