aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorAaron S. Hawley2013-01-08 14:13:31 -0500
committerStefan Monnier2013-01-08 14:13:31 -0500
commit3bace969f386056cedeaba7ac3661167d6d60190 (patch)
treed4dddc07a157d2f2be055c1d0a879d23d292de68 /lisp
parent1c851e98b60d08404e5138b67ccf5b9d72fb4e47 (diff)
downloademacs-3bace969f386056cedeaba7ac3661167d6d60190.tar.gz
emacs-3bace969f386056cedeaba7ac3661167d6d60190.zip
* lisp/simple.el (primitive-undo): Move from undo.c.
* src/undo.c (Fprimitive_undo): Move to simple.el. (syms_of_undo): Remove declaration for Sprimitive_undo. * test/automated/undo-tests.el: New file.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog4
-rw-r--r--lisp/simple.el135
2 files changed, 139 insertions, 0 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 18481cb5aa5..72390d1ff67 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
12013-01-08 Aaron S. Hawley <aaron.s.hawley@gmail.com>
2
3 * simple.el (primitive-undo): Move from undo.c.
4
12013-01-08 Stefan Monnier <monnier@iro.umontreal.ca> 52013-01-08 Stefan Monnier <monnier@iro.umontreal.ca>
2 6
3 * vc/pcvs.el (cvs-cleanup-collection): Extend meaning of `rm-handled'. 7 * vc/pcvs.el (cvs-cleanup-collection): Extend meaning of `rm-handled'.
diff --git a/lisp/simple.el b/lisp/simple.el
index 19140cba496..86c71cd2130 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1979,6 +1979,141 @@ then call `undo-more' one or more times to undo them."
1979 (if (null pending-undo-list) 1979 (if (null pending-undo-list)
1980 (setq pending-undo-list t)))) 1980 (setq pending-undo-list t))))
1981 1981
1982(defun primitive-undo (n list)
1983 "Undo N records from the front of the list LIST.
1984Return what remains of the list."
1985
1986 ;; This is a good feature, but would make undo-start
1987 ;; unable to do what is expected.
1988 ;;(when (null (car (list)))
1989 ;; ;; If the head of the list is a boundary, it is the boundary
1990 ;; ;; preceding this command. Get rid of it and don't count it.
1991 ;; (setq list (cdr list))))
1992
1993 (let ((arg n)
1994 ;; In a writable buffer, enable undoing read-only text that is
1995 ;; so because of text properties.
1996 (inhibit-read-only t)
1997 ;; Don't let `intangible' properties interfere with undo.
1998 (inhibit-point-motion-hooks t)
1999 ;; We use oldlist only to check for EQ. ++kfs
2000 (oldlist buffer-undo-list)
2001 (did-apply nil)
2002 (next nil))
2003 (while (> arg 0)
2004 (while (and (consp list)
2005 (progn
2006 (setq next (car list))
2007 (setq list (cdr list))
2008 ;; Exit inner loop at undo boundary.
2009 (not (null next))))
2010 ;; Handle an integer by setting point to that value.
2011 (cond
2012 ((integerp next) (goto-char next))
2013 ((consp next)
2014 (let ((car (car next))
2015 (cdr (cdr next)))
2016 (cond
2017 ;; Element (t . TIME) records previous modtime.
2018 ;; Preserve any flag of NONEXISTENT_MODTIME_NSECS or
2019 ;; UNKNOWN_MODTIME_NSECS.
2020 ((eq t car)
2021 ;; If this records an obsolete save
2022 ;; (not matching the actual disk file)
2023 ;; then don't mark unmodified.
2024 (when (or (equal cdr (visited-file-modtime))
2025 (and (consp cdr)
2026 (equal (list (car cdr) (cdr cdr))
2027 (visited-file-modtime))))
2028 (when (fboundp 'unlock-buffer)
2029 (unlock-buffer))
2030 (set-buffer-modified-p nil)))
2031 ;; Element (nil PROP VAL BEG . END) is property change.
2032 ((eq nil car)
2033 (let ((beg (nth 2 cdr))
2034 (end (nthcdr 3 cdr))
2035 (prop (car cdr))
2036 (val (cadr cdr)))
2037 (when (or (> (point-min) beg)
2038 (< (point-max) end))
2039 (error "Changes to be undone are outside visible portion of buffer"))
2040 (put-text-property beg end prop val)))
2041 ((and (integerp car) (integerp cdr))
2042 ;; Element (BEG . END) means range was inserted.
2043 (when (or (< car (point-min))
2044 (> cdr (point-max)))
2045 (error "Changes to be undone are outside visible portion of buffer"))
2046 ;; Set point first thing, so that undoing this undo
2047 ;; does not send point back to where it is now.
2048 (goto-char car)
2049 (delete-region car cdr))
2050 ((eq car 'apply)
2051 ;; Element (apply FUN . ARGS) means call FUN to undo.
2052 (let ((currbuff (current-buffer))
2053 (car (car cdr))
2054 (cdr (cdr cdr)))
2055 (if (integerp car)
2056 ;; Long format: (apply DELTA START END FUN . ARGS).
2057 (let* ((delta car)
2058 (start (car cdr))
2059 (end (cadr cdr))
2060 (start-mark (copy-marker start nil))
2061 (end-mark (copy-marker end t))
2062 (cdr (cddr cdr))
2063 (fun (car cdr))
2064 (args (cdr cdr)))
2065 (apply fun args) ;; Use `save-current-buffer'?
2066 ;; Check that the function did what the entry
2067 ;; said it would do.
2068 (unless (and (eq start
2069 (marker-position start-mark))
2070 (eq (+ delta end)
2071 (marker-position end-mark)))
2072 (error "Changes to be undone by function different than announced"))
2073 (set-marker start-mark nil)
2074 (set-marker end-mark nil))
2075 (apply car cdr))
2076 (unless (eq currbuff (current-buffer))
2077 (error "Undo function switched buffer"))
2078 (setq did-apply t)))
2079 ((and (stringp car) (integerp cdr))
2080 ;; Element (STRING . POS) means STRING was deleted.
2081 (let ((membuf car)
2082 (pos cdr))
2083 (when (or (< (abs pos) (point-min))
2084 (> (abs pos) (point-max)))
2085 (error "Changes to be undone are outside visible portion of buffer"))
2086 (if (< pos 0)
2087 (progn
2088 (goto-char (- pos))
2089 (insert membuf))
2090 (goto-char pos)
2091 ;; Now that we record marker adjustments
2092 ;; (caused by deletion) for undo,
2093 ;; we should always insert after markers,
2094 ;; so that undoing the marker adjustments
2095 ;; put the markers back in the right place.
2096 (insert membuf)
2097 (goto-char pos))))
2098 ((and (markerp car) (integerp cdr))
2099 ;; (MARKER . INTEGER) means a marker MARKER
2100 ;; was adjusted by INTEGER.
2101 (when (marker-buffer car)
2102 (set-marker car
2103 (- (marker-position car) cdr)
2104 (marker-buffer car))))
2105 (t (error "Unrecognized entry in undo list %S" next)))))
2106 (t (error "Unrecognized entry in undo list %S" next))))
2107 (setq arg (1- arg)))
2108 ;; Make sure an apply entry produces at least one undo entry,
2109 ;; so the test in `undo' for continuing an undo series
2110 ;; will work right.
2111 (if (and did-apply
2112 (eq oldlist buffer-undo-list))
2113 (setq buffer-undo-list
2114 (cons (list 'apply 'cdr nil) buffer-undo-list))))
2115 list)
2116
1982;; Deep copy of a list 2117;; Deep copy of a list
1983(defun undo-copy-list (list) 2118(defun undo-copy-list (list)
1984 "Make a copy of undo list LIST." 2119 "Make a copy of undo list LIST."