X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/e145a7fe95fb8f97407d125f94653ef95e42696d..fe41ae9e008dffa0e7a7c44dea558b57b3178d9c:/src/insdel.c diff --git a/src/insdel.c b/src/insdel.c index 3c7bc4b8bd..814d1571d3 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -1,13 +1,14 @@ /* Buffer insertion/deletion and gap motion for GNU Emacs. Copyright (C) 1985, 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ #include @@ -415,13 +414,8 @@ adjust_markers_for_insert (from, from_byte, to, to_byte, before_markers) for (m = BUF_MARKERS (current_buffer); m; m = m->next) { - /* In a single-byte buffer, a marker's two positions must be - equal. */ - if (Z == Z_BYTE) - { - if (m->charpos != m->bytepos) - abort (); - } + eassert (m->bytepos >= m->charpos + && m->bytepos - m->charpos <= Z_BYTE - Z); if (m->bytepos == from_byte) { @@ -468,9 +462,7 @@ adjust_point (nchars, nbytes) BUF_PT_BYTE (current_buffer) += nbytes; /* In a single-byte buffer, the two positions must be equal. */ - if (ZV == ZV_BYTE - && PT != PT_BYTE) - abort (); + eassert (PT_BYTE >= PT && PT_BYTE - PT <= ZV_BYTE - ZV); } /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of @@ -663,8 +655,8 @@ copy_text (from_addr, to_addr, nbytes, { int thislen, c; c = STRING_CHAR_AND_LENGTH (from_addr, bytes_left, thislen); - if (!ASCII_CHAR_P (c)) - c = multibyte_char_to_unibyte (c, tbl); + if (! ASCII_CHAR_P (c)) + c &= 0xFF; *to_addr++ = c; from_addr += thislen; bytes_left -= thislen; @@ -1178,7 +1170,7 @@ insert_from_string_1 (string, pos, pos_byte, nchars, nbytes, void insert_from_gap (nchars, nbytes) - register int nchars, nbytes; + register EMACS_INT nchars, nbytes; { if (NILP (current_buffer->enable_multibyte_characters)) nchars = nbytes; @@ -1358,7 +1350,7 @@ insert_from_buffer_1 (buf, from, nchars, inherit) /* Get the intervals for the part of the string we are inserting. */ intervals = BUF_INTERVALS (buf); - if (outgoing_nbytes < BUF_Z_BYTE (buf) - BUF_BEG_BYTE (buf)) + if (nchars < BUF_Z (buf) - BUF_BEG (buf)) { if (buf == current_buffer && PT <= from) from += nchars; @@ -2014,7 +2006,10 @@ del_range_2 (from, from_byte, to, to_byte, ret_string) Z -= nchars_del; GPT = from; GPT_BYTE = from_byte; - if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ + if (GAP_SIZE > 0 && !current_buffer->text->inhibit_shrinking) + /* Put an anchor, unless called from decode_coding_object which + needs to access the previous gap contents. */ + *(GPT_ADDR) = 0; if (GPT_BYTE < GPT) abort (); @@ -2170,6 +2165,21 @@ prepare_to_modify_buffer (start, end, preserve_ptr) #define FETCH_END \ (! NILP (end_marker) ? Fmarker_position (end_marker) : end) +/* Set a variable to nil if an error occurred. + Don't change the variable if there was no error. + VAL is a cons-cell (VARIABLE . NO-ERROR-FLAG). + VARIABLE is the variable to maybe set to nil. + NO-ERROR-FLAG is nil if there was an error, + anything else meaning no error (so this function does nothing). */ +Lisp_Object +reset_var_on_error (val) + Lisp_Object val; +{ + if (NILP (XCDR (val))) + Fset (XCAR (val), Qnil); + return Qnil; +} + /* Signal a change to the buffer immediately before it happens. START_INT and END_INT are the bounds of the text to be changed. @@ -2185,6 +2195,7 @@ signal_before_change (start_int, end_int, preserve_ptr) Lisp_Object start_marker, end_marker; Lisp_Object preserve_marker; struct gcpro gcpro1, gcpro2, gcpro3; + int count = SPECPDL_INDEX (); if (inhibit_modification_hooks) return; @@ -2196,6 +2207,8 @@ signal_before_change (start_int, end_int, preserve_ptr) end_marker = Qnil; GCPRO3 (preserve_marker, start_marker, end_marker); + specbind (Qinhibit_modification_hooks, Qt); + /* If buffer is unmodified, run a special hook for that case. */ if (SAVE_MODIFF >= MODIFF && !NILP (Vfirst_change_hook) @@ -2210,46 +2223,22 @@ signal_before_change (start_int, end_int, preserve_ptr) if (!NILP (Vbefore_change_functions)) { Lisp_Object args[3]; - Lisp_Object before_change_functions; - Lisp_Object after_change_functions; - struct gcpro gcpro1, gcpro2; - struct buffer *old = current_buffer; - struct buffer *new; + Lisp_Object rvoe_arg = Fcons (Qbefore_change_functions, Qnil); PRESERVE_VALUE; PRESERVE_START_END; - /* "Bind" before-change-functions and after-change-functions - to nil--but in a way that errors don't know about. - That way, if there's an error in them, they will stay nil. */ - before_change_functions = Vbefore_change_functions; - after_change_functions = Vafter_change_functions; - Vbefore_change_functions = Qnil; - Vafter_change_functions = Qnil; - GCPRO2 (before_change_functions, after_change_functions); + /* Mark before-change-functions to be reset to nil in case of error. */ + record_unwind_protect (reset_var_on_error, rvoe_arg); /* Actually run the hook functions. */ args[0] = Qbefore_change_functions; args[1] = FETCH_START; args[2] = FETCH_END; - run_hook_list_with_args (before_change_functions, 3, args); + Frun_hook_with_args (3, args); - /* "Unbind" the variables we "bound" to nil. Beware a - buffer-local hook which changes the buffer when run (e.g. W3). */ - if (old != current_buffer) - { - new = current_buffer; - set_buffer_internal (old); - Vbefore_change_functions = before_change_functions; - Vafter_change_functions = after_change_functions; - set_buffer_internal (new); - } - else - { - Vbefore_change_functions = before_change_functions; - Vafter_change_functions = after_change_functions; - } - UNGCPRO; + /* There was no error: unarm the reset_on_error. */ + XSETCDR (rvoe_arg, Qt); } if (current_buffer->overlays_before || current_buffer->overlays_after) @@ -2265,6 +2254,8 @@ signal_before_change (start_int, end_int, preserve_ptr) free_marker (end_marker); RESTORE_VALUE; UNGCPRO; + + unbind_to (count, Qnil); } /* Signal a change immediately after it happens. @@ -2278,6 +2269,7 @@ void signal_after_change (charpos, lendel, lenins) int charpos, lendel, lenins; { + int count = SPECPDL_INDEX (); if (inhibit_modification_hooks) return; @@ -2308,48 +2300,25 @@ signal_after_change (charpos, lendel, lenins) if (!NILP (combine_after_change_list)) Fcombine_after_change_execute (); + specbind (Qinhibit_modification_hooks, Qt); + if (!NILP (Vafter_change_functions)) { Lisp_Object args[4]; - Lisp_Object before_change_functions; - Lisp_Object after_change_functions; - struct buffer *old = current_buffer; - struct buffer *new; - struct gcpro gcpro1, gcpro2; - - /* "Bind" before-change-functions and after-change-functions - to nil--but in a way that errors don't know about. - That way, if there's an error in them, they will stay nil. */ - before_change_functions = Vbefore_change_functions; - after_change_functions = Vafter_change_functions; - Vbefore_change_functions = Qnil; - Vafter_change_functions = Qnil; - GCPRO2 (before_change_functions, after_change_functions); + Lisp_Object rvoe_arg = Fcons (Qafter_change_functions, Qnil); + + /* Mark after-change-functions to be reset to nil in case of error. */ + record_unwind_protect (reset_var_on_error, rvoe_arg); /* Actually run the hook functions. */ args[0] = Qafter_change_functions; XSETFASTINT (args[1], charpos); XSETFASTINT (args[2], charpos + lenins); XSETFASTINT (args[3], lendel); - run_hook_list_with_args (after_change_functions, - 4, args); + Frun_hook_with_args (4, args); - /* "Unbind" the variables we "bound" to nil. Beware a - buffer-local hook which changes the buffer when run (e.g. W3). */ - if (old != current_buffer) - { - new = current_buffer; - set_buffer_internal (old); - Vbefore_change_functions = before_change_functions; - Vafter_change_functions = after_change_functions; - set_buffer_internal (new); - } - else - { - Vbefore_change_functions = before_change_functions; - Vafter_change_functions = after_change_functions; - } - UNGCPRO; + /* There was no error: unarm the reset_on_error. */ + XSETCDR (rvoe_arg, Qt); } if (current_buffer->overlays_before || current_buffer->overlays_after) @@ -2365,6 +2334,8 @@ signal_after_change (charpos, lendel, lenins) if (lendel == 0) report_interval_modification (make_number (charpos), make_number (charpos + lenins)); + + unbind_to (count, Qnil); } Lisp_Object