diff options
| author | Dmitry Antipov | 2012-07-22 09:37:24 +0400 |
|---|---|---|
| committer | Dmitry Antipov | 2012-07-22 09:37:24 +0400 |
| commit | d36d71df9c550e69d8a469139714a188f221aea8 (patch) | |
| tree | 0e8aaf407ee05e20925765a434bbbcc99d8a9aa9 /src | |
| parent | 894bd8732db202ab5a2dd43cd0e949289b20c3f5 (diff) | |
| download | emacs-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/ChangeLog | 8 | ||||
| -rw-r--r-- | src/marker.c | 215 |
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 @@ | |||
| 1 | 2012-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 | |||
| 1 | 2012-07-22 Paul Eggert <eggert@cs.ucla.edu> | 9 | 2012-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 | |||
| 431 | attach_marker (struct Lisp_Marker *m, struct buffer *b, | 431 | attach_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 | ||
| 449 | DEFUN ("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 |
| 451 | BUFFER defaults to the current buffer. | 455 | corresponding to BUFFER if BUFFER is live, or NULL otherwise. */ |
| 452 | If POSITION is nil, makes marker point nowhere. | ||
| 453 | Then it no longer slows down editing in any buffer. | ||
| 454 | Returns 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); | 457 | static inline struct buffer * |
| 463 | m = XMARKER (marker); | 458 | live_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 | ||
| 509 | Lisp_Object | 480 | static inline Lisp_Object |
| 510 | set_marker_restricted (Lisp_Object marker, Lisp_Object pos, Lisp_Object buffer) | 481 | set_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 | 520 | DEFUN ("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 | 522 | which defaults to the current buffer. If POSITION is nil, |
| 546 | && b == m->buffer) | 523 | makes marker point nowhere so it no longer slows down |
| 547 | { | 524 | editing 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); | 532 | Lisp_Object |
| 558 | return marker; | 533 | set_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 | ||
| 564 | Lisp_Object | 542 | Lisp_Object |
| 565 | set_marker_both (Lisp_Object marker, Lisp_Object buffer, ptrdiff_t charpos, ptrdiff_t bytepos) | 543 | set_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 | ||
| 599 | Lisp_Object | 561 | Lisp_Object |
| 600 | set_marker_restricted_both (Lisp_Object marker, Lisp_Object buffer, ptrdiff_t charpos, ptrdiff_t bytepos) | 562 | set_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 |