Trailing whitepace deleted.
[emacs.git] / lisp / calc / calc-sel.el
blob07820a44b229b2ffbcdc2c729f2dcf89ab8b95f3
1 ;;; calc-sel.el --- data selection functions for Calc
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc.
5 ;; Author: David Gillespie <daveg@synaptics.com>
6 ;; Maintainers: D. Goel <deego@gnufans.org>
7 ;; Colin Walters <walters@debian.org>
9 ;; This file is part of GNU Emacs.
11 ;; GNU Emacs is distributed in the hope that it will be useful,
12 ;; but WITHOUT ANY WARRANTY. No author or distributor
13 ;; accepts responsibility to anyone for the consequences of using it
14 ;; or for whether it serves any particular purpose or works at all,
15 ;; unless he says so in writing. Refer to the GNU Emacs General Public
16 ;; License for full details.
18 ;; Everyone is granted permission to copy, modify and redistribute
19 ;; GNU Emacs, but only under the conditions described in the
20 ;; GNU Emacs General Public License. A copy of this license is
21 ;; supposed to have been given to you along with GNU Emacs so you
22 ;; can know your rights and responsibilities. It should be in a
23 ;; file named COPYING. Among other things, the copyright notice
24 ;; and this notice must be preserved on all copies.
26 ;;; Commentary:
28 ;;; Code:
30 ;; This file is autoloaded from calc-ext.el.
31 (require 'calc-ext)
33 (require 'calc-macs)
35 (defun calc-Need-calc-sel () nil)
38 ;;; Selection commands.
40 (defvar calc-keep-selection t)
42 (defun calc-select-here (num &optional once keep)
43 (interactive "P")
44 (calc-wrapper
45 (calc-prepare-selection)
46 (let ((found (calc-find-selected-part))
47 (entry calc-selection-cache-entry))
48 (or (and keep (nth 2 entry))
49 (progn
50 (if once (progn
51 (setq calc-keep-selection nil)
52 (message "(Selection will apply to next command only)")))
53 (calc-change-current-selection
54 (if found
55 (if (and num (> (setq num (prefix-numeric-value num)) 0))
56 (progn
57 (while (and (>= (setq num (1- num)) 0)
58 (not (eq found (car entry))))
59 (setq found (calc-find-assoc-parent-formula
60 (car entry) found)))
61 found)
62 (calc-grow-assoc-formula (car entry) found))
63 (car entry))))))))
65 (defun calc-select-once (num)
66 (interactive "P")
67 (calc-select-here num t))
69 (defun calc-select-here-maybe (num)
70 (interactive "P")
71 (calc-select-here num nil t))
73 (defun calc-select-once-maybe (num)
74 (interactive "P")
75 (calc-select-here num t t))
77 (defun calc-select-additional ()
78 (interactive)
79 (calc-wrapper
80 (let (calc-keep-selection)
81 (calc-prepare-selection))
82 (let ((found (calc-find-selected-part))
83 (entry calc-selection-cache-entry))
84 (calc-change-current-selection
85 (if found
86 (let ((sel (nth 2 entry)))
87 (if sel
88 (progn
89 (while (not (or (eq sel (car entry))
90 (calc-find-sub-formula sel found)))
91 (setq sel (calc-find-assoc-parent-formula
92 (car entry) sel)))
93 sel)
94 (calc-grow-assoc-formula (car entry) found)))
95 (car entry))))))
97 (defun calc-select-more (num)
98 (interactive "P")
99 (calc-wrapper
100 (calc-prepare-selection)
101 (let ((entry calc-selection-cache-entry))
102 (if (nth 2 entry)
103 (let ((sel (nth 2 entry)))
104 (while (and (not (eq sel (car entry)))
105 (>= (setq num (1- (prefix-numeric-value num))) 0))
106 (setq sel (calc-find-assoc-parent-formula (car entry) sel)))
107 (calc-change-current-selection sel))
108 (calc-select-here num)))))
110 (defun calc-select-less (num)
111 (interactive "p")
112 (calc-wrapper
113 (calc-prepare-selection)
114 (let ((found (calc-find-selected-part))
115 (entry calc-selection-cache-entry))
116 (calc-change-current-selection
117 (and found
118 (let ((sel (nth 2 entry))
119 old index op)
120 (while (and sel
121 (not (eq sel found))
122 (>= (setq num (1- num)) 0))
123 (setq old sel
124 index (calc-find-sub-formula sel found))
125 (and (setq sel (and index (nth index old)))
126 calc-assoc-selections
127 (setq op (assq (car-safe sel) calc-assoc-ops))
128 (memq (car old) (nth index op))
129 (setq num (1+ num))))
130 sel))))))
132 (defun calc-select-part (num)
133 (interactive "P")
134 (or num (setq num (- last-command-char ?0)))
135 (calc-wrapper
136 (calc-prepare-selection)
137 (let ((sel (calc-find-nth-part (or (nth 2 calc-selection-cache-entry)
138 (car calc-selection-cache-entry))
139 num)))
140 (if sel
141 (calc-change-current-selection sel)
142 (error "%d is not a valid sub-formula index" num)))))
144 (defun calc-find-nth-part (expr num)
145 (if (and calc-assoc-selections
146 (assq (car-safe expr) calc-assoc-ops))
147 (let (op)
148 (calc-find-nth-part-rec expr))
149 (if (eq (car-safe expr) 'intv)
150 (and (>= num 1) (<= num 2) (nth (1+ num) expr))
151 (and (not (Math-primp expr)) (>= num 1) (< num (length expr))
152 (nth num expr)))))
154 (defun calc-find-nth-part-rec (expr) ; uses num, op
155 (or (if (and (setq op (assq (car-safe (nth 1 expr)) calc-assoc-ops))
156 (memq (car expr) (nth 1 op)))
157 (calc-find-nth-part-rec (nth 1 expr))
158 (and (= (setq num (1- num)) 0)
159 (nth 1 expr)))
160 (if (and (setq op (assq (car-safe (nth 2 expr)) calc-assoc-ops))
161 (memq (car expr) (nth 2 op)))
162 (calc-find-nth-part-rec (nth 2 expr))
163 (and (= (setq num (1- num)) 0)
164 (nth 2 expr)))))
166 (defun calc-select-next (num)
167 (interactive "p")
168 (if (< num 0)
169 (calc-select-previous (- num))
170 (calc-wrapper
171 (calc-prepare-selection)
172 (let* ((entry calc-selection-cache-entry)
173 (sel (nth 2 entry)))
174 (if sel
175 (progn
176 (while (>= (setq num (1- num)) 0)
177 (let* ((parent (calc-find-parent-formula (car entry) sel))
178 (p parent)
180 (and (eq p t) (setq p nil))
181 (while (and (setq p (cdr p))
182 (not (eq (car p) sel))))
183 (if (cdr p)
184 (setq sel (or (and calc-assoc-selections
185 (setq op (assq (car-safe (nth 1 p))
186 calc-assoc-ops))
187 (memq (car parent) (nth 2 op))
188 (nth 1 (nth 1 p)))
189 (nth 1 p)))
190 (if (and calc-assoc-selections
191 (setq op (assq (car-safe parent) calc-assoc-ops))
192 (consp (setq p (calc-find-parent-formula
193 (car entry) parent)))
194 (eq (nth 1 p) parent)
195 (memq (car p) (nth 1 op)))
196 (setq sel (nth 2 p))
197 (error "No \"next\" sub-formula")))))
198 (calc-change-current-selection sel))
199 (if (Math-primp (car entry))
200 (calc-change-current-selection (car entry))
201 (calc-select-part num)))))))
203 (defun calc-select-previous (num)
204 (interactive "p")
205 (if (< num 0)
206 (calc-select-next (- num))
207 (calc-wrapper
208 (calc-prepare-selection)
209 (let* ((entry calc-selection-cache-entry)
210 (sel (nth 2 entry)))
211 (if sel
212 (progn
213 (while (>= (setq num (1- num)) 0)
214 (let* ((parent (calc-find-parent-formula (car entry) sel))
215 (p (cdr-safe parent))
216 (prev nil)
218 (if (eq (car-safe parent) 'intv) (setq p (cdr p)))
219 (while (and (not (eq (car p) sel))
220 (setq prev (car p)
221 p (cdr p))))
222 (if prev
223 (setq sel (or (and calc-assoc-selections
224 (setq op (assq (car-safe prev)
225 calc-assoc-ops))
226 (memq (car parent) (nth 1 op))
227 (nth 2 prev))
228 prev))
229 (if (and calc-assoc-selections
230 (setq op (assq (car-safe parent) calc-assoc-ops))
231 (consp (setq p (calc-find-parent-formula
232 (car entry) parent)))
233 (eq (nth 2 p) parent)
234 (memq (car p) (nth 2 op)))
235 (setq sel (nth 1 p))
236 (error "No \"previous\" sub-formula")))))
237 (calc-change-current-selection sel))
238 (if (Math-primp (car entry))
239 (calc-change-current-selection (car entry))
240 (let ((len (if (and calc-assoc-selections
241 (assq (car (car entry)) calc-assoc-ops))
242 (let (op (num 0))
243 (calc-find-nth-part-rec (car entry))
244 (- 1 num))
245 (length (car entry)))))
246 (calc-select-part (- len num)))))))))
248 (defun calc-find-parent-formula (expr part)
249 (cond ((eq expr part) t)
250 ((Math-primp expr) nil)
252 (let ((p expr) res)
253 (while (and (setq p (cdr p))
254 (not (setq res (calc-find-parent-formula
255 (car p) part)))))
256 (and p
257 (if (eq res t) expr res))))))
260 (defun calc-find-assoc-parent-formula (expr part)
261 (calc-grow-assoc-formula expr (calc-find-parent-formula expr part)))
263 (defun calc-grow-assoc-formula (expr part)
264 (if calc-assoc-selections
265 (let ((op (assq (car-safe part) calc-assoc-ops)))
266 (if op
267 (let (new)
268 (while (and (consp (setq new (calc-find-parent-formula
269 expr part)))
270 (memq (car new)
271 (nth (calc-find-sub-formula new part) op)))
272 (setq part new))))
273 part)
274 part))
276 (defun calc-find-sub-formula (expr part)
277 (cond ((eq expr part) t)
278 ((Math-primp expr) nil)
280 (let ((num 1))
281 (while (and (setq expr (cdr expr))
282 (not (calc-find-sub-formula (car expr) part)))
283 (setq num (1+ num)))
284 (and expr num)))))
286 (defun calc-unselect (num)
287 (interactive "P")
288 (calc-wrapper
289 (calc-prepare-selection num)
290 (calc-change-current-selection nil)))
292 (defun calc-clear-selections ()
293 (interactive)
294 (calc-wrapper
295 (let ((limit (calc-stack-size))
296 (n 1))
297 (while (<= n limit)
298 (if (calc-top n 'sel)
299 (progn
300 (calc-prepare-selection n)
301 (calc-change-current-selection nil)))
302 (setq n (1+ n))))
303 (calc-clear-command-flag 'position-point)))
305 (defun calc-show-selections (arg)
306 (interactive "P")
307 (calc-wrapper
308 (calc-preserve-point)
309 (setq calc-show-selections (if arg
310 (> (prefix-numeric-value arg) 0)
311 (not calc-show-selections)))
312 (let ((p calc-stack))
313 (while (and p
314 (or (null (nth 2 (car p)))
315 (equal (car p) calc-selection-cache-entry)))
316 (setq p (cdr p)))
317 (or (and p
318 (let ((calc-selection-cache-default-entry
319 calc-selection-cache-entry))
320 (calc-do-refresh)))
321 (and calc-selection-cache-entry
322 (let ((sel (nth 2 calc-selection-cache-entry)))
323 (setcar (nthcdr 2 calc-selection-cache-entry) nil)
324 (calc-change-current-selection sel)))))
325 (message (if calc-show-selections
326 "Displaying only selected part of formulas"
327 "Displaying all but selected part of formulas"))))
329 (defun calc-preserve-point ()
330 (or (looking-at "\\.\n+\\'")
331 (progn
332 (setq calc-final-point-line (+ (count-lines (point-min) (point))
333 (if (bolp) 1 0))
334 calc-final-point-column (current-column))
335 (calc-set-command-flag 'position-point))))
337 (defun calc-enable-selections (arg)
338 (interactive "P")
339 (calc-wrapper
340 (calc-preserve-point)
341 (setq calc-use-selections (if arg
342 (> (prefix-numeric-value arg) 0)
343 (not calc-use-selections)))
344 (calc-set-command-flag 'renum-stack)
345 (message (if calc-use-selections
346 "Commands operate only on selected sub-formulas"
347 "Selections of sub-formulas have no effect"))))
349 (defun calc-break-selections (arg)
350 (interactive "P")
351 (calc-wrapper
352 (calc-preserve-point)
353 (setq calc-assoc-selections (if arg
354 (<= (prefix-numeric-value arg) 0)
355 (not calc-assoc-selections)))
356 (message (if calc-assoc-selections
357 "Selection treats a+b+c as a sum of three terms"
358 "Selection treats a+b+c as (a+b)+c"))))
360 (defvar calc-selection-cache-entry nil)
361 (defun calc-prepare-selection (&optional num)
362 (or num (setq num (calc-locate-cursor-element (point))))
363 (setq calc-selection-true-num num
364 calc-keep-selection t)
365 (or (> num 0) (setq num 1))
366 ;; (if (or (< num 1) (> num (calc-stack-size)))
367 ;; (error "Cursor must be positioned on a stack element"))
368 (let* ((entry (calc-top num 'entry))
369 ww w)
370 (or (equal entry calc-selection-cache-entry)
371 (progn
372 (setcar entry (calc-encase-atoms (car entry)))
373 (setq calc-selection-cache-entry entry
374 calc-selection-cache-num num
375 calc-selection-cache-comp
376 (let ((math-comp-tagged t))
377 (math-compose-expr (car entry) 0))
378 calc-selection-cache-offset
379 (+ (car (math-stack-value-offset calc-selection-cache-comp))
380 (length calc-left-label)
381 (if calc-line-numbering 4 0))))))
382 (calc-preserve-point))
384 ;;; The following ensures that no two subformulas will be "eq" to each other!
385 (defun calc-encase-atoms (x)
386 (if (or (not (consp x))
387 (equal x '(float 0 0)))
388 (list 'cplx x 0)
389 (calc-encase-atoms-rec x)
392 (defun calc-encase-atoms-rec (x)
393 (or (Math-primp x)
394 (progn
395 (if (eq (car x) 'intv)
396 (setq x (cdr x)))
397 (while (setq x (cdr x))
398 (if (or (not (consp (car x)))
399 (equal (car x) '(float 0 0)))
400 (setcar x (list 'cplx (car x) 0))
401 (calc-encase-atoms-rec (car x)))))))
403 (defun calc-find-selected-part ()
404 (let* ((math-comp-sel-hpos (- (current-column) calc-selection-cache-offset))
405 toppt
406 (lcount 0)
407 (spaces 0)
408 (math-comp-sel-vpos (save-excursion
409 (beginning-of-line)
410 (let ((line (point)))
411 (calc-cursor-stack-index
412 calc-selection-cache-num)
413 (setq toppt (point))
414 (while (< (point) line)
415 (forward-line 1)
416 (setq spaces (+ spaces
417 (current-indentation))
418 lcount (1+ lcount)))
419 (- lcount (math-comp-ascent
420 calc-selection-cache-comp) -1))))
421 (math-comp-sel-cpos (- (point) toppt calc-selection-cache-offset
422 spaces lcount))
423 (math-comp-sel-tag nil))
424 (and (>= math-comp-sel-hpos 0)
425 (> calc-selection-true-num 0)
426 (math-composition-to-string calc-selection-cache-comp 1000000))
427 (nth 1 math-comp-sel-tag)))
429 (defun calc-change-current-selection (sub-expr)
430 (or (eq sub-expr (nth 2 calc-selection-cache-entry))
431 (let ((calc-prepared-composition calc-selection-cache-comp)
432 (buffer-read-only nil)
433 top)
434 (calc-set-command-flag 'renum-stack)
435 (setcar (nthcdr 2 calc-selection-cache-entry) sub-expr)
436 (calc-cursor-stack-index calc-selection-cache-num)
437 (setq top (point))
438 (calc-cursor-stack-index (1- calc-selection-cache-num))
439 (delete-region top (point))
440 (let ((calc-selection-cache-default-entry calc-selection-cache-entry))
441 (insert (math-format-stack-value calc-selection-cache-entry)
442 "\n")))))
444 (defun calc-top-selected (&optional n m)
445 (and calc-any-selections
446 calc-use-selections
447 (progn
448 (or n (setq n 1))
449 (or m (setq m 1))
450 (calc-check-stack (+ n m -1))
451 (let ((top (nthcdr (+ m calc-stack-top -1) calc-stack))
452 (sel nil))
453 (while (>= (setq n (1- n)) 0)
454 (if (nth 2 (car top))
455 (setq sel (if sel t (nth 2 (car top)))))
456 (setq top (cdr top)))
457 sel))))
459 (defun calc-replace-sub-formula (expr old new)
460 (setq new (calc-encase-atoms new))
461 (calc-replace-sub-formula-rec expr))
463 (defun calc-replace-sub-formula-rec (expr)
464 (cond ((eq expr old) new)
465 ((Math-primp expr) expr)
467 (cons (car expr)
468 (mapcar 'calc-replace-sub-formula-rec (cdr expr))))))
470 (defun calc-sel-error ()
471 (error "Illegal operation on sub-formulas"))
473 (defun calc-replace-selections (n vals m)
474 (if (calc-top-selected n m)
475 (let ((num (length vals)))
476 (calc-preserve-point)
477 (cond
478 ((= n num)
479 (let* ((old (calc-top-list n m 'entry))
480 (new nil)
481 (sel nil)
482 val)
483 (while old
484 (if (nth 2 (car old))
485 (setq val (calc-encase-atoms (car vals))
486 new (cons (calc-replace-sub-formula (car (car old))
487 (nth 2 (car old))
488 val)
489 new)
490 sel (cons val sel))
491 (setq new (cons (car vals) new)
492 sel (cons nil sel)))
493 (setq vals (cdr vals)
494 old (cdr old)))
495 (calc-pop-stack n m t)
496 (calc-push-list (nreverse new)
497 m (and calc-keep-selection (nreverse sel)))))
498 ((= num 1)
499 (let* ((old (calc-top-list n m 'entry))
500 more)
501 (while (and old (not (nth 2 (car old))))
502 (setq old (cdr old)))
503 (setq more old)
504 (while (and (setq more (cdr more)) (not (nth 2 (car more)))))
505 (and more
506 (calc-sel-error))
507 (calc-pop-stack n m t)
508 (if old
509 (let ((val (calc-encase-atoms (car vals))))
510 (calc-push-list (list (calc-replace-sub-formula
511 (car (car old))
512 (nth 2 (car old))
513 val))
514 m (and calc-keep-selection (list val))))
515 (calc-push-list vals))))
516 (t (calc-sel-error))))
517 (calc-pop-stack n m t)
518 (calc-push-list vals m)))
520 (defun calc-delete-selection (n)
521 (let ((entry (calc-top n 'entry)))
522 (if (nth 2 entry)
523 (if (eq (nth 2 entry) (car entry))
524 (progn
525 (calc-pop-stack 1 n t)
526 (calc-push-list '(0) n))
527 (let ((parent (calc-find-parent-formula (car entry) (nth 2 entry)))
528 (repl nil))
529 (calc-preserve-point)
530 (calc-pop-stack 1 n t)
531 (cond ((or (memq (car parent) '(* / %))
532 (and (eq (car parent) '^)
533 (eq (nth 2 parent) (nth 2 entry))))
534 (setq repl 1))
535 ((memq (car parent) '(vec calcFunc-min calcFunc-max)))
536 ((and (assq (car parent) calc-tweak-eqn-table)
537 (= (length parent) 3))
538 (setq repl 'del))
540 (setq repl 0)))
541 (cond
542 ((eq repl 'del)
543 (calc-push-list (list
544 (calc-normalize
545 (calc-replace-sub-formula
546 (car entry)
547 parent
548 (if (eq (nth 2 entry) (nth 1 parent))
549 (nth 2 parent)
550 (nth 1 parent)))))
552 (repl
553 (calc-push-list (list
554 (calc-normalize
555 (calc-replace-sub-formula (car entry)
556 (nth 2 entry)
557 repl)))
560 (calc-push-list (list
561 (calc-normalize
562 (calc-replace-sub-formula (car entry)
563 parent
564 (delq (nth 2 entry)
565 (copy-sequence
566 parent)))))
567 n)))))
568 (calc-pop-stack 1 n t))))
570 (defun calc-roll-down-with-selections (n m)
571 (let ((vals (append (calc-top-list m 1)
572 (calc-top-list (- n m) (1+ m))))
573 (sels (append (calc-top-list m 1 'sel)
574 (calc-top-list (- n m) (1+ m) 'sel))))
575 (calc-pop-push-list n vals 1 sels)))
577 (defun calc-roll-up-with-selections (n m)
578 (let ((vals (append (calc-top-list (- n m) 1)
579 (calc-top-list m (- n m -1))))
580 (sels (append (calc-top-list (- n m) 1 'sel)
581 (calc-top-list m (- n m -1) 'sel))))
582 (calc-pop-push-list n vals 1 sels)))
584 (defun calc-auto-selection (entry)
585 (or (nth 2 entry)
586 (progn
587 (and (boundp 'reselect) (setq reselect nil))
588 (calc-prepare-selection)
589 (calc-grow-assoc-formula (car entry) (calc-find-selected-part)))))
591 (defun calc-copy-selection ()
592 (interactive)
593 (calc-wrapper
594 (calc-preserve-point)
595 (let* ((num (max 1 (calc-locate-cursor-element (point))))
596 (entry (calc-top num 'entry)))
597 (calc-push (or (calc-auto-selection entry) (car entry))))))
599 (defun calc-del-selection ()
600 (interactive)
601 (calc-wrapper
602 (calc-preserve-point)
603 (let* ((num (max 1 (calc-locate-cursor-element (point))))
604 (entry (calc-top num 'entry))
605 (sel (calc-auto-selection entry)))
606 (setcar (nthcdr 2 entry) (and (not (eq sel (car entry))) sel))
607 (calc-delete-selection num))))
609 (defun calc-enter-selection ()
610 (interactive)
611 (calc-wrapper
612 (calc-preserve-point)
613 (let* ((num (max 1 (calc-locate-cursor-element (point))))
614 (reselect calc-keep-selection)
615 (entry (calc-top num 'entry))
616 (expr (car entry))
617 (sel (or (calc-auto-selection entry) expr))
618 alg)
619 (let ((calc-dollar-values (list sel))
620 (calc-dollar-used 0))
621 (setq alg (calc-do-alg-entry "" "Replace selection with: "))
622 (and alg
623 (progn
624 (setq alg (calc-encase-atoms (car alg)))
625 (calc-pop-push-record-list 1 "repl"
626 (list (calc-replace-sub-formula
627 expr sel alg))
629 (list (and reselect alg))))))
630 (calc-handle-whys))))
632 (defun calc-edit-selection ()
633 (interactive)
634 (calc-wrapper
635 (calc-preserve-point)
636 (let* ((num (max 1 (calc-locate-cursor-element (point))))
637 (reselect calc-keep-selection)
638 (entry (calc-top num 'entry))
639 (expr (car entry))
640 (sel (or (calc-auto-selection entry) expr))
641 alg)
642 (let ((str (math-showing-full-precision
643 (math-format-nice-expr sel (frame-width)))))
644 (calc-edit-mode (list 'calc-finish-selection-edit
645 num (list 'quote sel) reselect))
646 (insert str "\n"))))
647 (calc-show-edit-buffer))
649 (defun calc-finish-selection-edit (num sel reselect)
650 (let ((buf (current-buffer))
651 (str (buffer-substring (point) (point-max)))
652 (start (point)))
653 (switch-to-buffer calc-original-buffer)
654 (let ((val (math-read-expr str)))
655 (if (eq (car-safe val) 'error)
656 (progn
657 (switch-to-buffer buf)
658 (goto-char (+ start (nth 1 val)))
659 (error (nth 2 val))))
660 (calc-wrapper
661 (calc-preserve-point)
662 (if disp-trail
663 (calc-trail-display 1 t))
664 (setq val (calc-encase-atoms (calc-normalize val)))
665 (let ((expr (calc-top num 'full)))
666 (if (calc-find-sub-formula expr sel)
667 (calc-pop-push-record-list 1 "edit"
668 (list (calc-replace-sub-formula
669 expr sel val))
671 (list (and reselect val)))
672 (calc-push val)
673 (error "Original selection has been lost")))))))
675 (defun calc-sel-evaluate (arg)
676 (interactive "p")
677 (calc-slow-wrapper
678 (calc-preserve-point)
679 (let* ((num (max 1 (calc-locate-cursor-element (point))))
680 (reselect calc-keep-selection)
681 (entry (calc-top num 'entry))
682 (sel (or (calc-auto-selection entry) (car entry))))
683 (calc-with-default-simplification
684 (let ((math-simplify-only nil))
685 (calc-modify-simplify-mode arg)
686 (let ((val (calc-encase-atoms (calc-normalize sel))))
687 (calc-pop-push-record-list 1 "jsmp"
688 (list (calc-replace-sub-formula
689 (car entry) sel val))
691 (list (and reselect val))))))
692 (calc-handle-whys))))
694 (defun calc-sel-expand-formula (arg)
695 (interactive "p")
696 (calc-slow-wrapper
697 (calc-preserve-point)
698 (let* ((num (max 1 (calc-locate-cursor-element (point))))
699 (reselect calc-keep-selection)
700 (entry (calc-top num 'entry))
701 (sel (or (calc-auto-selection entry) (car entry))))
702 (calc-with-default-simplification
703 (let ((math-simplify-only nil))
704 (calc-modify-simplify-mode arg)
705 (let* ((math-expand-formulas (> arg 0))
706 (val (calc-normalize sel))
707 top)
708 (and (<= arg 0)
709 (setq top (math-expand-formula val))
710 (setq val (calc-normalize top)))
711 (setq val (calc-encase-atoms val))
712 (calc-pop-push-record-list 1 "jexf"
713 (list (calc-replace-sub-formula
714 (car entry) sel val))
716 (list (and reselect val))))))
717 (calc-handle-whys))))
719 (defun calc-sel-mult-both-sides (no-simp &optional divide)
720 (interactive "P")
721 (calc-wrapper
722 (calc-preserve-point)
723 (let* ((num (max 1 (calc-locate-cursor-element (point))))
724 (reselect calc-keep-selection)
725 (entry (calc-top num 'entry))
726 (expr (car entry))
727 (sel (or (calc-auto-selection entry) expr))
728 (func (car-safe sel))
729 alg lhs rhs)
730 (setq alg (calc-with-default-simplification
731 (car (calc-do-alg-entry ""
732 (if divide
733 "Divide both sides by: "
734 "Multiply both sides by: ")))))
735 (and alg
736 (progn
737 (if (and (or (eq func '/)
738 (assq func calc-tweak-eqn-table))
739 (= (length sel) 3))
740 (progn
741 (or (memq func '(/ calcFunc-eq calcFunc-neq))
742 (if (math-known-nonposp alg)
743 (progn
744 (setq func (nth 1 (assq func
745 calc-tweak-eqn-table)))
746 (or (math-known-negp alg)
747 (message "Assuming this factor is nonzero")))
748 (or (math-known-posp alg)
749 (if (math-known-nonnegp alg)
750 (message "Assuming this factor is nonzero")
751 (message "Assuming this factor is positive")))))
752 (setq lhs (list (if divide '/ '*) (nth 1 sel) alg)
753 rhs (list (if divide '/ '*) (nth 2 sel) alg))
754 (or no-simp
755 (progn
756 (setq lhs (math-simplify lhs)
757 rhs (math-simplify rhs))
758 (and (eq func '/)
759 (or (Math-equal (nth 1 sel) 1)
760 (Math-equal (nth 1 sel) -1)
761 (and (memq (car-safe (nth 2 sel)) '(+ -))
762 (memq (car-safe alg) '(+ -))))
763 (setq rhs (math-expand-term rhs)))))
764 (setq alg (calc-encase-atoms
765 (calc-normalize (list func lhs rhs)))))
766 (setq rhs (list (if divide '* '/) sel alg))
767 (or no-simp
768 (setq rhs (math-simplify rhs)))
769 (setq alg (calc-encase-atoms
770 (calc-normalize (if divide
771 (list '/ rhs alg)
772 (list '* alg rhs))))))
773 (calc-pop-push-record-list 1 (if divide "div" "mult")
774 (list (calc-replace-sub-formula
775 expr sel alg))
777 (list (and reselect alg)))))
778 (calc-handle-whys))))
780 (defun calc-sel-div-both-sides (no-simp)
781 (interactive "P")
782 (calc-sel-mult-both-sides no-simp t))
784 (defun calc-sel-add-both-sides (no-simp &optional subtract)
785 (interactive "P")
786 (calc-wrapper
787 (calc-preserve-point)
788 (let* ((num (max 1 (calc-locate-cursor-element (point))))
789 (reselect calc-keep-selection)
790 (entry (calc-top num 'entry))
791 (expr (car entry))
792 (sel (or (calc-auto-selection entry) expr))
793 (func (car-safe sel))
794 alg lhs rhs)
795 (setq alg (calc-with-default-simplification
796 (car (calc-do-alg-entry ""
797 (if subtract
798 "Subtract from both sides: "
799 "Add to both sides: ")))))
800 (and alg
801 (progn
802 (if (and (assq func calc-tweak-eqn-table)
803 (= (length sel) 3))
804 (progn
805 (setq lhs (list (if subtract '- '+) (nth 1 sel) alg)
806 rhs (list (if subtract '- '+) (nth 2 sel) alg))
807 (or no-simp
808 (setq lhs (math-simplify lhs)
809 rhs (math-simplify rhs)))
810 (setq alg (calc-encase-atoms
811 (calc-normalize (list func lhs rhs)))))
812 (setq rhs (list (if subtract '+ '-) sel alg))
813 (or no-simp
814 (setq rhs (math-simplify rhs)))
815 (setq alg (calc-encase-atoms
816 (calc-normalize (list (if subtract '- '+) alg rhs)))))
817 (calc-pop-push-record-list 1 (if subtract "sub" "add")
818 (list (calc-replace-sub-formula
819 expr sel alg))
821 (list (and reselect alg)))))
822 (calc-handle-whys))))
824 (defun calc-sel-sub-both-sides (no-simp)
825 (interactive "P")
826 (calc-sel-add-both-sides no-simp t))
828 ;;; calc-sel.el ends here