(calcVar-digit, calcVar-oper): Remove need for "var-" at the
[bpt/emacs.git] / lisp / calc / calc-embed.el
CommitLineData
3132f345
CW
1;;; calc-embed.el --- embed Calc in a buffer
2
af32d76e 3;; Copyright (C) 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc.
3132f345
CW
4
5;; Author: David Gillespie <daveg@synaptics.com>
adb0a616 6;; Maintainer: Jay Belanger <belanger@truman.edu>
136211a9
EZ
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is distributed in the hope that it will be useful,
11;; but WITHOUT ANY WARRANTY. No author or distributor
12;; accepts responsibility to anyone for the consequences of using it
13;; or for whether it serves any particular purpose or works at all,
14;; unless he says so in writing. Refer to the GNU Emacs General Public
15;; License for full details.
16
17;; Everyone is granted permission to copy, modify and redistribute
18;; GNU Emacs, but only under the conditions described in the
19;; GNU Emacs General Public License. A copy of this license is
20;; supposed to have been given to you along with GNU Emacs so you
21;; can know your rights and responsibilities. It should be in a
22;; file named COPYING. Among other things, the copyright notice
23;; and this notice must be preserved on all copies.
24
3132f345 25;;; Commentary:
136211a9 26
3132f345 27;;; Code:
136211a9
EZ
28
29;; This file is autoloaded from calc-ext.el.
136211a9 30
937640a6 31(require 'calc-ext)
136211a9
EZ
32(require 'calc-macs)
33
136211a9
EZ
34(defun calc-show-plain (n)
35 (interactive "P")
36 (calc-wrapper
37 (calc-set-command-flag 'renum-stack)
38 (message (if (calc-change-mode 'calc-show-plain n nil t)
3132f345
CW
39 "Including \"plain\" formulas in Calc Embedded mode"
40 "Omitting \"plain\" formulas in Calc Embedded mode"))))
136211a9
EZ
41
42
43(defvar calc-embedded-modes nil)
44(defvar calc-embedded-globals nil)
45(defvar calc-embedded-active nil)
3132f345 46(defvar calc-embedded-all-active nil)
136211a9 47(make-variable-buffer-local 'calc-embedded-all-active)
3132f345 48(defvar calc-embedded-some-active nil)
136211a9
EZ
49(make-variable-buffer-local 'calc-embedded-some-active)
50
136211a9
EZ
51(defvar calc-embedded-open-formula "\\`\\|^\n\\|\\$\\$?\\|\\\\\\[\\|^\\\\begin.*\n\\|^@.*\n\\|^\\.EQ.*\n\\|\\\\(\\|^%\n\\|^\\.\\\\\"\n"
52 "*A regular expression for the opening delimiter of a formula used by
53calc-embedded.")
54
55(defvar calc-embedded-close-formula "\\'\\|\n$\\|\\$\\$?\\|\\\\]\\|^\\\\end.*\n\\|^@.*\n\\|^\\.EN.*\n\\|\\\\)\\|\n%\n\\|^\\.\\\\\"\n"
56 "*A regular expression for the closing delimiter of a formula used by
57calc-embedded.")
58
59(defvar calc-embedded-open-word "^\\|[^-+0-9.eE]"
60 "*A regular expression for the opening delimiter of a formula used by
61calc-embedded-word.")
62
63(defvar calc-embedded-close-word "$\\|[^-+0-9.eE]"
64 "*A regular expression for the closing delimiter of a formula used by
65calc-embedded-word.")
66
67(defvar calc-embedded-open-plain "%%% "
68 "*A string which is the opening delimiter for a \"plain\" formula.
69If calc-show-plain mode is enabled, this is inserted at the front of
70each formula.")
71
72(defvar calc-embedded-close-plain " %%%\n"
73 "*A string which is the closing delimiter for a \"plain\" formula.
74See calc-embedded-open-plain.")
75
76(defvar calc-embedded-open-new-formula "\n\n"
77 "*A string which is inserted at front of formula by calc-embedded-new-formula.")
78
79(defvar calc-embedded-close-new-formula "\n\n"
80 "*A string which is inserted at end of formula by calc-embedded-new-formula.")
81
82(defvar calc-embedded-announce-formula "%Embed\n\\(% .*\n\\)*"
83 "*A regular expression which is sure to be followed by a calc-embedded formula." )
84
85(defvar calc-embedded-open-mode "% "
86 "*A string which should precede calc-embedded mode annotations.
87This is not required to be present for user-written mode annotations.")
88
89(defvar calc-embedded-close-mode "\n"
90 "*A string which should follow calc-embedded mode annotations.
91This is not required to be present for user-written mode annotations.")
92
93
94(defconst calc-embedded-mode-vars '(("precision" . calc-internal-prec)
95 ("word-size" . calc-word-size)
96 ("angles" . calc-angle-mode)
97 ("symbolic" . calc-symbolic-mode)
98 ("matrix" . calc-matrix-mode)
99 ("fractions" . calc-prefer-frac)
100 ("complex" . calc-complex-mode)
101 ("simplify" . calc-simplify-mode)
102 ("language" . the-language)
103 ("plain" . calc-show-plain)
104 ("break" . calc-line-breaking)
105 ("justify" . the-display-just)
106 ("left-label" . calc-left-label)
107 ("right-label" . calc-right-label)
108 ("radix" . calc-number-radix)
109 ("leading-zeros" . calc-leading-zeros)
110 ("grouping" . calc-group-digits)
111 ("group-char" . calc-group-char)
112 ("point-char" . calc-point-char)
113 ("frac-format" . calc-frac-format)
114 ("float-format" . calc-float-format)
115 ("complex-format" . calc-complex-format)
116 ("hms-format" . calc-hms-format)
117 ("date-format" . calc-date-format)
118 ("matrix-justify" . calc-matrix-just)
119 ("full-vectors" . calc-full-vectors)
120 ("break-vectors" . calc-break-vectors)
121 ("vector-commas" . calc-vector-commas)
122 ("vector-brackets" . calc-vector-brackets)
123 ("matrix-brackets" . calc-matrix-brackets)
124 ("strings" . calc-display-strings)
125))
126
127
128;;; Format of calc-embedded-info vector:
129;;; 0 Editing buffer.
130;;; 1 Calculator buffer.
131;;; 2 Top of current formula (marker).
132;;; 3 Bottom of current formula (marker).
133;;; 4 Top of current formula's delimiters (marker).
134;;; 5 Bottom of current formula's delimiters (marker).
135;;; 6 String representation of current formula.
136;;; 7 Non-nil if formula is embedded within a single line.
137;;; 8 Internal representation of current formula.
138;;; 9 Variable assigned by this formula, or nil.
139;;; 10 List of variables upon which this formula depends.
140;;; 11 Evaluated value of the formula, or nil.
141;;; 12 Mode settings for current formula.
142;;; 13 Local mode settings for current formula.
143;;; 14 Permanent mode settings for current formula.
144;;; 15 Global mode settings for editing buffer.
145
146
147;;; calc-embedded-active is an a-list keyed on buffers; each cdr is a
148;;; sorted list of calc-embedded-infos in that buffer. We do this
149;;; rather than using buffer-local variables because the latter are
150;;; thrown away when a buffer changes major modes.
151
adb0a616
JB
152;; The variables calc-embed-outer-top, calc-embed-outer-bot,
153;; calc-embed-top and calc-embed-bot are
154;; local to calc-do-embedded, calc-embedded-mark-formula,
155;; calc-embedded-duplicate, calc-embedded-new-formula and
156;; calc-embedded-make-info, but are used by calc-embedded-find-bounds,
157;; which is called (directly or indirectly) by the above functions.
158(defvar calc-embed-outer-top)
159(defvar calc-embed-outer-bot)
160(defvar calc-embed-top)
161(defvar calc-embed-bot)
136211a9 162
3132f345 163(defvar calc-embedded-quiet nil)
136211a9
EZ
164(defun calc-do-embedded (arg end obeg oend)
165 (if calc-embedded-info
166
167 ;; Turn embedded mode off or switch to a new buffer.
168 (cond ((eq (current-buffer) (aref calc-embedded-info 1))
169 (let ((calcbuf (current-buffer))
170 (buf (aref calc-embedded-info 0)))
171 (calc-embedded-original-buffer t)
172 (calc-embedded nil)
173 (switch-to-buffer calcbuf)))
174
175 ((eq (current-buffer) (aref calc-embedded-info 0))
176 (let* ((info calc-embedded-info)
177 (mode calc-embedded-modes))
178 (save-excursion
179 (set-buffer (aref info 1))
180 (if (and (> (calc-stack-size) 0)
181 (equal (calc-top 1 'full) (aref info 8)))
182 (let ((calc-no-refresh-evaltos t))
183 (if (calc-top 1 'sel)
184 (calc-unselect 1))
185 (calc-embedded-set-modes
186 (aref info 15) (aref info 12) (aref info 14))
187 (let ((calc-embedded-info nil))
188 (calc-wrapper (calc-pop-stack))))
189 (calc-set-mode-line)))
190 (setq calc-embedded-info nil
191 mode-line-buffer-identification (car mode)
192 truncate-lines (nth 2 mode)
193 buffer-read-only nil)
194 (use-local-map (nth 1 mode))
195 (set-buffer-modified-p (buffer-modified-p))
196 (or calc-embedded-quiet
3132f345 197 (message "Back to %s mode" mode-name))))
136211a9
EZ
198
199 (t
200 (if (buffer-name (aref calc-embedded-info 0))
201 (save-excursion
202 (set-buffer (aref calc-embedded-info 0))
af32d76e
EZ
203 (or (y-or-n-p (format "Cancel Calc Embedded mode in buffer %s? "
204 (buffer-name)))
136211a9
EZ
205 (keyboard-quit))
206 (calc-embedded nil)))
207 (calc-embedded arg end obeg oend)))
208
209 ;; Turn embedded mode on.
210 (calc-plain-buffer-only)
211 (let ((modes (list mode-line-buffer-identification
212 (current-local-map)
213 truncate-lines))
adb0a616 214 calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot
136211a9
EZ
215 info chg ident)
216 (barf-if-buffer-read-only)
217 (or calc-embedded-globals
218 (calc-find-globals))
219 (setq info (calc-embedded-make-info (point) nil t arg end obeg oend))
220 (if (eq (car-safe (aref info 8)) 'error)
221 (progn
222 (goto-char (nth 1 (aref info 8)))
223 (error (nth 2 (aref info 8)))))
224 (let ((mode-line-buffer-identification mode-line-buffer-identification)
225 (calc-embedded-info info)
226 (calc-embedded-no-reselect t))
227 (calc-wrapper
228 (let* ((okay nil)
229 (calc-no-refresh-evaltos t))
230 (setq chg (calc-embedded-set-modes
231 (aref info 15) (aref info 12) (aref info 13)))
232 (if (aref info 8)
233 (calc-push (calc-normalize (aref info 8)))
234 (calc-alg-entry)))
235 (setq calc-undo-list nil
236 calc-redo-list nil
237 ident mode-line-buffer-identification)))
238 (setq calc-embedded-info info
239 calc-embedded-modes modes
240 mode-line-buffer-identification ident
241 truncate-lines t
242 buffer-read-only t)
243 (set-buffer-modified-p (buffer-modified-p))
244 (use-local-map calc-mode-map)
245 (setq calc-no-refresh-evaltos nil)
246 (and chg calc-any-evaltos (calc-wrapper (calc-refresh-evaltos)))
247 (or (eq calc-embedded-quiet t)
3132f345 248 (message "Embedded Calc mode enabled; %s to return to normal"
136211a9
EZ
249 (if calc-embedded-quiet
250 "Type `M-# x'"
251 "Give this command again")))))
bf77c646 252 (scroll-down 0)) ; fix a bug which occurs when truncate-lines is changed.
136211a9
EZ
253
254
255(defun calc-embedded-select (arg)
256 (interactive "P")
257 (calc-embedded arg)
258 (and calc-embedded-info
259 (eq (car-safe (aref calc-embedded-info 8)) 'calcFunc-evalto)
260 (calc-select-part 1))
261 (and calc-embedded-info
262 (or (eq (car-safe (aref calc-embedded-info 8)) 'calcFunc-assign)
263 (and (eq (car-safe (aref calc-embedded-info 8)) 'calcFunc-evalto)
264 (eq (car-safe (nth 1 (aref calc-embedded-info 8)))
265 'calcFunc-assign)))
bf77c646 266 (calc-select-part 2)))
136211a9
EZ
267
268
269(defun calc-embedded-update-formula (arg)
270 (interactive "P")
271 (if arg
272 (let ((entry (assq (current-buffer) calc-embedded-active)))
273 (while (setq entry (cdr entry))
274 (and (eq (car-safe (aref (car entry) 8)) 'calcFunc-evalto)
275 (or (not (consp arg))
276 (and (<= (aref (car entry) 2) (region-beginning))
277 (>= (aref (car entry) 3) (region-end))))
278 (save-excursion
279 (calc-embedded-update (car entry) 14 t t)))))
280 (if (and calc-embedded-info
281 (eq (current-buffer) (aref calc-embedded-info 0))
282 (>= (point) (aref calc-embedded-info 4))
283 (<= (point) (aref calc-embedded-info 5)))
284 (calc-evaluate 1)
285 (let* ((opt (point))
286 (info (calc-embedded-make-info (point) nil t))
287 (pt (- opt (aref info 4))))
288 (or (eq (car-safe (aref info 8)) 'error)
289 (progn
290 (save-excursion
291 (calc-embedded-update info 14 'eval t))
bf77c646 292 (goto-char (+ (aref info 4) pt))))))))
136211a9
EZ
293
294
295(defun calc-embedded-edit (arg)
296 (interactive "P")
297 (let ((info (calc-embedded-make-info (point) nil t arg))
298 str)
299 (if (eq (car-safe (aref info 8)) 'error)
300 (progn
301 (goto-char (nth 1 (aref info 8)))
302 (error (nth 2 (aref info 8)))))
303 (calc-wrapper
304 (setq str (math-showing-full-precision
af32d76e 305 (math-format-nice-expr (aref info 8) (frame-width))))
136211a9
EZ
306 (calc-edit-mode (list 'calc-embedded-finish-edit info))
307 (insert str "\n")))
bf77c646 308 (calc-show-edit-buffer))
136211a9 309
adb0a616
JB
310(defvar calc-original-buffer)
311
136211a9
EZ
312(defun calc-embedded-finish-edit (info)
313 (let ((buf (current-buffer))
314 (str (buffer-substring (point) (point-max)))
315 (start (point))
316 pos)
317 (switch-to-buffer calc-original-buffer)
318 (let ((val (save-excursion
319 (set-buffer (aref info 1))
320 (let ((calc-language nil)
321 (math-expr-opers math-standard-opers))
322 (math-read-expr str)))))
323 (if (eq (car-safe val) 'error)
324 (progn
325 (switch-to-buffer buf)
326 (goto-char (+ start (nth 1 val)))
327 (error (nth 2 val))))
328 (calc-embedded-original-buffer t info)
329 (aset info 8 val)
bf77c646 330 (calc-embedded-update info 14 t t))))
136211a9
EZ
331
332(defun calc-do-embedded-activate (arg cbuf)
333 (calc-plain-buffer-only)
334 (if arg
335 (calc-embedded-forget))
336 (calc-find-globals)
337 (if (< (prefix-numeric-value arg) 0)
3132f345 338 (message "Deactivating %s for Calc Embedded mode" (buffer-name))
136211a9
EZ
339 (message "Activating %s for Calc Embedded mode..." (buffer-name))
340 (save-excursion
341 (let* ((active (assq (current-buffer) calc-embedded-active))
342 (info active)
343 (pat " := \\| \\\\gets \\| => \\| \\\\evalto "))
344 (if calc-embedded-announce-formula
345 (setq pat (format "%s\\|\\(%s\\)"
346 pat calc-embedded-announce-formula)))
347 (while (setq info (cdr info))
348 (or (equal (buffer-substring (aref (car info) 2) (aref (car info) 3))
349 (aref (car info) 6))
350 (setcdr active (delq (car info) (cdr active)))))
351 (goto-char (point-min))
352 (while (re-search-forward pat nil t)
bc47b3f8
EZ
353;;; (if (looking-at calc-embedded-open-formula)
354;;; (goto-char (match-end 1)))
136211a9
EZ
355 (setq info (calc-embedded-make-info (point) cbuf nil))
356 (or (eq (car-safe (aref info 8)) 'error)
357 (goto-char (aref info 5))))))
358 (message "Activating %s for Calc Embedded mode...done" (buffer-name)))
bf77c646 359 (calc-embedded-active-state t))
136211a9
EZ
360
361(defun calc-plain-buffer-only ()
362 (if (memq major-mode '(calc-mode calc-trail-mode calc-edit-mode))
bf77c646 363 (error "This command should be used in a normal editing buffer")))
136211a9
EZ
364
365(defun calc-embedded-active-state (state)
366 (or (assq 'calc-embedded-all-active minor-mode-alist)
367 (setq minor-mode-alist
368 (cons '(calc-embedded-all-active " Active")
369 (cons '(calc-embedded-some-active " ~Active")
370 minor-mode-alist))))
371 (let ((active (assq (current-buffer) calc-embedded-active)))
372 (or (cdr active)
373 (setq state nil)))
374 (and (eq state 'more) calc-embedded-all-active (setq state t))
375 (setq calc-embedded-all-active (eq state t)
376 calc-embedded-some-active (not (memq state '(nil t))))
bf77c646 377 (set-buffer-modified-p (buffer-modified-p)))
136211a9
EZ
378
379
380(defun calc-embedded-original-buffer (switch &optional info)
381 (or info (setq info calc-embedded-info))
382 (or (buffer-name (aref info 0))
383 (progn
384 (error "Calc embedded mode: Original buffer has been killed")))
385 (if switch
bf77c646 386 (set-buffer (aref info 0))))
136211a9
EZ
387
388(defun calc-embedded-word ()
389 (interactive)
bf77c646 390 (calc-embedded '(4)))
136211a9
EZ
391
392(defun calc-embedded-mark-formula (&optional body-only)
393 "Put point at the beginning of this Calc formula, mark at the end.
394This normally marks the whole formula, including surrounding delimiters.
395With any prefix argument, marks only the formula itself."
396 (interactive "P")
397 (and (eq major-mode 'calc-mode)
398 (error "This command should be used in a normal editing buffer"))
adb0a616 399 (let (calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot)
136211a9
EZ
400 (save-excursion
401 (calc-embedded-find-bounds body-only))
adb0a616
JB
402 (push-mark (if body-only calc-embed-bot calc-embed-outer-bot) t)
403 (goto-char (if body-only calc-embed-top calc-embed-outer-top))))
136211a9
EZ
404
405(defun calc-embedded-find-bounds (&optional plain)
406 ;; (while (and (bolp) (eq (following-char) ?\n))
407 ;; (forward-char 1))
408 (and (eolp) (bolp) (not (eq (char-after (- (point) 2)) ?\n))
409 (forward-char -1))
410 (let ((home (point)))
411 (or (and (looking-at calc-embedded-open-formula)
412 (not (looking-at calc-embedded-close-formula)))
413 (re-search-backward calc-embedded-open-formula nil t)
414 (error "Can't find start of formula"))
415 (and (eq (preceding-char) ?\$) ; backward search for \$\$? won't back
416 (eq (following-char) ?\$) ; up over a second $, so do it by hand.
417 (forward-char -1))
adb0a616 418 (setq calc-embed-outer-top (point))
136211a9
EZ
419 (goto-char (match-end 0))
420 (if (eq (following-char) ?\n)
421 (forward-char 1))
422 (or (bolp)
423 (while (eq (following-char) ?\ )
424 (forward-char 1)))
425 (or (eq plain 'plain)
426 (if (looking-at (regexp-quote calc-embedded-open-plain))
427 (progn
428 (goto-char (match-end 0))
429 (search-forward calc-embedded-close-plain))))
adb0a616 430 (setq calc-embed-top (point))
136211a9
EZ
431 (or (re-search-forward calc-embedded-close-formula nil t)
432 (error "Can't find end of formula"))
433 (if (< (point) home)
434 (error "Not inside a formula"))
435 (and (eq (following-char) ?\n) (not (bolp))
436 (forward-char 1))
adb0a616 437 (setq calc-embed-outer-bot (point))
136211a9
EZ
438 (goto-char (match-beginning 0))
439 (if (eq (preceding-char) ?\n)
440 (backward-char 1))
441 (or (eolp)
442 (while (eq (preceding-char) ?\ )
443 (backward-char 1)))
adb0a616 444 (setq calc-embed-bot (point))))
136211a9
EZ
445
446(defun calc-embedded-kill-formula ()
447 "Kill the formula surrounding point.
448If Calc Embedded mode was active, this deactivates it.
449The formula (including its surrounding delimiters) is saved in the kill ring.
450The command \\[yank] can retrieve it from there."
451 (interactive)
452 (and calc-embedded-info
453 (calc-embedded nil))
454 (calc-embedded-mark-formula)
455 (kill-region (point) (mark))
bf77c646 456 (pop-mark))
136211a9
EZ
457
458(defun calc-embedded-copy-formula-as-kill ()
459 "Save the formula surrounding point as if killed, but don't kill it."
460 (interactive)
461 (save-excursion
462 (calc-embedded-mark-formula)
463 (copy-region-as-kill (point) (mark))
bf77c646 464 (pop-mark)))
136211a9
EZ
465
466(defun calc-embedded-duplicate ()
467 (interactive)
468 (let ((already calc-embedded-info)
adb0a616 469 calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot new-top)
136211a9
EZ
470 (if calc-embedded-info
471 (progn
adb0a616
JB
472 (setq calc-embed-top (+ (aref calc-embedded-info 2))
473 calc-embed-bot (+ (aref calc-embedded-info 3))
474 calc-embed-outer-top (+ (aref calc-embedded-info 4))
475 calc-embed-outer-bot (+ (aref calc-embedded-info 5)))
136211a9
EZ
476 (calc-embedded nil))
477 (calc-embedded-find-bounds))
adb0a616 478 (goto-char calc-embed-outer-bot)
136211a9
EZ
479 (insert "\n")
480 (setq new-top (point))
adb0a616
JB
481 (insert-buffer-substring (current-buffer)
482 calc-embed-outer-top calc-embed-outer-bot)
483 (goto-char (+ new-top (- calc-embed-top calc-embed-outer-top)))
136211a9 484 (let ((calc-embedded-quiet (if already t 'x)))
adb0a616
JB
485 (calc-embedded (+ new-top (- calc-embed-top calc-embed-outer-top))
486 (+ new-top (- calc-embed-bot calc-embed-outer-top))
136211a9 487 new-top
adb0a616 488 (+ new-top (- calc-embed-outer-bot calc-embed-outer-top))))))
136211a9
EZ
489
490(defun calc-embedded-next (arg)
491 (interactive "P")
492 (setq arg (prefix-numeric-value arg))
493 (let* ((active (cdr (assq (current-buffer) calc-embedded-active)))
494 (p active)
495 (num (length active)))
496 (or active
497 (error "No active formulas in buffer"))
498 (cond ((= arg 0))
499 ((= arg -1)
500 (if (<= (point) (aref (car active) 3))
501 (goto-char (aref (nth (1- num) active) 2))
502 (while (and (cdr p)
503 (> (point) (aref (nth 1 p) 3)))
504 (setq p (cdr p)))
505 (goto-char (aref (car p) 2))))
506 ((< arg -1)
507 (calc-embedded-next -1)
508 (calc-embedded-next (+ (* num 1000) arg 1)))
509 (t
510 (setq arg (1+ (% (1- arg) num)))
511 (while (and p (>= (point) (aref (car p) 2)))
512 (setq p (cdr p)))
513 (while (> (setq arg (1- arg)) 0)
514 (setq p (if p (cdr p) (cdr active))))
bf77c646 515 (goto-char (aref (car (or p active)) 2))))))
136211a9
EZ
516
517(defun calc-embedded-previous (arg)
518 (interactive "p")
bf77c646 519 (calc-embedded-next (- (prefix-numeric-value arg))))
136211a9
EZ
520
521(defun calc-embedded-new-formula ()
522 (interactive)
523 (and (eq major-mode 'calc-mode)
524 (error "This command should be used in a normal editing buffer"))
525 (if calc-embedded-info
526 (calc-embedded nil))
adb0a616 527 (let (calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot)
136211a9
EZ
528 (if (and (eq (preceding-char) ?\n)
529 (string-match "\\`\n" calc-embedded-open-new-formula))
530 (progn
adb0a616 531 (setq calc-embed-outer-top (1- (point)))
136211a9
EZ
532 (forward-char -1)
533 (insert (substring calc-embedded-open-new-formula 1)))
adb0a616 534 (setq calc-embed-outer-top (point))
136211a9 535 (insert calc-embedded-open-new-formula))
adb0a616 536 (setq calc-embed-top (point))
136211a9 537 (insert " ")
adb0a616 538 (setq calc-embed-bot (point))
136211a9
EZ
539 (insert calc-embedded-close-new-formula)
540 (if (and (eq (following-char) ?\n)
541 (string-match "\n\\'" calc-embedded-close-new-formula))
542 (delete-char 1))
adb0a616
JB
543 (setq calc-embed-outer-bot (point))
544 (goto-char calc-embed-top)
136211a9 545 (let ((calc-embedded-quiet 'x))
adb0a616 546 (calc-embedded calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot))))
136211a9
EZ
547
548(defun calc-embedded-forget ()
549 (interactive)
550 (setq calc-embedded-active (delq (assq (current-buffer) calc-embedded-active)
551 calc-embedded-active))
bf77c646 552 (calc-embedded-active-state nil))
136211a9 553
adb0a616
JB
554;; The variables calc-embed-prev-modes is local to calc-embedded-update,
555;; but is used by calc-embedded-set-modes.
556(defvar calc-embed-prev-modes)
136211a9
EZ
557
558(defun calc-embedded-set-modes (gmodes modes local-modes &optional temp)
559 (let ((the-language (calc-embedded-language))
560 (the-display-just (calc-embedded-justify))
561 (v gmodes)
562 (changed nil)
563 found value)
564 (while v
565 (or (symbolp (car v))
566 (and (setq found (assq (car (car v)) modes))
567 (not (eq (cdr found) 'default)))
568 (and (setq found (assq (car (car v)) local-modes))
569 (not (eq (cdr found) 'default)))
570 (progn
571 (if (eq (setq value (cdr (car v))) 'default)
f10b7b1b 572 (setq value (list (nth 1 (assq (car (car v)) calc-mode-var-list)))))
136211a9
EZ
573 (equal (symbol-value (car (car v))) value))
574 (progn
575 (setq changed t)
adb0a616
JB
576 (if temp (setq calc-embed-prev-modes
577 (cons (cons (car (car v))
578 (symbol-value (car (car v))))
579 calc-embed-prev-modes)))
136211a9
EZ
580 (set (car (car v)) value)))
581 (setq v (cdr v)))
582 (setq v modes)
583 (while v
584 (or (and (setq found (assq (car (car v)) local-modes))
585 (not (eq (cdr found) 'default)))
586 (eq (setq value (cdr (car v))) 'default)
587 (equal (symbol-value (car (car v))) value)
588 (progn
589 (setq changed t)
adb0a616 590 (if temp (setq calc-embed-prev-modes (cons (cons (car (car v))
136211a9 591 (symbol-value (car (car v))))
adb0a616 592 calc-embed-prev-modes)))
136211a9
EZ
593 (set (car (car v)) value)))
594 (setq v (cdr v)))
595 (setq v local-modes)
596 (while v
597 (or (eq (setq value (cdr (car v))) 'default)
598 (equal (symbol-value (car (car v))) value)
599 (progn
600 (setq changed t)
adb0a616 601 (if temp (setq calc-embed-prev-modes (cons (cons (car (car v))
136211a9 602 (symbol-value (car (car v))))
adb0a616 603 calc-embed-prev-modes)))
136211a9
EZ
604 (set (car (car v)) value)))
605 (setq v (cdr v)))
606 (and changed (not (eq temp t))
607 (progn
608 (calc-embedded-set-justify the-display-just)
609 (calc-embedded-set-language the-language)))
610 (and changed (not temp)
611 (progn
612 (setq calc-full-float-format (list (if (eq (car calc-float-format)
613 'fix)
614 'float
615 (car calc-float-format))
616 0))
617 (calc-refresh)))
bf77c646 618 changed))
136211a9
EZ
619
620(defun calc-embedded-language ()
621 (if calc-language-option
622 (list calc-language calc-language-option)
bf77c646 623 calc-language))
136211a9
EZ
624
625(defun calc-embedded-set-language (lang)
626 (let ((option nil))
627 (if (consp lang)
628 (setq option (nth 1 lang)
629 lang (car lang)))
630 (or (and (eq lang calc-language)
631 (equal option calc-language-option))
bf77c646 632 (calc-set-language lang option t))))
136211a9
EZ
633
634(defun calc-embedded-justify ()
635 (if calc-display-origin
636 (list calc-display-just calc-display-origin)
bf77c646 637 calc-display-just))
136211a9
EZ
638
639(defun calc-embedded-set-justify (just)
640 (if (consp just)
641 (setq calc-display-origin (nth 1 just)
642 calc-display-just (car just))
643 (setq calc-display-just just
bf77c646 644 calc-display-origin nil)))
136211a9
EZ
645
646
647(defun calc-find-globals ()
648 (interactive)
649 (and (eq major-mode 'calc-mode)
650 (error "This command should be used in a normal editing buffer"))
651 (make-local-variable 'calc-embedded-globals)
652 (let ((case-fold-search nil)
653 (modes nil)
654 (save-pt (point))
655 found value)
656 (goto-char (point-min))
657 (while (re-search-forward "\\[calc-global-mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)\\]" nil t)
658 (and (setq found (assoc (buffer-substring (match-beginning 1)
659 (match-end 1))
660 calc-embedded-mode-vars))
661 (or (assq (cdr found) modes)
662 (setq modes (cons (cons (cdr found)
663 (car (read-from-string
664 (buffer-substring
665 (match-beginning 2)
666 (match-end 2)))))
667 modes)))))
668 (setq calc-embedded-globals (cons t modes))
bf77c646 669 (goto-char save-pt)))
136211a9
EZ
670
671(defun calc-embedded-find-modes ()
672 (let ((case-fold-search nil)
673 (save-pt (point))
674 (no-defaults t)
675 (modes nil)
676 (emodes nil)
677 (pmodes nil)
678 found value)
679 (while (and no-defaults (search-backward "[calc-" nil t))
680 (forward-char 6)
681 (or (and (looking-at "mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]")
682 (setq found (assoc (buffer-substring (match-beginning 1)
683 (match-end 1))
684 calc-embedded-mode-vars))
685 (or (assq (cdr found) modes)
686 (setq modes (cons (cons (cdr found)
687 (car (read-from-string
688 (buffer-substring
689 (match-beginning 2)
690 (match-end 2)))))
691 modes))))
692 (and (looking-at "perm-mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]")
693 (setq found (assoc (buffer-substring (match-beginning 1)
694 (match-end 1))
695 calc-embedded-mode-vars))
696 (or (assq (cdr found) pmodes)
697 (setq pmodes (cons (cons (cdr found)
698 (car (read-from-string
699 (buffer-substring
700 (match-beginning 2)
701 (match-end 2)))))
702 pmodes))))
703 (and (looking-at "edit-mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]")
704 (setq found (assoc (buffer-substring (match-beginning 1)
705 (match-end 1))
706 calc-embedded-mode-vars))
707 (or (assq (cdr found) emodes)
708 (setq emodes (cons (cons (cdr found)
709 (car (read-from-string
710 (buffer-substring
711 (match-beginning 2)
712 (match-end 2)))))
713 emodes))))
714 (and (looking-at "defaults]")
715 (setq no-defaults nil)))
716 (backward-char 6))
717 (goto-char save-pt)
bf77c646 718 (list modes emodes pmodes)))
136211a9 719
adb0a616
JB
720;; The variable calc-embed-vars-used is local to calc-embedded-make-info,
721;; calc-embedded-evaluate-expr and calc-embedded-update, but is
722;; used by calc-embedded-find-vars, which is called by the above functions.
723(defvar calc-embed-vars-used)
136211a9
EZ
724
725(defun calc-embedded-make-info (point cbuf fresh &optional
adb0a616
JB
726 calc-embed-top calc-embed-bot
727 calc-embed-outer-top calc-embed-outer-bot)
136211a9
EZ
728 (let* ((bufentry (assq (current-buffer) calc-embedded-active))
729 (found bufentry)
adb0a616
JB
730 (force (and fresh calc-embed-top))
731 (fixed calc-embed-top)
136211a9
EZ
732 (new-info nil)
733 info str)
734 (or found
735 (setq found (list (current-buffer))
736 calc-embedded-active (cons found calc-embedded-active)))
737 (while (and (cdr found)
738 (> point (aref (car (cdr found)) 3)))
739 (setq found (cdr found)))
740 (if (and (cdr found)
741 (>= point (aref (nth 1 found) 2)))
742 (setq info (nth 1 found))
743 (setq info (make-vector 16 nil)
744 new-info t
745 fresh t)
746 (aset info 0 (current-buffer))
747 (aset info 1 (or cbuf (save-excursion
748 (calc-create-buffer)
749 (current-buffer)))))
adb0a616
JB
750 (if (and (integerp calc-embed-top) (not calc-embed-bot))
751 ; started with a user-supplied argument
136211a9
EZ
752 (progn
753 (if (= (setq arg (prefix-numeric-value arg)) 0)
754 (progn
755 (aset info 2 (copy-marker (region-beginning)))
756 (aset info 3 (copy-marker (region-end))))
757 (aset info (if (> arg 0) 2 3) (point-marker))
758 (forward-line arg)
759 (aset info (if (> arg 0) 3 2) (point-marker)))
760 (aset info 4 (copy-marker (aref info 2)))
761 (aset info 5 (copy-marker (aref info 3))))
762 (if (aref info 4)
adb0a616
JB
763 (setq calc-embed-top (aref info 2)
764 fixed calc-embed-top)
765 (if (consp calc-embed-top)
136211a9
EZ
766 (let ((calc-embedded-open-formula calc-embedded-open-word)
767 (calc-embedded-close-formula calc-embedded-close-word))
768 (calc-embedded-find-bounds 'plain))
adb0a616 769 (or calc-embed-top
136211a9 770 (calc-embedded-find-bounds 'plain)))
adb0a616
JB
771 (aset info 2 (copy-marker (min calc-embed-top calc-embed-bot)))
772 (aset info 3 (copy-marker (max calc-embed-top calc-embed-bot)))
773 (aset info 4 (copy-marker (or calc-embed-outer-top (aref info 2))))
774 (aset info 5 (copy-marker (or calc-embed-outer-bot (aref info 3))))))
136211a9
EZ
775 (goto-char (aref info 2))
776 (if new-info
777 (progn
778 (or (bolp) (aset info 7 t))
779 (goto-char (aref info 3))
780 (or (bolp) (eolp) (aset info 7 t))))
781 (if fresh
782 (let ((modes (calc-embedded-find-modes)))
783 (aset info 12 (car modes))
784 (aset info 13 (nth 1 modes))
785 (aset info 14 (nth 2 modes))))
786 (aset info 15 calc-embedded-globals)
787 (setq str (buffer-substring (aref info 2) (aref info 3)))
788 (if (or force
789 (not (equal str (aref info 6))))
790 (if (and fixed (aref info 6))
791 (progn
792 (aset info 4 nil)
793 (calc-embedded-make-info point cbuf nil)
794 (setq new-info nil))
795 (let* ((open-plain calc-embedded-open-plain)
796 (close-plain calc-embedded-close-plain)
797 (pref-len (length open-plain))
adb0a616 798 (calc-embed-vars-used nil)
136211a9
EZ
799 suff-pos val temp)
800 (save-excursion
801 (set-buffer (aref info 1))
802 (calc-embedded-set-modes (aref info 15)
803 (aref info 12) (aref info 14))
804 (if (and (> (length str) pref-len)
805 (equal (substring str 0 pref-len) open-plain)
806 (setq suff-pos (string-match (regexp-quote close-plain)
807 str pref-len)))
808 (setq val (math-read-plain-expr
809 (substring str pref-len suff-pos)))
810 (if (string-match "[^ \t\n]" str)
811 (setq pref-len 0
812 val (math-read-big-expr str))
813 (setq val nil))))
814 (if (eq (car-safe val) 'error)
815 (setq val (list 'error
816 (+ (aref info 2) pref-len (nth 1 val))
817 (nth 2 val))))
818 (aset info 6 str)
819 (aset info 8 val)
820 (setq temp val)
821 (if (eq (car-safe temp) 'calcFunc-evalto)
822 (setq temp (nth 1 temp))
823 (if (eq (car-safe temp) 'error)
824 (if new-info
825 (setq new-info nil)
826 (setcdr found (delq info (cdr found)))
827 (calc-embedded-active-state 'less))))
828 (aset info 9 (and (eq (car-safe temp) 'calcFunc-assign)
829 (nth 1 temp)))
830 (if (memq (car-safe val) '(calcFunc-evalto calcFunc-assign))
831 (calc-embedded-find-vars val))
adb0a616 832 (aset info 10 calc-embed-vars-used)
136211a9
EZ
833 (aset info 11 nil))))
834 (if new-info
835 (progn
836 (setcdr found (cons info (cdr found)))
837 (calc-embedded-active-state 'more)))
bf77c646 838 info))
136211a9
EZ
839
840(defun calc-embedded-find-vars (x)
841 (cond ((Math-primp x)
842 (and (eq (car-safe x) 'var)
adb0a616
JB
843 (not (assoc x calc-embed-vars-used))
844 (setq calc-embed-vars-used (cons (list x) calc-embed-vars-used))))
136211a9
EZ
845 ((eq (car x) 'calcFunc-evalto)
846 (calc-embedded-find-vars (nth 1 x)))
847 ((eq (car x) 'calcFunc-assign)
848 (calc-embedded-find-vars (nth 2 x)))
849 (t
850 (and (eq (car x) 'calcFunc-subscr)
851 (eq (car-safe (nth 1 x)) 'var)
852 (Math-primp (nth 2 x))
adb0a616
JB
853 (not (assoc x calc-embed-vars-used))
854 (setq calc-embed-vars-used (cons (list x) calc-embed-vars-used)))
136211a9 855 (while (setq x (cdr x))
bf77c646 856 (calc-embedded-find-vars (car x))))))
136211a9
EZ
857
858
859(defun calc-embedded-evaluate-expr (x)
adb0a616
JB
860 (let ((calc-embed-vars-used (aref calc-embedded-info 10)))
861 (or calc-embed-vars-used (calc-embedded-find-vars x))
862 (if calc-embed-vars-used
136211a9
EZ
863 (let ((active (assq (aref calc-embedded-info 0) calc-embedded-active))
864 (args nil))
865 (save-excursion
866 (calc-embedded-original-buffer t)
867 (or active
868 (progn
869 (calc-embedded-activate)
870 (setq active (assq (aref calc-embedded-info 0)
871 calc-embedded-active))))
adb0a616
JB
872 (while calc-embed-vars-used
873 (calc-embedded-eval-get-var (car (car calc-embed-vars-used)) active)
874 (setq calc-embed-vars-used (cdr calc-embed-vars-used))))
136211a9 875 (calc-embedded-subst x))
bf77c646 876 (calc-normalize (math-evaluate-expr-rec x)))))
136211a9
EZ
877
878(defun calc-embedded-subst (x)
879 (if (and (eq (car-safe x) 'calcFunc-evalto) (cdr x))
880 (let ((rhs (calc-embedded-subst (nth 1 x))))
881 (list 'calcFunc-evalto
882 (nth 1 x)
883 (if (eq (car-safe rhs) 'calcFunc-assign) (nth 2 rhs) rhs)))
884 (if (and (eq (car-safe x) 'calcFunc-assign) (= (length x) 3))
885 (list 'calcFunc-assign
886 (nth 1 x)
887 (calc-embedded-subst (nth 2 x)))
bf77c646 888 (calc-normalize (math-evaluate-expr-rec (math-multi-subst-rec x))))))
136211a9
EZ
889
890(defun calc-embedded-eval-get-var (var base)
891 (let ((entry base)
892 (point (aref calc-embedded-info 2))
893 (last nil)
894 val)
895 (while (and (setq entry (cdr entry))
896 (or (not (equal var (aref (car entry) 9)))
897 (and (> point (aref (car entry) 3))
898 (setq last entry)))))
899 (if last
900 (setq entry last))
901 (if entry
902 (progn
903 (setq entry (car entry))
904 (if (equal (buffer-substring (aref entry 2) (aref entry 3))
905 (aref entry 6))
906 (progn
907 (or (aref entry 11)
908 (save-excursion
909 (calc-embedded-update entry 14 t nil)))
910 (setq val (aref entry 11))
911 (if (eq (car-safe val) 'calcFunc-evalto)
912 (setq val (nth 2 val)))
913 (if (eq (car-safe val) 'calcFunc-assign)
914 (setq val (nth 2 val)))
915 (setq args (cons (cons var val) args)))
916 (calc-embedded-activate)
bf77c646 917 (calc-embedded-eval-get-var var base))))))
136211a9
EZ
918
919
920(defun calc-embedded-update (info which need-eval need-display
921 &optional str entry old-val)
adb0a616 922 (let* ((calc-embed-prev-modes nil)
136211a9
EZ
923 (open-plain calc-embedded-open-plain)
924 (close-plain calc-embedded-close-plain)
adb0a616 925 (calc-embed-vars-used nil)
136211a9
EZ
926 (evalled nil)
927 (val (aref info 8))
928 (old-eval (aref info 11)))
929 (or old-val (setq old-val val))
930 (if (eq (car-safe val) 'calcFunc-evalto)
931 (setq need-display t))
932 (unwind-protect
933 (progn
934 (set-buffer (aref info 1))
935 (and which
936 (calc-embedded-set-modes (aref info 15) (aref info 12)
937 (aref info which)
938 (if need-display 'full t)))
939 (if (memq (car-safe val) '(calcFunc-evalto calcFunc-assign))
940 (calc-embedded-find-vars val))
941 (if need-eval
942 (let ((calc-embedded-info info))
943 (setq val (math-evaluate-expr val)
944 evalled val)))
945 (if (or (eq need-eval 'eval) (eq (car-safe val) 'calcFunc-evalto))
946 (aset info 8 val))
947 (aset info 9 nil)
adb0a616 948 (aset info 10 calc-embed-vars-used)
136211a9
EZ
949 (aset info 11 nil)
950 (if (or need-display (eq (car-safe val) 'calcFunc-evalto))
951 (let ((extra (if (eq calc-language 'big) 1 0)))
952 (or entry (setq entry (list val 1 nil)))
953 (or str (progn
954 (setq str (let ((calc-line-numbering nil))
955 (math-format-stack-value entry)))
956 (if (eq calc-language 'big)
957 (setq str (substring str 0 -1)))))
958 (and calc-show-plain
959 (setq str (concat open-plain
960 (math-showing-full-precision
961 (math-format-flat-expr val 0))
962 close-plain
963 str)))
964 (save-excursion
965 (calc-embedded-original-buffer t info)
966 (or (equal str (aref info 6))
967 (let ((delta (- (aref info 5) (aref info 3)))
968 (buffer-read-only nil))
969 (goto-char (aref info 2))
970 (delete-region (point) (aref info 3))
971 (and (> (nth 1 entry) (1+ extra))
972 (aref info 7)
973 (progn
974 (aset info 7 nil)
975 (delete-horizontal-space)
976 (insert "\n\n")
977 (delete-horizontal-space)
978 (backward-char 1)))
979 (insert str)
980 (set-marker (aref info 3) (point))
981 (set-marker (aref info 5) (+ (point) delta))
982 (aset info 6 str))))))
983 (if (eq (car-safe val) 'calcFunc-evalto)
984 (progn
985 (setq evalled (nth 2 val)
986 val (nth 1 val))))
987 (if (eq (car-safe val) 'calcFunc-assign)
988 (progn
989 (aset info 9 (nth 1 val))
990 (aset info 11 (or evalled
991 (let ((calc-embedded-info info))
992 (math-evaluate-expr (nth 2 val)))))
993 (or (equal old-eval (aref info 11))
994 (calc-embedded-var-change (nth 1 val) (aref info 0))))
995 (if (eq (car-safe old-val) 'calcFunc-evalto)
996 (setq old-val (nth 1 old-val)))
997 (if (eq (car-safe old-val) 'calcFunc-assign)
998 (calc-embedded-var-change (nth 1 old-val) (aref info 0)))))
999 (set-buffer (aref info 1))
adb0a616
JB
1000 (while calc-embed-prev-modes
1001 (cond ((eq (car (car calc-embed-prev-modes)) 'the-language)
136211a9 1002 (if need-display
adb0a616
JB
1003 (calc-embedded-set-language (cdr (car calc-embed-prev-modes)))))
1004 ((eq (car (car calc-embed-prev-modes)) 'the-display-just)
136211a9 1005 (if need-display
adb0a616 1006 (calc-embedded-set-justify (cdr (car calc-embed-prev-modes)))))
136211a9 1007 (t
adb0a616
JB
1008 (set (car (car calc-embed-prev-modes))
1009 (cdr (car calc-embed-prev-modes)))))
b9bc92b4 1010 (setq calc-embed-prev-modes (cdr calc-embed-prev-modes))))))
136211a9
EZ
1011
1012
1013
1014
1015;;; These are hooks called by the main part of Calc.
1016
3132f345 1017(defvar calc-embedded-no-reselect nil)
136211a9
EZ
1018(defun calc-embedded-select-buffer ()
1019 (if (eq (current-buffer) (aref calc-embedded-info 0))
1020 (let ((info calc-embedded-info)
1021 horiz vert)
1022 (if (and (or (< (point) (aref info 4))
1023 (> (point) (aref info 5)))
1024 (not calc-embedded-no-reselect))
1025 (let ((calc-embedded-quiet t))
1026 (message "(Switching Calc Embedded mode to new formula.)")
1027 (calc-embedded nil)
1028 (calc-embedded nil)))
1029 (setq horiz (max (min (current-column) (- (point) (aref info 2))) 0)
1030 vert (if (<= (aref info 2) (point))
1031 (- (count-lines (aref info 2) (point))
1032 (if (bolp) 0 1))
1033 0))
1034 (set-buffer (aref info 1))
1035 (if calc-show-plain
1036 (if (= vert 0)
1037 (setq horiz 0)
1038 (setq vert (1- vert))))
1039 (calc-cursor-stack-index 1)
1040 (if calc-line-numbering
1041 (setq horiz (+ horiz 4)))
1042 (if (> vert 0)
1043 (forward-line vert))
1044 (forward-char (min horiz
1045 (- (point-max) (point)))))
bf77c646 1046 (calc-select-buffer)))
136211a9
EZ
1047
1048(defun calc-embedded-finish-command ()
1049 (let ((buf (current-buffer))
1050 horiz vert)
1051 (save-excursion
1052 (set-buffer (aref calc-embedded-info 1))
1053 (if (> (calc-stack-size) 0)
1054 (let ((pt (point))
1055 (col (current-column))
1056 (bol (bolp)))
1057 (calc-cursor-stack-index 0)
1058 (if (< pt (point))
1059 (progn
1060 (calc-cursor-stack-index 1)
1061 (if (>= pt (point))
1062 (progn
1063 (setq horiz (- col (if calc-line-numbering 4 0))
1064 vert (- (count-lines (point) pt)
1065 (if bol 0 1)))
1066 (if calc-show-plain
1067 (setq vert (max 1 (1+ vert))))))))
1068 (goto-char pt))))
1069 (if horiz
1070 (progn
1071 (set-buffer (aref calc-embedded-info 0))
1072 (goto-char (aref calc-embedded-info 2))
1073 (if (> vert 0)
1074 (forward-line vert))
1075 (forward-char (max horiz 0))
bf77c646 1076 (set-buffer buf)))))
136211a9
EZ
1077
1078(defun calc-embedded-stack-change ()
1079 (or calc-executing-macro
1080 (save-excursion
1081 (set-buffer (aref calc-embedded-info 1))
1082 (let* ((info calc-embedded-info)
1083 (extra-line (if (eq calc-language 'big) 1 0))
1084 (the-point (point))
1085 (empty (= (calc-stack-size) 0))
1086 (entry (if empty
1087 (list '(var empty var-empty) 1 nil)
1088 (calc-top 1 'entry)))
1089 (old-val (aref info 8))
1090 top bot str)
1091 (if empty
1092 (setq str "empty")
1093 (save-excursion
1094 (calc-cursor-stack-index 1)
1095 (setq top (point))
1096 (calc-cursor-stack-index 0)
1097 (setq bot (- (point) extra-line))
1098 (setq str (buffer-substring top (- bot 1))))
1099 (if calc-line-numbering
1100 (let ((pos 0))
1101 (setq str (substring str 4))
1102 (while (setq pos (string-match "\n...." str pos))
1103 (setq str (concat (substring str 0 (1+ pos))
1104 (substring str (+ pos 5)))
1105 pos (1+ pos))))))
1106 (calc-embedded-original-buffer t)
1107 (aset info 8 (car entry))
bf77c646 1108 (calc-embedded-update info 13 nil t str entry old-val)))))
136211a9
EZ
1109
1110(defun calc-embedded-mode-line-change ()
1111 (let ((str mode-line-buffer-identification))
1112 (save-excursion
1113 (calc-embedded-original-buffer t)
1114 (setq mode-line-buffer-identification str)
bf77c646 1115 (set-buffer-modified-p (buffer-modified-p)))))
136211a9
EZ
1116
1117(defun calc-embedded-modes-change (vars)
1118 (if (eq (car vars) 'calc-language) (setq vars '(the-language)))
1119 (if (eq (car vars) 'calc-display-just) (setq vars '(the-display-just)))
1120 (while (and vars
1121 (not (rassq (car vars) calc-embedded-mode-vars)))
1122 (setq vars (cdr vars)))
1123 (if (and vars calc-mode-save-mode (not (eq calc-mode-save-mode 'save)))
1124 (save-excursion
1125 (let* ((save-mode calc-mode-save-mode)
1126 (header (if (eq save-mode 'local)
1127 "calc-mode:"
1128 (format "calc-%s-mode:" save-mode)))
1129 (the-language (calc-embedded-language))
1130 (the-display-just (calc-embedded-justify))
1131 (values (mapcar 'symbol-value vars))
1132 (num (cond ((eq save-mode 'local) 12)
1133 ((eq save-mode 'edit) 13)
1134 ((eq save-mode 'perm) 14)
1135 (t nil)))
1136 base limit mname mlist)
1137 (calc-embedded-original-buffer t)
1138 (save-excursion
1139 (if (eq save-mode 'global)
1140 (setq base (point-max)
1141 limit (point-min)
1142 mlist calc-embedded-globals)
1143 (goto-char (aref calc-embedded-info 4))
1144 (beginning-of-line)
1145 (setq base (point)
1146 limit (max (- (point) 1000) (point-min))
1147 mlist (and num (aref calc-embedded-info num)))
1148 (and (re-search-backward
1149 (format "\\(%s\\)[^\001]*\\(%s\\)\\|\\[calc-defaults]"
1150 calc-embedded-open-formula
1151 calc-embedded-close-formula) limit t)
1152 (setq limit (point))))
1153 (while vars
1154 (goto-char base)
1155 (if (setq mname (car (rassq (car vars)
1156 calc-embedded-mode-vars)))
1157 (let ((buffer-read-only nil)
1158 (found (assq (car vars) mlist)))
1159 (if found
1160 (setcdr found (car values))
1161 (setq mlist (cons (cons (car vars) (car values)) mlist))
1162 (if num
1163 (aset calc-embedded-info num mlist)
1164 (if (eq save-mode 'global)
1165 (setq calc-embedded-globals mlist))))
1166 (if (re-search-backward
1167 (format "\\[%s *%s: *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]"
1168 header mname)
1169 limit t)
1170 (progn
1171 (goto-char (match-beginning 1))
1172 (delete-region (point) (match-end 1))
1173 (insert (prin1-to-string (car values))))
1174 (goto-char base)
1175 (insert-before-markers
1176 calc-embedded-open-mode
1177 "[" header " " mname ": "
1178 (prin1-to-string (car values)) "]"
1179 calc-embedded-close-mode))))
1180 (setq vars (cdr vars)
bf77c646 1181 values (cdr values))))))))
136211a9
EZ
1182
1183(defun calc-embedded-var-change (var &optional buf)
1184 (if (symbolp var)
1185 (setq var (list 'var
1186 (if (string-match "\\`var-.+\\'"
1187 (symbol-name var))
1188 (intern (substring (symbol-name var) 4))
1189 var)
1190 var)))
1191 (save-excursion
1192 (let ((manual (not calc-auto-recompute))
1193 (bp calc-embedded-active)
1194 (first t))
1195 (if buf (setq bp (memq (assq buf bp) bp)))
1196 (while bp
1197 (let ((calc-embedded-no-reselect t)
1198 (p (and (buffer-name (car (car bp)))
1199 (cdr (car bp)))))
1200 (while p
1201 (if (assoc var (aref (car p) 10))
1202 (if manual
1203 (if (aref (car p) 11)
1204 (progn
1205 (aset (car p) 11 nil)
1206 (if (aref (car p) 9)
1207 (calc-embedded-var-change (aref (car p) 9)))))
1208 (set-buffer (aref (car p) 0))
1209 (if (equal (buffer-substring (aref (car p) 2)
1210 (aref (car p) 3))
1211 (aref (car p) 6))
1212 (let ((calc-embedded-info nil))
1213 (or calc-embedded-quiet
1214 (message "Recomputing..."))
1215 (setq first nil)
1216 (calc-wrapper
1217 (set-buffer (aref (car p) 0))
1218 (calc-embedded-update (car p) 14 t nil)))
1219 (setcdr (car bp) (delq (car p) (cdr (car bp))))
1220 (message
3132f345 1221 "(Tried to recompute but formula was changed or missing)"))))
136211a9
EZ
1222 (setq p (cdr p))))
1223 (setq bp (if buf nil (cdr bp))))
bf77c646 1224 (or first calc-embedded-quiet (message "")))))
136211a9 1225
937640a6
JB
1226(provide 'calc-embed)
1227
ab5796a9 1228;;; arch-tag: 1b8f311e-fba1-40d3-b8c3-1d6f68fd26fc
bf77c646 1229;;; calc-embed.el ends here