]> code.delx.au - gnu-emacs/blob - lisp/calc/calc-embed.el
Add simplification rules for calcFunc-sec, calcFunc-csc, calcFunc-cot,
[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\\|^\\\\begin{.*[^x]}.*\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\\|^\\\\end{.*[^x]}.*\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 (looking-at "[ \t]*$")
421 (end-of-line))
422 (if (eq (following-char) ?\n)
423 (forward-char 1))
424 (or (bolp)
425 (while (eq (following-char) ?\ )
426 (forward-char 1)))
427 (or (eq plain 'plain)
428 (if (looking-at (regexp-quote calc-embedded-open-plain))
429 (progn
430 (goto-char (match-end 0))
431 (search-forward calc-embedded-close-plain))))
432 (setq calc-embed-top (point))
433 (or (re-search-forward calc-embedded-close-formula nil t)
434 (error "Can't find end of formula"))
435 (if (< (point) home)
436 (error "Not inside a formula"))
437 (and (eq (following-char) ?\n) (not (bolp))
438 (forward-char 1))
439 (setq calc-embed-outer-bot (point))
440 (goto-char (match-beginning 0))
441 (if (eq (preceding-char) ?\n)
442 (backward-char 1))
443 (or (eolp)
444 (while (eq (preceding-char) ?\ )
445 (backward-char 1)))
446 (setq calc-embed-bot (point))))
447
448 (defun calc-embedded-kill-formula ()
449 "Kill the formula surrounding point.
450 If Calc Embedded mode was active, this deactivates it.
451 The formula (including its surrounding delimiters) is saved in the kill ring.
452 The command \\[yank] can retrieve it from there."
453 (interactive)
454 (and calc-embedded-info
455 (calc-embedded nil))
456 (calc-embedded-mark-formula)
457 (kill-region (point) (mark))
458 (pop-mark))
459
460 (defun calc-embedded-copy-formula-as-kill ()
461 "Save the formula surrounding point as if killed, but don't kill it."
462 (interactive)
463 (save-excursion
464 (calc-embedded-mark-formula)
465 (copy-region-as-kill (point) (mark))
466 (pop-mark)))
467
468 (defun calc-embedded-duplicate ()
469 (interactive)
470 (let ((already calc-embedded-info)
471 calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot new-top)
472 (if calc-embedded-info
473 (progn
474 (setq calc-embed-top (+ (aref calc-embedded-info 2))
475 calc-embed-bot (+ (aref calc-embedded-info 3))
476 calc-embed-outer-top (+ (aref calc-embedded-info 4))
477 calc-embed-outer-bot (+ (aref calc-embedded-info 5)))
478 (calc-embedded nil))
479 (calc-embedded-find-bounds))
480 (goto-char calc-embed-outer-bot)
481 (insert "\n")
482 (setq new-top (point))
483 (insert-buffer-substring (current-buffer)
484 calc-embed-outer-top calc-embed-outer-bot)
485 (goto-char (+ new-top (- calc-embed-top calc-embed-outer-top)))
486 (let ((calc-embedded-quiet (if already t 'x)))
487 (calc-embedded (+ new-top (- calc-embed-top calc-embed-outer-top))
488 (+ new-top (- calc-embed-bot calc-embed-outer-top))
489 new-top
490 (+ new-top (- calc-embed-outer-bot calc-embed-outer-top))))))
491
492 (defun calc-embedded-next (arg)
493 (interactive "P")
494 (setq arg (prefix-numeric-value arg))
495 (let* ((active (cdr (assq (current-buffer) calc-embedded-active)))
496 (p active)
497 (num (length active)))
498 (or active
499 (error "No active formulas in buffer"))
500 (cond ((= arg 0))
501 ((= arg -1)
502 (if (<= (point) (aref (car active) 3))
503 (goto-char (aref (nth (1- num) active) 2))
504 (while (and (cdr p)
505 (> (point) (aref (nth 1 p) 3)))
506 (setq p (cdr p)))
507 (goto-char (aref (car p) 2))))
508 ((< arg -1)
509 (calc-embedded-next -1)
510 (calc-embedded-next (+ (* num 1000) arg 1)))
511 (t
512 (setq arg (1+ (% (1- arg) num)))
513 (while (and p (>= (point) (aref (car p) 2)))
514 (setq p (cdr p)))
515 (while (> (setq arg (1- arg)) 0)
516 (setq p (if p (cdr p) (cdr active))))
517 (goto-char (aref (car (or p active)) 2))))))
518
519 (defun calc-embedded-previous (arg)
520 (interactive "p")
521 (calc-embedded-next (- (prefix-numeric-value arg))))
522
523 (defun calc-embedded-new-formula ()
524 (interactive)
525 (and (eq major-mode 'calc-mode)
526 (error "This command should be used in a normal editing buffer"))
527 (if calc-embedded-info
528 (calc-embedded nil))
529 (let (calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot)
530 (if (and (eq (preceding-char) ?\n)
531 (string-match "\\`\n" calc-embedded-open-new-formula))
532 (progn
533 (setq calc-embed-outer-top (1- (point)))
534 (forward-char -1)
535 (insert (substring calc-embedded-open-new-formula 1)))
536 (setq calc-embed-outer-top (point))
537 (insert calc-embedded-open-new-formula))
538 (setq calc-embed-top (point))
539 (insert " ")
540 (setq calc-embed-bot (point))
541 (insert calc-embedded-close-new-formula)
542 (if (and (eq (following-char) ?\n)
543 (string-match "\n\\'" calc-embedded-close-new-formula))
544 (delete-char 1))
545 (setq calc-embed-outer-bot (point))
546 (goto-char calc-embed-top)
547 (let ((calc-embedded-quiet 'x))
548 (calc-embedded calc-embed-top calc-embed-bot calc-embed-outer-top calc-embed-outer-bot))))
549
550 (defun calc-embedded-forget ()
551 (interactive)
552 (setq calc-embedded-active (delq (assq (current-buffer) calc-embedded-active)
553 calc-embedded-active))
554 (calc-embedded-active-state nil))
555
556 ;; The variables calc-embed-prev-modes is local to calc-embedded-update,
557 ;; but is used by calc-embedded-set-modes.
558 (defvar calc-embed-prev-modes)
559
560 (defun calc-embedded-set-modes (gmodes modes local-modes &optional temp)
561 (let ((the-language (calc-embedded-language))
562 (the-display-just (calc-embedded-justify))
563 (v gmodes)
564 (changed nil)
565 found value)
566 (while v
567 (or (symbolp (car v))
568 (and (setq found (assq (car (car v)) modes))
569 (not (eq (cdr found) 'default)))
570 (and (setq found (assq (car (car v)) local-modes))
571 (not (eq (cdr found) 'default)))
572 (progn
573 (if (eq (setq value (cdr (car v))) 'default)
574 (setq value (list (nth 1 (assq (car (car v)) calc-mode-var-list)))))
575 (equal (symbol-value (car (car v))) value))
576 (progn
577 (setq changed t)
578 (if temp (setq calc-embed-prev-modes
579 (cons (cons (car (car v))
580 (symbol-value (car (car v))))
581 calc-embed-prev-modes)))
582 (set (car (car v)) value)))
583 (setq v (cdr v)))
584 (setq v modes)
585 (while v
586 (or (and (setq found (assq (car (car v)) local-modes))
587 (not (eq (cdr found) 'default)))
588 (eq (setq value (cdr (car v))) 'default)
589 (equal (symbol-value (car (car v))) value)
590 (progn
591 (setq changed t)
592 (if temp (setq calc-embed-prev-modes (cons (cons (car (car v))
593 (symbol-value (car (car v))))
594 calc-embed-prev-modes)))
595 (set (car (car v)) value)))
596 (setq v (cdr v)))
597 (setq v local-modes)
598 (while v
599 (or (eq (setq value (cdr (car v))) 'default)
600 (equal (symbol-value (car (car v))) value)
601 (progn
602 (setq changed t)
603 (if temp (setq calc-embed-prev-modes (cons (cons (car (car v))
604 (symbol-value (car (car v))))
605 calc-embed-prev-modes)))
606 (set (car (car v)) value)))
607 (setq v (cdr v)))
608 (and changed (not (eq temp t))
609 (progn
610 (calc-embedded-set-justify the-display-just)
611 (calc-embedded-set-language the-language)))
612 (and changed (not temp)
613 (progn
614 (setq calc-full-float-format (list (if (eq (car calc-float-format)
615 'fix)
616 'float
617 (car calc-float-format))
618 0))
619 (calc-refresh)))
620 changed))
621
622 (defun calc-embedded-language ()
623 (if calc-language-option
624 (list calc-language calc-language-option)
625 calc-language))
626
627 (defun calc-embedded-set-language (lang)
628 (let ((option nil))
629 (if (consp lang)
630 (setq option (nth 1 lang)
631 lang (car lang)))
632 (or (and (eq lang calc-language)
633 (equal option calc-language-option))
634 (calc-set-language lang option t))))
635
636 (defun calc-embedded-justify ()
637 (if calc-display-origin
638 (list calc-display-just calc-display-origin)
639 calc-display-just))
640
641 (defun calc-embedded-set-justify (just)
642 (if (consp just)
643 (setq calc-display-origin (nth 1 just)
644 calc-display-just (car just))
645 (setq calc-display-just just
646 calc-display-origin nil)))
647
648
649 (defun calc-find-globals ()
650 (interactive)
651 (and (eq major-mode 'calc-mode)
652 (error "This command should be used in a normal editing buffer"))
653 (make-local-variable 'calc-embedded-globals)
654 (let ((case-fold-search nil)
655 (modes nil)
656 (save-pt (point))
657 found value)
658 (goto-char (point-min))
659 (while (re-search-forward "\\[calc-global-mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)\\]" nil t)
660 (and (setq found (assoc (buffer-substring (match-beginning 1)
661 (match-end 1))
662 calc-embedded-mode-vars))
663 (or (assq (cdr found) modes)
664 (setq modes (cons (cons (cdr found)
665 (car (read-from-string
666 (buffer-substring
667 (match-beginning 2)
668 (match-end 2)))))
669 modes)))))
670 (setq calc-embedded-globals (cons t modes))
671 (goto-char save-pt)))
672
673 (defun calc-embedded-find-modes ()
674 (let ((case-fold-search nil)
675 (save-pt (point))
676 (no-defaults t)
677 (modes nil)
678 (emodes nil)
679 (pmodes nil)
680 found value)
681 (while (and no-defaults (search-backward "[calc-" nil t))
682 (forward-char 6)
683 (or (and (looking-at "mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]")
684 (setq found (assoc (buffer-substring (match-beginning 1)
685 (match-end 1))
686 calc-embedded-mode-vars))
687 (or (assq (cdr found) modes)
688 (setq modes (cons (cons (cdr found)
689 (car (read-from-string
690 (buffer-substring
691 (match-beginning 2)
692 (match-end 2)))))
693 modes))))
694 (and (looking-at "perm-mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]")
695 (setq found (assoc (buffer-substring (match-beginning 1)
696 (match-end 1))
697 calc-embedded-mode-vars))
698 (or (assq (cdr found) pmodes)
699 (setq pmodes (cons (cons (cdr found)
700 (car (read-from-string
701 (buffer-substring
702 (match-beginning 2)
703 (match-end 2)))))
704 pmodes))))
705 (and (looking-at "edit-mode: *\\([-a-z]+\\): *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]")
706 (setq found (assoc (buffer-substring (match-beginning 1)
707 (match-end 1))
708 calc-embedded-mode-vars))
709 (or (assq (cdr found) emodes)
710 (setq emodes (cons (cons (cdr found)
711 (car (read-from-string
712 (buffer-substring
713 (match-beginning 2)
714 (match-end 2)))))
715 emodes))))
716 (and (looking-at "defaults]")
717 (setq no-defaults nil)))
718 (backward-char 6))
719 (goto-char save-pt)
720 (list modes emodes pmodes)))
721
722 ;; The variable calc-embed-vars-used is local to calc-embedded-make-info,
723 ;; calc-embedded-evaluate-expr and calc-embedded-update, but is
724 ;; used by calc-embedded-find-vars, which is called by the above functions.
725 (defvar calc-embed-vars-used)
726
727 (defun calc-embedded-make-info (point cbuf fresh &optional
728 calc-embed-top calc-embed-bot
729 calc-embed-outer-top calc-embed-outer-bot)
730 (let* ((bufentry (assq (current-buffer) calc-embedded-active))
731 (found bufentry)
732 (force (and fresh calc-embed-top))
733 (fixed calc-embed-top)
734 (new-info nil)
735 info str)
736 (or found
737 (setq found (list (current-buffer))
738 calc-embedded-active (cons found calc-embedded-active)))
739 (while (and (cdr found)
740 (> point (aref (car (cdr found)) 3)))
741 (setq found (cdr found)))
742 (if (and (cdr found)
743 (>= point (aref (nth 1 found) 2)))
744 (setq info (nth 1 found))
745 (setq info (make-vector 16 nil)
746 new-info t
747 fresh t)
748 (aset info 0 (current-buffer))
749 (aset info 1 (or cbuf (save-excursion
750 (calc-create-buffer)
751 (current-buffer)))))
752 (if (and (integerp calc-embed-top) (not calc-embed-bot))
753 ; started with a user-supplied argument
754 (progn
755 (if (= (setq arg (prefix-numeric-value arg)) 0)
756 (progn
757 (aset info 2 (copy-marker (region-beginning)))
758 (aset info 3 (copy-marker (region-end))))
759 (aset info (if (> arg 0) 2 3) (point-marker))
760 (forward-line arg)
761 (aset info (if (> arg 0) 3 2) (point-marker)))
762 (aset info 4 (copy-marker (aref info 2)))
763 (aset info 5 (copy-marker (aref info 3))))
764 (if (aref info 4)
765 (setq calc-embed-top (aref info 2)
766 fixed calc-embed-top)
767 (if (consp calc-embed-top)
768 (let ((calc-embedded-open-formula calc-embedded-open-word)
769 (calc-embedded-close-formula calc-embedded-close-word))
770 (calc-embedded-find-bounds 'plain))
771 (or calc-embed-top
772 (calc-embedded-find-bounds 'plain)))
773 (aset info 2 (copy-marker (min calc-embed-top calc-embed-bot)))
774 (aset info 3 (copy-marker (max calc-embed-top calc-embed-bot)))
775 (aset info 4 (copy-marker (or calc-embed-outer-top (aref info 2))))
776 (aset info 5 (copy-marker (or calc-embed-outer-bot (aref info 3))))))
777 (goto-char (aref info 2))
778 (if new-info
779 (progn
780 (or (bolp) (aset info 7 t))
781 (goto-char (aref info 3))
782 (or (bolp) (eolp) (aset info 7 t))))
783 (if fresh
784 (let ((modes (calc-embedded-find-modes)))
785 (aset info 12 (car modes))
786 (aset info 13 (nth 1 modes))
787 (aset info 14 (nth 2 modes))))
788 (aset info 15 calc-embedded-globals)
789 (setq str (buffer-substring (aref info 2) (aref info 3)))
790 (if (or force
791 (not (equal str (aref info 6))))
792 (if (and fixed (aref info 6))
793 (progn
794 (aset info 4 nil)
795 (calc-embedded-make-info point cbuf nil)
796 (setq new-info nil))
797 (let* ((open-plain calc-embedded-open-plain)
798 (close-plain calc-embedded-close-plain)
799 (pref-len (length open-plain))
800 (calc-embed-vars-used nil)
801 suff-pos val temp)
802 (save-excursion
803 (set-buffer (aref info 1))
804 (calc-embedded-set-modes (aref info 15)
805 (aref info 12) (aref info 14))
806 (if (and (> (length str) pref-len)
807 (equal (substring str 0 pref-len) open-plain)
808 (setq suff-pos (string-match (regexp-quote close-plain)
809 str pref-len)))
810 (setq val (math-read-plain-expr
811 (substring str pref-len suff-pos)))
812 (if (string-match "[^ \t\n]" str)
813 (setq pref-len 0
814 val (math-read-big-expr str))
815 (setq val nil))))
816 (if (eq (car-safe val) 'error)
817 (setq val (list 'error
818 (+ (aref info 2) pref-len (nth 1 val))
819 (nth 2 val))))
820 (aset info 6 str)
821 (aset info 8 val)
822 (setq temp val)
823 (if (eq (car-safe temp) 'calcFunc-evalto)
824 (setq temp (nth 1 temp))
825 (if (eq (car-safe temp) 'error)
826 (if new-info
827 (setq new-info nil)
828 (setcdr found (delq info (cdr found)))
829 (calc-embedded-active-state 'less))))
830 (aset info 9 (and (eq (car-safe temp) 'calcFunc-assign)
831 (nth 1 temp)))
832 (if (memq (car-safe val) '(calcFunc-evalto calcFunc-assign))
833 (calc-embedded-find-vars val))
834 (aset info 10 calc-embed-vars-used)
835 (aset info 11 nil))))
836 (if new-info
837 (progn
838 (setcdr found (cons info (cdr found)))
839 (calc-embedded-active-state 'more)))
840 info))
841
842 (defun calc-embedded-find-vars (x)
843 (cond ((Math-primp x)
844 (and (eq (car-safe x) 'var)
845 (not (assoc x calc-embed-vars-used))
846 (setq calc-embed-vars-used (cons (list x) calc-embed-vars-used))))
847 ((eq (car x) 'calcFunc-evalto)
848 (calc-embedded-find-vars (nth 1 x)))
849 ((eq (car x) 'calcFunc-assign)
850 (calc-embedded-find-vars (nth 2 x)))
851 (t
852 (and (eq (car x) 'calcFunc-subscr)
853 (eq (car-safe (nth 1 x)) 'var)
854 (Math-primp (nth 2 x))
855 (not (assoc x calc-embed-vars-used))
856 (setq calc-embed-vars-used (cons (list x) calc-embed-vars-used)))
857 (while (setq x (cdr x))
858 (calc-embedded-find-vars (car x))))))
859
860
861 (defun calc-embedded-evaluate-expr (x)
862 (let ((calc-embed-vars-used (aref calc-embedded-info 10)))
863 (or calc-embed-vars-used (calc-embedded-find-vars x))
864 (if calc-embed-vars-used
865 (let ((active (assq (aref calc-embedded-info 0) calc-embedded-active))
866 (args nil))
867 (save-excursion
868 (calc-embedded-original-buffer t)
869 (or active
870 (progn
871 (calc-embedded-activate)
872 (setq active (assq (aref calc-embedded-info 0)
873 calc-embedded-active))))
874 (while calc-embed-vars-used
875 (calc-embedded-eval-get-var (car (car calc-embed-vars-used)) active)
876 (setq calc-embed-vars-used (cdr calc-embed-vars-used))))
877 (calc-embedded-subst x))
878 (calc-normalize (math-evaluate-expr-rec x)))))
879
880 (defun calc-embedded-subst (x)
881 (if (and (eq (car-safe x) 'calcFunc-evalto) (cdr x))
882 (let ((rhs (calc-embedded-subst (nth 1 x))))
883 (list 'calcFunc-evalto
884 (nth 1 x)
885 (if (eq (car-safe rhs) 'calcFunc-assign) (nth 2 rhs) rhs)))
886 (if (and (eq (car-safe x) 'calcFunc-assign) (= (length x) 3))
887 (list 'calcFunc-assign
888 (nth 1 x)
889 (calc-embedded-subst (nth 2 x)))
890 (calc-normalize (math-evaluate-expr-rec (math-multi-subst x nil nil))))))
891
892 (defun calc-embedded-eval-get-var (var base)
893 (let ((entry base)
894 (point (aref calc-embedded-info 2))
895 (last nil)
896 val)
897 (while (and (setq entry (cdr entry))
898 (or (not (equal var (aref (car entry) 9)))
899 (and (> point (aref (car entry) 3))
900 (setq last entry)))))
901 (if last
902 (setq entry last))
903 (if entry
904 (progn
905 (setq entry (car entry))
906 (if (equal (buffer-substring (aref entry 2) (aref entry 3))
907 (aref entry 6))
908 (progn
909 (or (aref entry 11)
910 (save-excursion
911 (calc-embedded-update entry 14 t nil)))
912 (setq val (aref entry 11))
913 (if (eq (car-safe val) 'calcFunc-evalto)
914 (setq val (nth 2 val)))
915 (if (eq (car-safe val) 'calcFunc-assign)
916 (setq val (nth 2 val)))
917 (setq args (cons (cons var val) args)))
918 (calc-embedded-activate)
919 (calc-embedded-eval-get-var var base))))))
920
921
922 (defun calc-embedded-update (info which need-eval need-display
923 &optional str entry old-val)
924 (let* ((calc-embed-prev-modes nil)
925 (open-plain calc-embedded-open-plain)
926 (close-plain calc-embedded-close-plain)
927 (calc-embed-vars-used nil)
928 (evalled nil)
929 (val (aref info 8))
930 (old-eval (aref info 11)))
931 (or old-val (setq old-val val))
932 (if (eq (car-safe val) 'calcFunc-evalto)
933 (setq need-display t))
934 (unwind-protect
935 (progn
936 (set-buffer (aref info 1))
937 (and which
938 (calc-embedded-set-modes (aref info 15) (aref info 12)
939 (aref info which)
940 (if need-display 'full t)))
941 (if (memq (car-safe val) '(calcFunc-evalto calcFunc-assign))
942 (calc-embedded-find-vars val))
943 (if need-eval
944 (let ((calc-embedded-info info))
945 (setq val (math-evaluate-expr val)
946 evalled val)))
947 (if (or (eq need-eval 'eval) (eq (car-safe val) 'calcFunc-evalto))
948 (aset info 8 val))
949 (aset info 9 nil)
950 (aset info 10 calc-embed-vars-used)
951 (aset info 11 nil)
952 (if (or need-display (eq (car-safe val) 'calcFunc-evalto))
953 (let ((extra (if (eq calc-language 'big) 1 0)))
954 (or entry (setq entry (list val 1 nil)))
955 (or str (progn
956 (setq str (let ((calc-line-numbering nil))
957 (math-format-stack-value entry)))
958 (if (eq calc-language 'big)
959 (setq str (substring str 0 -1)))))
960 (and calc-show-plain
961 (setq str (concat open-plain
962 (math-showing-full-precision
963 (math-format-flat-expr val 0))
964 close-plain
965 str)))
966 (save-excursion
967 (calc-embedded-original-buffer t info)
968 (or (equal str (aref info 6))
969 (let ((delta (- (aref info 5) (aref info 3)))
970 (adjbot 0)
971 (buffer-read-only nil))
972 (goto-char (aref info 2))
973 (delete-region (point) (aref info 3))
974 (and (> (nth 1 entry) (1+ extra))
975 (aref info 7)
976 (progn
977 (delete-horizontal-space)
978 (if (looking-at "\n")
979 ;; If there's a newline there, don't add one
980 (insert "\n")
981 (insert "\n\n")
982 (delete-horizontal-space)
983 (setq adjbot 1)
984 ; (setq delta (1+ delta))
985 (backward-char 1))))
986 (insert str)
987 (set-marker (aref info 3) (+ (point) adjbot))
988 (set-marker (aref info 5) (+ (point) delta))
989 (aset info 6 str))))))
990 (if (eq (car-safe val) 'calcFunc-evalto)
991 (progn
992 (setq evalled (nth 2 val)
993 val (nth 1 val))))
994 (if (eq (car-safe val) 'calcFunc-assign)
995 (progn
996 (aset info 9 (nth 1 val))
997 (aset info 11 (or evalled
998 (let ((calc-embedded-info info))
999 (math-evaluate-expr (nth 2 val)))))
1000 (or (equal old-eval (aref info 11))
1001 (calc-embedded-var-change (nth 1 val) (aref info 0))))
1002 (if (eq (car-safe old-val) 'calcFunc-evalto)
1003 (setq old-val (nth 1 old-val)))
1004 (if (eq (car-safe old-val) 'calcFunc-assign)
1005 (calc-embedded-var-change (nth 1 old-val) (aref info 0)))))
1006 (set-buffer (aref info 1))
1007 (while calc-embed-prev-modes
1008 (cond ((eq (car (car calc-embed-prev-modes)) 'the-language)
1009 (if need-display
1010 (calc-embedded-set-language (cdr (car calc-embed-prev-modes)))))
1011 ((eq (car (car calc-embed-prev-modes)) 'the-display-just)
1012 (if need-display
1013 (calc-embedded-set-justify (cdr (car calc-embed-prev-modes)))))
1014 (t
1015 (set (car (car calc-embed-prev-modes))
1016 (cdr (car calc-embed-prev-modes)))))
1017 (setq calc-embed-prev-modes (cdr calc-embed-prev-modes))))))
1018
1019
1020
1021
1022 ;;; These are hooks called by the main part of Calc.
1023
1024 (defvar calc-embedded-no-reselect nil)
1025 (defun calc-embedded-select-buffer ()
1026 (if (eq (current-buffer) (aref calc-embedded-info 0))
1027 (let ((info calc-embedded-info)
1028 horiz vert)
1029 (if (and (or (< (point) (aref info 4))
1030 (> (point) (aref info 5)))
1031 (not calc-embedded-no-reselect))
1032 (let ((calc-embedded-quiet t))
1033 (message "(Switching Calc Embedded mode to new formula.)")
1034 (calc-embedded nil)
1035 (calc-embedded nil)))
1036 (setq horiz (max (min (current-column) (- (point) (aref info 2))) 0)
1037 vert (if (<= (aref info 2) (point))
1038 (- (count-lines (aref info 2) (point))
1039 (if (bolp) 0 1))
1040 0))
1041 (set-buffer (aref info 1))
1042 (if calc-show-plain
1043 (if (= vert 0)
1044 (setq horiz 0)
1045 (setq vert (1- vert))))
1046 (calc-cursor-stack-index 1)
1047 (if calc-line-numbering
1048 (setq horiz (+ horiz 4)))
1049 (if (> vert 0)
1050 (forward-line vert))
1051 (forward-char (min horiz
1052 (- (point-max) (point)))))
1053 (calc-select-buffer)))
1054
1055 (defun calc-embedded-finish-command ()
1056 (let ((buf (current-buffer))
1057 horiz vert)
1058 (save-excursion
1059 (set-buffer (aref calc-embedded-info 1))
1060 (if (> (calc-stack-size) 0)
1061 (let ((pt (point))
1062 (col (current-column))
1063 (bol (bolp)))
1064 (calc-cursor-stack-index 0)
1065 (if (< pt (point))
1066 (progn
1067 (calc-cursor-stack-index 1)
1068 (if (>= pt (point))
1069 (progn
1070 (setq horiz (- col (if calc-line-numbering 4 0))
1071 vert (- (count-lines (point) pt)
1072 (if bol 0 1)))
1073 (if calc-show-plain
1074 (setq vert (max 1 (1+ vert))))))))
1075 (goto-char pt))))
1076 (if horiz
1077 (progn
1078 (set-buffer (aref calc-embedded-info 0))
1079 (goto-char (aref calc-embedded-info 2))
1080 (if (> vert 0)
1081 (forward-line vert))
1082 (forward-char (max horiz 0))
1083 (set-buffer buf)))))
1084
1085 (defun calc-embedded-stack-change ()
1086 (or calc-executing-macro
1087 (save-excursion
1088 (set-buffer (aref calc-embedded-info 1))
1089 (let* ((info calc-embedded-info)
1090 (extra-line (if (eq calc-language 'big) 1 0))
1091 (the-point (point))
1092 (empty (= (calc-stack-size) 0))
1093 (entry (if empty
1094 (list '(var empty var-empty) 1 nil)
1095 (calc-top 1 'entry)))
1096 (old-val (aref info 8))
1097 top bot str)
1098 (if empty
1099 (setq str "empty")
1100 (save-excursion
1101 (calc-cursor-stack-index 1)
1102 (setq top (point))
1103 (calc-cursor-stack-index 0)
1104 (setq bot (- (point) extra-line))
1105 (setq str (buffer-substring top (- bot 1))))
1106 (if calc-line-numbering
1107 (let ((pos 0))
1108 (setq str (substring str 4))
1109 (while (setq pos (string-match "\n...." str pos))
1110 (setq str (concat (substring str 0 (1+ pos))
1111 (substring str (+ pos 5)))
1112 pos (1+ pos))))))
1113 (calc-embedded-original-buffer t)
1114 (aset info 8 (car entry))
1115 (calc-embedded-update info 13 nil t str entry old-val)))))
1116
1117 (defun calc-embedded-mode-line-change ()
1118 (let ((str mode-line-buffer-identification))
1119 (save-excursion
1120 (calc-embedded-original-buffer t)
1121 (setq mode-line-buffer-identification str)
1122 (set-buffer-modified-p (buffer-modified-p)))))
1123
1124 (defun calc-embedded-modes-change (vars)
1125 (if (eq (car vars) 'calc-language) (setq vars '(the-language)))
1126 (if (eq (car vars) 'calc-display-just) (setq vars '(the-display-just)))
1127 (while (and vars
1128 (not (rassq (car vars) calc-embedded-mode-vars)))
1129 (setq vars (cdr vars)))
1130 (if (and vars calc-mode-save-mode (not (eq calc-mode-save-mode 'save)))
1131 (save-excursion
1132 (let* ((save-mode calc-mode-save-mode)
1133 (header (if (eq save-mode 'local)
1134 "calc-mode:"
1135 (format "calc-%s-mode:" save-mode)))
1136 (the-language (calc-embedded-language))
1137 (the-display-just (calc-embedded-justify))
1138 (values (mapcar 'symbol-value vars))
1139 (num (cond ((eq save-mode 'local) 12)
1140 ((eq save-mode 'edit) 13)
1141 ((eq save-mode 'perm) 14)
1142 (t nil)))
1143 base limit mname mlist)
1144 (calc-embedded-original-buffer t)
1145 (save-excursion
1146 (if (eq save-mode 'global)
1147 (setq base (point-max)
1148 limit (point-min)
1149 mlist calc-embedded-globals)
1150 (goto-char (aref calc-embedded-info 4))
1151 (beginning-of-line)
1152 (setq base (point)
1153 limit (max (- (point) 1000) (point-min))
1154 mlist (and num (aref calc-embedded-info num)))
1155 (and (re-search-backward
1156 (format "\\(%s\\)[^\001]*\\(%s\\)\\|\\[calc-defaults]"
1157 calc-embedded-open-formula
1158 calc-embedded-close-formula) limit t)
1159 (setq limit (point))))
1160 (while vars
1161 (goto-char base)
1162 (if (setq mname (car (rassq (car vars)
1163 calc-embedded-mode-vars)))
1164 (let ((buffer-read-only nil)
1165 (found (assq (car vars) mlist)))
1166 (if found
1167 (setcdr found (car values))
1168 (setq mlist (cons (cons (car vars) (car values)) mlist))
1169 (if num
1170 (aset calc-embedded-info num mlist)
1171 (if (eq save-mode 'global)
1172 (setq calc-embedded-globals mlist))))
1173 (if (re-search-backward
1174 (format "\\[%s *%s: *\\(\"\\([^\"\n\\]\\|\\\\.\\)*\"\\|[- ()a-zA-Z0-9]+\\)]"
1175 header mname)
1176 limit t)
1177 (progn
1178 (goto-char (match-beginning 1))
1179 (delete-region (point) (match-end 1))
1180 (insert (prin1-to-string (car values))))
1181 (goto-char base)
1182 (insert-before-markers
1183 calc-embedded-open-mode
1184 "[" header " " mname ": "
1185 (prin1-to-string (car values)) "]"
1186 calc-embedded-close-mode))))
1187 (setq vars (cdr vars)
1188 values (cdr values))))))))
1189
1190 (defun calc-embedded-var-change (var &optional buf)
1191 (if (symbolp var)
1192 (setq var (list 'var
1193 (if (string-match "\\`var-.+\\'"
1194 (symbol-name var))
1195 (intern (substring (symbol-name var) 4))
1196 var)
1197 var)))
1198 (save-excursion
1199 (let ((manual (not calc-auto-recompute))
1200 (bp calc-embedded-active)
1201 (first t))
1202 (if buf (setq bp (memq (assq buf bp) bp)))
1203 (while bp
1204 (let ((calc-embedded-no-reselect t)
1205 (p (and (buffer-name (car (car bp)))
1206 (cdr (car bp)))))
1207 (while p
1208 (if (assoc var (aref (car p) 10))
1209 (if manual
1210 (if (aref (car p) 11)
1211 (progn
1212 (aset (car p) 11 nil)
1213 (if (aref (car p) 9)
1214 (calc-embedded-var-change (aref (car p) 9)))))
1215 (set-buffer (aref (car p) 0))
1216 (if (equal (buffer-substring (aref (car p) 2)
1217 (aref (car p) 3))
1218 (aref (car p) 6))
1219 (let ((calc-embedded-info nil))
1220 (or calc-embedded-quiet
1221 (message "Recomputing..."))
1222 (setq first nil)
1223 (calc-wrapper
1224 (set-buffer (aref (car p) 0))
1225 (calc-embedded-update (car p) 14 t nil)))
1226 (setcdr (car bp) (delq (car p) (cdr (car bp))))
1227 (message
1228 "(Tried to recompute but formula was changed or missing)"))))
1229 (setq p (cdr p))))
1230 (setq bp (if buf nil (cdr bp))))
1231 (or first calc-embedded-quiet (message "")))))
1232
1233 (provide 'calc-embed)
1234
1235 ;;; arch-tag: 1b8f311e-fba1-40d3-b8c3-1d6f68fd26fc
1236 ;;; calc-embed.el ends here