X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/31f8ab72fb4fb6c13bca39a3adb5b05b92dccebb..fb3cd89b5f1b6ec5d72c1202a961948d8575cc52:/src/marker.c diff --git a/src/marker.c b/src/marker.c index e68245db9e..b3f9e0b4b8 100644 --- a/src/marker.c +++ b/src/marker.c @@ -1,5 +1,5 @@ /* Markers: examining, setting and deleting. - Copyright (C) 1985, 1997 Free Software Foundation, Inc. + Copyright (C) 1985, 1997, 1998 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -32,6 +32,13 @@ static int cached_bytepos; static struct buffer *cached_buffer; static int cached_modiff; +static void byte_char_debug_check P_ ((struct buffer *, int, int)); + +/* Nonzero means enable debugging checks on byte/char correspondences. */ + +static int byte_debug_flag; + +void clear_charpos_cache (b) struct buffer *b; { @@ -58,7 +65,12 @@ clear_charpos_cache (b) int changed = 0; \ \ if (this_charpos == charpos) \ - return (BYTEPOS); \ + { \ + int value = (BYTEPOS); \ + if (byte_debug_flag) \ + byte_char_debug_check (b, charpos, value); \ + return value; \ + } \ else if (this_charpos > charpos) \ { \ if (this_charpos < best_above) \ @@ -78,10 +90,37 @@ clear_charpos_cache (b) if (changed) \ { \ if (best_above - best_below == best_above_byte - best_below_byte) \ - return best_below_byte + (charpos - best_below); \ + { \ + int value = best_below_byte + (charpos - best_below); \ + if (byte_debug_flag) \ + byte_char_debug_check (b, charpos, value); \ + return value; \ + } \ } \ } +static void +byte_char_debug_check (b, charpos, bytepos) + struct buffer *b; + int charpos, bytepos; +{ + int nchars = 0; + + if (bytepos > BUF_GPT_BYTE (b)) + { + nchars = multibyte_chars_in_text (BUF_BEG_ADDR (b), + BUF_GPT_BYTE (b) - BUF_BEG_BYTE (b)); + nchars += multibyte_chars_in_text (BUF_GAP_END_ADDR (b), + bytepos - BUF_GPT_BYTE (b)); + } + else + nchars = multibyte_chars_in_text (BUF_BEG_ADDR (b), + bytepos - BUF_BEG_BYTE (b)); + + if (charpos - 1 != nchars) + abort (); +} + int charpos_to_bytepos (charpos) int charpos; @@ -95,7 +134,6 @@ buf_charpos_to_bytepos (b, charpos) int charpos; { Lisp_Object tail; - int gapend_byte = BUF_GPT_BYTE (b) + BUF_GAP_SIZE (b); int best_above, best_above_byte; int best_below, best_below_byte; @@ -132,7 +170,7 @@ buf_charpos_to_bytepos (b, charpos) CONSIDER (cached_charpos, cached_bytepos); tail = BUF_MARKERS (b); - while (XSYMBOL (tail) != XSYMBOL (Qnil)) + while (! NILP (tail)) { CONSIDER (XMARKER (tail)->charpos, XMARKER (tail)->bytepos); @@ -164,11 +202,15 @@ buf_charpos_to_bytepos (b, charpos) It will last until the next GC. */ if (record) { - Lisp_Object marker; + Lisp_Object marker, buffer; marker = Fmake_marker (); - set_marker_both (marker, Qnil, best_below, best_below_byte); + XSETBUFFER (buffer, b); + set_marker_both (marker, buffer, best_below, best_below_byte); } + if (byte_debug_flag) + byte_char_debug_check (b, charpos, best_below_byte); + cached_buffer = b; cached_modiff = BUF_MODIFF (b); cached_charpos = best_below; @@ -191,11 +233,15 @@ buf_charpos_to_bytepos (b, charpos) It will last until the next GC. */ if (record) { - Lisp_Object marker; + Lisp_Object marker, buffer; marker = Fmake_marker (); - set_marker_both (marker, Qnil, best_above, best_above_byte); + XSETBUFFER (buffer, b); + set_marker_both (marker, buffer, best_above, best_above_byte); } + if (byte_debug_flag) + byte_char_debug_check (b, charpos, best_above_byte); + cached_buffer = b; cached_modiff = BUF_MODIFF (b); cached_charpos = best_above; @@ -218,7 +264,12 @@ buf_charpos_to_bytepos (b, charpos) int changed = 0; \ \ if (this_bytepos == bytepos) \ - return (CHARPOS); \ + { \ + int value = (CHARPOS); \ + if (byte_debug_flag) \ + byte_char_debug_check (b, value, bytepos); \ + return value; \ + } \ else if (this_bytepos > bytepos) \ { \ if (this_bytepos < best_above_byte) \ @@ -238,7 +289,12 @@ buf_charpos_to_bytepos (b, charpos) if (changed) \ { \ if (best_above - best_below == best_above_byte - best_below_byte) \ - return best_below + (bytepos - best_below_byte); \ + { \ + int value = best_below + (bytepos - best_below_byte); \ + if (byte_debug_flag) \ + byte_char_debug_check (b, value, bytepos); \ + return value; \ + } \ } \ } @@ -282,7 +338,7 @@ buf_bytepos_to_charpos (b, bytepos) CONSIDER (cached_bytepos, cached_charpos); tail = BUF_MARKERS (b); - while (XSYMBOL (tail) != XSYMBOL (Qnil)) + while (! NILP (tail)) { CONSIDER (XMARKER (tail)->bytepos, XMARKER (tail)->charpos); @@ -301,7 +357,7 @@ buf_bytepos_to_charpos (b, bytepos) if (bytepos - best_below_byte < best_above_byte - bytepos) { - int record = best_above_byte - bytepos > 5000; + int record = bytepos - best_below_byte > 5000; while (best_below_byte < bytepos) { @@ -311,14 +367,20 @@ buf_bytepos_to_charpos (b, bytepos) /* If this position is quite far from the nearest known position, cache the correspondence by creating a marker here. - It will last until the next GC. */ - if (record) + It will last until the next GC. + But don't do it if BUF_MARKERS is nil; + that is a signal from Fset_buffer_multibyte. */ + if (record && ! NILP (BUF_MARKERS (b))) { - Lisp_Object marker; + Lisp_Object marker, buffer; marker = Fmake_marker (); - set_marker_both (marker, Qnil, best_below, best_below_byte); + XSETBUFFER (buffer, b); + set_marker_both (marker, buffer, best_below, best_below_byte); } + if (byte_debug_flag) + byte_char_debug_check (b, best_below, bytepos); + cached_buffer = b; cached_modiff = BUF_MODIFF (b); cached_charpos = best_below; @@ -338,14 +400,20 @@ buf_bytepos_to_charpos (b, bytepos) /* If this position is quite far from the nearest known position, cache the correspondence by creating a marker here. - It will last until the next GC. */ - if (record) + It will last until the next GC. + But don't do it if BUF_MARKERS is nil; + that is a signal from Fset_buffer_multibyte. */ + if (record && ! NILP (BUF_MARKERS (b))) { - Lisp_Object marker; + Lisp_Object marker, buffer; marker = Fmake_marker (); - set_marker_both (marker, Qnil, best_above, best_above_byte); + XSETBUFFER (buffer, b); + set_marker_both (marker, buffer, best_above, best_above_byte); } + if (byte_debug_flag) + byte_char_debug_check (b, best_above, bytepos); + cached_buffer = b; cached_modiff = BUF_MODIFF (b); cached_charpos = best_above; @@ -559,16 +627,7 @@ set_marker_both (marker, buffer, charpos, bytepos) register struct Lisp_Marker *m; CHECK_MARKER (marker, 0); - /* If position is nil or a marker that points nowhere, - make this marker point nowhere. */ - if (NILP (charpos) - || (MARKERP (charpos) && !XMARKER (charpos)->buffer)) - { - unchain_marker (marker); - return marker; - } - CHECK_NUMBER_COERCE_MARKER (charpos, 1); if (NILP (buffer)) b = current_buffer; else @@ -686,9 +745,11 @@ unchain_marker (marker) if (EQ (b->name, Qnil)) abort (); + XMARKER (marker)->buffer = 0; + tail = BUF_MARKERS (b); prev = Qnil; - while (XSYMBOL (tail) != XSYMBOL (Qnil)) + while (! GC_NILP (tail)) { next = XMARKER (tail)->chain; XUNMARK (next); @@ -711,13 +772,17 @@ unchain_marker (marker) XMARKER (prev)->chain = next; XSETMARKBIT (XMARKER (prev)->chain, omark); } - break; + /* We have removed the marker from the chain; + no need to scan the rest of the chain. */ + return; } else prev = tail; tail = next; } - XMARKER (marker)->buffer = 0; + + /* Marker was not in its chain. */ + abort (); } /* Return the char position of marker MARKER, as a C integer. */ @@ -765,16 +830,14 @@ see `marker-insertion-type'.") { register Lisp_Object new; - if (INTEGERP (marker) || MARKERP (marker)) - { - new = Fmake_marker (); - Fset_marker (new, marker, - (MARKERP (marker) ? Fmarker_buffer (marker) : Qnil)); - XMARKER (new)->insertion_type = !NILP (type); - return new; - } - else + if (! (INTEGERP (marker) || MARKERP (marker))) marker = wrong_type_argument (Qinteger_or_marker_p, marker); + + new = Fmake_marker (); + Fset_marker (new, marker, + (MARKERP (marker) ? Fmarker_buffer (marker) : Qnil)); + XMARKER (new)->insertion_type = !NILP (type); + return new; } DEFUN ("marker-insertion-type", Fmarker_insertion_type, @@ -820,7 +883,7 @@ DEFUN ("buffer-has-markers-at", Fbuffer_has_markers_at, Sbuffer_has_markers_at, charno = Z; for (tail = BUF_MARKERS (current_buffer); - XSYMBOL (tail) != XSYMBOL (Qnil); + !NILP (tail); tail = XMARKER (tail)->chain) if (XMARKER (tail)->charpos == charno) return Qt; @@ -838,4 +901,9 @@ syms_of_marker () defsubr (&Smarker_insertion_type); defsubr (&Sset_marker_insertion_type); defsubr (&Sbuffer_has_markers_at); + + DEFVAR_BOOL ("byte-debug-flag", &byte_debug_flag, + "Non-nil enables debugging checks in byte/char position conversions."); + byte_debug_flag = 0; + }