From: Chong Yidong Date: Sun, 13 Mar 2011 22:25:16 +0000 (-0400) Subject: Fix BUF_* macros to handle indirect buffers properly (Bug#8219). X-Git-Tag: emacs-pretest-24.0.90~104^2~275^2~585 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=cffc6f3bd9b5dbb9825502928bd9dd58ddbac02e;p=emacs.git Fix BUF_* macros to handle indirect buffers properly (Bug#8219). * buffer.h (BUF_BEGV, BUF_BEGV_BYTE, BUF_ZV, BUF_ZV_BYTE, BUF_PT) (BUF_PT_BYTE): Rewrite to handle indirect buffers (Bug#8219). These macros can no longer be used for assignment. * buffer.c (Fget_buffer_create, Fmake_indirect_buffer): Assign struct members directly, instead of using BUF_BEGV etc. (record_buffer_markers, fetch_buffer_markers): New functions for recording and fetching special buffer markers. (set_buffer_internal_1, set_buffer_temp): Use them. * lread.c (unreadchar): Use SET_BUF_PT_BOTH. * insdel.c (adjust_point): Use SET_BUF_PT_BOTH. * intervals.c (temp_set_point_both): Use SET_BUF_PT_BOTH. (get_local_map): Use SET_BUF_BEGV_BOTH and SET_BUF_ZV_BOTH. * xdisp.c (hscroll_window_tree): (reconsider_clip_changes): Use PT instead of BUF_PT. --- diff --git a/src/ChangeLog b/src/ChangeLog index 3d5f3e0c387..bad9b8dd4b7 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,25 @@ +2011-03-13 Chong Yidong + + * buffer.h (BUF_BEGV, BUF_BEGV_BYTE, BUF_ZV, BUF_ZV_BYTE, BUF_PT) + (BUF_PT_BYTE): Rewrite to handle indirect buffers (Bug#8219). + These macros can no longer be used for assignment. + + * buffer.c (Fget_buffer_create, Fmake_indirect_buffer): Assign + struct members directly, instead of using BUF_BEGV etc. + (record_buffer_markers, fetch_buffer_markers): New functions for + recording and fetching special buffer markers. + (set_buffer_internal_1, set_buffer_temp): Use them. + + * lread.c (unreadchar): Use SET_BUF_PT_BOTH. + + * insdel.c (adjust_point): Use SET_BUF_PT_BOTH. + + * intervals.c (temp_set_point_both): Use SET_BUF_PT_BOTH. + (get_local_map): Use SET_BUF_BEGV_BOTH and SET_BUF_ZV_BOTH. + + * xdisp.c (hscroll_window_tree): + (reconsider_clip_changes): Use PT instead of BUF_PT. + 2011-03-13 Eli Zaretskii * makefile.w32-in ($(BLD)/editfns.$(O)): Depend on diff --git a/src/buffer.c b/src/buffer.c index 448c9236387..01940728275 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -330,15 +330,17 @@ even if it is dead. The return value is never nil. */) if (! BUF_BEG_ADDR (b)) buffer_memory_full (); - BUF_PT (b) = BEG; + b->pt = BEG; + b->begv = BEG; + b->zv = BEG; + b->pt_byte = BEG_BYTE; + b->begv_byte = BEG_BYTE; + b->zv_byte = BEG_BYTE; + BUF_GPT (b) = BEG; - BUF_BEGV (b) = BEG; - BUF_ZV (b) = BEG; - BUF_Z (b) = BEG; - BUF_PT_BYTE (b) = BEG_BYTE; BUF_GPT_BYTE (b) = BEG_BYTE; - BUF_BEGV_BYTE (b) = BEG_BYTE; - BUF_ZV_BYTE (b) = BEG_BYTE; + + BUF_Z (b) = BEG; BUF_Z_BYTE (b) = BEG_BYTE; BUF_MODIFF (b) = 1; BUF_CHARS_MODIFF (b) = 1; @@ -489,6 +491,53 @@ clone_per_buffer_values (struct buffer *from, struct buffer *to) BVAR (to, local_var_alist) = buffer_lisp_local_variables (from); } + +/* If buffer B has markers to record PT, BEGV and ZV when it is not + current, update these markers. */ + +static void +record_buffer_markers (struct buffer *b) +{ + if (! NILP (BVAR (b, pt_marker))) + { + Lisp_Object buffer; + + eassert (!NILP (BVAR (b, begv_marker))); + eassert (!NILP (BVAR (b, zv_marker))); + + XSETBUFFER (buffer, b); + set_marker_both (BVAR (b, pt_marker), buffer, b->pt, b->pt_byte); + set_marker_both (BVAR (b, begv_marker), buffer, b->begv, b->begv_byte); + set_marker_both (BVAR (b, zv_marker), buffer, b->zv, b->zv_byte); + } +} + + +/* If buffer B has markers to record PT, BEGV and ZV when it is not + current, fetch these values into B->begv etc. */ + +static void +fetch_buffer_markers (struct buffer *b) +{ + if (! NILP (BVAR (b, pt_marker))) + { + Lisp_Object m; + + eassert (!NILP (BVAR (b, begv_marker))); + eassert (!NILP (BVAR (b, zv_marker))); + + m = BVAR (b, pt_marker); + SET_BUF_PT_BOTH (b, marker_position (m), marker_byte_position (m)); + + m = BVAR (b, begv_marker); + SET_BUF_BEGV_BOTH (b, marker_position (m), marker_byte_position (m)); + + m = BVAR (b, zv_marker); + SET_BUF_ZV_BOTH (b, marker_position (m), marker_byte_position (m)); + } +} + + DEFUN ("make-indirect-buffer", Fmake_indirect_buffer, Smake_indirect_buffer, 2, 3, "bMake indirect buffer (to buffer): \nBName of indirect buffer: ", @@ -527,12 +576,12 @@ CLONE nil means the indirect buffer's state is reset to default values. */) /* Use the base buffer's text object. */ b->text = b->base_buffer->text; - BUF_BEGV (b) = BUF_BEGV (b->base_buffer); - BUF_ZV (b) = BUF_ZV (b->base_buffer); - BUF_PT (b) = BUF_PT (b->base_buffer); - BUF_BEGV_BYTE (b) = BUF_BEGV_BYTE (b->base_buffer); - BUF_ZV_BYTE (b) = BUF_ZV_BYTE (b->base_buffer); - BUF_PT_BYTE (b) = BUF_PT_BYTE (b->base_buffer); + b->pt = b->base_buffer->pt; + b->begv = b->base_buffer->begv; + b->zv = b->base_buffer->zv; + b->pt_byte = b->base_buffer->pt_byte; + b->begv_byte = b->base_buffer->begv_byte; + b->zv_byte = b->base_buffer->zv_byte; b->newline_cache = 0; b->width_run_cache = 0; @@ -562,24 +611,23 @@ CLONE nil means the indirect buffer's state is reset to default values. */) /* Make sure the base buffer has markers for its narrowing. */ if (NILP (BVAR (b->base_buffer, pt_marker))) { + eassert (NILP (BVAR (b, begv_marker))); + eassert (NILP (BVAR (b, zv_marker))); + BVAR (b->base_buffer, pt_marker) = Fmake_marker (); set_marker_both (BVAR (b->base_buffer, pt_marker), base_buffer, - BUF_PT (b->base_buffer), - BUF_PT_BYTE (b->base_buffer)); - } - if (NILP (BVAR (b->base_buffer, begv_marker))) - { + b->base_buffer->pt, + b->base_buffer->pt_byte); + BVAR (b->base_buffer, begv_marker) = Fmake_marker (); set_marker_both (BVAR (b->base_buffer, begv_marker), base_buffer, - BUF_BEGV (b->base_buffer), - BUF_BEGV_BYTE (b->base_buffer)); - } - if (NILP (BVAR (b->base_buffer, zv_marker))) - { + b->base_buffer->begv, + b->base_buffer->begv_byte); + BVAR (b->base_buffer, zv_marker) = Fmake_marker (); set_marker_both (BVAR (b->base_buffer, zv_marker), base_buffer, - BUF_ZV (b->base_buffer), - BUF_ZV_BYTE (b->base_buffer)); + b->base_buffer->zv, + b->base_buffer->zv_byte); XMARKER (BVAR (b->base_buffer, zv_marker))->insertion_type = 1; } @@ -587,11 +635,11 @@ CLONE nil means the indirect buffer's state is reset to default values. */) { /* Give the indirect buffer markers for its narrowing. */ BVAR (b, pt_marker) = Fmake_marker (); - set_marker_both (BVAR (b, pt_marker), buf, BUF_PT (b), BUF_PT_BYTE (b)); + set_marker_both (BVAR (b, pt_marker), buf, b->pt, b->pt_byte); BVAR (b, begv_marker) = Fmake_marker (); - set_marker_both (BVAR (b, begv_marker), buf, BUF_BEGV (b), BUF_BEGV_BYTE (b)); + set_marker_both (BVAR (b, begv_marker), buf, b->begv, b->begv_byte); BVAR (b, zv_marker) = Fmake_marker (); - set_marker_both (BVAR (b, zv_marker), buf, BUF_ZV (b), BUF_ZV_BYTE (b)); + set_marker_both (BVAR (b, zv_marker), buf, b->zv, b->zv_byte); XMARKER (BVAR (b, zv_marker))->insertion_type = 1; } else @@ -1796,27 +1844,7 @@ set_buffer_internal_1 (register struct buffer *b) /* If the old current buffer has markers to record PT, BEGV and ZV when it is not current, update them now. */ - if (! NILP (BVAR (old_buf, pt_marker))) - { - Lisp_Object obuf; - XSETBUFFER (obuf, old_buf); - set_marker_both (BVAR (old_buf, pt_marker), obuf, - BUF_PT (old_buf), BUF_PT_BYTE (old_buf)); - } - if (! NILP (BVAR (old_buf, begv_marker))) - { - Lisp_Object obuf; - XSETBUFFER (obuf, old_buf); - set_marker_both (BVAR (old_buf, begv_marker), obuf, - BUF_BEGV (old_buf), BUF_BEGV_BYTE (old_buf)); - } - if (! NILP (BVAR (old_buf, zv_marker))) - { - Lisp_Object obuf; - XSETBUFFER (obuf, old_buf); - set_marker_both (BVAR (old_buf, zv_marker), obuf, - BUF_ZV (old_buf), BUF_ZV_BYTE (old_buf)); - } + record_buffer_markers (old_buf); } /* Get the undo list from the base buffer, so that it appears @@ -1826,21 +1854,7 @@ set_buffer_internal_1 (register struct buffer *b) /* If the new current buffer has markers to record PT, BEGV and ZV when it is not current, fetch them now. */ - if (! NILP (BVAR (b, pt_marker))) - { - BUF_PT (b) = marker_position (BVAR (b, pt_marker)); - BUF_PT_BYTE (b) = marker_byte_position (BVAR (b, pt_marker)); - } - if (! NILP (BVAR (b, begv_marker))) - { - BUF_BEGV (b) = marker_position (BVAR (b, begv_marker)); - BUF_BEGV_BYTE (b) = marker_byte_position (BVAR (b, begv_marker)); - } - if (! NILP (BVAR (b, zv_marker))) - { - BUF_ZV (b) = marker_position (BVAR (b, zv_marker)); - BUF_ZV_BYTE (b) = marker_byte_position (BVAR (b, zv_marker)); - } + fetch_buffer_markers (b); /* Look down buffer's list of local Lisp variables to find and update any that forward into C variables. */ @@ -1876,50 +1890,13 @@ set_buffer_temp (struct buffer *b) old_buf = current_buffer; current_buffer = b; - if (old_buf) - { - /* If the old current buffer has markers to record PT, BEGV and ZV - when it is not current, update them now. */ - if (! NILP (BVAR (old_buf, pt_marker))) - { - Lisp_Object obuf; - XSETBUFFER (obuf, old_buf); - set_marker_both (BVAR (old_buf, pt_marker), obuf, - BUF_PT (old_buf), BUF_PT_BYTE (old_buf)); - } - if (! NILP (BVAR (old_buf, begv_marker))) - { - Lisp_Object obuf; - XSETBUFFER (obuf, old_buf); - set_marker_both (BVAR (old_buf, begv_marker), obuf, - BUF_BEGV (old_buf), BUF_BEGV_BYTE (old_buf)); - } - if (! NILP (BVAR (old_buf, zv_marker))) - { - Lisp_Object obuf; - XSETBUFFER (obuf, old_buf); - set_marker_both (BVAR (old_buf, zv_marker), obuf, - BUF_ZV (old_buf), BUF_ZV_BYTE (old_buf)); - } - } + /* If the old current buffer has markers to record PT, BEGV and ZV + when it is not current, update them now. */ + record_buffer_markers (old_buf); /* If the new current buffer has markers to record PT, BEGV and ZV when it is not current, fetch them now. */ - if (! NILP (BVAR (b, pt_marker))) - { - BUF_PT (b) = marker_position (BVAR (b, pt_marker)); - BUF_PT_BYTE (b) = marker_byte_position (BVAR (b, pt_marker)); - } - if (! NILP (BVAR (b, begv_marker))) - { - BUF_BEGV (b) = marker_position (BVAR (b, begv_marker)); - BUF_BEGV_BYTE (b) = marker_byte_position (BVAR (b, begv_marker)); - } - if (! NILP (BVAR (b, zv_marker))) - { - BUF_ZV (b) = marker_position (BVAR (b, zv_marker)); - BUF_ZV_BYTE (b) = marker_byte_position (BVAR (b, zv_marker)); - } + fetch_buffer_markers (b); } DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0, diff --git a/src/buffer.h b/src/buffer.h index 65c7168d60a..0975d2e3adc 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -107,27 +107,46 @@ along with GNU Emacs. If not, see . */ #define BUF_BEG(buf) (BEG) #define BUF_BEG_BYTE(buf) (BEG_BYTE) -/* !!!FIXME: all the BUF_BEGV/BUF_ZV/BUF_PT macros are flawed: - on indirect (or base) buffers, that value is only correct if that buffer - is the current_buffer, or if the buffer's text hasn't been modified (via - an indirect buffer) since it was last current. */ +/* The BUF_BEGV[_BYTE], BUF_ZV[_BYTE], and BUF_PT[_BYTE] macros cannot + be used for assignment; use SET_BUF_* macros below for that. */ /* Position of beginning of accessible range of buffer. */ -#define BUF_BEGV(buf) ((buf)->begv) -#define BUF_BEGV_BYTE(buf) ((buf)->begv_byte) +#define BUF_BEGV(buf) \ + (buf == current_buffer ? BEGV \ + : NILP (BVAR (buf, begv_marker)) ? buf->begv \ + : marker_position (BVAR (buf, begv_marker))) + +#define BUF_BEGV_BYTE(buf) \ + (buf == current_buffer ? BEGV_BYTE \ + : NILP (BVAR (buf, begv_marker)) ? buf->begv_byte \ + : marker_byte_position (BVAR (buf, begv_marker))) /* Position of point in buffer. */ -#define BUF_PT(buf) ((buf)->pt) -#define BUF_PT_BYTE(buf) ((buf)->pt_byte) +#define BUF_PT(buf) \ + (buf == current_buffer ? PT \ + : NILP (BVAR (buf, pt_marker)) ? buf->pt \ + : marker_position (BVAR (buf, pt_marker))) + +#define BUF_PT_BYTE(buf) \ + (buf == current_buffer ? PT_BYTE \ + : NILP (BVAR (buf, pt_marker)) ? buf->pt_byte \ + : marker_byte_position (BVAR (buf, pt_marker))) + +/* Position of end of accessible range of buffer. */ +#define BUF_ZV(buf) \ + (buf == current_buffer ? ZV \ + : NILP (BVAR (buf, zv_marker)) ? buf->zv \ + : marker_position (BVAR (buf, zv_marker))) + +#define BUF_ZV_BYTE(buf) \ + (buf == current_buffer ? ZV_BYTE \ + : NILP (BVAR (buf, zv_marker)) ? buf->zv_byte \ + : marker_byte_position (BVAR (buf, zv_marker))) /* Position of gap in buffer. */ #define BUF_GPT(buf) ((buf)->text->gpt) #define BUF_GPT_BYTE(buf) ((buf)->text->gpt_byte) -/* Position of end of accessible range of buffer. */ -#define BUF_ZV(buf) ((buf)->zv) -#define BUF_ZV_BYTE(buf) ((buf)->zv_byte) - /* Position of end of buffer. */ #define BUF_Z(buf) ((buf)->text->z) #define BUF_Z_BYTE(buf) ((buf)->text->z_byte) @@ -235,8 +254,6 @@ extern void enlarge_buffer_text (struct buffer *, EMACS_INT); /* Macros for setting the BEGV, ZV or PT of a given buffer. - SET_BUF_PT* seet to be redundant. Get rid of them? - The ..._BOTH macros take both a charpos and a bytepos, which must correspond to each other. diff --git a/src/insdel.c b/src/insdel.c index 7fcf9522a33..bdf6aff1717 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -411,9 +411,7 @@ adjust_markers_for_insert (EMACS_INT from, EMACS_INT from_byte, static void adjust_point (EMACS_INT nchars, EMACS_INT nbytes) { - BUF_PT (current_buffer) += nchars; - BUF_PT_BYTE (current_buffer) += nbytes; - + SET_BUF_PT_BOTH (current_buffer, PT + nchars, PT_BYTE + nbytes); /* In a single-byte buffer, the two positions must be equal. */ eassert (PT_BYTE >= PT && PT_BYTE - PT <= ZV_BYTE - ZV); } diff --git a/src/intervals.c b/src/intervals.c index 6aee6e9d7fa..12b2789cc77 100644 --- a/src/intervals.c +++ b/src/intervals.c @@ -1892,8 +1892,7 @@ temp_set_point_both (struct buffer *buffer, if (charpos > BUF_ZV (buffer) || charpos < BUF_BEGV (buffer)) abort (); - BUF_PT_BYTE (buffer) = bytepos; - BUF_PT (buffer) = charpos; + SET_BUF_PT_BOTH (buffer, charpos, bytepos); } /* Set point "temporarily", without checking any text properties. */ @@ -2312,10 +2311,9 @@ get_local_map (register EMACS_INT position, register struct buffer *buffer, old_zv = BUF_ZV (buffer); old_begv_byte = BUF_BEGV_BYTE (buffer); old_zv_byte = BUF_ZV_BYTE (buffer); - BUF_BEGV (buffer) = BUF_BEG (buffer); - BUF_ZV (buffer) = BUF_Z (buffer); - BUF_BEGV_BYTE (buffer) = BUF_BEG_BYTE (buffer); - BUF_ZV_BYTE (buffer) = BUF_Z_BYTE (buffer); + + SET_BUF_BEGV_BOTH (buffer, BUF_BEG (buffer), BUF_BEG_BYTE (buffer)); + SET_BUF_ZV_BOTH (buffer, BUF_Z (buffer), BUF_Z_BYTE (buffer)); XSETFASTINT (lispy_position, position); XSETBUFFER (lispy_buffer, buffer); @@ -2329,10 +2327,8 @@ get_local_map (register EMACS_INT position, register struct buffer *buffer, if (NILP (prop)) prop = get_pos_property (lispy_position, type, lispy_buffer); - BUF_BEGV (buffer) = old_begv; - BUF_ZV (buffer) = old_zv; - BUF_BEGV_BYTE (buffer) = old_begv_byte; - BUF_ZV_BYTE (buffer) = old_zv_byte; + SET_BUF_BEGV_BOTH (buffer, old_begv, old_begv_byte); + SET_BUF_ZV_BOTH (buffer, old_zv, old_zv_byte); /* Use the local map only if it is valid. */ prop = get_keymap (prop, 0, 0); diff --git a/src/lread.c b/src/lread.c index 8a5f6ecd691..3c5b627f98c 100644 --- a/src/lread.c +++ b/src/lread.c @@ -368,15 +368,15 @@ unreadchar (Lisp_Object readcharfun, int c) else if (BUFFERP (readcharfun)) { struct buffer *b = XBUFFER (readcharfun); + EMACS_INT charpos = BUF_PT (b); EMACS_INT bytepos = BUF_PT_BYTE (b); - BUF_PT (b)--; if (! NILP (BVAR (b, enable_multibyte_characters))) BUF_DEC_POS (b, bytepos); else bytepos--; - BUF_PT_BYTE (b) = bytepos; + SET_BUF_PT_BOTH (b, charpos - 1, bytepos); } else if (MARKERP (readcharfun)) { diff --git a/src/xdisp.c b/src/xdisp.c index f2477a2eca5..a7955f41e0c 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -10909,7 +10909,7 @@ hscroll_window_tree (Lisp_Object window) current_buffer = XBUFFER (w->buffer); if (w == XWINDOW (selected_window)) - pt = BUF_PT (current_buffer); + pt = PT; else { pt = marker_position (w->pointm); @@ -11347,7 +11347,7 @@ reconsider_clip_changes (struct window *w, struct buffer *b) EMACS_INT pt; if (w == XWINDOW (selected_window)) - pt = BUF_PT (current_buffer); + pt = PT; else pt = marker_position (w->pointm);