diff options
Diffstat (limited to 'src/intervals.c')
-rw-r--r-- | src/intervals.c | 167 |
1 files changed, 83 insertions, 84 deletions
diff --git a/src/intervals.c b/src/intervals.c index 3db80ebed4a..78f4f6b6174 100644 --- a/src/intervals.c +++ b/src/intervals.c @@ -1,5 +1,5 @@ /* Code for doing intervals. - Copyright (C) 1993-1995, 1997-1998, 2001-2017 Free Software + Copyright (C) 1993-1995, 1997-1998, 2001-2022 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -117,7 +117,7 @@ create_root_interval (Lisp_Object parent) /* Make the interval TARGET have exactly the properties of SOURCE. */ void -copy_properties (register INTERVAL source, register INTERVAL target) +copy_properties (INTERVAL source, INTERVAL target) { if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target)) return; @@ -165,10 +165,11 @@ merge_properties (register INTERVAL source, register INTERVAL target) } } -/* Return true if the two intervals have the same properties. */ +/* Return true if the two intervals have the same properties. + If use_equal is true, use Fequal for comparisons instead of EQ. */ -bool -intervals_equal (INTERVAL i0, INTERVAL i1) +static bool +intervals_equal_1 (INTERVAL i0, INTERVAL i1, bool use_equal) { Lisp_Object i0_cdr, i0_sym; Lisp_Object i1_cdr, i1_val; @@ -197,13 +198,14 @@ intervals_equal (INTERVAL i0, INTERVAL i1) } /* i0 has something i1 doesn't. */ - if (EQ (i1_val, Qnil)) + if (NILP (i1_val)) return false; /* i0 and i1 both have sym, but it has different values in each. */ if (!CONSP (i1_val) || (i1_val = XCDR (i1_val), !CONSP (i1_val)) - || !EQ (XCAR (i1_val), XCAR (i0_cdr))) + || use_equal ? NILP (Fequal (XCAR (i1_val), XCAR (i0_cdr))) + : !EQ (XCAR (i1_val), XCAR (i0_cdr))) return false; i0_cdr = XCDR (i0_cdr); @@ -217,6 +219,14 @@ intervals_equal (INTERVAL i0, INTERVAL i1) /* Lengths of the two plists were equal. */ return (NILP (i0_cdr) && NILP (i1_cdr)); } + +/* Return true if the two intervals have the same properties. */ + +bool +intervals_equal (INTERVAL i0, INTERVAL i1) +{ + return intervals_equal_1 (i0, i1, false); +} /* Traverse an interval tree TREE, performing FUNCTION on each node. @@ -298,7 +308,7 @@ rotate_right (INTERVAL A) set_interval_parent (c, A); /* A's total length is decreased by the length of B and its left child. */ - A->total_length -= B->total_length - TOTAL_LENGTH (c); + A->total_length -= TOTAL_LENGTH (B) - TOTAL_LENGTH0 (c); eassert (TOTAL_LENGTH (A) > 0); eassert (LENGTH (A) > 0); @@ -349,7 +359,7 @@ rotate_left (INTERVAL A) set_interval_parent (c, A); /* A's total length is decreased by the length of B and its right child. */ - A->total_length -= B->total_length - TOTAL_LENGTH (c); + A->total_length -= TOTAL_LENGTH (B) - TOTAL_LENGTH0 (c); eassert (TOTAL_LENGTH (A) > 0); eassert (LENGTH (A) > 0); @@ -713,13 +723,23 @@ previous_interval (register INTERVAL interval) return NULL; } -/* Find the interval containing POS given some non-NULL INTERVAL - in the same tree. Note that we need to update interval->position - if we go down the tree. - To speed up the process, we assume that the ->position of - I and all its parents is already uptodate. */ +/* Set the ->position field of I's parent, based on I->position. */ +#define SET_PARENT_POSITION(i) \ + if (AM_LEFT_CHILD (i)) \ + INTERVAL_PARENT (i)->position = \ + i->position + TOTAL_LENGTH (i) - LEFT_TOTAL_LENGTH (i); \ + else \ + INTERVAL_PARENT (i)->position = \ + i->position - LEFT_TOTAL_LENGTH (i) \ + - LENGTH (INTERVAL_PARENT (i)) + +/* Find the interval containing POS, given some interval I in + the same tree. Note that we update interval->position in each + interval we traverse, assuming it is already correctly set for the + argument I. We don't assume that any other interval already has a + correctly set ->position. */ INTERVAL -update_interval (register INTERVAL i, ptrdiff_t pos) +update_interval (INTERVAL i, ptrdiff_t pos) { if (!i) return NULL; @@ -729,7 +749,7 @@ update_interval (register INTERVAL i, ptrdiff_t pos) if (pos < i->position) { /* Move left. */ - if (pos >= i->position - TOTAL_LENGTH (i->left)) + if (pos >= i->position - LEFT_TOTAL_LENGTH (i)) { i->left->position = i->position - TOTAL_LENGTH (i->left) + LEFT_TOTAL_LENGTH (i->left); @@ -738,13 +758,16 @@ update_interval (register INTERVAL i, ptrdiff_t pos) else if (NULL_PARENT (i)) error ("Point before start of properties"); else - i = INTERVAL_PARENT (i); + { + SET_PARENT_POSITION (i); + i = INTERVAL_PARENT (i); + } continue; } else if (pos >= INTERVAL_LAST_POS (i)) { /* Move right. */ - if (pos < INTERVAL_LAST_POS (i) + TOTAL_LENGTH (i->right)) + if (pos < INTERVAL_LAST_POS (i) + RIGHT_TOTAL_LENGTH (i)) { i->right->position = INTERVAL_LAST_POS (i) + LEFT_TOTAL_LENGTH (i->right); @@ -753,7 +776,10 @@ update_interval (register INTERVAL i, ptrdiff_t pos) else if (NULL_PARENT (i)) error ("Point %"pD"d after end of properties", pos); else - i = INTERVAL_PARENT (i); + { + SET_PARENT_POSITION (i); + i = INTERVAL_PARENT (i); + } continue; } else @@ -1171,7 +1197,7 @@ delete_interval (register INTERVAL i) register INTERVAL parent; ptrdiff_t amt = LENGTH (i); - eassert (amt == 0); /* Only used on zero-length intervals now. */ + eassert (amt <= 0); /* Only used on zero total-length intervals now. */ if (ROOT_INTERVAL_P (i)) { @@ -1557,8 +1583,8 @@ graft_intervals_into_buffer (INTERVAL source, ptrdiff_t position, if (!inherit && tree && length > 0) { XSETBUFFER (buf, buffer); - set_text_properties_1 (make_number (position), - make_number (position + length), + set_text_properties_1 (make_fixnum (position), + make_fixnum (position + length), Qnil, buf, find_interval (tree, position)); } @@ -1711,11 +1737,11 @@ lookup_char_property (Lisp_Object plist, Lisp_Object prop, bool textprop) { tail = XCDR (tail); for (; NILP (fallback) && CONSP (tail); tail = XCDR (tail)) - fallback = Fplist_get (plist, XCAR (tail)); + fallback = plist_get (plist, XCAR (tail)); } if (textprop && NILP (fallback) && CONSP (Vdefault_text_properties)) - fallback = Fplist_get (Vdefault_text_properties, prop); + fallback = plist_get (Vdefault_text_properties, prop); return fallback; } @@ -1793,7 +1819,7 @@ adjust_for_invis_intang (ptrdiff_t pos, ptrdiff_t test_offs, ptrdiff_t adj, /* POS + ADJ would be beyond the buffer bounds, so do no adjustment. */ return pos; - test_pos = make_number (pos + test_offs); + test_pos = make_fixnum (pos + test_offs); invis_propval = get_char_property_and_overlay (test_pos, Qinvisible, Qnil, @@ -1806,7 +1832,7 @@ adjust_for_invis_intang (ptrdiff_t pos, ptrdiff_t test_offs, ptrdiff_t adj, such that an insertion at POS would inherit it. */ && (NILP (invis_overlay) /* Invisible property is from a text-property. */ - ? (text_property_stickiness (Qinvisible, make_number (pos), Qnil) + ? (text_property_stickiness (Qinvisible, make_fixnum (pos), Qnil) == (test_offs == 0 ? 1 : -1)) /* Invisible property is from an overlay. */ : (test_offs == 0 @@ -1926,8 +1952,8 @@ set_point_both (ptrdiff_t charpos, ptrdiff_t bytepos) if (! NILP (intangible_propval)) { - while (XINT (pos) > BEGV - && EQ (Fget_char_property (make_number (XINT (pos) - 1), + while (XFIXNUM (pos) > BEGV + && EQ (Fget_char_property (make_fixnum (XFIXNUM (pos) - 1), Qintangible, Qnil), intangible_propval)) pos = Fprevious_char_property_change (pos, Qnil); @@ -1937,7 +1963,7 @@ set_point_both (ptrdiff_t charpos, ptrdiff_t bytepos) property is `front-sticky', perturb it to be one character earlier -- this ensures that point can never move to the beginning of an invisible/intangible/front-sticky region. */ - charpos = adjust_for_invis_intang (XINT (pos), 0, -1, 0); + charpos = adjust_for_invis_intang (XFIXNUM (pos), 0, -1, 0); } } else @@ -1954,12 +1980,12 @@ set_point_both (ptrdiff_t charpos, ptrdiff_t bytepos) /* If preceding char is intangible, skip forward over all chars with matching intangible property. */ - intangible_propval = Fget_char_property (make_number (charpos - 1), + intangible_propval = Fget_char_property (make_fixnum (charpos - 1), Qintangible, Qnil); if (! NILP (intangible_propval)) { - while (XINT (pos) < ZV + while (XFIXNUM (pos) < ZV && EQ (Fget_char_property (pos, Qintangible, Qnil), intangible_propval)) pos = Fnext_char_property_change (pos, Qnil); @@ -1969,7 +1995,7 @@ set_point_both (ptrdiff_t charpos, ptrdiff_t bytepos) property is `rear-sticky', perturb it to be one character later -- this ensures that point can never move to the end of an invisible/intangible/rear-sticky region. */ - charpos = adjust_for_invis_intang (XINT (pos), -1, 1, 0); + charpos = adjust_for_invis_intang (XFIXNUM (pos), -1, 1, 0); } } @@ -2026,18 +2052,18 @@ set_point_both (ptrdiff_t charpos, ptrdiff_t bytepos) enter_after = Qnil; if (! EQ (leave_before, enter_before) && !NILP (leave_before)) - call2 (leave_before, make_number (old_position), - make_number (charpos)); + call2 (leave_before, make_fixnum (old_position), + make_fixnum (charpos)); if (! EQ (leave_after, enter_after) && !NILP (leave_after)) - call2 (leave_after, make_number (old_position), - make_number (charpos)); + call2 (leave_after, make_fixnum (old_position), + make_fixnum (charpos)); if (! EQ (enter_before, leave_before) && !NILP (enter_before)) - call2 (enter_before, make_number (old_position), - make_number (charpos)); + call2 (enter_before, make_fixnum (old_position), + make_fixnum (charpos)); if (! EQ (enter_after, leave_after) && !NILP (enter_after)) - call2 (enter_after, make_number (old_position), - make_number (charpos)); + call2 (enter_after, make_fixnum (old_position), + make_fixnum (charpos)); } } @@ -2055,7 +2081,7 @@ move_if_not_intangible (ptrdiff_t position) if (! NILP (Vinhibit_point_motion_hooks)) /* If intangible is inhibited, always move point to POSITION. */ ; - else if (PT < position && XINT (pos) < ZV) + else if (PT < position && XFIXNUM (pos) < ZV) { /* We want to move forward, so check the text before POSITION. */ @@ -2065,23 +2091,23 @@ move_if_not_intangible (ptrdiff_t position) /* If following char is intangible, skip back over all chars with matching intangible property. */ if (! NILP (intangible_propval)) - while (XINT (pos) > BEGV - && EQ (Fget_char_property (make_number (XINT (pos) - 1), + while (XFIXNUM (pos) > BEGV + && EQ (Fget_char_property (make_fixnum (XFIXNUM (pos) - 1), Qintangible, Qnil), intangible_propval)) pos = Fprevious_char_property_change (pos, Qnil); } - else if (XINT (pos) > BEGV) + else if (XFIXNUM (pos) > BEGV) { /* We want to move backward, so check the text after POSITION. */ - intangible_propval = Fget_char_property (make_number (XINT (pos) - 1), + intangible_propval = Fget_char_property (make_fixnum (XFIXNUM (pos) - 1), Qintangible, Qnil); /* If following char is intangible, skip forward over all chars with matching intangible property. */ if (! NILP (intangible_propval)) - while (XINT (pos) < ZV + while (XFIXNUM (pos) < ZV && EQ (Fget_char_property (pos, Qintangible, Qnil), intangible_propval)) pos = Fnext_char_property_change (pos, Qnil); @@ -2096,7 +2122,7 @@ move_if_not_intangible (ptrdiff_t position) try moving to POSITION (which means we actually move farther if POSITION is inside of intangible text). */ - if (XINT (pos) != PT) + if (XFIXNUM (pos) != PT) SET_PT (position); } @@ -2145,15 +2171,15 @@ get_property_and_range (ptrdiff_t pos, Lisp_Object prop, Lisp_Object *val, /* Return the proper local keymap TYPE for position POSITION in BUFFER; TYPE should be one of `keymap' or `local-map'. Use the map - specified by the PROP property, if any. Otherwise, if TYPE is - `local-map' use BUFFER's local map. */ + specified by the TYPE property, if any. Otherwise, if TYPE is + `local-map', use BUFFER's local map. */ Lisp_Object get_local_map (ptrdiff_t position, struct buffer *buffer, Lisp_Object type) { Lisp_Object prop, lispy_position, lispy_buffer; ptrdiff_t old_begv, old_zv, old_begv_byte, old_zv_byte; - ptrdiff_t count = SPECPDL_INDEX (); + specpdl_ref count = SPECPDL_INDEX (); position = clip_to_bounds (BUF_BEGV (buffer), position, BUF_ZV (buffer)); @@ -2274,7 +2300,7 @@ compare_string_intervals (Lisp_Object s1, Lisp_Object s2) /* If we ever find a mismatch between the strings, they differ. */ - if (! intervals_equal (i1, i2)) + if (! intervals_equal_1 (i1, i2, true)) return 0; /* Advance POS till the end of the shorter interval, @@ -2318,23 +2344,10 @@ set_intervals_multibyte_1 (INTERVAL i, bool multi_flag, if (multi_flag) { - ptrdiff_t temp; - left_end_byte = start_byte + LEFT_TOTAL_LENGTH (i); + left_end_byte + = advance_to_char_boundary (start_byte + LEFT_TOTAL_LENGTH (i)); left_end = BYTE_TO_CHAR (left_end_byte); - - temp = CHAR_TO_BYTE (left_end); - - /* If LEFT_END_BYTE is in the middle of a character, - adjust it and LEFT_END to a char boundary. */ - if (left_end_byte > temp) - { - left_end_byte = temp; - } - if (left_end_byte < temp) - { - left_end--; - left_end_byte = CHAR_TO_BYTE (left_end); - } + eassert (CHAR_TO_BYTE (left_end) == left_end_byte); } else { @@ -2351,24 +2364,10 @@ set_intervals_multibyte_1 (INTERVAL i, bool multi_flag, if (multi_flag) { - ptrdiff_t temp; - - right_start_byte = end_byte - RIGHT_TOTAL_LENGTH (i); + right_start_byte + = advance_to_char_boundary (end_byte - RIGHT_TOTAL_LENGTH (i)); right_start = BYTE_TO_CHAR (right_start_byte); - - /* If RIGHT_START_BYTE is in the middle of a character, - adjust it and RIGHT_START to a char boundary. */ - temp = CHAR_TO_BYTE (right_start); - - if (right_start_byte < temp) - { - right_start_byte = temp; - } - if (right_start_byte > temp) - { - right_start++; - right_start_byte = CHAR_TO_BYTE (right_start); - } + eassert (CHAR_TO_BYTE (right_start) == right_start_byte); } else { |