X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/a7a39468d688c006f26b8fb804ac87fc7f4fde68..71c44c04bb996abe77db8efd88255fde06532b10:/src/undo.c diff --git a/src/undo.c b/src/undo.c index b4e16bfd0e..2d491a4122 100644 --- a/src/undo.c +++ b/src/undo.c @@ -1,13 +1,13 @@ /* undo handling for GNU Emacs. - Copyright (C) 1990, 1993, 1994, 2000, 2002, 2004, 2005 - Free Software Foundation, Inc. + Copyright (C) 1990, 1993, 1994, 2000, 2001, 2002, 2003, 2004, + 2005, 2006, 2007, 2008, 2009, 2010 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 2, 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,15 +15,15 @@ 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., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +along with GNU Emacs. If not, see . */ #include +#include #include "lisp.h" #include "buffer.h" #include "commands.h" +#include "window.h" /* Limits controlling how much undo information to keep. */ @@ -37,7 +37,12 @@ Lisp_Object Vundo_outer_limit; Lisp_Object Vundo_outer_limit_function; /* Last buffer for which undo information was recorded. */ -Lisp_Object last_undo_buffer; +/* BEWARE: This is not traced by the GC, so never dereference it! */ +struct buffer *last_undo_buffer; + +/* Position of point last time we inserted a boundary. */ +struct buffer *last_boundary_buffer; +EMACS_INT last_boundary_position; Lisp_Object Qinhibit_read_only; @@ -52,25 +57,37 @@ Lisp_Object Qapply; an undo-boundary. */ Lisp_Object pending_boundary; +/* Nonzero means do not record point in record_point. */ + +int undo_inhibit_record_point; + /* Record point as it was at beginning of this command (if necessary) - And prepare the undo info for recording a change. + and prepare the undo info for recording a change. PT is the position of point that will naturally occur as a result of the undo record that will be added just after this command terminates. */ static void -record_point (pt) - int pt; +record_point (int pt) { int at_boundary; + /* Don't record position of pt when undo_inhibit_record_point holds. */ + if (undo_inhibit_record_point) + return; + /* Allocate a cons cell to be the undo boundary after this command. */ if (NILP (pending_boundary)) pending_boundary = Fcons (Qnil, Qnil); - if (!BUFFERP (last_undo_buffer) - || current_buffer != XBUFFER (last_undo_buffer)) + if ((current_buffer != last_undo_buffer) + /* Don't call Fundo_boundary for the first change. Otherwise we + risk overwriting last_boundary_position in Fundo_boundary with + PT of the current buffer and as a consequence not insert an + undo boundary because last_boundary_position will equal pt in + the test at the end of the present function (Bug#731). */ + && (MODIFF > SAVE_MODIFF)) Fundo_boundary (); - XSETBUFFER (last_undo_buffer, current_buffer); + last_undo_buffer = current_buffer; if (CONSP (current_buffer->undo_list)) { @@ -100,12 +117,10 @@ record_point (pt) /* If we are just after an undo boundary, and point wasn't at start of deleted range, record where it was. */ if (at_boundary - && last_point_position != pt - /* If we're called from batch mode, this could be nil. */ - && BUFFERP (last_point_position_buffer) - && current_buffer == XBUFFER (last_point_position_buffer)) + && current_buffer == last_boundary_buffer + && last_boundary_position != pt) current_buffer->undo_list - = Fcons (make_number (last_point_position), current_buffer->undo_list); + = Fcons (make_number (last_boundary_position), current_buffer->undo_list); } /* Record an insertion that just happened or is about to happen, @@ -114,8 +129,7 @@ record_point (pt) because we don't need to record the contents.) */ void -record_insert (beg, length) - int beg, length; +record_insert (int beg, int length) { Lisp_Object lbeg, lend; @@ -150,9 +164,7 @@ record_insert (beg, length) of the characters in STRING, at location BEG. */ void -record_delete (beg, string) - int beg; - Lisp_Object string; +record_delete (int beg, Lisp_Object string) { Lisp_Object sbeg; @@ -180,9 +192,7 @@ record_delete (beg, string) won't be inverted automatically by undoing the buffer modification. */ void -record_marker_adjustment (marker, adjustment) - Lisp_Object marker; - int adjustment; +record_marker_adjustment (Lisp_Object marker, int adjustment) { if (EQ (current_buffer->undo_list, Qt)) return; @@ -191,10 +201,9 @@ record_marker_adjustment (marker, adjustment) if (NILP (pending_boundary)) pending_boundary = Fcons (Qnil, Qnil); - if (!BUFFERP (last_undo_buffer) - || current_buffer != XBUFFER (last_undo_buffer)) + if (current_buffer != last_undo_buffer) Fundo_boundary (); - XSETBUFFER (last_undo_buffer, current_buffer); + last_undo_buffer = current_buffer; current_buffer->undo_list = Fcons (Fcons (marker, make_number (adjustment)), @@ -206,8 +215,7 @@ record_marker_adjustment (marker, adjustment) The replacement must not change the number of characters. */ void -record_change (beg, length) - int beg, length; +record_change (int beg, int length) { record_delete (beg, make_buffer_string (beg, beg + length, 1)); record_insert (beg, length); @@ -218,7 +226,7 @@ record_change (beg, length) we can tell whether it is obsolete because the file was saved again. */ void -record_first_change () +record_first_change (void) { Lisp_Object high, low; struct buffer *base_buffer = current_buffer; @@ -226,10 +234,9 @@ record_first_change () if (EQ (current_buffer->undo_list, Qt)) return; - if (!BUFFERP (last_undo_buffer) - || current_buffer != XBUFFER (last_undo_buffer)) + if (current_buffer != last_undo_buffer) Fundo_boundary (); - XSETBUFFER (last_undo_buffer, current_buffer); + last_undo_buffer = current_buffer; if (base_buffer->base_buffer) base_buffer = base_buffer->base_buffer; @@ -243,27 +250,25 @@ record_first_change () for LENGTH characters starting at position BEG in BUFFER. */ void -record_property_change (beg, length, prop, value, buffer) - int beg, length; - Lisp_Object prop, value, buffer; +record_property_change (int beg, int length, Lisp_Object prop, Lisp_Object value, Lisp_Object buffer) { Lisp_Object lbeg, lend, entry; - struct buffer *obuf = current_buffer; + struct buffer *obuf = current_buffer, *buf = XBUFFER (buffer); int boundary = 0; - if (EQ (XBUFFER (buffer)->undo_list, Qt)) + if (EQ (buf->undo_list, Qt)) return; /* Allocate a cons cell to be the undo boundary after this command. */ if (NILP (pending_boundary)) pending_boundary = Fcons (Qnil, Qnil); - if (!EQ (buffer, last_undo_buffer)) + if (buf != last_undo_buffer) boundary = 1; - last_undo_buffer = buffer; + last_undo_buffer = buf; /* Switch temporarily to the buffer that was changed. */ - current_buffer = XBUFFER (buffer); + current_buffer = buf; if (boundary) Fundo_boundary (); @@ -303,6 +308,8 @@ but another undo command will undo to the previous boundary. */) else current_buffer->undo_list = Fcons (Qnil, current_buffer->undo_list); } + last_boundary_position = PT; + last_boundary_buffer = current_buffer; return Qnil; } @@ -312,8 +319,7 @@ but another undo command will undo to the previous boundary. */) In some cases this works by calling undo-outer-limit-function. */ void -truncate_undo_list (b) - struct buffer *b; +truncate_undo_list (struct buffer *b) { Lisp_Object list; Lisp_Object prev, next, last_boundary; @@ -378,11 +384,12 @@ truncate_undo_list (b) && size_so_far > XINT (Vundo_outer_limit) && !NILP (Vundo_outer_limit_function)) { - Lisp_Object temp = last_undo_buffer; + Lisp_Object tem; + struct buffer *temp = last_undo_buffer; /* Normally the function this calls is undo-outer-limit-truncate. */ - if (! NILP (call1 (Vundo_outer_limit_function, - make_number (size_so_far)))) + tem = call1 (Vundo_outer_limit_function, make_number (size_so_far)); + if (! NILP (tem)) { /* The function is responsible for making any desired changes in buffer-undo-list. */ @@ -540,6 +547,8 @@ Return what remains of the list. */) beg = Fcar (cdr); end = Fcdr (cdr); + if (XINT (beg) < BEGV || XINT (end) > ZV) + error ("Changes to be undone are outside visible portion of buffer"); Fput_text_property (beg, end, prop, val, Qnil); } else if (INTEGERP (car) && INTEGERP (cdr)) @@ -646,17 +655,20 @@ Return what remains of the list. */) } void -syms_of_undo () +syms_of_undo (void) { - Qinhibit_read_only = intern ("inhibit-read-only"); + Qinhibit_read_only = intern_c_string ("inhibit-read-only"); staticpro (&Qinhibit_read_only); - Qapply = intern ("apply"); + Qapply = intern_c_string ("apply"); staticpro (&Qapply); pending_boundary = Qnil; staticpro (&pending_boundary); + last_undo_buffer = NULL; + last_boundary_buffer = NULL; + defsubr (&Sprimitive_undo); defsubr (&Sundo_boundary); @@ -668,7 +680,7 @@ value, the earlier commands that came before it are forgotten. The size is counted as the number of bytes occupied, which includes both saved text and other data. */); - undo_limit = 20000; + undo_limit = 80000; DEFVAR_INT ("undo-strong-limit", &undo_strong_limit, doc: /* Don't keep more than this much size of undo information. @@ -680,7 +692,7 @@ is never discarded for this reason. The size is counted as the number of bytes occupied, which includes both saved text and other data. */); - undo_strong_limit = 30000; + undo_strong_limit = 120000; DEFVAR_LISP ("undo-outer-limit", &Vundo_outer_limit, doc: /* Outer limit on size of undo information for one command. @@ -697,7 +709,7 @@ In fact, this calls the function which is the value of `undo-outer-limit-function' with one argument, the size. The text above describes the behavior of the function that variable usually specifies. */); - Vundo_outer_limit = make_number (3000000); + Vundo_outer_limit = make_number (12000000); DEFVAR_LISP ("undo-outer-limit-function", &Vundo_outer_limit_function, doc: /* Function to call when an undo list exceeds `undo-outer-limit'. @@ -709,6 +721,10 @@ If it returns nil, the other forms of truncation are done. Garbage collection is inhibited around the call to this function, so it must make sure not to do a lot of consing. */); Vundo_outer_limit_function = Qnil; + + DEFVAR_BOOL ("undo-inhibit-record-point", &undo_inhibit_record_point, + doc: /* Non-nil means do not record `point' in `buffer-undo-list'. */); + undo_inhibit_record_point = 0; } /* arch-tag: d546ee01-4aed-4ffb-bb8b-eefaae50d38a