X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/6eabc4c2f76441f11cc344891d3849ad3631ab15..739d627a477191703f57ca4cfbd1bf8dc25625f9:/src/insdel.c diff --git a/src/insdel.c b/src/insdel.c index 65d60b6b8e..2919c183ab 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -1,12 +1,13 @@ /* 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 + Free Software Foundation, Inc. This file is part of GNU Emacs. 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 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, @@ -24,7 +25,7 @@ Boston, MA 02110-1301, USA. */ #include "lisp.h" #include "intervals.h" #include "buffer.h" -#include "charset.h" +#include "character.h" #include "window.h" #include "blockinput.h" #include "region-cache.h" @@ -415,13 +416,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 +464,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 @@ -659,22 +653,11 @@ copy_text (from_addr, to_addr, nbytes, int bytes_left = nbytes; Lisp_Object tbl = Qnil; - /* We set the variable tbl to the reverse table of - Vnonascii_translation_table in advance. */ - if (CHAR_TABLE_P (Vnonascii_translation_table)) - { - tbl = Fchar_table_extra_slot (Vnonascii_translation_table, - make_number (0)); - if (!CHAR_TABLE_P (tbl)) - tbl = Qnil; - } - - /* Convert multibyte to single byte. */ while (bytes_left > 0) { int thislen, c; c = STRING_CHAR_AND_LENGTH (from_addr, bytes_left, thislen); - if (!SINGLE_BYTE_CHAR_P (c)) + if (!ASCII_CHAR_P (c)) c = multibyte_char_to_unibyte (c, tbl); *to_addr++ = c; from_addr += thislen; @@ -1180,6 +1163,50 @@ insert_from_string_1 (string, pos, pos_byte, nchars, nbytes, current_buffer, inherit); adjust_point (nchars, outgoing_nbytes); + + CHECK_MARKERS (); +} + +/* Insert a sequence of NCHARS chars which occupy NBYTES bytes + starting at GPT_ADDR. */ + +void +insert_from_gap (nchars, nbytes) + register EMACS_INT nchars, nbytes; +{ + if (NILP (current_buffer->enable_multibyte_characters)) + nchars = nbytes; + + record_insert (GPT, nchars); + MODIFF++; + + GAP_SIZE -= nbytes; + GPT += nchars; + ZV += nchars; + Z += nchars; + GPT_BYTE += nbytes; + ZV_BYTE += nbytes; + Z_BYTE += nbytes; + if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ + + if (GPT_BYTE < GPT) + abort (); + + adjust_overlays_for_insert (GPT - nchars, nchars); + adjust_markers_for_insert (GPT - nchars, GPT_BYTE - nbytes, + GPT, GPT_BYTE, 0); + + if (BUF_INTERVALS (current_buffer) != 0) + { + offset_intervals (current_buffer, GPT - nchars, nchars); + graft_intervals_into_buffer (NULL_INTERVAL, GPT - nchars, nchars, + current_buffer, 0); + } + + if (GPT - nchars < PT) + adjust_point (nchars, nbytes); + + CHECK_MARKERS (); } /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the @@ -2137,6 +2164,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. @@ -2152,6 +2194,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; @@ -2163,6 +2206,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) @@ -2177,46 +2222,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) @@ -2232,6 +2253,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. @@ -2245,6 +2268,7 @@ void signal_after_change (charpos, lendel, lenins) int charpos, lendel, lenins; { + int count = SPECPDL_INDEX (); if (inhibit_modification_hooks) return; @@ -2275,48 +2299,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) @@ -2332,6 +2333,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