Merge from emacs-24; up to 2012-12-19T19:51:40Z!monnier@iro.umontreal.ca
[bpt/emacs.git] / lisp / calc / calc-yank.el
CommitLineData
3132f345
CW
1;;; calc-yank.el --- kill-ring functionality for Calc
2
ab422c4d 3;; Copyright (C) 1990-1993, 2001-2013 Free Software Foundation, Inc.
3132f345
CW
4
5;; Author: David Gillespie <daveg@synaptics.com>
e8fff8ed 6;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
136211a9
EZ
7
8;; This file is part of GNU Emacs.
9
662c9c64 10;; GNU Emacs is free software: you can redistribute it and/or modify
7c671b23 11;; it under the terms of the GNU General Public License as published by
662c9c64
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
7c671b23 14
136211a9 15;; GNU Emacs is distributed in the hope that it will be useful,
7c671b23
GM
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
662c9c64 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
136211a9 22
3132f345 23;;; Commentary:
136211a9 24
3132f345 25;;; Code:
136211a9
EZ
26
27;; This file is autoloaded from calc-ext.el.
136211a9 28
b1687f60 29(require 'calc-ext)
136211a9
EZ
30(require 'calc-macs)
31
136211a9
EZ
32;;; Kill ring commands.
33
34(defun calc-kill (nn &optional no-delete)
35 (interactive "P")
36 (if (eq major-mode 'calc-mode)
37 (calc-wrapper
38 (calc-force-refresh)
39 (calc-set-command-flag 'no-align)
40 (let ((num (max (calc-locate-cursor-element (point)) 1))
41 (n (prefix-numeric-value nn)))
42 (if (< n 0)
43 (progn
44 (if (eobp)
45 (setq num (1- num)))
46 (setq num (- num n)
47 n (- n))))
87bd269a 48 (calc-check-stack num)
136211a9
EZ
49 (let ((stuff (calc-top-list n (- num n -1))))
50 (calc-cursor-stack-index num)
51 (let ((first (point)))
52 (calc-cursor-stack-index (- num n))
53 (if (null nn)
54 (backward-char 1)) ; don't include newline for raw C-k
55 (copy-region-as-kill first (point))
56 (if (not no-delete)
57 (calc-pop-stack n (- num n -1))))
58 (setq calc-last-kill (cons (car kill-ring) stuff)))))
bf77c646 59 (kill-line nn)))
136211a9
EZ
60
61(defun calc-force-refresh ()
62 (if (or calc-executing-macro calc-display-dirty)
63 (let ((calc-executing-macro nil))
bf77c646 64 (calc-refresh))))
136211a9
EZ
65
66(defun calc-locate-cursor-element (pt)
67 (save-excursion
68 (goto-char (point-max))
bf77c646 69 (calc-locate-cursor-scan (- calc-stack-top) calc-stack pt)))
136211a9
EZ
70
71(defun calc-locate-cursor-scan (n stack pt)
72 (if (or (<= (point) pt)
73 (null stack))
74 n
75 (forward-line (- (nth 1 (car stack))))
bf77c646 76 (calc-locate-cursor-scan (1+ n) (cdr stack) pt)))
136211a9
EZ
77
78(defun calc-kill-region (top bot &optional no-delete)
79 (interactive "r")
80 (if (eq major-mode 'calc-mode)
81 (calc-wrapper
82 (calc-force-refresh)
83 (calc-set-command-flag 'no-align)
84 (let* ((top-num (calc-locate-cursor-element top))
87bd269a
JB
85 (top-pos (save-excursion
86 (calc-cursor-stack-index top-num)
87 (point)))
136211a9 88 (bot-num (calc-locate-cursor-element (1- bot)))
87bd269a
JB
89 (bot-pos (save-excursion
90 (calc-cursor-stack-index (max 0 (1- bot-num)))
91 (point)))
136211a9 92 (num (- top-num bot-num -1)))
87bd269a 93 (copy-region-as-kill top-pos bot-pos)
136211a9
EZ
94 (setq calc-last-kill (cons (car kill-ring)
95 (calc-top-list num bot-num)))
96 (if (not no-delete)
97 (calc-pop-stack num bot-num))))
98 (if no-delete
99 (copy-region-as-kill top bot)
bf77c646 100 (kill-region top bot))))
136211a9
EZ
101
102(defun calc-copy-as-kill (n)
103 (interactive "P")
bf77c646 104 (calc-kill n t))
136211a9
EZ
105
106(defun calc-copy-region-as-kill (top bot)
107 (interactive "r")
bf77c646 108 (calc-kill-region top bot t))
136211a9 109
2378f044
SM
110;; This function uses calc-last-kill if possible to get an exact result,
111;; otherwise it just parses the yanked string.
112;; Modified to use Emacs 19 extended concept of kill-ring. -- daveg 12/15/96
113;;;###autoload
136211a9
EZ
114(defun calc-yank ()
115 (interactive)
116 (calc-wrapper
117 (calc-pop-push-record-list
118 0 "yank"
119 (let ((thing (if (fboundp 'current-kill)
120 (current-kill 0 t)
121 (car kill-ring-yank-pointer))))
122 (if (eq (car-safe calc-last-kill) thing)
123 (cdr calc-last-kill)
124 (if (stringp thing)
125 (let ((val (math-read-exprs (calc-clean-newlines thing))))
126 (if (eq (car-safe val) 'error)
127 (progn
128 (setq val (math-read-exprs thing))
129 (if (eq (car-safe val) 'error)
130 (error "Bad format in yanked data")
131 val))
bf77c646 132 val))))))))
136211a9 133
c80e3b4a 134;;; The Calc set- and get-register commands are modified versions of functions
c8a991aa
JB
135;;; in register.el
136
137(defvar calc-register-alist nil
138 "Alist of elements (NAME . (TEXT . CALCVAL)).
139NAME is a character (a number).
140TEXT and CALCVAL are the TEXT and internal structure of stack entries.")
141
142(defun calc-set-register (register text calcval)
143 "Set the contents of the Calc register REGISTER to (TEXT . CALCVAL),
144as well as set the contents of the Emacs register REGISTER to TEXT."
145 (set-register register text)
146 (let ((aelt (assq register calc-register-alist)))
147 (if aelt
148 (setcdr aelt (cons text calcval))
149 (push (cons register (cons text calcval)) calc-register-alist))))
150
151(defun calc-get-register (reg)
152 "Return the CALCVAL portion of the contents of the Calc register REG,
153unless the TEXT portion doesn't match the contents of the Emacs register REG,
154in which case either return the contents of the Emacs register (if it is
155text) or `nil'."
156 (let ((cval (cdr (assq reg calc-register-alist)))
157 (val (cdr (assq reg register-alist))))
2e4daa0e
JB
158 (if (stringp val)
159 (if (and (stringp (car cval))
160 (string= (car cval) val))
c8a991aa
JB
161 (cdr cval)
162 val))))
163
164(defun calc-copy-to-register (register start end &optional delete-flag)
165 "Copy the lines in the region into register REGISTER.
166With prefix arg, delete as well."
167 (interactive "cCopy to register: \nr\nP")
168 (if (eq major-mode 'calc-mode)
169 (let* ((top-num (calc-locate-cursor-element start))
170 (top-pos (save-excursion
171 (calc-cursor-stack-index top-num)
172 (point)))
173 (bot-num (calc-locate-cursor-element (1- end)))
174 (bot-pos (save-excursion
175 (calc-cursor-stack-index (max 0 (1- bot-num)))
176 (point)))
177 (num (- top-num bot-num -1))
178 (str (buffer-substring top-pos bot-pos)))
179 (calc-set-register register str (calc-top-list num bot-num))
180 (if delete-flag
181 (calc-wrapper
182 (calc-pop-stack num bot-num))))
183 (copy-to-register register start end delete-flag)))
184
185(defun calc-insert-register (register)
186 "Insert the contents of register REGISTER."
187 (interactive "cInsert register: ")
188 (if (eq major-mode 'calc-mode)
189 (let ((val (calc-get-register register)))
190 (calc-wrapper
191 (calc-pop-push-record-list
192 0 "insr"
193 (if (not val)
194 (error "Bad format in register data")
195 (if (consp val)
196 val
197 (let ((nval (math-read-exprs (calc-clean-newlines val))))
198 (if (eq (car-safe nval) 'error)
199 (progn
200 (setq nval (math-read-exprs val))
201 (if (eq (car-safe nval) 'error)
202 (error "Bad format in register data")
203 nval))
204 nval)))))))
205 (insert-register register)))
206
207(defun calc-add-to-register (register start end prepend delete-flag)
208 "Add the lines in the region to register REGISTER.
c80e3b4a 209If PREPEND is non-nil, add them to the beginning of the register,
c8a991aa
JB
210otherwise the end. If DELETE-FLAG is non-nil, also delete the region."
211 (let* ((top-num (calc-locate-cursor-element start))
212 (top-pos (save-excursion
213 (calc-cursor-stack-index top-num)
214 (point)))
215 (bot-num (calc-locate-cursor-element (1- end)))
216 (bot-pos (save-excursion
217 (calc-cursor-stack-index (max 0 (1- bot-num)))
218 (point)))
219 (num (- top-num bot-num -1))
220 (str (buffer-substring top-pos bot-pos))
221 (calcval (calc-top-list num bot-num))
222 (cval (cdr (assq register calc-register-alist))))
223 (if (not cval)
224 (calc-set-register register str calcval)
225 (if prepend
226 (calc-set-register
227 register
228 (concat str (car cval))
229 (append calcval (cdr cval)))
230 (calc-set-register
231 register
232 (concat (car cval) str)
233 (append (cdr cval) calcval))))
234 (if delete-flag
235 (calc-wrapper
236 (calc-pop-stack num bot-num)))))
237
238(defun calc-append-to-register (register start end &optional delete-flag)
239 "Copy the lines in the region to the end of register REGISTER.
240With prefix arg, also delete the region."
241 (interactive "cAppend to register: \nr\nP")
242 (if (eq major-mode 'calc-mode)
243 (calc-add-to-register register start end nil delete-flag)
244 (append-to-register register start end delete-flag)))
c80e3b4a 245
c8a991aa
JB
246(defun calc-prepend-to-register (register start end &optional delete-flag)
247 "Copy the lines in the region to the beginning of register REGISTER.
248With prefix arg, also delete the region."
249 (interactive "cPrepend to register: \nr\nP")
250 (if (eq major-mode 'calc-mode)
251 (calc-add-to-register register start end t delete-flag)
252 (prepend-to-register register start end delete-flag)))
c80e3b4a 253
c8a991aa
JB
254
255
136211a9
EZ
256(defun calc-clean-newlines (s)
257 (cond
a1506d29 258
136211a9
EZ
259 ;; Omit leading/trailing whitespace
260 ((or (string-match "\\`[ \n\r]+\\([^\001]*\\)\\'" s)
261 (string-match "\\`\\([^\001]*\\)[ \n\r]+\\'" s))
262 (calc-clean-newlines (math-match-substring s 1)))
263
264 ;; Convert newlines to commas
265 ((string-match "\\`\\(.*\\)[\n\r]+\\([^\001]*\\)\\'" s)
266 (calc-clean-newlines (concat (math-match-substring s 1) ","
267 (math-match-substring s 2))))
a1506d29 268
bf77c646 269 (t s)))
136211a9
EZ
270
271
272(defun calc-do-grab-region (top bot arg)
3132f345
CW
273 (when (memq major-mode '(calc-mode calc-trail-mode))
274 (error "This command works only in a regular text buffer"))
136211a9
EZ
275 (let* ((from-buffer (current-buffer))
276 (calc-was-started (get-buffer-window "*Calculator*"))
277 (single nil)
278 data vals pos)
279 (if arg
280 (if (consp arg)
281 (setq single t)
282 (setq arg (prefix-numeric-value arg))
283 (if (= arg 0)
9b026d9f
GM
284 (setq top (point-at-bol)
285 bot (point-at-eol))
136211a9
EZ
286 (save-excursion
287 (setq top (point))
288 (forward-line arg)
289 (if (> arg 0)
290 (setq bot (point))
291 (setq bot top
292 top (point)))))))
293 (setq data (buffer-substring top bot))
294 (calc)
295 (if single
296 (setq vals (math-read-expr data))
297 (setq vals (math-read-expr (concat "[" data "]")))
298 (and (eq (car-safe vals) 'vec)
299 (= (length vals) 2)
300 (eq (car-safe (nth 1 vals)) 'vec)
301 (setq vals (nth 1 vals))))
302 (if (eq (car-safe vals) 'error)
303 (progn
304 (if calc-was-started
305 (pop-to-buffer from-buffer)
306 (calc-quit t)
307 (switch-to-buffer from-buffer))
308 (goto-char top)
309 (forward-char (+ (nth 1 vals) (if single 0 1)))
310 (error (nth 2 vals))))
311 (calc-slow-wrapper
bf77c646 312 (calc-enter-result 0 "grab" vals))))
136211a9
EZ
313
314
315(defun calc-do-grab-rectangle (top bot arg &optional reduce)
316 (and (memq major-mode '(calc-mode calc-trail-mode))
3132f345 317 (error "This command works only in a regular text buffer"))
136211a9
EZ
318 (let* ((col1 (save-excursion (goto-char top) (current-column)))
319 (col2 (save-excursion (goto-char bot) (current-column)))
320 (from-buffer (current-buffer))
321 (calc-was-started (get-buffer-window "*Calculator*"))
322 data mat vals lnum pt pos)
323 (if (= col1 col2)
324 (save-excursion
3132f345
CW
325 (unless (= col1 0)
326 (error "Point and mark must be at beginning of line, or define a rectangle"))
136211a9
EZ
327 (goto-char top)
328 (while (< (point) bot)
329 (setq pt (point))
330 (forward-line 1)
331 (setq data (cons (buffer-substring pt (1- (point))) data)))
332 (setq data (nreverse data)))
333 (setq data (extract-rectangle top bot)))
334 (calc)
335 (setq mat (list 'vec)
336 lnum 0)
3132f345
CW
337 (when arg
338 (setq arg (if (consp arg) 0 (prefix-numeric-value arg))))
136211a9
EZ
339 (while data
340 (if (natnump arg)
341 (progn
342 (if (= arg 0)
343 (setq arg 1000000))
344 (setq pos 0
345 vals (list 'vec))
346 (let ((w (length (car data)))
347 j v)
348 (while (< pos w)
349 (setq j (+ pos arg)
350 v (if (>= j w)
351 (math-read-expr (substring (car data) pos))
352 (math-read-expr (substring (car data) pos j))))
353 (if (eq (car-safe v) 'error)
354 (setq vals v w 0)
355 (setq vals (nconc vals (list v))
356 pos j)))))
357 (if (string-match "\\` *-?[0-9][0-9]?[0-9]?[0-9]?[0-9]?[0-9]? *\\'"
358 (car data))
ca9cbc31 359 (setq vals (list 'vec (string-to-number (car data))))
136211a9
EZ
360 (if (and (null arg)
361 (string-match "[[{][^][{}]*[]}]" (car data)))
362 (setq pos (match-beginning 0)
363 vals (math-read-expr (math-match-substring (car data) 0)))
364 (let ((s (if (string-match
365 "\\`\\([0-9]+:[ \t]\\)?\\(.*[^, \t]\\)[, \t]*\\'"
366 (car data))
367 (math-match-substring (car data) 2)
368 (car data))))
369 (setq pos -1
370 vals (math-read-expr (concat "[" s "]")))
371 (if (eq (car-safe vals) 'error)
372 (let ((v2 (math-read-expr s)))
3132f345
CW
373 (unless (eq (car-safe v2) 'error)
374 (setq vals (list 'vec v2)))))))))
136211a9
EZ
375 (if (eq (car-safe vals) 'error)
376 (progn
377 (if calc-was-started
378 (pop-to-buffer from-buffer)
379 (calc-quit t)
380 (switch-to-buffer from-buffer))
381 (goto-char top)
382 (forward-line lnum)
383 (forward-char (+ (nth 1 vals) (min col1 col2) pos))
384 (error (nth 2 vals))))
3132f345
CW
385 (unless (equal vals '(vec))
386 (setq mat (cons vals mat)))
136211a9
EZ
387 (setq data (cdr data)
388 lnum (1+ lnum)))
389 (calc-slow-wrapper
390 (if reduce
391 (calc-enter-result 0 "grb+" (list reduce '(var add var-add)
392 (nreverse mat)))
bf77c646 393 (calc-enter-result 0 "grab" (nreverse mat))))))
136211a9
EZ
394
395
396(defun calc-copy-to-buffer (nn)
397 "Copy the top of stack into an editing buffer."
398 (interactive "P")
399 (let ((thebuf (and (not (memq major-mode '(calc-mode calc-trail-mode)))
400 (current-buffer)))
401 (movept nil)
402 oldbuf newbuf)
403 (calc-wrapper
404 (save-excursion
405 (calc-force-refresh)
406 (let ((n (prefix-numeric-value nn))
407 (eat-lnums calc-line-numbering)
408 (big-offset (if (eq calc-language 'big) 1 0))
409 top bot)
410 (setq oldbuf (current-buffer)
411 newbuf (or thebuf
412 (calc-find-writable-buffer (buffer-list) 0)
413 (calc-find-writable-buffer (buffer-list) 1)
414 (error "No other buffer")))
415 (cond ((and (or (null nn)
416 (consp nn))
417 (= (calc-substack-height 0)
418 (- (1- (calc-substack-height 1)) big-offset)))
419 (calc-cursor-stack-index 1)
420 (if (looking-at
421 (if calc-line-numbering "[0-9]+: *[^ \n]" " *[^ \n]"))
422 (goto-char (1- (match-end 0))))
423 (setq eat-lnums nil
424 top (point))
425 (calc-cursor-stack-index 0)
426 (setq bot (- (1- (point)) big-offset)))
427 ((> n 0)
428 (calc-cursor-stack-index n)
429 (setq top (point))
430 (calc-cursor-stack-index 0)
431 (setq bot (- (point) big-offset)))
432 ((< n 0)
433 (calc-cursor-stack-index (- n))
434 (setq top (point))
435 (calc-cursor-stack-index (1- (- n)))
436 (setq bot (point)))
437 (t
438 (goto-char (point-min))
439 (forward-line 1)
440 (setq top (point))
441 (calc-cursor-stack-index 0)
442 (setq bot (point))))
6df9b6d7 443 (with-current-buffer newbuf
136211a9
EZ
444 (if (consp nn)
445 (kill-region (region-beginning) (region-end)))
446 (push-mark (point) t)
447 (if (and overwrite-mode (not (consp nn)))
6df9b6d7 448 (calc-overwrite-string (with-current-buffer oldbuf
136211a9
EZ
449 (buffer-substring top bot))
450 eat-lnums)
451 (or (bolp) (setq eat-lnums nil))
452 (insert-buffer-substring oldbuf top bot)
453 (and eat-lnums
454 (let ((n 1))
455 (while (and (> (point) (mark))
456 (progn
457 (forward-line -1)
458 (>= (point) (mark))))
459 (delete-char 4)
460 (setq n (1+ n)))
461 (forward-line n))))
3132f345
CW
462 (when thebuf
463 (setq movept (point)))
464 (when (get-buffer-window (current-buffer))
465 (set-window-point (get-buffer-window (current-buffer))
466 (point)))))))
467 (when movept
468 (goto-char movept))
469 (when (and (consp nn)
470 (not thebuf))
471 (calc-quit t)
472 (switch-to-buffer newbuf))))
136211a9
EZ
473
474(defun calc-overwrite-string (str eat-lnums)
3132f345
CW
475 (when (string-match "\n\\'" str)
476 (setq str (substring str 0 -1)))
477 (when eat-lnums
478 (setq str (substring str 4)))
136211a9
EZ
479 (if (and (string-match "\\`[-+]?[0-9.]+\\(e-?[0-9]+\\)?\\'" str)
480 (looking-at "[-+]?[0-9.]+\\(e-?[0-9]+\\)?"))
481 (progn
482 (delete-region (point) (match-end 0))
483 (insert str))
484 (let ((i 0))
485 (while (< i (length str))
e93c003e 486 (if (= (setq last-command-event (aref str i)) ?\n)
136211a9
EZ
487 (or (= i (1- (length str)))
488 (let ((pt (point)))
489 (end-of-line)
490 (delete-region pt (point))
491 (if (eobp)
492 (insert "\n")
493 (forward-char 1))
494 (if eat-lnums (setq i (+ i 4)))))
495 (self-insert-command 1))
bf77c646 496 (setq i (1+ i))))))
136211a9 497
2378f044
SM
498;; First, require that buffer is visible and does not begin with "*"
499;; Second, require only that it not begin with "*Calc"
136211a9
EZ
500(defun calc-find-writable-buffer (buf mode)
501 (and buf
502 (if (or (string-match "\\`\\( .*\\|\\*Calc.*\\)"
503 (buffer-name (car buf)))
504 (and (= mode 0)
505 (or (string-match "\\`\\*.*" (buffer-name (car buf)))
506 (not (get-buffer-window (car buf))))))
507 (calc-find-writable-buffer (cdr buf) mode)
bf77c646 508 (car buf))))
136211a9
EZ
509
510
511(defun calc-edit (n)
512 (interactive "p")
513 (calc-slow-wrapper
3132f345
CW
514 (when (eq n 0)
515 (setq n (calc-stack-size)))
136211a9
EZ
516 (let* ((flag nil)
517 (allow-ret (> n 1))
518 (list (math-showing-full-precision
519 (mapcar (if (> n 1)
520 (function (lambda (x)
521 (math-format-flat-expr x 0)))
522 (function
523 (lambda (x)
524 (if (math-vectorp x) (setq allow-ret t))
8f66f479 525 (math-format-nice-expr x (frame-width)))))
136211a9
EZ
526 (if (> n 0)
527 (calc-top-list n)
528 (calc-top-list 1 (- n)))))))
529 (calc-edit-mode (list 'calc-finish-stack-edit (or flag n)) allow-ret)
530 (while list
531 (insert (car list) "\n")
532 (setq list (cdr list)))))
bf77c646 533 (calc-show-edit-buffer))
136211a9
EZ
534
535(defun calc-alg-edit (str)
536 (calc-edit-mode '(calc-finish-stack-edit 0))
537 (calc-show-edit-buffer)
538 (insert str "\n")
539 (backward-char 1)
bf77c646 540 (calc-set-command-flag 'do-edit))
136211a9 541
2378f044
SM
542(defvar calc-edit-mode-map
543 (let ((map (make-sparse-keymap)))
544 (define-key map "\n" 'calc-edit-finish)
545 (define-key map "\r" 'calc-edit-return)
546 (define-key map "\C-c\C-c" 'calc-edit-finish)
547 map)
548 "Keymap for use by the calc-edit command.")
136211a9 549
3f53a1f4
JB
550(defvar calc-original-buffer)
551(defvar calc-return-buffer)
552(defvar calc-one-window)
553(defvar calc-edit-handler)
554(defvar calc-restore-trail)
555(defvar calc-allow-ret)
f57a0962 556(defvar calc-edit-top)
3f53a1f4 557
136211a9
EZ
558(defun calc-edit-mode (&optional handler allow-ret title)
559 "Calculator editing mode. Press RET, LFD, or C-c C-c to finish.
560To cancel the edit, simply kill the *Calc Edit* buffer."
561 (interactive)
3132f345
CW
562 (unless handler
563 (error "This command can be used only indirectly through calc-edit"))
136211a9
EZ
564 (let ((oldbuf (current-buffer))
565 (buf (get-buffer-create "*Calc Edit*")))
566 (set-buffer buf)
567 (kill-all-local-variables)
568 (use-local-map calc-edit-mode-map)
569 (setq buffer-read-only nil)
570 (setq truncate-lines nil)
571 (setq major-mode 'calc-edit-mode)
572 (setq mode-name "Calc Edit")
5c5fb26b 573 (run-mode-hooks 'calc-edit-mode-hook)
136211a9
EZ
574 (make-local-variable 'calc-original-buffer)
575 (setq calc-original-buffer oldbuf)
576 (make-local-variable 'calc-return-buffer)
577 (setq calc-return-buffer oldbuf)
578 (make-local-variable 'calc-one-window)
579 (setq calc-one-window (and (one-window-p t) pop-up-windows))
580 (make-local-variable 'calc-edit-handler)
581 (setq calc-edit-handler handler)
582 (make-local-variable 'calc-restore-trail)
583 (setq calc-restore-trail (get-buffer-window (calc-trail-buffer)))
584 (make-local-variable 'calc-allow-ret)
585 (setq calc-allow-ret allow-ret)
48e7c397
JB
586 (let ((inhibit-read-only t))
587 (erase-buffer))
c80e3b4a 588 (add-hook 'kill-buffer-hook (lambda ()
dcbdf573
JB
589 (let ((calc-edit-handler nil))
590 (calc-edit-finish t))
591 (message "(Cancelled)")) t t)
72e53dcd 592 (insert (propertize
c80e3b4a 593 (concat
72e53dcd
JB
594 (or title title "Calc Edit Mode. ")
595 "Press `C-c C-c'"
596 (if allow-ret "" " or RET")
597 " to finish, `C-x k RET' to cancel.\n\n")
f57a0962
JB
598 'font-lock-face 'italic 'read-only t 'rear-nonsticky t 'front-sticky t))
599 (make-local-variable 'calc-edit-top)
600 (setq calc-edit-top (point))))
136211a9
EZ
601(put 'calc-edit-mode 'mode-class 'special)
602
603(defun calc-show-edit-buffer ()
604 (let ((buf (current-buffer)))
605 (if (and (one-window-p t) pop-up-windows)
606 (pop-to-buffer (get-buffer-create "*Calc Edit*"))
607 (and calc-embedded-info (get-buffer-window (aref calc-embedded-info 1))
608 (select-window (get-buffer-window (aref calc-embedded-info 1))))
609 (switch-to-buffer (get-buffer-create "*Calc Edit*")))
610 (setq calc-return-buffer buf)
8f66f479 611 (if (and (< (window-width) (frame-width))
136211a9
EZ
612 calc-display-trail)
613 (let ((win (get-buffer-window (calc-trail-buffer))))
614 (if win
615 (delete-window win))))
616 (set-buffer-modified-p nil)
f57a0962 617 (goto-char calc-edit-top)))
136211a9
EZ
618
619(defun calc-edit-return ()
620 (interactive)
621 (if (and (boundp 'calc-allow-ret) calc-allow-ret)
622 (newline)
bf77c646 623 (calc-edit-finish)))
136211a9 624
7fc684b3
JB
625;; The variable calc-edit-disp-trail is local to calc-edit finish, but
626;; is used by calc-finish-selection-edit and calc-finish-stack-edit.
627(defvar calc-edit-disp-trail)
628
136211a9
EZ
629(defun calc-edit-finish (&optional keep)
630 "Finish calc-edit mode. Parse buffer contents and push them on the stack."
631 (interactive "P")
632 (message "Working...")
633 (or (and (boundp 'calc-original-buffer)
634 (boundp 'calc-return-buffer)
635 (boundp 'calc-one-window)
636 (boundp 'calc-edit-handler)
637 (boundp 'calc-restore-trail)
638 (eq major-mode 'calc-edit-mode))
3132f345 639 (error "This command is valid only in buffers created by calc-edit"))
136211a9
EZ
640 (let ((buf (current-buffer))
641 (original calc-original-buffer)
642 (return calc-return-buffer)
643 (one-window calc-one-window)
7fc684b3 644 (calc-edit-disp-trail calc-restore-trail))
136211a9 645 (save-excursion
3132f345
CW
646 (when (or (null (buffer-name original))
647 (progn
648 (set-buffer original)
649 (not (eq major-mode 'calc-mode))))
650 (error "Original calculator buffer has been corrupted")))
f57a0962 651 (goto-char calc-edit-top)
136211a9
EZ
652 (if (buffer-modified-p)
653 (eval calc-edit-handler))
a1ed7bec 654 (if (and one-window (not (one-window-p t)))
136211a9
EZ
655 (delete-window))
656 (if (get-buffer-window return)
657 (select-window (get-buffer-window return))
658 (switch-to-buffer return))
659 (if keep
660 (bury-buffer buf)
661 (kill-buffer buf))
7fc684b3 662 (if calc-edit-disp-trail
136211a9
EZ
663 (calc-wrapper
664 (calc-trail-display 1 t)))
bf77c646 665 (message "")))
136211a9
EZ
666
667(defun calc-edit-cancel ()
668 "Cancel calc-edit mode. Ignore the Calc Edit buffer and don't change stack."
669 (interactive)
670 (let ((calc-edit-handler nil))
671 (calc-edit-finish))
bf77c646 672 (message "(Cancelled)"))
136211a9
EZ
673
674(defun calc-finish-stack-edit (num)
675 (let ((buf (current-buffer))
f57a0962 676 (str (buffer-substring calc-edit-top (point-max)))
136211a9
EZ
677 (start (point))
678 pos)
679 (if (and (integerp num) (> num 1))
680 (while (setq pos (string-match "\n." str))
681 (aset str pos ?\,)))
682 (switch-to-buffer calc-original-buffer)
683 (let ((vals (let ((calc-language nil)
84812f0e 684 (math-expr-opers (math-standard-ops)))
136211a9
EZ
685 (and (string-match "[^\n\t ]" str)
686 (math-read-exprs str)))))
3132f345
CW
687 (when (eq (car-safe vals) 'error)
688 (switch-to-buffer buf)
689 (goto-char (+ start (nth 1 vals)))
690 (error (nth 2 vals)))
136211a9
EZ
691 (calc-wrapper
692 (if (symbolp num)
693 (progn
694 (set num (car vals))
695 (calc-refresh-evaltos num))
7fc684b3 696 (if calc-edit-disp-trail
136211a9
EZ
697 (calc-trail-display 1 t))
698 (and vals
e93c003e 699 (let ((calc-simplify-mode (if (eq last-command-event ?\C-j)
136211a9
EZ
700 'none
701 calc-simplify-mode)))
702 (if (>= num 0)
703 (calc-enter-result num "edit" vals)
bf77c646 704 (calc-enter-result 1 "edit" vals (- num))))))))))
136211a9 705
b1687f60
JB
706(provide 'calc-yank)
707
2378f044
SM
708;; Local variables:
709;; generated-autoload-file: "calc-loaddefs.el"
710;; End:
711
bf77c646 712;;; calc-yank.el ends here