calc-sel.el 27 KB

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