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