X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/0270b8776e451b6cce79e68dc788837c2f6b0ef8..54a72868e6b4d3001918d57884c8cf74ec8f9b8b:/src/intervals.c diff --git a/src/intervals.c b/src/intervals.c index 21048f93cb..5d9550da79 100644 --- a/src/intervals.c +++ b/src/intervals.c @@ -1,5 +1,6 @@ /* Code for doing intervals. - Copyright (C) 1993, 1994, 1995, 1997, 1998, 2002 Free Software Foundation, Inc. + Copyright (C) 1993, 1994, 1995, 1997, 1998, 2001, 2002, 2003, 2004, + 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -15,8 +16,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ /* NOTES: @@ -77,7 +78,7 @@ create_root_interval (parent) - BUF_BEG (XBUFFER (parent))); CHECK_TOTAL_LENGTH (new); BUF_INTERVALS (XBUFFER (parent)) = new; - new->position = 1; + new->position = BEG; } else if (STRINGP (parent)) { @@ -121,20 +122,27 @@ merge_properties (source, target) MERGE_INTERVAL_CACHE (source, target); o = source->plist; - while (! EQ (o, Qnil)) + while (CONSP (o)) { - sym = Fcar (o); - val = Fmemq (sym, target->plist); + sym = XCAR (o); + o = XCDR (o); + CHECK_CONS (o); + + val = target->plist; + while (CONSP (val) && !EQ (XCAR (val), sym)) + { + val = XCDR (val); + if (!CONSP (val)) + break; + val = XCDR (val); + } if (NILP (val)) { - o = Fcdr (o); - val = Fcar (o); + val = XCAR (o); target->plist = Fcons (sym, Fcons (val, target->plist)); - o = Fcdr (o); } - else - o = Fcdr (Fcdr (o)); + o = XCDR (o); } } @@ -145,8 +153,8 @@ int intervals_equal (i0, i1) INTERVAL i0, i1; { - register Lisp_Object i0_cdr, i0_sym, i1_val; - register int i1_len; + register Lisp_Object i0_cdr, i0_sym; + register Lisp_Object i1_cdr, i1_val; if (DEFAULT_INTERVAL_P (i0) && DEFAULT_INTERVAL_P (i1)) return 1; @@ -154,38 +162,43 @@ intervals_equal (i0, i1) if (DEFAULT_INTERVAL_P (i0) || DEFAULT_INTERVAL_P (i1)) return 0; - i1_len = XFASTINT (Flength (i1->plist)); - if (i1_len & 0x1) /* Paranoia -- plists are always even */ - abort (); - i1_len /= 2; i0_cdr = i0->plist; - while (!NILP (i0_cdr)) - { - /* Lengths of the two plists were unequal. */ - if (i1_len == 0) - return 0; - - i0_sym = Fcar (i0_cdr); - i1_val = Fmemq (i0_sym, i1->plist); + i1_cdr = i1->plist; + while (CONSP (i0_cdr) && CONSP (i1_cdr)) + { + i0_sym = XCAR (i0_cdr); + i0_cdr = XCDR (i0_cdr); + if (!CONSP (i0_cdr)) + return 0; /* abort (); */ + i1_val = i1->plist; + while (CONSP (i1_val) && !EQ (XCAR (i1_val), i0_sym)) + { + i1_val = XCDR (i1_val); + if (!CONSP (i1_val)) + return 0; /* abort (); */ + i1_val = XCDR (i1_val); + } /* i0 has something i1 doesn't. */ if (EQ (i1_val, Qnil)) return 0; /* i0 and i1 both have sym, but it has different values in each. */ - i0_cdr = Fcdr (i0_cdr); - if (! EQ (Fcar (Fcdr (i1_val)), Fcar (i0_cdr))) + if (!CONSP (i1_val) + || (i1_val = XCDR (i1_val), !CONSP (i1_val)) + || !EQ (XCAR (i1_val), XCAR (i0_cdr))) return 0; - i0_cdr = Fcdr (i0_cdr); - i1_len--; - } + i0_cdr = XCDR (i0_cdr); - /* Lengths of the two plists were unequal. */ - if (i1_len > 0) - return 0; + i1_cdr = XCDR (i1_cdr); + if (!CONSP (i1_cdr)) + return 0; /* abort (); */ + i1_cdr = XCDR (i1_cdr); + } - return 1; + /* Lengths of the two plists were equal. */ + return (NILP (i0_cdr) && NILP (i1_cdr)); } @@ -666,8 +679,8 @@ find_interval (tree, position) else { tree->position - = (position - relative_position /* the left edge of *tree */ - + LEFT_TOTAL_LENGTH (tree)); /* the left edge of this interval */ + = (position - relative_position /* left edge of *tree. */ + + LEFT_TOTAL_LENGTH (tree)); /* left edge of this interval. */ return tree; } @@ -788,14 +801,14 @@ update_interval (i, pos) /* Move right. */ if (pos < INTERVAL_LAST_POS (i) + TOTAL_LENGTH (i->right)) { - i->right->position = INTERVAL_LAST_POS (i) + - LEFT_TOTAL_LENGTH (i->right); + i->right->position = INTERVAL_LAST_POS (i) + + LEFT_TOTAL_LENGTH (i->right); i = i->right; /* Move to the right child */ } else if (NULL_PARENT (i)) - error ("Point after end of properties"); + error ("Point %d after end of properties", pos); else - i = INTERVAL_PARENT (i); + i = INTERVAL_PARENT (i); continue; } else @@ -1125,19 +1138,19 @@ merge_properties_sticky (pleft, pright) rrear = textget (pright, Qrear_nonsticky); /* Go through each element of PRIGHT. */ - for (tail1 = pright; CONSP (tail1); tail1 = Fcdr (Fcdr (tail1))) + for (tail1 = pright; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) { Lisp_Object tmp; - sym = Fcar (tail1); + sym = XCAR (tail1); /* Sticky properties get special treatment. */ if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky)) continue; - rval = Fcar (Fcdr (tail1)); - for (tail2 = pleft; CONSP (tail2); tail2 = Fcdr (Fcdr (tail2))) - if (EQ (sym, Fcar (tail2))) + rval = Fcar (XCDR (tail1)); + for (tail2 = pleft; CONSP (tail2); tail2 = Fcdr (XCDR (tail2))) + if (EQ (sym, XCAR (tail2))) break; /* Indicate whether the property is explicitly defined on the left. @@ -1183,24 +1196,24 @@ merge_properties_sticky (pleft, pright) } /* Now go through each element of PLEFT. */ - for (tail2 = pleft; CONSP (tail2); tail2 = Fcdr (Fcdr (tail2))) + for (tail2 = pleft; CONSP (tail2); tail2 = Fcdr (XCDR (tail2))) { Lisp_Object tmp; - sym = Fcar (tail2); + sym = XCAR (tail2); /* Sticky properties get special treatment. */ if (EQ (sym, Qrear_nonsticky) || EQ (sym, Qfront_sticky)) continue; /* If sym is in PRIGHT, we've already considered it. */ - for (tail1 = pright; CONSP (tail1); tail1 = Fcdr (Fcdr (tail1))) - if (EQ (sym, Fcar (tail1))) + for (tail1 = pright; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) + if (EQ (sym, XCAR (tail1))) break; if (! NILP (tail1)) continue; - lval = Fcar (Fcdr (tail2)); + lval = Fcar (XCDR (tail2)); /* Even if lrear or rfront say nothing about the stickiness of SYM, Vtext_property_default_nonsticky may give default @@ -1710,6 +1723,7 @@ graft_intervals_into_buffer (source, position, length, buffer, inherit) { register INTERVAL under, over, this, prev; register INTERVAL tree; + int over_used; tree = BUF_INTERVALS (buffer); @@ -1728,6 +1742,7 @@ graft_intervals_into_buffer (source, position, length, buffer, inherit) Qnil, buf, 0); } if (! NULL_INTERVAL_P (BUF_INTERVALS (buffer))) + /* Shouldn't be necessary. -stef */ BUF_INTERVALS (buffer) = balance_an_interval (BUF_INTERVALS (buffer)); return; } @@ -1741,7 +1756,8 @@ graft_intervals_into_buffer (source, position, length, buffer, inherit) Lisp_Object buf; XSETBUFFER (buf, buffer); BUF_INTERVALS (buffer) = reproduce_tree_obj (source, buf); - BUF_INTERVALS (buffer)->position = 1; + BUF_INTERVALS (buffer)->position = BEG; + BUF_INTERVALS (buffer)->up_obj = 1; /* Explicitly free the old tree here? */ @@ -1763,7 +1779,8 @@ graft_intervals_into_buffer (source, position, length, buffer, inherit) about inserting properly. For now, just waste the old intervals. */ { BUF_INTERVALS (buffer) = reproduce_tree (source, INTERVAL_PARENT (tree)); - BUF_INTERVALS (buffer)->position = 1; + BUF_INTERVALS (buffer)->position = BEG; + BUF_INTERVALS (buffer)->up_obj = 1; /* Explicitly free the old tree here. */ return; @@ -1811,21 +1828,42 @@ graft_intervals_into_buffer (source, position, length, buffer, inherit) adjust_intervals_for_insertion, so stickiness has already been taken care of. */ + /* OVER is the interval we are copying from next. + OVER_USED says how many characters' worth of OVER + have already been copied into target intervals. + UNDER is the next interval in the target. */ + over_used = 0; while (! NULL_INTERVAL_P (over)) { - if (LENGTH (over) < LENGTH (under)) + /* If UNDER is longer than OVER, split it. */ + if (LENGTH (over) - over_used < LENGTH (under)) { - this = split_interval_left (under, LENGTH (over)); + this = split_interval_left (under, LENGTH (over) - over_used); copy_properties (under, this); } else this = under; - copy_properties (over, this); + + /* THIS is now the interval to copy or merge into. + OVER covers all of it. */ if (inherit) merge_properties (over, this); else copy_properties (over, this); - over = next_interval (over); + + /* If THIS and OVER end at the same place, + advance OVER to a new source interval. */ + if (LENGTH (this) == LENGTH (over) - over_used) + { + over = next_interval (over); + over_used = 0; + } + else + /* Otherwise just record that more of OVER has been used. */ + over_used += LENGTH (this); + + /* Always advance to a new target interval. */ + under = next_interval (this); } if (! NULL_INTERVAL_P (BUF_INTERVALS (buffer))) @@ -1872,11 +1910,13 @@ lookup_char_property (plist, prop, textprop) return fallback; /* Check for alternative properties */ tail = Fassq (prop, Vchar_property_alias_alist); - if (NILP (tail)) - return tail; - tail = XCDR (tail); - for (; NILP (fallback) && CONSP (tail); tail = XCDR (tail)) - fallback = Fplist_get (plist, XCAR (tail)); + if (! NILP (tail)) + { + tail = XCDR (tail); + for (; NILP (fallback) && CONSP (tail); tail = XCDR (tail)) + fallback = Fplist_get (plist, XCAR (tail)); + } + if (textprop && NILP (fallback) && CONSP (Vdefault_text_properties)) fallback = Fplist_get (Vdefault_text_properties, prop); return fallback; @@ -1963,7 +2003,7 @@ adjust_for_invis_intang (pos, test_offs, adj, test_intang) 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)) + ? (text_property_stickiness (Qinvisible, make_number (pos), Qnil) == (test_offs == 0 ? 1 : -1)) /* Invisible property is from an overlay. */ : (test_offs == 0 @@ -1986,6 +2026,10 @@ set_point_both (buffer, charpos, bytepos) register INTERVAL to, from, toprev, fromprev; int buffer_point; int old_position = BUF_PT (buffer); + /* This ensures that we move forward past intangible text when the + initial position is the same as the destination, in the rare + instances where this is important, e.g. in line-move-finish + (simple.el). */ int backwards = (charpos < old_position ? 1 : 0); int have_overlays; int original_position; @@ -2006,8 +2050,7 @@ set_point_both (buffer, charpos, bytepos) if (charpos > BUF_ZV (buffer) || charpos < BUF_BEGV (buffer)) abort (); - have_overlays = (! NILP (buffer->overlays_before) - || ! NILP (buffer->overlays_after)); + have_overlays = (buffer->overlays_before || buffer->overlays_after); /* If we have no text properties and overlays, then we can do it quickly. */ @@ -2167,36 +2210,38 @@ set_point_both (buffer, charpos, bytepos) Lisp_Object leave_after, leave_before, enter_after, enter_before; if (fromprev) - leave_after = textget (fromprev->plist, Qpoint_left); + leave_before = textget (fromprev->plist, Qpoint_left); else - leave_after = Qnil; + leave_before = Qnil; + if (from) - leave_before = textget (from->plist, Qpoint_left); + leave_after = textget (from->plist, Qpoint_left); else - leave_before = Qnil; + leave_after = Qnil; if (toprev) - enter_after = textget (toprev->plist, Qpoint_entered); + enter_before = textget (toprev->plist, Qpoint_entered); else - enter_after = Qnil; + enter_before = Qnil; + if (to) - enter_before = textget (to->plist, Qpoint_entered); + enter_after = textget (to->plist, Qpoint_entered); else - enter_before = Qnil; + 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_number (old_position), + make_number (charpos)); if (! EQ (leave_after, enter_after) && !NILP (leave_after)) - call2 (leave_after, make_number (old_position), - make_number (charpos)); + call2 (leave_after, make_number (old_position), + make_number (charpos)); if (! EQ (enter_before, leave_before) && !NILP (enter_before)) - call2 (enter_before, make_number (old_position), - make_number (charpos)); + call2 (enter_before, make_number (old_position), + make_number (charpos)); if (! EQ (enter_after, leave_after) && !NILP (enter_after)) - call2 (enter_after, make_number (old_position), - make_number (charpos)); + call2 (enter_after, make_number (old_position), + make_number (charpos)); } } @@ -2247,6 +2292,10 @@ move_if_not_intangible (position) pos = Fnext_char_property_change (pos, Qnil); } + else if (position < BEGV) + position = BEGV; + else if (position > ZV) + position = ZV; /* If the whole stretch between PT and POSITION isn't intangible, try moving to POSITION (which means we actually move farther @@ -2306,7 +2355,9 @@ get_property_and_range (pos, prop, val, start, end, object) /* 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. */ + `local-map' use BUFFER's local map. + + POSITION must be in the accessible part of BUFFER. */ Lisp_Object get_local_map (position, buffer, type) @@ -2318,7 +2369,7 @@ get_local_map (position, buffer, type) int old_begv, old_zv, old_begv_byte, old_zv_byte; /* Perhaps we should just change `position' to the limit. */ - if (position > BUF_Z (buffer) || position < BUF_BEG (buffer)) + if (position > BUF_ZV (buffer) || position < BUF_BEGV (buffer)) abort (); /* Ignore narrowing, so that a local map continues to be valid even if @@ -2332,13 +2383,17 @@ get_local_map (position, buffer, type) BUF_BEGV_BYTE (buffer) = BUF_BEG_BYTE (buffer); BUF_ZV_BYTE (buffer) = BUF_Z_BYTE (buffer); - /* There are no properties at the end of the buffer, so in that case - check for a local map on the last character of the buffer instead. */ - if (position == BUF_Z (buffer) && BUF_Z (buffer) > BUF_BEG (buffer)) - --position; XSETFASTINT (lispy_position, position); XSETBUFFER (lispy_buffer, buffer); + /* First check if the CHAR has any property. This is because when + we click with the mouse, the mouse pointer is really pointing + to the CHAR after POS. */ prop = Fget_char_property (lispy_position, type, lispy_buffer); + /* If not, look at the POS's properties. This is necessary because when + editing a field with a `local-map' property, we want insertion at the end + to obey the `local-map' property. */ + if (NILP (prop)) + prop = get_pos_property (lispy_position, type, lispy_buffer); BUF_BEGV (buffer) = old_begv; BUF_ZV (buffer) = old_zv; @@ -2493,7 +2548,7 @@ set_intervals_multibyte_1 (i, multi_flag, start, start_byte, end, 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. */ + adjust it and LEFT_END to a char boundary. */ if (left_end_byte > temp) { left_end_byte = temp; @@ -2525,7 +2580,7 @@ set_intervals_multibyte_1 (i, multi_flag, start, start_byte, end, end_byte) 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. */ + adjust it and RIGHT_START to a char boundary. */ temp = CHAR_TO_BYTE (right_start); if (right_start_byte < temp) @@ -2581,3 +2636,6 @@ set_intervals_multibyte (multi_flag) set_intervals_multibyte_1 (BUF_INTERVALS (current_buffer), multi_flag, BEG, BEG_BYTE, Z, Z_BYTE); } + +/* arch-tag: 3d402b60-083c-4271-b4a3-ebd9a74bfe27 + (do not change this comment) */