calc-sel.el 27 KB

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