/* undo handling for GNU Emacs.
- Copyright (C) 1990, 1993, 1994, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1993, 1994, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Emacs.
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. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
#include "lisp.h"
#include "buffer.h"
#include "commands.h"
+#include "window.h"
/* Limits controlling how much undo information to keep. */
Lisp_Object Qinhibit_read_only;
+/* Marker for function call undo list elements. */
+
+Lisp_Object Qapply;
+
/* The first time a command records something for undo.
it also allocates the undo-boundary object
which will be added to the list at the end of the command.
/* 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)
+ /* If we're called from batch mode, this could be nil. */
&& current_buffer == XBUFFER (last_point_position_buffer))
- current_buffer->undo_list
- = Fcons (make_number (last_point_position), current_buffer->undo_list);
+ {
+ /* If we have switched windows, use the point value
+ from the window we are in. */
+ if (! EQ (last_point_position_window, selected_window))
+ last_point_position = marker_position (XWINDOW (selected_window)->pointm);
+
+ if (last_point_position != pt)
+ current_buffer->undo_list
+ = Fcons (make_number (last_point_position), current_buffer->undo_list);
+ }
}
/* Record an insertion that just happened or is about to happen,
&& size_so_far > XINT (Vundo_outer_limit)
&& !NILP (Vundo_outer_limit_function))
{
- Lisp_Object temp = last_undo_buffer;
+ Lisp_Object temp = last_undo_buffer, tem;
/* 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. */
Lisp_Object next;
int count = SPECPDL_INDEX ();
register int arg;
+ Lisp_Object oldlist;
+ int did_apply = 0;
#if 0 /* This is a good feature, but would make undo-start
unable to do what is expected. */
arg = XINT (n);
next = Qnil;
GCPRO2 (next, list);
+ /* I don't think we need to gcpro oldlist, as we use it only
+ to check for EQ. ++kfs */
/* In a writable buffer, enable undoing read-only text that is so
because of text properties. */
/* Don't let `intangible' properties interfere with undo. */
specbind (Qinhibit_point_motion_hooks, Qt);
+ oldlist = current_buffer->undo_list;
+
while (arg > 0)
{
while (CONSP (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))
Fgoto_char (car);
Fdelete_region (car, cdr);
}
- else if (SYMBOLP (car))
+ else if (EQ (car, Qapply))
{
- Lisp_Object oldlist = current_buffer->undo_list;
- /* Element (FUNNAME . ARGS) means call FUNNAME to undo. */
- apply1 (car, cdr);
- /* Make sure this produces at least one undo entry,
- so the test in `undo' for continuing an undo series
- will work right. */
- if (EQ (oldlist, current_buffer->undo_list))
- current_buffer->undo_list
- = Fcons (list2 (Qcdr, Qnil), current_buffer->undo_list);
+ /* Element (apply FUN . ARGS) means call FUN to undo. */
+ struct buffer *save_buffer = current_buffer;
+
+ car = Fcar (cdr);
+ cdr = Fcdr (cdr);
+ if (INTEGERP (car))
+ {
+ /* Long format: (apply DELTA START END FUN . ARGS). */
+ Lisp_Object delta = car;
+ Lisp_Object start = Fcar (cdr);
+ Lisp_Object end = Fcar (Fcdr (cdr));
+ Lisp_Object start_mark = Fcopy_marker (start, Qnil);
+ Lisp_Object end_mark = Fcopy_marker (end, Qt);
+
+ cdr = Fcdr (Fcdr (cdr));
+ apply1 (Fcar (cdr), Fcdr (cdr));
+
+ /* Check that the function did what the entry said it
+ would do. */
+ if (!EQ (start, Fmarker_position (start_mark))
+ || (XINT (delta) + XINT (end)
+ != marker_position (end_mark)))
+ error ("Changes to be undone by function different than announced");
+ Fset_marker (start_mark, Qnil, Qnil);
+ Fset_marker (end_mark, Qnil, Qnil);
+ }
+ else
+ apply1 (car, cdr);
+
+ if (save_buffer != current_buffer)
+ error ("Undo function switched buffer");
+ did_apply = 1;
}
else if (STRINGP (car) && INTEGERP (cdr))
{
arg--;
}
+
+ /* Make sure an apply entry produces at least one undo entry,
+ so the test in `undo' for continuing an undo series
+ will work right. */
+ if (did_apply
+ && EQ (oldlist, current_buffer->undo_list))
+ current_buffer->undo_list
+ = Fcons (list3 (Qapply, Qcdr, Qnil), current_buffer->undo_list);
+
UNGCPRO;
return unbind_to (count, list);
}
Qinhibit_read_only = intern ("inhibit-read-only");
staticpro (&Qinhibit_read_only);
+ Qapply = intern ("apply");
+ staticpro (&Qapply);
+
pending_boundary = Qnil;
staticpro (&pending_boundary);
`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 (300000);
+ Vundo_outer_limit = make_number (3000000);
DEFVAR_LISP ("undo-outer-limit-function", &Vundo_outer_limit_function,
doc: /* Function to call when an undo list exceeds `undo-outer-limit'.