diff options
Diffstat (limited to 'src/insdel.c')
| -rw-r--r-- | src/insdel.c | 109 |
1 files changed, 49 insertions, 60 deletions
diff --git a/src/insdel.c b/src/insdel.c index 87010cd8251..246ba80f290 100644 --- a/src/insdel.c +++ b/src/insdel.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* Buffer insertion/deletion and gap motion for GNU Emacs. | 1 | /* Buffer insertion/deletion and gap motion for GNU Emacs. |
| 2 | Copyright (C) 1985-1986, 1993-1995, 1997-2012 | 2 | Copyright (C) 1985-1986, 1993-1995, 1997-2013 Free Software |
| 3 | Free Software Foundation, Inc. | 3 | Foundation, Inc. |
| 4 | 4 | ||
| 5 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| 6 | 6 | ||
| @@ -84,21 +84,14 @@ check_markers (void) | |||
| 84 | 84 | ||
| 85 | #endif /* MARKER_DEBUG */ | 85 | #endif /* MARKER_DEBUG */ |
| 86 | 86 | ||
| 87 | /* Move gap to position CHARPOS. | ||
| 88 | Note that this can quit! */ | ||
| 89 | |||
| 90 | void | ||
| 91 | move_gap (ptrdiff_t charpos) | ||
| 92 | { | ||
| 93 | move_gap_both (charpos, charpos_to_bytepos (charpos)); | ||
| 94 | } | ||
| 95 | |||
| 96 | /* Move gap to byte position BYTEPOS, which is also char position CHARPOS. | 87 | /* Move gap to byte position BYTEPOS, which is also char position CHARPOS. |
| 97 | Note that this can quit! */ | 88 | Note that this can quit! */ |
| 98 | 89 | ||
| 99 | void | 90 | void |
| 100 | move_gap_both (ptrdiff_t charpos, ptrdiff_t bytepos) | 91 | move_gap_both (ptrdiff_t charpos, ptrdiff_t bytepos) |
| 101 | { | 92 | { |
| 93 | eassert (charpos == BYTE_TO_CHAR (bytepos) | ||
| 94 | && bytepos == CHAR_TO_BYTE (charpos)); | ||
| 102 | if (bytepos < GPT_BYTE) | 95 | if (bytepos < GPT_BYTE) |
| 103 | gap_left (charpos, bytepos, 0); | 96 | gap_left (charpos, bytepos, 0); |
| 104 | else if (bytepos > GPT_BYTE) | 97 | else if (bytepos > GPT_BYTE) |
| @@ -388,14 +381,13 @@ make_gap_larger (ptrdiff_t nbytes_added) | |||
| 388 | ptrdiff_t real_gap_loc_byte; | 381 | ptrdiff_t real_gap_loc_byte; |
| 389 | ptrdiff_t old_gap_size; | 382 | ptrdiff_t old_gap_size; |
| 390 | ptrdiff_t current_size = Z_BYTE - BEG_BYTE + GAP_SIZE; | 383 | ptrdiff_t current_size = Z_BYTE - BEG_BYTE + GAP_SIZE; |
| 391 | enum { enough_for_a_while = 2000 }; | ||
| 392 | 384 | ||
| 393 | if (BUF_BYTES_MAX - current_size < nbytes_added) | 385 | if (BUF_BYTES_MAX - current_size < nbytes_added) |
| 394 | buffer_overflow (); | 386 | buffer_overflow (); |
| 395 | 387 | ||
| 396 | /* If we have to get more space, get enough to last a while; | 388 | /* If we have to get more space, get enough to last a while; |
| 397 | but do not exceed the maximum buffer size. */ | 389 | but do not exceed the maximum buffer size. */ |
| 398 | nbytes_added = min (nbytes_added + enough_for_a_while, | 390 | nbytes_added = min (nbytes_added + GAP_BYTES_DFL, |
| 399 | BUF_BYTES_MAX - current_size); | 391 | BUF_BYTES_MAX - current_size); |
| 400 | 392 | ||
| 401 | enlarge_buffer_text (current_buffer, nbytes_added); | 393 | enlarge_buffer_text (current_buffer, nbytes_added); |
| @@ -413,8 +405,7 @@ make_gap_larger (ptrdiff_t nbytes_added) | |||
| 413 | GPT_BYTE = Z_BYTE + GAP_SIZE; | 405 | GPT_BYTE = Z_BYTE + GAP_SIZE; |
| 414 | GAP_SIZE = nbytes_added; | 406 | GAP_SIZE = nbytes_added; |
| 415 | 407 | ||
| 416 | /* Move the new gap down to be consecutive with the end of the old one. | 408 | /* Move the new gap down to be consecutive with the end of the old one. */ |
| 417 | This adjusts the markers properly too. */ | ||
| 418 | gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1); | 409 | gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1); |
| 419 | 410 | ||
| 420 | /* Now combine the two into one large gap. */ | 411 | /* Now combine the two into one large gap. */ |
| @@ -443,9 +434,9 @@ make_gap_smaller (ptrdiff_t nbytes_removed) | |||
| 443 | ptrdiff_t real_beg_unchanged; | 434 | ptrdiff_t real_beg_unchanged; |
| 444 | ptrdiff_t new_gap_size; | 435 | ptrdiff_t new_gap_size; |
| 445 | 436 | ||
| 446 | /* Make sure the gap is at least 20 bytes. */ | 437 | /* Make sure the gap is at least GAP_BYTES_MIN bytes. */ |
| 447 | if (GAP_SIZE - nbytes_removed < 20) | 438 | if (GAP_SIZE - nbytes_removed < GAP_BYTES_MIN) |
| 448 | nbytes_removed = GAP_SIZE - 20; | 439 | nbytes_removed = GAP_SIZE - GAP_BYTES_MIN; |
| 449 | 440 | ||
| 450 | /* Prevent quitting in move_gap. */ | 441 | /* Prevent quitting in move_gap. */ |
| 451 | tem = Vinhibit_quit; | 442 | tem = Vinhibit_quit; |
| @@ -468,8 +459,7 @@ make_gap_smaller (ptrdiff_t nbytes_removed) | |||
| 468 | Z_BYTE += new_gap_size; | 459 | Z_BYTE += new_gap_size; |
| 469 | GAP_SIZE = nbytes_removed; | 460 | GAP_SIZE = nbytes_removed; |
| 470 | 461 | ||
| 471 | /* Move the unwanted pretend gap to the end of the buffer. This | 462 | /* Move the unwanted pretend gap to the end of the buffer. */ |
| 472 | adjusts the markers properly too. */ | ||
| 473 | gap_right (Z, Z_BYTE); | 463 | gap_right (Z, Z_BYTE); |
| 474 | 464 | ||
| 475 | enlarge_buffer_text (current_buffer, -nbytes_removed); | 465 | enlarge_buffer_text (current_buffer, -nbytes_removed); |
| @@ -500,7 +490,20 @@ make_gap (ptrdiff_t nbytes_added) | |||
| 500 | make_gap_smaller (-nbytes_added); | 490 | make_gap_smaller (-nbytes_added); |
| 501 | #endif | 491 | #endif |
| 502 | } | 492 | } |
| 503 | 493 | ||
| 494 | /* Add NBYTES to B's gap. It's enough to temporarily | ||
| 495 | fake current_buffer and avoid real switch to B. */ | ||
| 496 | |||
| 497 | void | ||
| 498 | make_gap_1 (struct buffer *b, ptrdiff_t nbytes) | ||
| 499 | { | ||
| 500 | struct buffer *oldb = current_buffer; | ||
| 501 | |||
| 502 | current_buffer = b; | ||
| 503 | make_gap (nbytes); | ||
| 504 | current_buffer = oldb; | ||
| 505 | } | ||
| 506 | |||
| 504 | /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR. | 507 | /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR. |
| 505 | FROM_MULTIBYTE says whether the incoming text is multibyte. | 508 | FROM_MULTIBYTE says whether the incoming text is multibyte. |
| 506 | TO_MULTIBYTE says whether to store the text as multibyte. | 509 | TO_MULTIBYTE says whether to store the text as multibyte. |
| @@ -655,17 +658,6 @@ insert_before_markers_and_inherit (const char *string, | |||
| 655 | } | 658 | } |
| 656 | } | 659 | } |
| 657 | 660 | ||
| 658 | /* Subroutine used by the insert functions above. */ | ||
| 659 | |||
| 660 | void | ||
| 661 | insert_1 (const char *string, ptrdiff_t nbytes, | ||
| 662 | bool inherit, bool prepare, bool before_markers) | ||
| 663 | { | ||
| 664 | insert_1_both (string, chars_in_text ((unsigned char *) string, nbytes), | ||
| 665 | nbytes, inherit, prepare, before_markers); | ||
| 666 | } | ||
| 667 | |||
| 668 | |||
| 669 | #ifdef BYTE_COMBINING_DEBUG | 661 | #ifdef BYTE_COMBINING_DEBUG |
| 670 | 662 | ||
| 671 | /* See if the bytes before POS/POS_BYTE combine with bytes | 663 | /* See if the bytes before POS/POS_BYTE combine with bytes |
| @@ -985,10 +977,11 @@ insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, | |||
| 985 | } | 977 | } |
| 986 | 978 | ||
| 987 | /* Insert a sequence of NCHARS chars which occupy NBYTES bytes | 979 | /* Insert a sequence of NCHARS chars which occupy NBYTES bytes |
| 988 | starting at GPT_ADDR. */ | 980 | starting at GAP_END_ADDR - NBYTES (if text_at_gap_tail) and at |
| 981 | GPT_ADDR (if not text_at_gap_tail). */ | ||
| 989 | 982 | ||
| 990 | void | 983 | void |
| 991 | insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes) | 984 | insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail) |
| 992 | { | 985 | { |
| 993 | if (NILP (BVAR (current_buffer, enable_multibyte_characters))) | 986 | if (NILP (BVAR (current_buffer, enable_multibyte_characters))) |
| 994 | nchars = nbytes; | 987 | nchars = nbytes; |
| @@ -997,10 +990,13 @@ insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes) | |||
| 997 | MODIFF++; | 990 | MODIFF++; |
| 998 | 991 | ||
| 999 | GAP_SIZE -= nbytes; | 992 | GAP_SIZE -= nbytes; |
| 1000 | GPT += nchars; | 993 | if (! text_at_gap_tail) |
| 994 | { | ||
| 995 | GPT += nchars; | ||
| 996 | GPT_BYTE += nbytes; | ||
| 997 | } | ||
| 1001 | ZV += nchars; | 998 | ZV += nchars; |
| 1002 | Z += nchars; | 999 | Z += nchars; |
| 1003 | GPT_BYTE += nbytes; | ||
| 1004 | ZV_BYTE += nbytes; | 1000 | ZV_BYTE += nbytes; |
| 1005 | Z_BYTE += nbytes; | 1001 | Z_BYTE += nbytes; |
| 1006 | if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ | 1002 | if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ |
| @@ -1018,7 +1014,7 @@ insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes) | |||
| 1018 | current_buffer, 0); | 1014 | current_buffer, 0); |
| 1019 | } | 1015 | } |
| 1020 | 1016 | ||
| 1021 | if (GPT - nchars < PT) | 1017 | if (! text_at_gap_tail && GPT - nchars < PT) |
| 1022 | adjust_point (nchars, nbytes); | 1018 | adjust_point (nchars, nbytes); |
| 1023 | 1019 | ||
| 1024 | check_markers (); | 1020 | check_markers (); |
| @@ -1755,9 +1751,9 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte, | |||
| 1755 | 1751 | ||
| 1756 | return deletion; | 1752 | return deletion; |
| 1757 | } | 1753 | } |
| 1758 | 1754 | ||
| 1759 | /* Call this if you're about to change the region of BUFFER from | 1755 | /* Call this if you're about to change the region of current buffer |
| 1760 | character positions START to END. This checks the read-only | 1756 | from character positions START to END. This checks the read-only |
| 1761 | properties of the region, calls the necessary modification hooks, | 1757 | properties of the region, calls the necessary modification hooks, |
| 1762 | and warns the next redisplay that it should pay attention to that | 1758 | and warns the next redisplay that it should pay attention to that |
| 1763 | area. | 1759 | area. |
| @@ -1766,16 +1762,11 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte, | |||
| 1766 | Otherwise set CHARS_MODIFF to the new value of MODIFF. */ | 1762 | Otherwise set CHARS_MODIFF to the new value of MODIFF. */ |
| 1767 | 1763 | ||
| 1768 | void | 1764 | void |
| 1769 | modify_region (struct buffer *buffer, ptrdiff_t start, ptrdiff_t end, | 1765 | modify_region_1 (ptrdiff_t start, ptrdiff_t end, bool preserve_chars_modiff) |
| 1770 | bool preserve_chars_modiff) | ||
| 1771 | { | 1766 | { |
| 1772 | struct buffer *old_buffer = current_buffer; | ||
| 1773 | |||
| 1774 | set_buffer_internal (buffer); | ||
| 1775 | |||
| 1776 | prepare_to_modify_buffer (start, end, NULL); | 1767 | prepare_to_modify_buffer (start, end, NULL); |
| 1777 | 1768 | ||
| 1778 | BUF_COMPUTE_UNCHANGED (buffer, start - 1, end); | 1769 | BUF_COMPUTE_UNCHANGED (current_buffer, start - 1, end); |
| 1779 | 1770 | ||
| 1780 | if (MODIFF <= SAVE_MODIFF) | 1771 | if (MODIFF <= SAVE_MODIFF) |
| 1781 | record_first_change (); | 1772 | record_first_change (); |
| @@ -1783,11 +1774,9 @@ modify_region (struct buffer *buffer, ptrdiff_t start, ptrdiff_t end, | |||
| 1783 | if (! preserve_chars_modiff) | 1774 | if (! preserve_chars_modiff) |
| 1784 | CHARS_MODIFF = MODIFF; | 1775 | CHARS_MODIFF = MODIFF; |
| 1785 | 1776 | ||
| 1786 | bset_point_before_scroll (buffer, Qnil); | 1777 | bset_point_before_scroll (current_buffer, Qnil); |
| 1787 | |||
| 1788 | set_buffer_internal (old_buffer); | ||
| 1789 | } | 1778 | } |
| 1790 | 1779 | ||
| 1791 | /* Check that it is okay to modify the buffer between START and END, | 1780 | /* Check that it is okay to modify the buffer between START and END, |
| 1792 | which are char positions. | 1781 | which are char positions. |
| 1793 | 1782 | ||
| @@ -1807,9 +1796,10 @@ prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end, | |||
| 1807 | if (!NILP (BVAR (current_buffer, read_only))) | 1796 | if (!NILP (BVAR (current_buffer, read_only))) |
| 1808 | Fbarf_if_buffer_read_only (); | 1797 | Fbarf_if_buffer_read_only (); |
| 1809 | 1798 | ||
| 1810 | /* Let redisplay consider other windows than selected_window | 1799 | /* If we're modifying the buffer other than shown in a selected window, |
| 1811 | if modifying another buffer. */ | 1800 | let redisplay consider other windows if this buffer is visible. */ |
| 1812 | if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer) | 1801 | if (XBUFFER (XWINDOW (selected_window)->contents) != current_buffer |
| 1802 | && buffer_window_count (current_buffer)) | ||
| 1813 | ++windows_or_buffers_changed; | 1803 | ++windows_or_buffers_changed; |
| 1814 | 1804 | ||
| 1815 | if (buffer_intervals (current_buffer)) | 1805 | if (buffer_intervals (current_buffer)) |
| @@ -1861,7 +1851,7 @@ prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end, | |||
| 1861 | : (!NILP (Vselect_active_regions) | 1851 | : (!NILP (Vselect_active_regions) |
| 1862 | && !NILP (Vtransient_mark_mode)))) | 1852 | && !NILP (Vtransient_mark_mode)))) |
| 1863 | { | 1853 | { |
| 1864 | ptrdiff_t b = XMARKER (BVAR (current_buffer, mark))->charpos; | 1854 | ptrdiff_t b = marker_position (BVAR (current_buffer, mark)); |
| 1865 | ptrdiff_t e = PT; | 1855 | ptrdiff_t e = PT; |
| 1866 | if (b < e) | 1856 | if (b < e) |
| 1867 | Vsaved_region_selection = make_buffer_string (b, e, 0); | 1857 | Vsaved_region_selection = make_buffer_string (b, e, 0); |
| @@ -2027,9 +2017,8 @@ signal_after_change (ptrdiff_t charpos, ptrdiff_t lendel, ptrdiff_t lenins) | |||
| 2027 | && current_buffer != XBUFFER (combine_after_change_buffer)) | 2017 | && current_buffer != XBUFFER (combine_after_change_buffer)) |
| 2028 | Fcombine_after_change_execute (); | 2018 | Fcombine_after_change_execute (); |
| 2029 | 2019 | ||
| 2030 | elt = Fcons (make_number (charpos - BEG), | 2020 | elt = list3i (charpos - BEG, Z - (charpos - lendel + lenins), |
| 2031 | Fcons (make_number (Z - (charpos - lendel + lenins)), | 2021 | lenins - lendel); |
| 2032 | Fcons (make_number (lenins - lendel), Qnil))); | ||
| 2033 | combine_after_change_list | 2022 | combine_after_change_list |
| 2034 | = Fcons (elt, combine_after_change_list); | 2023 | = Fcons (elt, combine_after_change_list); |
| 2035 | combine_after_change_buffer = Fcurrent_buffer (); | 2024 | combine_after_change_buffer = Fcurrent_buffer (); |
| @@ -2087,7 +2076,7 @@ Fcombine_after_change_execute_1 (Lisp_Object val) | |||
| 2087 | 2076 | ||
| 2088 | DEFUN ("combine-after-change-execute", Fcombine_after_change_execute, | 2077 | DEFUN ("combine-after-change-execute", Fcombine_after_change_execute, |
| 2089 | Scombine_after_change_execute, 0, 0, 0, | 2078 | Scombine_after_change_execute, 0, 0, 0, |
| 2090 | doc: /* This function is for use internally in `combine-after-change-calls'. */) | 2079 | doc: /* This function is for use internally in the function `combine-after-change-calls'. */) |
| 2091 | (void) | 2080 | (void) |
| 2092 | { | 2081 | { |
| 2093 | ptrdiff_t count = SPECPDL_INDEX (); | 2082 | ptrdiff_t count = SPECPDL_INDEX (); |
| @@ -2179,7 +2168,7 @@ syms_of_insdel (void) | |||
| 2179 | combine_after_change_buffer = Qnil; | 2168 | combine_after_change_buffer = Qnil; |
| 2180 | 2169 | ||
| 2181 | DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls, | 2170 | DEFVAR_LISP ("combine-after-change-calls", Vcombine_after_change_calls, |
| 2182 | doc: /* Used internally by the `combine-after-change-calls' macro. */); | 2171 | doc: /* Used internally by the function `combine-after-change-calls' macro. */); |
| 2183 | Vcombine_after_change_calls = Qnil; | 2172 | Vcombine_after_change_calls = Qnil; |
| 2184 | 2173 | ||
| 2185 | DEFVAR_BOOL ("inhibit-modification-hooks", inhibit_modification_hooks, | 2174 | DEFVAR_BOOL ("inhibit-modification-hooks", inhibit_modification_hooks, |