[Phemlock-cvs] CVS update: phemlock/src/new-undo.lisp

Aleksandar Bakic abakic at common-lisp.net
Thu Dec 23 23:58:28 UTC 2004


Update of /project/phemlock/cvsroot/phemlock/src
In directory common-lisp.net:/tmp/cvs-serv12917/src

Modified Files:
	new-undo.lisp 
Log Message:
Identified initial, partial "undo protocol".

Date: Fri Dec 24 00:58:26 2004
Author: abakic

Index: phemlock/src/new-undo.lisp
diff -u phemlock/src/new-undo.lisp:1.1.1.1 phemlock/src/new-undo.lisp:1.2
--- phemlock/src/new-undo.lisp:1.1.1.1	Fri Jul  9 15:37:45 2004
+++ phemlock/src/new-undo.lisp	Fri Dec 24 00:58:24 2004
@@ -4,24 +4,26 @@
 
 ;;; Ouch! this all isn't _that_ easy.
 
-(defmacro add-logging (attr)
-  `(defmethod (setf ,attr) :around (new-value line)
-    (let ((old (,attr line)))
-      (push `(,',attr ,line ,old ,new-value) *log*))
-    (call-next-method)))
-
-(add-logging line-previous)
-(add-logging line-next)
-(add-logging mark-line)
-
-(defun dada ()
-  (let ((log *log*)
-        (*log* nil))
-    (dolist (k log)
-      (destructuring-bind (slot object old new) k
-        (funcall (fdefinition `(setf ,slot)) old object)))))
+;; (defmacro add-logging (attr)
+;;   `(defmethod (setf ,attr) :around (new-value line)
+;;     (let ((old (,attr line)))
+;;       (push `(,',attr ,line ,old ,new-value) *log*))
+;;     (call-next-method)))
+
+;; (add-logging line-previous)
+;; (add-logging line-next)
+;; (add-logging mark-line)
+
+;; (defun dada ()
+;;   (let ((log *log*)
+;;         (*log* nil))
+;;     (dolist (k log)
+;;       (destructuring-bind (slot object old new) k
+;;         (funcall (fdefinition `(setf ,slot)) old object)))))
 ;;;;
 
+(defvar *performing-undo* nil)
+
 (defun mark-position (mark)
   (let ((line-no 0)
         (line (mark-line mark)))
@@ -32,30 +34,105 @@
     (list (line-buffer (mark-line mark))
           line-no (mark-charpos mark))))
 
+;;; below, I am not quite sure about left vs. right inserting --amb
+
 (defmethod insert-character :around (mark character)
-  (push `(insert-character ,(mark-position mark) ,character)
-        *log*)
-  (call-next-method))
+  (with-mark ((start mark :right-inserting))
+    (prog1
+	(call-next-method)
+      (unless (or *performing-undo*
+		  (eq (line-buffer (mark-line mark)) *echo-area-buffer*))
+	(push `(delete-characters ,(mark-position start)) *log*)))))
 
 (defmethod insert-string :around (mark string &optional (start 0) (end (length string)))
-  (push `(insert-string ,(mark-position mark) ,(subseq string start end))
-        *log*)
-  (call-next-method))
+  (if (car (mark-position mark)) ; used with kill-ring?
+      (progn
+	(with-mark ((start mark :right-inserting)
+		    (end mark :left-inserting))
+	  (prog1
+	      (call-next-method)
+	    (unless (or *performing-undo*
+			(eq (line-buffer (mark-line mark)) *echo-area-buffer*))
+	      (push
+	       `(delete-region ,(mark-position start) ,(mark-position end))
+	       *log*)))))
+      (call-next-method)))
+
+(defmethod insert-region :around (mark region)
+  (with-mark ((start mark :right-inserting)
+	      (end mark :left-inserting))
+    (prog1
+	(call-next-method)
+      (unless (or *performing-undo*
+		  (eq (line-buffer (mark-line mark)) *echo-area-buffer*))
+	(push
+	 `(delete-region ,(mark-position start) ,(mark-position end))
+	 *log*)))))
 
 (defmethod delete-characters :around (mark &optional (n 1))
-  (push `(delete-characters ,(mark-position mark) ,n)
-        *log*)
-  (call-next-method))
-
-(defun dada (q)
-  (dolist (k q)
-    (ecase (car k)
-      (insert-character
-       (destructuring-bind ((buffer line-no char-pos) char) (cdr k)
-         (delete-characters (position-mark buffer line-no char-pos)))))))
+  (with-mark ((start mark :right-inserting)
+	      (end mark :left-inserting))
+    (character-offset end n)
+    (let ((string (region-to-string (region start end))))
+      (prog1
+	  (call-next-method)
+	(unless (or *performing-undo*
+		    (eq (line-buffer (mark-line mark)) *echo-area-buffer*))
+	  (push
+	   `(insert-string ,(mark-position start) ,string)
+	   *log*))))))
+
+(defmethod delete-region :around (region)
+  (with-mark ((start (region-start region) :right-inserting)
+	      (end (region-end region) :left-inserting))
+    (let ((string (region-to-string region)))
+      (prog1
+	  (call-next-method)
+	(unless (or *performing-undo*
+		    (eq (line-buffer (mark-line (region-start region)))
+			*echo-area-buffer*))
+	  (push
+	   `(insert-string ,(mark-position start) ,string)
+	   *log*))))))
+
+(defmethod delete-and-save-region :around (region)
+  (with-mark ((start (region-start region) :right-inserting)
+	      (end (region-end region) :left-inserting))
+    (let ((string (region-to-string region)))
+      (prog1
+	  (call-next-method)
+	(unless (or *performing-undo*
+		    (eq (line-buffer (mark-line (region-start region)))
+			*echo-area-buffer*))
+	  (push
+	   `(insert-string ,(mark-position start) ,string)
+	   *log*))))))
+
+(defun dada ()
+  (let ((*performing-undo* t))
+    (do ((k (pop *log*) (pop *log*)))
+	((null k))
+      (undo k))))
+
+(defun undo (k)
+  (ecase (car k)
+    (delete-characters
+     (destructuring-bind ((buffer line-no char-pos)) (cdr k)
+       (delete-characters (position-mark buffer line-no char-pos))))
+    (delete-region
+     (destructuring-bind ((buffer1 line-no1 char-pos1)
+			  (buffer2 line-no2 char-pos2)) (cdr k)
+       (delete-region
+	(region (position-mark buffer1 line-no1 char-pos1)
+		(position-mark buffer2 line-no2 char-pos2)))))
+    (insert-string
+     (destructuring-bind ((buffer line-no char-pos) string) (cdr k)
+       (insert-string (position-mark buffer line-no char-pos) string)))))
 
 (defun position-mark (buffer line-no char-pos)
   (let ((line (mark-line (buffer-start-mark buffer))))
     (dotimes (i line-no)
-      (setf line (line-next line)))
+      (if line
+	(setf line (line-next line))
+	(error "Line is NIL")))
     (mark line char-pos)))




More information about the Phemlock-cvs mailing list