calc-undo.el 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. ;;; calc-undo.el --- undo functions for Calc
  2. ;; Copyright (C) 1990-1993, 2001-2012 Free Software Foundation, Inc.
  3. ;; Author: David Gillespie <daveg@synaptics.com>
  4. ;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;; Code:
  18. ;; This file is autoloaded from calc-ext.el.
  19. (require 'calc-ext)
  20. (require 'calc-macs)
  21. ;;; Undo.
  22. ;;;###autoload
  23. (defun calc-undo (n)
  24. (interactive "p")
  25. (when calc-executing-macro
  26. (error "Use C-x e, not X, to run a keyboard macro that uses Undo"))
  27. (if (<= n 0)
  28. (if (< n 0)
  29. (calc-redo (- n))
  30. (calc-last-args 1))
  31. (calc-wrapper
  32. (when (null (nthcdr (1- n) calc-undo-list))
  33. (error "No further undo information available"))
  34. (setq calc-undo-list
  35. (prog1
  36. (nthcdr n calc-undo-list)
  37. (let ((saved-stack-top calc-stack-top))
  38. (let ((calc-stack-top 0))
  39. (calc-handle-undos calc-undo-list n))
  40. (setq calc-stack-top saved-stack-top))))
  41. (message "Undo!"))))
  42. (defun calc-handle-undos (cl n)
  43. (when (> n 0)
  44. (let ((old-redo calc-redo-list))
  45. (setq calc-undo-list nil)
  46. (calc-handle-undo (car cl))
  47. (setq calc-redo-list (append calc-undo-list old-redo)))
  48. (calc-handle-undos (cdr cl) (1- n))))
  49. (defun calc-handle-undo (list)
  50. (when list
  51. (let ((action (car list)))
  52. (cond
  53. ((eq (car action) 'push)
  54. (calc-pop-stack 1 (nth 1 action) t))
  55. ((eq (car action) 'pop)
  56. (calc-push-list (nth 2 action) (nth 1 action)))
  57. ((eq (car action) 'set)
  58. (calc-record-undo (list 'set (nth 1 action)
  59. (symbol-value (nth 1 action))))
  60. (set (nth 1 action) (nth 2 action)))
  61. ((eq (car action) 'store)
  62. (let ((v (intern (nth 1 action))))
  63. (calc-record-undo (list 'store (nth 1 action)
  64. (and (boundp v) (symbol-value v))))
  65. (if (y-or-n-p (format "Un-store variable %s? "
  66. (calc-var-name (nth 1 action))))
  67. (progn
  68. (if (nth 2 action)
  69. (set v (nth 2 action))
  70. (makunbound v))
  71. (calc-refresh-evaltos v)))))
  72. ((eq (car action) 'eval)
  73. (calc-record-undo (append (list 'eval (nth 2 action) (nth 1 action))
  74. (cdr (cdr (cdr action)))))
  75. (apply (nth 1 action) (cdr (cdr (cdr action))))))
  76. (calc-handle-undo (cdr list)))))
  77. (defun calc-redo (n)
  78. (interactive "p")
  79. (when calc-executing-macro
  80. (error "Use C-x e, not X, to run a keyboard macro that uses Redo"))
  81. (if (<= n 0)
  82. (calc-undo (- n))
  83. (calc-wrapper
  84. (when (null (nthcdr (1- n) calc-redo-list))
  85. (error "Unable to redo"))
  86. (setq calc-redo-list
  87. (prog1
  88. (nthcdr n calc-redo-list)
  89. (let ((saved-stack-top calc-stack-top))
  90. (let ((calc-stack-top 0))
  91. (calc-handle-redos calc-redo-list n))
  92. (setq calc-stack-top saved-stack-top))))
  93. (message "Redo!"))))
  94. (defun calc-handle-redos (cl n)
  95. (when (> n 0)
  96. (let ((old-undo calc-undo-list))
  97. (setq calc-undo-list nil)
  98. (calc-handle-undo (car cl))
  99. (setq calc-undo-list (append calc-undo-list old-undo)))
  100. (calc-handle-redos (cdr cl) (1- n))))
  101. (defun calc-last-args (n)
  102. (interactive "p")
  103. (when calc-executing-macro
  104. (error "Use C-x e, not X, to run a keyboard macro that uses last-args"))
  105. (calc-wrapper
  106. (let ((urec (calc-find-last-x calc-undo-list n)))
  107. (if urec
  108. (calc-handle-last-x urec)
  109. (error "Not enough undo information available")))))
  110. (defun calc-handle-last-x (list)
  111. (when list
  112. (let ((action (car list)))
  113. (if (eq (car action) 'pop)
  114. (calc-pop-push-record-list 0 "larg"
  115. (delq 'top-of-stack (nth 2 action))))
  116. (calc-handle-last-x (cdr list)))))
  117. (defun calc-find-last-x (ul n)
  118. (when ul
  119. (if (calc-undo-does-pushes (car ul))
  120. (if (<= n 1)
  121. (car ul)
  122. (calc-find-last-x (cdr ul) (1- n)))
  123. (calc-find-last-x (cdr ul) n))))
  124. (defun calc-undo-does-pushes (list)
  125. (and list
  126. (or (eq (car (car list)) 'pop)
  127. (calc-undo-does-pushes (cdr list)))))
  128. (provide 'calc-undo)
  129. ;;; calc-undo.el ends here