]> code.delx.au - gnu-emacs/blob - lisp/calc/calc-embed.el
(calc-embedded-finish-edit): Use calc-edit-top for the beginning of
[gnu-emacs] / lisp / calc / calc-embed.el
1 ;;; calc-embed.el --- embed Calc in a buffer
2
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc.
4
5 ;; Author: David Gillespie <daveg@synaptics.com>
6 ;; Maintainer: Jay Belanger <belanger@truman.edu>
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
25 ;;; Commentary:
26
27 ;;; Code:
28
29 ;; This file is autoloaded from calc-ext.el.
30
31 (require 'calc-ext)
32 (require 'calc-macs)
33
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)
39 "Including \"plain\" formulas in Calc Embedded mode"
40 "Omitting \"plain\" formulas in Calc Embedded mode"))))
41
42
43 (defvar calc-embedded-modes nil)
44 (defvar calc-embedded-globals nil)
45 (defvar calc-embedded-active nil)
46 (defvar calc-embedded-all-active nil)
47 (make-variable-buffer-local 'calc-embedded-all-active)
48 (defvar calc-embedded-some-active nil)
49 (make-variable-buffer-local 'calc-embedded-some-active)
50
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
53 calc-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
57 calc-embedded.")
58
59 (defvar calc-embedded-open-word "^\\|[^-+0-9.eE]"
60 "*A regular expression for the opening delimiter of a formula used by
61 calc-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
65 calc-embedded-word.")
66
67 (defvar calc-embedded-open-plain "%%% "
68 "*A string which is the opening delimiter for a \"plain\" formula.
69 If calc-show-plain mode is enabled, this is inserted at the front of
70 each formula.")
71
72 (defvar calc-embedded-close-plain " %%%\n"
73 "*A string which is the closing delimiter for a \"plain\" formula.
74 See 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.
87 This 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.
91 This 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
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)
162
163 (defvar calc-embedded-quiet nil)
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
197 (message "Back to %s mode" mode-name))))
198
199 (t
200 (if (buffer-name (aref calc-embedded-info 0))
201 (save-excursion
202 (set-buffer (aref calc-embedded-info 0))
203 (or (y-or-n-p (format "Cancel Calc Embedded mode in buffer %s? "
204 (buffer-name)))
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))
214 calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot
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)
248 (message "Embedded Calc mode enabled; %s to return to normal"
249 (if calc-embedded-quiet
250 "Type `M-# x'"
251 "Give this command again")))))
252 (scroll-down 0)) ; fix a bug which occurs when truncate-lines is changed.
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)))
266 (calc-select-part 2)))
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))
292 (goto-char (+ (aref info 4) pt))))))))
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
305 (math-format-nice-expr (aref info 8) (frame-width))))
306 (calc-edit-mode (list 'calc-embedded-finish-edit info))
307 (insert str "\n")))
308 (calc-show-edit-buffer))
309
310 (defvar calc-original-buffer)
311 (defvar calc-edit-top)
312 (defun calc-embedded-finish-edit (info)
313 (let ((buf (current-buffer))
314 (str (buffer-substring calc-edit-top (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)
330 (calc-embedded-update info 14 t t))))
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)
338 (message "Deactivating %s for Calc Embedded mode" (buffer-name))
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)
353 ;;; (if (looking-at calc-embedded-open-formula)
354 ;;; (goto-char (match-end 1)))
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)))
359 (calc-embedded-active-state t))
360
361 (defun calc-plain-buffer-only ()
362 (if (memq major-mode '(calc-mode calc-trail-mode calc-edit-mode))
363 (error "This command should be used in a normal editing buffer")))
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))))
377 (set-buffer-modified-p (buffer-modified-p)))
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
386 (set-buffer (aref info 0))))
387
388 (defun calc-embedded-word ()
389 (interactive)
390 (calc-embedded '(4)))
391
392 (defun calc-embedded-mark-formula (&optional body-only)
393 "Put point at the beginning of this Calc formula, mark at the end.
394 This normally marks the whole formula, including surrounding delimiters.
395 With 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"))
399 (let (calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot)
400 (save-excursion
401 (calc-embedded-find-bounds body-only))
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))))
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))
418 (setq calc-embed-outer-top (point))
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))))
430 (setq calc-embed-top (point))
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))
437 (setq calc-embed-outer-bot (point))
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)))
444 (setq calc-embed-bot (point))))
445
446 (defun calc-embedded-kill-formula ()
447 "Kill the formula surrounding point.
448 If Calc Embedded mode was active, this deactivates it.
449 The formula (including its surrounding delimiters) is saved in the kill ring.
450 The 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))
456 (pop-mark))
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))
464 (pop-mark)))
465
466 (defun calc-embedded-duplicate ()
467 (interactive)
468 (let ((already calc-embedded-info)
469 calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot new-top)
470 (if calc-embedded-info
471 (progn
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)))
476 (calc-embedded nil))
477 (calc-embedded-find-bounds))
478 (goto-char calc-embed-outer-bot)
479 (insert "\n")
480 (setq new-top (point))
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)))
484 (let ((calc-embedded-quiet (if already t 'x)))
485 (calc-embedded (+ new-top (- calc-embed-top calc-embed-outer-top))
486 (+ new-top (- calc-embed-bot calc-embed-outer-top))
487 new-top
488 (+ new-top (- calc-embed-outer-bot calc-embed-outer-top))))))
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))))
515 (goto-char (aref (car (or p active)) 2))))))
516
517 (defun calc-embedded-previous (arg)
518 (interactive "p")
519 (calc-embedded-next (- (prefix-numeric-value arg))))
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))
527 (let (calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot)
528 (if (and (eq (preceding-char) ?\n)
529 (string-match "\\`\n" calc-embedded-open-new-formula))
530 (progn
531 (setq calc-embed-outer-top (1- (point)))
532 (forward-char -1)
533 (insert (substring calc-embedded-open-new-formula 1)))
534 (setq calc-embed-outer-top (point))
535 (insert calc-embedded-open-new-formula))
536 (setq calc-embed-top (point))
537 (insert " ")
538 (setq calc-embed-bot (point))
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))
543 (setq calc-embed-outer-bot (point))
544 (goto-char calc-embed-top)
545 (let ((calc-embedded-quiet 'x))
546 (calc-embedded calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot))))
547
548 (defun calc-embedded-forget ()
549 (interactive)
550 (setq calc-embedded-active (delq (assq (current-buffer) calc-embedded-active)
551 calc-embedded-active))
552 (calc-embedded-active-state nil))
553
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)
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)
572 (setq value (list (nth 1 (assq (car (car v)) calc-mode-var-list)))))
573 (equal (symbol-value (car (car v))) value))
574 (progn
575 (setq changed t)
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)))
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)
590 (if temp (setq calc-embed-prev-modes (cons (cons (car (car v))
591 (symbol-value (car (car v))))
592 calc-embed-prev-modes)))
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)
601 (if temp (setq calc-embed-prev-modes (cons (cons (car (car v))
602 (symbol-value (car (car v))))
603 calc-embed-prev-modes)))
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)))
618 changed))
619
620 (defun calc-embedded-language ()
621 (if calc-language-option
622 (list calc-language calc-language-option)
623 calc-language))
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))
632 (calc-set-language lang option t))))
633
634 (defun calc-embedded-justify ()
635 (if calc-display-origin
636 (list calc-display-just calc-display-origin)
637 calc-display-just))
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
644 calc-display-origin nil)))
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))
669 (goto-char save-pt)))
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)
718 (list modes emodes pmodes)))
719
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)
724
725 (defun calc-embedded-make-info (point cbuf fresh &optional
726 calc-embed-top calc-embed-bot
727 calc-embed-outer-top calc-embed-outer-bot)
728 (let* ((bufentry (assq (current-buffer) calc-embedded-active))
729 (found bufentry)
730 (force (and fresh calc-embed-top))
731 (fixed calc-embed-top)
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)))))
750 (if (and (integerp calc-embed-top) (not calc-embed-bot))
751 ; started with a user-supplied argument
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)
763 (setq calc-embed-top (aref info 2)
764 fixed calc-embed-top)
765 (if (consp calc-embed-top)
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))
769 (or calc-embed-top
770 (calc-embedded-find-bounds 'plain)))
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))))))
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))
798 (calc-embed-vars-used nil)
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))
832 (aset info 10 calc-embed-vars-used)
833 (aset info 11 nil))))
834 (if new-info
835 (progn
836 (setcdr found (cons info (cdr found)))
837 (calc-embedded-active-state 'more)))
838 info))
839
840 (defun calc-embedded-find-vars (x)
841 (cond ((Math-primp x)
842 (and (eq (car-safe x) 'var)
843 (not (assoc x calc-embed-vars-used))
844 (setq calc-embed-vars-used (cons (list x) calc-embed-vars-used))))
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))
853 (not (assoc x calc-embed-vars-used))
854 (setq calc-embed-vars-used (cons (list x) calc-embed-vars-used)))
855 (while (setq x (cdr x))
856 (calc-embedded-find-vars (car x))))))
857
858
859 (defun calc-embedded-evaluate-expr (x)
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
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))))
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))))
875 (calc-embedded-subst x))
876 (calc-normalize (math-evaluate-expr-rec x)))))
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)))
888 (calc-normalize (math-evaluate-expr-rec (math-multi-subst-rec x))))))
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)
917 (calc-embedded-eval-get-var var base))))))
918
919
920 (defun calc-embedded-update (info which need-eval need-display
921 &optional str entry old-val)
922 (let* ((calc-embed-prev-modes nil)
923 (open-plain calc-embedded-open-plain)
924 (close-plain calc-embedded-close-plain)
925 (calc-embed-vars-used nil)
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)
948 (aset info 10 calc-embed-vars-used)
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))
1000 (while calc-embed-prev-modes
1001 (cond ((eq (car (car calc-embed-prev-modes)) 'the-language)
1002 (if need-display
1003 (calc-embedded-set-language (cdr (car calc-embed-prev-modes)))))
1004 ((eq (car (car calc-embed-prev-modes)) 'the-display-just)
1005 (if need-display
1006 (calc-embedded-set-justify (cdr (car calc-embed-prev-modes)))))
1007 (t
1008 (set (car (car calc-embed-prev-modes))
1009 (cdr (car calc-embed-prev-modes)))))
1010 (setq calc-embed-prev-modes (cdr calc-embed-prev-modes))))))
1011
1012
1013
1014
1015 ;;; These are hooks called by the main part of Calc.
1016
1017 (defvar calc-embedded-no-reselect nil)
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)))))
1046 (calc-select-buffer)))
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))
1076 (set-buffer buf)))))
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))
1108 (calc-embedded-update info 13 nil t str entry old-val)))))
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)
1115 (set-buffer-modified-p (buffer-modified-p)))))
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)
1181 values (cdr values))))))))
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
1221 "(Tried to recompute but formula was changed or missing)"))))
1222 (setq p (cdr p))))
1223 (setq bp (if buf nil (cdr bp))))
1224 (or first calc-embedded-quiet (message "")))))
1225
1226 (provide 'calc-embed)
1227
1228 ;;; arch-tag: 1b8f311e-fba1-40d3-b8c3-1d6f68fd26fc
1229 ;;; calc-embed.el ends here