home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / modes / math / math-mode.el < prev    next >
Encoding:
Text File  |  1989-05-24  |  145.6 KB  |  4,772 lines

  1. ;;; Mathematica notebook interface.
  2. ;;; Copyright 1989 Daniel LaLiberte
  3.  
  4. ;;; $Header: /home/srg/1/liberte/math/RCS/math-mode.el,v 1.5 89/05/24 23:43:00 liberte Exp Locker: liberte $
  5. ;;; $Log:    math-mode.el,v $
  6. ;;; Revision 1.5  89/05/24  23:43:00  liberte
  7. ;;; Fix math-package-mode self-insert-command.
  8. ;;; Fix adjustment of indentation for closed cells.
  9. ;;; 
  10. ;;; Revision 1.4  89/05/24  02:13:37  liberte
  11. ;;; Fix problem with missing output prompts.
  12. ;;; Fix cell relabelling problem for closed cells.
  13. ;;; 
  14. ;;; Revision 1.3  89/05/22  00:03:24  liberte
  15. ;;; Add math-package-mode.
  16. ;;; Fix save of math buffer some more - always set write-file-hook.
  17. ;;; Fix indentation of strings.
  18. ;;; 
  19.  
  20. ;;------------------------------------------------------------
  21. ;; To use math-mode, include the following in your .emacs
  22. ;; Make sure that math-mode.el and mathtalk.el are in your load-path.
  23. ;; Also make sure that math-path is set to the name of the
  24. ;; program to execute the emacsfrontend and that that program
  25. ;; is in your Unix PATH variable.
  26.  
  27. ;; (setq auto-mode-alist (append
  28. ;;                (list
  29. ;;            (cons "\\.nb$" 'math-mode)
  30. ;;            (cons "\\.nbl$" 'math-mode))
  31. ;;            auto-mode-alist))
  32.  
  33. ;; (autoload 'math-mode "math-mode")
  34. ;; (autoload 'math "math-mode" "start up mathematica in math buffer" t)
  35.  
  36. ;;-------------------------------------------------------------
  37. ;; Start up math-mode by executing M-x math
  38. ;; or edit a file with .nb or .nbl suffix.   The .nb suffix
  39. ;; is for notebook files created with the Macintosh version
  40. ;; of Mathematica.  These files are automatically converted
  41. ;; to a file with the .nbl suffix that uses the math-mode notebook format.
  42.  
  43. ;; Once in math-mode, use describe-mode (C-h m) to learn
  44. ;; about math-mode commands.  You may want to read the manual
  45. ;; to learn about the structure of notebooks and evaluation
  46. ;; of Mathematica expressions.
  47.  
  48. ;;-------------------------------------------------------------
  49.  
  50. ;; Byte compiling will speed up execution enormously because math-mode
  51. ;; uses macros that use macros.
  52.  
  53. (provide 'math-mode)
  54. (require 'math-mode)  ; must load for byte-compile so cell macros are defined
  55.  
  56. ;;; uses mathtalk to communicate with Mathematica
  57. (require 'mathtalk)
  58.  
  59.  
  60. ;;------------------
  61. ;; Math mode
  62.  
  63. (defvar math-eval-init-cells 'ask
  64.   "*nil if should never evaluate initialization cells.
  65. t if should always evaluate without asking.
  66. Otherwise ask.")
  67.  
  68. (defvar math-use-structure-labels nil
  69.   "*If non-nil, then include within each label the cell structure indicator.
  70. Buffer local.  Default nil.")
  71.  
  72. (defconst math-buffer-name "math" 
  73.   "Name of buffer for doing math in.")
  74.  
  75. (defconst math-macnb2nbl "macnb2nbl"
  76.   "Program to convert macintosh notebooks to nbl form.")
  77.  
  78. ;;(defvar math-save-notebook-lisp t
  79. ;;  "*Non-nil if notebooks should be saved in lisp form.")
  80.  
  81. ;; (defvar math-save-notebook-text nil
  82. ;;  "*Non-nil if notebooks should also be saved in text form.")
  83.  
  84. (defvar math-show-debug nil
  85.   "*If non-nil, show the mathematica debug buffer.")
  86.  
  87. (defvar math-mode-map nil "")
  88.  
  89. (if (and math-mode-map   ; do this just once
  90.      (not math-show-debug)) ; unless debugging
  91.     nil
  92.  
  93.   (progn
  94.     (setq math-mode-map (make-keymap))
  95.  
  96.     (let ((i 32))
  97.       (while (< i 127)
  98.     (define-key math-mode-map (char-to-string i) 'math-self-insert-command)
  99.     (setq i (1+ i)))
  100.       )
  101.  
  102.     (define-key math-mode-map "\C-cK" 'kill-math)
  103.  
  104.     ;; could combine into one math-save-buffer and request format
  105.     (define-key math-mode-map "\C-cM" 'write-math-mac-notebook)
  106.     (define-key math-mode-map "\C-cP" 'write-math-package)
  107.     ;;(define-key math-mode-map "\C-xs" 'write-math-lisp-notebook) ; not needed
  108.  
  109.     (define-key math-mode-map "\C-c\C-n" 'math-next-cell)
  110.     (define-key math-mode-map "\C-c\C-p" 'math-previous-cell)
  111.     (define-key math-mode-map "\C-c\C-u" 'math-parent-cell)
  112.     (define-key math-mode-map "\C-c\C-f" 'math-forward-cell)
  113.     (define-key math-mode-map "\C-c\C-b" 'math-backward-cell)
  114.     (define-key math-mode-map "\C-c\C-i" 'math-insert-new-text-cell)
  115.     (define-key math-mode-map "\C-c\C-k" 'math-kill-current-cell)
  116.     (define-key math-mode-map "\C-ck" 'math-kill-region)
  117.     (define-key math-mode-map "\C-c\C-w" 'math-set-current-cell-as-kill)
  118.     (define-key math-mode-map "\C-c\C-y" 'math-yank-killed-cells)
  119.     (define-key math-mode-map "\C-c\C-@" 'math-mark-current-cell)
  120.     (define-key math-mode-map "\C-cc" 'math-copy-backward-cell)
  121.     (define-key math-mode-map "\C-cg" 'math-group-region)
  122.     (define-key math-mode-map "\C-cG" 'math-ungroup-current-group)
  123.     (define-key math-mode-map "\C-c\C-s" 'math-split-group)
  124.     (define-key math-mode-map "\C-c\C-j" 'math-join-cell)
  125.  
  126.     (define-key math-mode-map "\C-c\C-o" 'math-toggle-cell-output)
  127.     (define-key math-mode-map "\C-c\C-c" 'math-toggle-close-cell)
  128.     (define-key math-mode-map "\C-c\C-l" 'math-toggle-structure-labels)
  129.  
  130.     (define-key math-mode-map "\C-cA" 'math-toggle-active)
  131.     (define-key math-mode-map "\C-cI" 'math-toggle-initialization)
  132.     (define-key math-mode-map "\C-cU" 'math-toggle-auto-active)
  133.     (define-key math-mode-map "\C-cF" 'math-set-style)
  134.  
  135.     (define-key math-mode-map "\C-cc" 'math-complete-symbol)
  136.     (define-key math-mode-map "\C-j" 'math-eval-current-cell)
  137.  
  138.     (define-key math-mode-map "\C-m" 'math-newline-and-indent)
  139.     (define-key math-mode-map "\t" 'math-maybe-indent-line)
  140.     (define-key math-mode-map "\M-\C-q" 'math-indent-exp)
  141.  
  142.     ;;  (define-key math-mode-map "\C-cC" 'check-math-cell)
  143.  
  144.     ))
  145.  
  146. (defvar math-mode-syntax-table nil)
  147.  
  148. (if math-mode-syntax-table
  149.     ()
  150.   (setq math-mode-syntax-table (make-syntax-table))
  151.   (let ((i 0))
  152.     (while (< i 128)            ; control chars
  153.       (modify-syntax-entry i "_   " math-mode-syntax-table)
  154.       (setq i (1+ i)))
  155.     )
  156.  
  157.   (modify-syntax-entry ?\  "    " math-mode-syntax-table)
  158.   (modify-syntax-entry ?\t "    " math-mode-syntax-table)
  159.   (modify-syntax-entry ?\n "    " math-mode-syntax-table)
  160.   (modify-syntax-entry ?\r "    " math-mode-syntax-table)
  161.   (modify-syntax-entry ?\f "    " math-mode-syntax-table)
  162.  
  163.   (modify-syntax-entry ?\[ "(]  " math-mode-syntax-table)
  164.   (modify-syntax-entry ?\] ")[  " math-mode-syntax-table)
  165.   (modify-syntax-entry ?\{ "(}  " math-mode-syntax-table)
  166.   (modify-syntax-entry ?\} "){  " math-mode-syntax-table)
  167.   (modify-syntax-entry ?\( "() 1" math-mode-syntax-table)
  168.   (modify-syntax-entry ?\) ")( 4" math-mode-syntax-table)
  169.   (modify-syntax-entry ?* ". 23" math-mode-syntax-table)
  170.  
  171.   (modify-syntax-entry ?+ "." math-mode-syntax-table)
  172.   (modify-syntax-entry ?- "." math-mode-syntax-table)
  173.   (modify-syntax-entry ?= "." math-mode-syntax-table)
  174.   (modify-syntax-entry ?< "." math-mode-syntax-table)
  175.   (modify-syntax-entry ?> "." math-mode-syntax-table)
  176.   (modify-syntax-entry ?| "." math-mode-syntax-table)
  177.   (modify-syntax-entry ?\" "\"" math-mode-syntax-table)
  178.   (modify-syntax-entry ?/ ".   " math-mode-syntax-table)
  179.   (modify-syntax-entry ?' ".   " math-mode-syntax-table)
  180.   (modify-syntax-entry ?` "'   " math-mode-syntax-table)
  181.   (modify-syntax-entry ?, ".   " math-mode-syntax-table)
  182.   (modify-syntax-entry ?. ".   " math-mode-syntax-table)
  183.   (modify-syntax-entry ?; ".   " math-mode-syntax-table)
  184.   (modify-syntax-entry ?: ".   " math-mode-syntax-table)
  185.   (modify-syntax-entry ?_ "'   " math-mode-syntax-table)
  186.   (modify-syntax-entry ?\? ".   " math-mode-syntax-table)
  187.   (modify-syntax-entry ?~ "_   " math-mode-syntax-table)
  188.  
  189.   (modify-syntax-entry ?!".   " math-mode-syntax-table)
  190.   (modify-syntax-entry ?@ ".   " math-mode-syntax-table)
  191.   (modify-syntax-entry ?# "'   " math-mode-syntax-table)
  192.   (modify-syntax-entry ?$ "'   " math-mode-syntax-table)
  193.   (modify-syntax-entry ?% "'" math-mode-syntax-table)
  194.   (modify-syntax-entry ?^ "." math-mode-syntax-table)
  195.   (modify-syntax-entry ?& "." math-mode-syntax-table)
  196.   (modify-syntax-entry ?\\ "\\   " math-mode-syntax-table)
  197.   )
  198.  
  199.  
  200. (defvar math-mode nil
  201.   "Non-nil if math-mode is active for this buffer.")
  202.  
  203. (defun math ()
  204.   "Start up math-mode in a new buffer called 'math'.
  205. Or if it already exists, switch to math."
  206.   ;; could allow more than one by changing buffer names!!
  207.   (interactive)
  208.   (let ((buf (get-buffer-create math-buffer-name)))
  209.     (switch-to-buffer buf)
  210.     (if (not math-mode)            ; did it exist already?
  211.     (math-mode)
  212.       )))
  213.  
  214.  
  215. (defun math-mode ()
  216.   "Major mode to interface with Mathematica.
  217. This should only be called automatically on a new or existing
  218. notebook file.  Use math to start up Mathematica in a math buffer.
  219.  
  220. Commands:
  221. \\{math-mode-map}
  222.  
  223. Turning on math mode calls the value of text-mode-hook and then
  224. math-mode-hook, if they are non-nil."
  225.  
  226.   (setup-math-mode)
  227.   (if (buffer-file-name)
  228.       (math-mode-on-notebook-file))
  229.   (finish-math-mode-initialization)
  230.   )
  231.  
  232.  
  233. (defun math-mode-maybe ()
  234.   "Ask to invoke math-mode for the current buffer.
  235. For use with .m and .nb files in auto-mode-alist."
  236.   (if (y-or-n-p "Invoke math-mode? ")
  237.       (math-mode)
  238.     (math-package-mode)
  239.     ))
  240.  
  241.  
  242. (defun setup-math-mode ()
  243.   "Internal.  Set up local variables for math-mode."
  244.  
  245.   (kill-all-local-variables)
  246.  
  247.   (setq selective-display t)
  248.  
  249.   (use-local-map math-mode-map)
  250.  
  251.   (setq mode-name "Math")
  252.   (setq major-mode 'math-mode)
  253.   (make-local-variable 'math-mode)
  254.   (setq math-mode t)
  255.  
  256.   ;; probably could include a few abbreviations!!
  257.   (if (not (boundp 'math-mode-abbrev-table))
  258.       (define-abbrev-table 'math-mode-abbrev-table ()))
  259.   (setq local-abbrev-table math-mode-abbrev-table)
  260.  
  261.   (set-syntax-table math-mode-syntax-table)
  262.  
  263.   (make-local-variable 'indent-line-function)
  264.   (setq indent-line-function 'math-maybe-indent-line)
  265.  
  266.   ;; this needs some work - possibly replace the paragraph filler
  267.   (make-local-variable 'paragraph-start)
  268.   (setq paragraph-start (concat "^[ \t\n\f]\\|^"
  269.                 math-cell-label-text-regexp
  270.                 "\\|" page-delimiter))
  271.  
  272.   (make-local-variable 'paragraph-separate)
  273.   (setq paragraph-separate (concat "^[ \t\f]*$\\|^"
  274.                    math-cell-label-text-regexp))
  275.  
  276.   (make-local-variable 'comment-start)
  277.   (setq comment-start "(* ")
  278.   (make-local-variable 'comment-end)
  279.   (setq comment-end " *)")
  280.   (make-local-variable 'comment-column)
  281.   (setq comment-column 32)
  282.   (make-local-variable 'comment-start-skip)
  283.   (setq comment-start-skip "(\\*+ *")
  284.   (make-local-variable 'comment-indent-hook)
  285.   (setq comment-indent-hook 'math-comment-indent)
  286. ;;  (make-local-variable 'parse-sexp-ignore-comments)
  287. ;;  (setq parse-sexp-ignore-comments t)
  288.  
  289.   (init-math-cell-vector)
  290.   (make-local-variable 'math-last-input-cell)
  291.   (setq math-last-input-cell nil)
  292.  
  293.   (make-local-variable 'current-math-cell-start)
  294.   (setq current-math-cell-start (point-marker))
  295.   (make-local-variable 'current-math-cell-end)
  296.   (setq current-math-cell-end (point-marker))
  297.   (make-local-variable 'current-math-cell-index)
  298.   (setq current-math-cell-index 0)
  299.   
  300.   (make-local-variable 'math-use-structure-labels)
  301.   ;; use default value
  302.   (setq math-use-structure-labels (default-value 'math-use-structure-labels))
  303.   )
  304.  
  305.  
  306.  
  307. ;; add math-goto-first-cell to find-file-hooks - could be buffer local
  308. (or (memq 'math-goto-first-cell find-file-hooks)
  309.     (setq find-file-hooks (cons 'math-goto-first-cell find-file-hooks)))
  310.  
  311. ;; add math-save-buffer to write-file-hooks
  312. (if (not (memq 'math-save-buffer write-file-hooks))
  313.     (setq write-file-hooks (cons 'math-save-buffer write-file-hooks)))
  314.  
  315.  
  316. (defun math-goto-first-cell ()
  317.   "Go to the first math-cell in notebook."
  318.   (if math-mode
  319.       (progn
  320.     (if (not math-cell-vector)
  321.         (error "math-mode is not properly initialized."))
  322.     (let ((first-math-cell (first-math-cell)))
  323.       (if first-math-cell
  324.           (math-move-to-cell first-math-cell))))))
  325.  
  326.  
  327.  
  328. ;; These should match the auto-mode-alist entries.
  329. (defconst math-nb-suffix ".nb" "Suffix for macintosh format notebook file.")
  330. (defconst math-nbl-suffix ".nbl" "Suffix for math-mode format notebook file.")
  331. (defconst math-nbl-regexp "\\.nbl$" "Pattern for matching math-nbl-suffix")
  332.  
  333. (defconst math-package-suffix ".m" "Suffix for Mathematica package file.")
  334.  
  335.  
  336. (defun math-mode-on-notebook-file ()
  337.   "Called to determine how math-mode should be activated for the
  338. current buffer that has an associated file.  Ask to use the newer of the .nb
  339. or .nbl versions of a notebook."
  340.  
  341.   (let* ((filename (file-name-nondirectory (buffer-file-name)))
  342.      (start-with-nbl (string-match (concat "\\" math-nbl-suffix "$")
  343.                        filename))
  344.      (filename-root (math-file-name-root filename))
  345.      (nb-filename (concat filename-root math-nb-suffix))
  346.      (nbl-filename (concat filename-root math-nbl-suffix))
  347.      (package-filename (concat filename-root math-package-suffix))
  348.  
  349.      ;; find the newest of the three files
  350.      (newest-file
  351.       (if (file-newer-than-file-p nbl-filename nb-filename)
  352.           (if (file-newer-than-file-p nbl-filename package-filename)
  353.           nbl-filename
  354.         package-filename)
  355.         (if (file-newer-than-file-p nb-filename package-filename)
  356.         nb-filename
  357.           package-filename))))
  358.       
  359.     (if (and (file-exists-p newest-file)
  360.          (not (string= newest-file filename)))
  361.     ;; ask to use newest file instead
  362.     (if (yes-or-no-p
  363.          (format "%s is newer.  Use it instead? "
  364.              newest-file))
  365.         (progn
  366.           (erase-buffer)
  367.           (insert-file-contents newest-file)
  368.           (setq filename newest-file))))
  369.  
  370.     (if (> (buffer-size) 0)
  371.     (cond
  372.      ((string= filename nb-filename)
  373.       (convert-math-notebook-file))
  374.  
  375.      ((string= filename nbl-filename)
  376.       (convert-math-mode-lisp-to-internal))
  377.       
  378.      ((string= filename package-filename)
  379.       (convert-math-package))
  380.  
  381.      (t (error "Bad filename: %s" filename))))
  382.  
  383.     ;; change the visited file to the nbl form.
  384.     (set-visited-file-name nbl-filename)
  385.     (if start-with-nbl
  386.     (not-modified))
  387.  
  388.     (auto-save-mode -1)            ; avoid annoying auto-save messages
  389.    
  390.     ;; the following should be a user option I suppose
  391.     (setq file-precious-flag t)        ; copy the original file on save
  392.    
  393.     ))
  394.  
  395.  
  396. (defun math-package-to-nbl ()
  397.   "Convert the package in the current buffer to an nbl buffer."
  398.   (interactive)
  399.   (let* ((filename (file-name-nondirectory (buffer-file-name)))
  400.      (start-with-nbl (string-match (concat "\\" math-nbl-suffix "$")
  401.                        filename))
  402.      (filename-root (math-file-name-root filename))
  403.      (nbl-filename (concat filename-root math-nbl-suffix))
  404.      (package-filename (concat filename-root math-package-suffix))
  405.      )
  406.     (if start-with-nbl
  407.     (error "%s is already an nbl buffer." filename))
  408.     (if (not (string= filename package-filename))
  409.     (error "%s is not a package buffer." filename))
  410.     (if (get-buffer nbl-filename)
  411.     (error "%s buffer already exists." nbl-filename))
  412.  
  413.     (setup-math-mode)
  414.     (convert-math-package)
  415.       
  416.     ;; change the visited file to the nbl form.
  417.     (set-visited-file-name nbl-filename)
  418.     (if start-with-nbl
  419.     (not-modified))
  420.   
  421.     (auto-save-mode -1)            ; avoid annoying auto-save messages
  422.    
  423.     ;; the following should be a user option I suppose
  424.     (setq file-precious-flag t)        ; copy the original file on save
  425.   
  426.     (finish-math-mode-initialization)
  427.     ))
  428.  
  429.  
  430. (defun math-file-name-root (name)
  431.   "Return the root of the file name NAME.
  432. The root is missing the tail end suffix of the name, that is,
  433. everything following the last \".\"."
  434.   (setq name (file-name-nondirectory
  435.           (or name
  436.           (read-file-name "Save to file: " default-directory "math"))))
  437.   (if (string-match "\\.[^.]*$" name)
  438.       (substring name 0 (match-beginning 0))
  439.     name)
  440.   )
  441.       
  442.  
  443. (defun finish-math-mode-initialization ()
  444.   "Finish up math-mode initialization on the current buffer.
  445. The buffer is either empty or contains an internally formatted notebook."
  446.   (run-hooks 'text-mode-hook 'math-mode-hook)
  447.  
  448.   (if (= 0 (buffer-size))        ; if empty
  449.       (progn
  450.     (math-insert-new-input-cell nil)
  451.     (math-check-current-cell nil))
  452.     
  453.     ;; not empty
  454.     (math-check-current-cell nil)
  455.     (if math-eval-init-cells
  456.     (if (or (eq t math-eval-init-cells)
  457.         (y-or-n-p "Evaluate initialization cells? "))
  458.         (math-eval-init-cells)))
  459.     )
  460.  
  461.   (math-setup-change-hooks)
  462.   (buffer-enable-undo (current-buffer))
  463.   )
  464.  
  465.  
  466.  
  467.  
  468. ;;;---------------------------------------------
  469. ;; Math package mode.
  470.  
  471. (defvar math-package-mode-map nil "")
  472.  
  473. (if (and math-package-mode-map   ; do this just once
  474.      (not math-show-debug)) ; unless debugging
  475.     nil
  476.  
  477.   (progn
  478.     (setq math-package-mode-map (make-keymap))
  479.  
  480.     (let ((i 32))
  481.       (while (< i 127)
  482.     (define-key math-package-mode-map (char-to-string i) 
  483.       'self-insert-command)
  484.     (setq i (1+ i)))
  485.       )
  486.  
  487.     (define-key math-package-mode-map "\C-m" 'newline-and-indent)
  488.     (define-key math-package-mode-map "\t" 'math-package-indent-line)
  489.     (define-key math-package-mode-map "\M-\C-q" 'math-package-indent-exp)
  490.  
  491.     ))
  492.  
  493.  
  494.  
  495. (defun math-package-mode ()
  496.   "Set up local variables for math-package-mode."
  497.   (interactive)
  498.   (kill-all-local-variables)
  499.  
  500. ;;  (setq selective-display t)
  501.  
  502.   (use-local-map math-package-mode-map)
  503.  
  504.   (setq mode-name "Math Package")
  505.   (setq major-mode 'math-package-mode)
  506.   (make-local-variable 'math-package-mode)
  507.   (setq math-package-mode t)
  508.  
  509.   ;; probably could include a few abbreviations!!
  510. ;;  (if (not (boundp 'math-package-mode-abbrev-table))
  511. ;;      (define-abbrev-table 'math-package-mode-abbrev-table ()))
  512. ;;  (setq local-abbrev-table math-package-mode-abbrev-table)
  513.  
  514.   (set-syntax-table math-mode-syntax-table)
  515.  
  516.   (make-local-variable 'indent-line-function)
  517.   (setq indent-line-function 'math-package-indent-line)
  518.  
  519.   ;; this needs some work - possibly replace the paragraph filler
  520. ;;  (make-local-variable 'paragraph-start)
  521. ;;  (setq paragraph-start (concat "^[ \t\n\f]\\|^"
  522. ;;                math-cell-label-text-regexp
  523. ;;                "\\|" page-delimiter))
  524.  
  525. ;;  (make-local-variable 'paragraph-separate)
  526. ;;  (setq paragraph-separate (concat "^[ \t\f]*$\\|^"
  527. ;;                   math-cell-label-text-regexp))
  528.  
  529.   (make-local-variable 'comment-start)
  530.   (setq comment-start "(* ")
  531.   (make-local-variable 'comment-end)
  532.   (setq comment-end " *)")
  533.   (make-local-variable 'comment-column)
  534.   (setq comment-column 32)
  535.   (make-local-variable 'comment-start-skip)
  536.   (setq comment-start-skip "(\\*+ *")
  537.   (make-local-variable 'comment-indent-hook)
  538.   (setq comment-indent-hook 'math-comment-indent)
  539. ;;  (make-local-variable 'parse-sexp-ignore-comments)
  540. ;;  (setq parse-sexp-ignore-comments t)
  541.  
  542.   )
  543.  
  544. (defun math-package-indent-line (&optional arg)
  545.   "Indent current line as Math code.
  546. With argument, indent any additional lines of the same expression
  547. rigidly along with this one."
  548.   (interactive "P")
  549.   (math-indent-line arg))
  550.  
  551.  
  552.  
  553.  
  554. ;---------------------------------------------
  555. ; Debugging and errors
  556.  
  557. (defun to-math-debug (msg)
  558.   "Same as to-math-buffer except to a debug window."
  559.   (if math-show-debug
  560.       (let
  561.           ((obuf (current-buffer))
  562.            (owin (selected-window))
  563.            math-debug-window
  564.            math-debug-buffer
  565.            )
  566.         (set-buffer
  567.      (setq math-debug-buffer (get-buffer-create "*math-debug*")))
  568.         (setq math-debug-window
  569.               (display-buffer math-debug-buffer))
  570.  
  571.         (goto-char (point-max))
  572.         (insert msg)
  573.         (forward-line (- 1 (window-height math-debug-window)))
  574.         (set-window-start math-debug-window (point) )
  575. ;;;       (message "point: %s  window: %s  buffer: %s" (point)
  576. ;;;                math-debug-window math-debug-buffer)
  577. ;;;       (sit-for 1)
  578. ;;;       (update-display)
  579.         (bury-buffer math-debug-buffer)
  580.         (set-buffer obuf)
  581.         )
  582.     )
  583.   )
  584.  
  585. (defun math-error (str &rest args)
  586.   "Copy error to math-debug and show error message to user."
  587.   (if math-show-debug
  588.       (progn
  589.         (to-math-debug (apply 'format (concat " >>> " str " <<<\n") args))
  590.         (apply 'error str args)
  591.         )))
  592.  
  593.  
  594.  
  595.   
  596.  
  597. ;;------------
  598. ;; Math-Cell labels
  599.  
  600.  
  601. ;;(defconst math-nb-heading-start-regexp "^::\\["
  602. ;;  "Regular expression to match the special notebook control heading.")
  603.  
  604. ;;(defconst math-cell-heading-or-subheading-start-regexp "^[;:]\\["
  605. ;;  "Regular expression to match the beginning of a heading or subheading line.")
  606.  
  607. (defconst math-cell-heading-start-regexp "^:\\["
  608.   "Regular expression to match the beginning of a heading line.
  609. Any line whose beginning matches this regexp is considered a math-cell-heading.")
  610.  
  611.  
  612. (defconst math-cell-depth-char ?\>
  613.   "Character used to show depth of a math-cell.")
  614.  
  615. (defconst math-cell-beginning-char "-"
  616.   "String used to label the start of every math-cell, unless it has a name.
  617. It should be at least one character long to hide the marker after.")
  618.  
  619. (defconst math-group-beginning-char "="
  620.   "String used to label the start of every math-cell, unless it has a name.
  621. It should be at least one character long to hide the marker after.")
  622.  
  623. ;;(defconst show-depth-always nil
  624. ;;  "If non-nil, show the depth of a math-cell even if there is a name field.")
  625.  
  626. (defconst math-cell-message-label "[a-zA-Z0-9]+::[a-zA-Z0-9]+:"
  627.   "Regular expression to match a message math-cell label.")
  628.  
  629. (defconst math-cell-label-text-regexp
  630.   (concat
  631.    "\\("
  632.    "\\("
  633.    "[" math-cell-beginning-char math-group-beginning-char "]"
  634.    (char-to-string math-cell-depth-char)
  635.    "+ \\)?\\(In\\[[0-9]+\\]:=\\|Out\\[[0-9]+\\]\\(//[^=]+\\)?=\\|"
  636.    math-cell-message-label
  637.    "\\)\\|"
  638.    "[" math-cell-beginning-char math-group-beginning-char "]"
  639.    (char-to-string math-cell-depth-char)
  640.    "+\\) ?")
  641.   "Same as math-cell-label-regexp, but without prefix.")
  642.  
  643. (defconst math-cell-label-regexp
  644.   (concat
  645.    "[\n\r]" ; must be at beginning of line, may be hidden
  646.    math-cell-label-text-regexp)
  647.   "Regular expression matching a math-cell label.
  648. Last space is optional.")
  649.  
  650. (defun math-match-cell-label ()
  651.   "Match the next math-cell label after point."
  652.   (re-search-forward math-cell-label-regexp nil 'move)
  653.   )
  654.  
  655. (defun math-back-to-cell-label ()
  656.   "Move point back to the previous math-cell label.
  657. This is the char before the label so that math-match-cell-label will match it.
  658.  If at end of file, back up to the label of last math-cell."
  659.   (if (re-search-forward "[\n\r]\\|\\'" nil 'move)
  660.       (re-search-backward math-cell-label-regexp nil 'move))
  661.   )
  662.  
  663.  
  664. (defun math-label-to-contents ()
  665.   "Move point from somewhere in the label to the start of the math-cell contents."
  666.   (re-search-backward "[\n\r]")  ; first math-cell not at beginning of buffer
  667.   (math-match-cell-label))
  668.  
  669. (defun math-end-of-contents ()
  670.   "Move point from somewhere in a math-cell to the end of its contents."
  671.   (if (math-match-cell-label) ; goto next math-cell or end of file
  672.       (progn
  673.     (goto-char (match-beginning 0))
  674.     (skip-chars-backward "\n\r")
  675.     ))
  676.   )
  677.  
  678.  
  679.  
  680. ;;;-------------------------------
  681. ;;; Accessing math-cell info fields
  682.  
  683.  
  684. (defconst math-cell-fields '
  685.   (name
  686.    font
  687.    closed
  688.    inactive
  689.    initialization
  690.    autoActive
  691.    Cclosed
  692.    startGroup
  693.    endGroup
  694.    output
  695.  
  696.    extras   ;; unrecognized extra fields
  697.  
  698.    ;; the rest are for the emacs frontend
  699.    output-form  ;; ;[o]
  700.    input-form   ;; ;[i] ??
  701.    eval
  702.  
  703.    styles  ;; ;[s]
  704.    contents
  705.    next-indent-width
  706.    last-indent-width
  707.  
  708.    previous
  709.    next
  710.    backward
  711.    forward
  712.    parent
  713.  
  714.    index
  715.    depth
  716.    point ; should be the last field
  717.    )
  718.   "List of names of fields of a math-cell heading.
  719. The first few are standard names; remaining are internal to
  720. the emacs front end.")
  721.  
  722. (defconst number-of-math-cell-fields (length math-cell-fields))
  723.  
  724. ;;; set the math-cell-field property of each field name to an ordinal value.
  725. (let ((i 0))
  726.   (mapcar (function (lambda (field)
  727.               (put field 'math-cell-field i)
  728.               (setq i (1+ i))))
  729.       math-cell-fields))
  730.             
  731. ;; previous expression must be evaluated before next
  732. (defconst math-cell-standard-fields
  733.   (get 'contents 'math-cell-field)
  734.   "Number of standard (non-internal) fields in math-cell heading.")
  735.  
  736.  
  737. (defmacro math-cell-fieldq (math-cell-index field)
  738.   "Access the FIELD field of the math-cell referenced by math-cell-index.
  739. FIELD is unevaluated."
  740.   (` (aref (aref math-cell-vector (, math-cell-index))
  741.        (, (get field 'math-cell-field)))
  742.      ))
  743.  
  744.  
  745. (defmacro math-cell-field (math-cell-index field)
  746.   "Same as math-cell-field except field is not quoted."
  747.   (` (aref (aref math-cell-vector (, math-cell-index))
  748.        (get (, field) 'math-cell-field))
  749.      ))
  750.  
  751.  
  752.  
  753. ;; the argument to the following macros
  754. ;; should always be math-cell-index since the above field macros use that
  755.  
  756. (defmacro math-cell-contents (math-cell-index)
  757.   (` (math-cell-fieldq (, math-cell-index) contents)))
  758.  
  759. (defmacro math-cell-name (math-cell-index)
  760.   (` (car (math-cell-fieldq (, math-cell-index) name))))
  761.  
  762. (defmacro math-cell-font (math-cell-index)
  763.   (` (car (math-cell-fieldq (, math-cell-index) font))))
  764.   
  765. (defmacro math-cell-eval-p (math-cell-index)
  766.   (` (math-cell-fieldq (, math-cell-index) eval)))
  767.  
  768. (defmacro math-cell-closed-p (math-cell-index)
  769.   (` (math-cell-fieldq (, math-cell-index) closed)))
  770.  
  771. (defmacro math-cell-inactive-p (math-cell-index)
  772.   (` (math-cell-fieldq (, math-cell-index) inactive)))
  773.  
  774. (defmacro math-cell-initialization-p (math-cell-index)
  775.   (` (math-cell-fieldq (, math-cell-index) initialization)))
  776.  
  777. (defmacro math-cell-autoActive-p (math-cell-index)
  778.   (` (math-cell-fieldq (, math-cell-index) autoActive)))
  779.  
  780. (defmacro math-cell-group-closed-p (math-cell-index)
  781.   (` (math-cell-fieldq (, math-cell-index) Cclosed)))
  782.  
  783. (defmacro math-cell-start-group-p (math-cell-index)
  784.   (` (math-cell-fieldq (, math-cell-index) startGroup)))
  785.  
  786. (defmacro math-cell-end-group-p (math-cell-index)
  787.   (` (math-cell-fieldq (, math-cell-index) endGroup)))
  788.  
  789.  
  790. (defmacro math-cell-end-group (math-cell-index)
  791.   "Return the number of endGroups for this math-cell"
  792.   (` (or (math-cell-fieldq (, math-cell-index) endGroup) 0)))
  793.  
  794.  
  795. (defmacro math-cell-previous (math-cell-index)
  796.   "previous math-cell at the leaf level"
  797.   (` (math-cell-fieldq (, math-cell-index) previous)))
  798.  
  799. (defmacro math-cell-next (math-cell-index)
  800.   "next math-cell at the leaf level"
  801.   (` (math-cell-fieldq (, math-cell-index) next)))
  802.  
  803. (defmacro math-cell-backward (math-cell-index)
  804.   "previous math-cell at the same level in the group."
  805.   (` (math-cell-fieldq (, math-cell-index) backward)))
  806.  
  807. (defmacro math-cell-forward (math-cell-index)
  808.   "next math-cell at the same level in the group."
  809.   (` (math-cell-fieldq (, math-cell-index) forward)))
  810.  
  811. (defmacro math-cell-parent (math-cell-index)
  812.   (` (math-cell-fieldq (, math-cell-index) parent)))
  813.  
  814. (defmacro math-cell-offspring (math-cell-index)
  815.   (` (math-cell-fieldq (, math-cell-index) next)))
  816.  
  817.  
  818.  
  819. (defmacro math-cell-depth (math-cell-index)
  820.   (` (math-cell-fieldq (, math-cell-index) depth)))
  821.  
  822. (defmacro math-cell-point (math-cell-index)
  823.   (` (math-cell-fieldq (, math-cell-index) point)))
  824.  
  825. (defmacro math-cell-output-p (math-cell-index)
  826.   (` (math-cell-fieldq (, math-cell-index) output)))
  827.  
  828. (defmacro math-cell-output-form (math-cell-index)
  829.   (` (math-cell-fieldq (, math-cell-index) output-form)))
  830.  
  831. (defmacro math-cell-input-form (math-cell-index)
  832.   (` (math-cell-fieldq (, math-cell-index) input-form)))
  833.  
  834. (defmacro math-cell-next-indent (math-cell-index)
  835.   (` (math-cell-fieldq (, math-cell-index) next-indent-width)))
  836.  
  837. (defmacro math-cell-last-indent (math-cell-index)
  838.   (` (math-cell-fieldq (, math-cell-index) last-indent-width)))
  839.  
  840.  
  841. ;;;------------------
  842. ;;; setting math-cell fields
  843.  
  844. (defmacro set-math-cell  (math-cell-index field &optional value)
  845.   "Set math-cell MATH-CELL-INDEX field FIELD to VALUE, which may be nil."
  846.   (` (and (, math-cell-index)        ; this could be dangerous!!
  847.       (aset (aref math-cell-vector (, math-cell-index))
  848.         (, (get (eval field) 'math-cell-field))
  849.         (, value)
  850.         ))))
  851.  
  852. ;;-----------------------------------
  853. ;; The math-cell vector
  854. ;; This vector holds all the cells for a buffer.
  855.  
  856. (defvar math-cell-vector-length 0
  857.   "Current length of math-cell-vector.")
  858.  
  859. (defconst math-cell-vector-increment 100
  860.   "How much to add to math-cell-vector as necessary.")
  861.   
  862. (defvar math-cell-vector nil
  863.   "A vector of all cells in a buffer.  nil values indicate an empty cell.")
  864.  
  865. (defvar free-math-cells nil
  866.   "List of indexes of free math-cells.")
  867.  
  868. (defun init-math-cell-vector ()
  869.   "Initialize math-cell-vector and associated things to empty.
  870. Make all associated variables buffer-local."
  871.   (make-local-variable 'math-cell-vector)
  872.   (setq math-cell-vector [])
  873.   (make-local-variable 'math-cell-vector-length)
  874.   (setq math-cell-vector-length 0)
  875.   (make-local-variable 'free-math-cells)
  876.   (setq free-math-cells nil)
  877.   (make-local-variable 'math-cell-markers)
  878.   (setq math-cell-markers nil)
  879.   )
  880.  
  881.  
  882. ;; the math-cell-vector never shrinks!!
  883. (defun grow-math-cell-vector ()
  884.   "More math-cells are needed, so add the amount in math-cell-vector-increment."
  885.   (let ((i (+ math-cell-vector-length math-cell-vector-increment)))
  886.     (setq math-cell-vector
  887.       (vconcat math-cell-vector
  888.            (make-vector math-cell-vector-increment nil)))
  889.     (while (> i math-cell-vector-length) ; watch for off-by-one error
  890.       (setq i (1- i))
  891.       (setq free-math-cells (cons i free-math-cells))
  892.       ))
  893.   (setq math-cell-vector-length (length math-cell-vector))
  894.   )
  895.  
  896.  
  897. (defun new-math-cell-info (&optional math-cell-heading)
  898.   "Find an empty spot in math-cell-vector to put MATH-CELL-HEADING.  
  899. Add index field and return the new index."
  900.  
  901.   (if (not math-cell-heading)
  902.       (setq math-cell-heading (make-vector (length math-cell-fields) nil)))
  903.   
  904.   (let (math-cell-index)
  905.     (if (not free-math-cells)
  906.     (progn
  907.       ;;    (garbage-collect-math-cells)
  908.       ;;      (if (not free-math-cells) )
  909.       (grow-math-cell-vector)))
  910.     (setq math-cell-index  (car free-math-cells))
  911.     (setq free-math-cells (cdr free-math-cells))
  912.       
  913.     (aset math-cell-vector math-cell-index math-cell-heading)
  914.     (set-math-cell math-cell-index 'index math-cell-index)
  915.     math-cell-index
  916.     ))
  917.  
  918.  
  919. (defun delete-math-cell-info (math-cell-index)
  920.   "Delete the math-cell-heading info of MATH-CELL-INDEX.
  921. The math-cell info may already be nil, in which case nothing is done."
  922.   (if (and (< math-cell-index math-cell-vector-length)
  923.        (aref math-cell-vector math-cell-index))
  924.       (progn
  925.     (delete-math-cell-marker math-cell-index)
  926.     (setq free-math-cells (cons math-cell-index free-math-cells))
  927.     (aset math-cell-vector math-cell-index nil)
  928.     )))
  929.  
  930.  
  931.  
  932. ;;------------------------------
  933. ;; Consistency checks
  934.  
  935. (defun check-math-cell (&optional math-cell-index)
  936.   "Check that MATH-CELL-INDEX is correctly connected to its neighbors."
  937.   (interactive)
  938.   (or math-cell-index
  939.       (setq math-cell-index (current-math-cell)))
  940.   (let ((next (math-cell-next math-cell-index))
  941.     (previous (math-cell-previous math-cell-index))
  942.     (forward (math-cell-forward math-cell-index))
  943.     (backward (math-cell-backward math-cell-index))
  944.     (parent (math-cell-parent math-cell-index))
  945.     (pnt (math-cell-point math-cell-index))
  946.     )
  947.     (if pnt
  948.     (save-excursion (goto-math-cell math-cell-index)))
  949.     (if next
  950.     (or (and
  951.          (= math-cell-index (math-cell-previous next))
  952.          (/= math-cell-index next))
  953.         (math-error "%s <> (previous next:%s)" math-cell-index next)))
  954.     (if previous
  955.     (or (and
  956.          (= math-cell-index (math-cell-next previous))
  957.          (/= math-cell-index previous))
  958.         (math-error "%s <> (next previous:%s)" math-cell-index previous)))
  959.     (if forward
  960.     (or (and
  961.          (= math-cell-index (math-cell-backward forward))
  962.          (/= math-cell-index forward))
  963.         (math-error "%s <> (backward forward:%s)" math-cell-index forward)))
  964.     (if backward
  965.     (or (and
  966.          (= math-cell-index (math-cell-forward backward))
  967.          (/= math-cell-index backward))
  968.         (math-error "%s <> (forward backward:%s)" math-cell-index backward)))
  969.     (if parent
  970.     (let ((child (math-cell-next parent)))
  971.       (while (and child (not (eq child math-cell-index)))
  972.         (or (= parent (math-cell-parent child))
  973.         (math-error "%s <> (child parent:%s)" child parent))
  974.         (setq child (math-cell-forward child)))
  975.       (or (eq math-cell-index child)
  976.           (math-error "%s <> (child parent:%s)" math-cell-index parent))))
  977.     ))
  978.       
  979.     
  980.  
  981.  
  982.  
  983. ;;--------------------------------
  984. ;; Killing cells
  985. ;; These are globals since only one set of killed cells
  986. ;; can exist, like the character kills without the kill-ring
  987.  
  988. (defvar killed-math-cells-buffer nil
  989.   "The buffer in which killed-math-cells exist.  There may only be one.
  990. Thus, a new kill-math-cells command must first remove old killed-math-cells.")
  991.  
  992. (defvar killed-math-cells nil
  993.   "List of killed math-cells that havent been removed yet
  994. because they may be yanked later.")
  995.  
  996. (defvar dead-math-cells nil 
  997.   "List of other math-cells which havent been removed,
  998. but will never be yanked.  The purpose of using this is that some killed
  999. math-cells may also be permanently (unrecoverably) dead, but we cannot
  1000. easily remove only some killed math-cells, so we just remember them 
  1001. for later removal.")
  1002.  
  1003. (defvar math-yank-with-copy nil
  1004.   "Global flag that indicates whether a math-yank should be performed
  1005. with copy instead of by simply relinking.
  1006. A copy must be done if the math-cells
  1007. being yanked already have been yanked in the notebook.
  1008. So, if math-yank-with-copy is non-nil, then the killed math-cells should
  1009. not be removed.
  1010. A copy must also be made if the yank is across buffers, but that is
  1011. checked separately since it can change as the current buffer changes.
  1012. Dont change this yourself.")
  1013.  
  1014.  
  1015. (defun kill-math-cell-info (math-cell-index)
  1016.   "Kill the math-cell info of MATH-CELL-INDEX.
  1017. The killed math-cell is put on killed-math-cell list.
  1018. This is called by math-kill-cell."
  1019.   (setq killed-math-cells-buffer (current-buffer))
  1020.   (setq math-yank-with-copy nil)    ; fresh kill can be relinked
  1021.   (setq killed-math-cells (cons math-cell-index killed-math-cells))
  1022.   ;; delete the math-cell marker too
  1023.   (delete-math-cell-marker math-cell-index)
  1024.   )
  1025.  
  1026. ;;(defun live-buffer-p (buf)
  1027. ;;  "Return nil if BUF is nil or a deleted buffer."
  1028. ;;  (and buf (buffer-name buf)))
  1029.  
  1030. (defun remove-killed-math-cells ()
  1031.   "Remove the killed-math-cells and any connected by 'next field.
  1032. Also remove any dead-math-cells."
  1033.   (if (and killed-math-cells-buffer    ; anything killed cells?
  1034.        (buffer-name killed-math-cells-buffer)) ; buffer killed?
  1035.  
  1036.       (let ((sav-buffer (current-buffer)))
  1037.     (set-buffer killed-math-cells-buffer)
  1038.  
  1039.     ;; dont remove killed-math-cells if yanked or in another buffer
  1040.     (if (not math-yank-with-copy)
  1041.         (while killed-math-cells
  1042.           (let ((math-cell-index (car killed-math-cells)))
  1043.         (while math-cell-index
  1044.           (delete-math-cell-info
  1045.            (prog1 math-cell-index ; get the next cell before deleting
  1046.              (setq math-cell-index (math-cell-next math-cell-index))
  1047.              ))))
  1048.           (setq killed-math-cells (cdr killed-math-cells))
  1049.           ))
  1050.  
  1051.     ;; always remove dead math-cells
  1052.     (while dead-math-cells
  1053.       (let ((math-cell-index (car dead-math-cells)))
  1054.         (while math-cell-index
  1055.           (delete-math-cell-info
  1056.            (prog1 math-cell-index    ; get the next cell before deleting
  1057.          (setq math-cell-index (math-cell-next math-cell-index))
  1058.          ))))
  1059.       (setq dead-math-cells (cdr dead-math-cells))
  1060.       )
  1061.  
  1062.     (set-buffer sav-buffer)
  1063.     ))
  1064.  
  1065.   ;; no more killed math cells
  1066.   (setq killed-math-cells nil)
  1067.   (setq dead-math-cells nil)
  1068.   (setq killed-math-cells-buffer nil)
  1069.   (setq math-yank-with-copy nil)
  1070.   )
  1071.  
  1072.  
  1073.  
  1074. ;;;-----------------------------
  1075. ;;; Math-Cell Markers
  1076. ;;; We need to have a separate list of math-cell markers
  1077. ;;; so that it can be searched through for the current math-cell.
  1078.  
  1079. (defvar math-cell-markers nil
  1080.   "An alist of math-cell markers and the math-cell index it is for.")
  1081.  
  1082. (defun add-math-cell-marker (math-cell-index marker)
  1083.   "Add an marker/index pair to the front of math-cell-markers."
  1084.   (setq math-cell-markers 
  1085.     (cons (cons marker math-cell-index) math-cell-markers)))
  1086.  
  1087. (defun delete-math-cell-marker (math-cell-index)
  1088.   "Delete the marker from math-cell-markers indexed by MATH-CELL-INDEX."
  1089.   (setq math-cell-markers
  1090.     (delq (rassq math-cell-index math-cell-markers) math-cell-markers)))
  1091.  
  1092. (defun replace-math-cell-marker (math-cell-index marker)
  1093.   (delete-math-cell-marker math-cell-index)
  1094.   (add-math-cell-marker math-cell-index marker))
  1095.  
  1096.  
  1097. (defun find-math-cell-marker ()
  1098.   "Find the math-cell with a marker at the current point.
  1099. Return that math-cell index.  Should not return nil."
  1100.   (let* ((temp-marker (point-marker))
  1101.      (math-cell (cdr (assoc temp-marker math-cell-markers))))
  1102.     (if (not math-cell)
  1103.     (math-error
  1104.      "Bad cell marker at point %s.  This is a bug; please report."
  1105.      (point)))
  1106.     math-cell
  1107.     ))
  1108.  
  1109.       
  1110. (defun current-math-cell ()
  1111.   "Return the index of the enclosing open math-cell.
  1112. If before the first math-cell, return the first math-cell index."
  1113.   ;; this doesnt save-excursion since often that is not needed.  
  1114.  
  1115.   (if (or (eobp) (looking-at "[ \t\n\r\f]"))
  1116.       (skip-chars-backward " \t\n\r\f"))
  1117.   (beginning-of-line)            ; skip any closed math-cells
  1118.   (if (not (math-back-to-cell-label))
  1119.       (progn                ; then look forward
  1120.     (math-match-cell-label)
  1121.     (math-back-to-cell-label)))
  1122.  
  1123.   (if (not (eobp))
  1124.       (forward-char 1))
  1125.   (if (not (eobp))
  1126.       (forward-char 1))
  1127.   (if (eobp)
  1128.       nil
  1129.     (find-math-cell-marker)
  1130.     )
  1131.   )
  1132.  
  1133.  
  1134. (defun goto-math-cell (math-cell-index)
  1135.   "Goto the math-cell point of MATH-CELL-INDEX, if it exists,
  1136. else try to find where it might be."
  1137.   (if math-cell-index
  1138.       (let ((pnt (math-cell-point math-cell-index)))
  1139.     (if pnt
  1140.         (progn
  1141.           (goto-char pnt)
  1142.           (and math-show-debug 
  1143.            ;; consistency check
  1144.            (not (eq (find-math-cell-marker) math-cell-index))
  1145.            (math-error "cell marker not at cell: %s"
  1146.                    math-cell-index))
  1147.           pnt)
  1148.       (math-error "cell %s has no point" math-cell-index)
  1149.       ))))
  1150.  
  1151.  
  1152. ;;---------------------------
  1153. ;; Changing math-cell info fields
  1154.  
  1155. (defun edit-math-cell-attributes ()
  1156.   "Allow user to edit some of the the cell attributes of the current cell."
  1157.   (interactive)
  1158.   (let ((math-cell-index (current-math-cell)))
  1159.     (if math-cell-index
  1160.     (let ((active (not (math-cell-inactive-p math-cell-index)))
  1161.           (initialization (math-cell-initialization-p math-cell-index))
  1162.           (auto-active (math-cell-autoActive-p math-cell-index))
  1163.           )
  1164.       (edit-options            ; uses a modified edit-options
  1165.         '(active initialization auto-active))
  1166.       (recursive-edit)
  1167.       
  1168.       ;; done with options
  1169.       ;; should check each option to see if it was changed.
  1170.       (set-math-cell math-cell-index 'inactive (not active))
  1171.       (set-math-cell math-cell-index 'initialization initialization)
  1172.       (set-math-cell math-cell-index 'autoActive auto-active)
  1173.       ))))
  1174.  
  1175.  
  1176. ;;; These are not generally useful - could be macros
  1177.  
  1178. (defun open-math-cell (math-cell-index)
  1179.   (set-math-cell math-cell-index 'closed))
  1180.  
  1181. (defun open-math-group (math-cell-index)
  1182.   (set-math-cell math-cell-index 'Cclosed)
  1183.   )
  1184.  
  1185.  
  1186.  
  1187. ;;;--------------------
  1188. ;;; Moving between math-cells
  1189.  
  1190.  
  1191. (defun math-move-to-cell (math-cell-index)
  1192.   (if math-cell-index
  1193.       (progn
  1194.     (goto-math-cell math-cell-index)
  1195.     (math-label-to-contents))))
  1196.  
  1197. (defun math-move-to-current-cell ()
  1198.   (interactive)
  1199.   (math-move-to-cell (current-math-cell)))
  1200.  
  1201.  
  1202. (defun move-to-math-cell-rel (direction)
  1203.   "Move the point to inside the math-cell in the given DIRECTION relative
  1204. to the current math-cell."
  1205.   (let* ((math-cell-index (save-excursion (current-math-cell)))
  1206.      (dest-index (math-cell-field math-cell-index direction))
  1207.      )
  1208.     (if (not dest-index)
  1209.     (message "No cell in that direction")
  1210.       (goto-math-cell dest-index)
  1211.  
  1212.       (if (memq direction '(next forward))
  1213.       (progn
  1214.         (re-search-backward "[\n\r]")
  1215.         (search-forward "\n"))
  1216.     (current-math-cell))
  1217.       (math-label-to-contents))
  1218.     ))
  1219.  
  1220. (defun math-next-cell ()
  1221.   (interactive)
  1222.   (move-to-math-cell-rel 'next))
  1223.  
  1224. (defun math-previous-cell ()
  1225.   (interactive)
  1226.   (move-to-math-cell-rel 'previous))
  1227.  
  1228. (defun math-backward-cell ()
  1229.   (interactive)
  1230.   (move-to-math-cell-rel 'backward))
  1231.  
  1232. (defun math-forward-cell ()
  1233.   (interactive)
  1234.   (move-to-math-cell-rel 'forward))
  1235.  
  1236. (defun math-parent-cell ()
  1237.   (interactive)
  1238.   (move-to-math-cell-rel 'parent))
  1239.  
  1240.  
  1241. (defun first-math-cell ()
  1242.   "Return the first math-cell of the notebook."
  1243.   ;; find the first math-cell
  1244.   (if (> (length math-cell-vector) 0)
  1245.       (let ((first-math-cell 0))
  1246.     ;; go forward until non-nil
  1247.     (while (not (aref math-cell-vector first-math-cell))
  1248.       (setq first-math-cell (1+ first-math-cell)))
  1249.     ;; backup til no previous
  1250.     (while (math-cell-previous first-math-cell)
  1251.       (setq first-math-cell (math-cell-previous first-math-cell)))
  1252.     first-math-cell
  1253.     )))
  1254.  
  1255.  
  1256.  
  1257.  
  1258. ;;;-----------------------------
  1259. ;;; Math-Cell hiding and showing
  1260.  
  1261. (defun math-ensure-blank-line ()
  1262.   "Make sure there are at least two blank lines around point."
  1263.   ;; bob and eob count for one blank line
  1264.   (if (not (bobp))
  1265.       (progn
  1266.     (forward-char -1)
  1267.     (if (looking-at "[\n\r]")
  1268.         (forward-char 1)
  1269.       (if (not (eobp))
  1270.           (forward-char 1))
  1271.       (insert "\n"))))
  1272.  
  1273.   (if (or (eobp) (looking-at "[\n\r]"))
  1274.       nil
  1275.     (insert "\n")
  1276.     (forward-char -1)
  1277.     ))
  1278.  
  1279.  
  1280. (defun math-flag-region (from to flag)
  1281.   "Hides or shows lines from FROM to TO, according to FLAG.  If FLAG
  1282. is \\n (newline character) then text is shown, while if FLAG is \\r
  1283. \(control-M) the text is hidden."
  1284.   (subst-char-in-region from to
  1285.                         (if (= flag ?\n) ?\r ?\n)
  1286.                         flag 'noundo))
  1287.  
  1288.  
  1289. (defun math-hide-group (math-cell-index)
  1290.   "Hide the group of which the MATH-CELL-INDEX is the head."
  1291.  
  1292.   (let ((forward-math-cell (math-cell-forward math-cell-index))
  1293.     (next-math-cell (math-cell-next math-cell-index))
  1294.     (parent-math-cell nil))
  1295.  
  1296.     ;; show the head math-cell (up to next math-cell)
  1297.     (goto-math-cell math-cell-index)
  1298.     (math-back-to-cell-label)
  1299.     (math-ensure-blank-line)
  1300.     (if (not (bobp))
  1301.     (forward-char -1))
  1302.  
  1303.     (math-flag-region (point)
  1304.               (progn
  1305.             (goto-math-cell next-math-cell)
  1306.             (math-back-to-cell-label)
  1307.             (point))
  1308.               ?\n)
  1309.     
  1310.     ;; positioned just before next-math-cell label
  1311.     ;; insert an extra newline if needed
  1312.     (math-ensure-blank-line)
  1313.     (insert "\n") (delete-backward-char 1) ; work around to force redisplay
  1314.  
  1315.     ;; hide the math-cells in the group
  1316.     (math-flag-region
  1317.      (point)
  1318.      (progn
  1319.        (if (not forward-math-cell)
  1320.        ;; then this is the last math-cell in a group
  1321.        (progn
  1322.          ;; loop to find a parent that has a forward sibling
  1323.          (setq parent-math-cell math-cell-index)
  1324.          (while
  1325.          (and (setq parent-math-cell
  1326.                 (math-cell-parent parent-math-cell))
  1327.               (not
  1328.                (setq forward-math-cell
  1329.                  (math-cell-forward parent-math-cell))))
  1330.            )
  1331.          ))
  1332.  
  1333.        (if (not forward-math-cell)
  1334.        (goto-char (point-max))    ; must be last math-cell in notebook
  1335.      (goto-math-cell forward-math-cell)
  1336.      (math-back-to-cell-label)
  1337.      (math-ensure-blank-line)
  1338.      (forward-char -1)        ; leave a blank line showing
  1339.      )
  1340.  
  1341.        (point))
  1342.      ?\r)
  1343.     )
  1344.   )
  1345.  
  1346.  
  1347. (defun math-show-group (math-cell-index)
  1348.   "Show the open group of which the MATH-CELL-INDEX is the head.
  1349. Called recursively on subgroups if they are open."
  1350.  
  1351.   (let ((next-math-cell (math-cell-next math-cell-index)) ; first offspring
  1352.     )
  1353.  
  1354.     ;; show the header math-cell
  1355.     (goto-math-cell math-cell-index)
  1356.     (math-back-to-cell-label)
  1357.     (math-ensure-blank-line)
  1358.     
  1359.     (if (not (bobp))
  1360.     (forward-char -1))        ; show any previous blank line
  1361.  
  1362.     (math-flag-region (point)
  1363.               (progn
  1364.             (goto-math-cell next-math-cell)
  1365.             (math-back-to-cell-label)
  1366.             (forward-char 1)
  1367.             (point))
  1368.               ?\n)
  1369.  
  1370.     ;; delete any extra newlines at end of math-cell
  1371.     (forward-char -2)
  1372.     (if (looking-at  "[\n\r][\n\r]")    ; two in a row?
  1373.     (delete-char 1))
  1374.     (insert "\n") (delete-backward-char 1) ; force redisplay
  1375.  
  1376.     (while next-math-cell
  1377.       (show-or-hide-math-cell next-math-cell)
  1378.       (setq next-math-cell (math-cell-forward next-math-cell)))
  1379.     )
  1380.   )
  1381.  
  1382.  
  1383. (defun math-hide-entry (math-cell-index)
  1384.   "Hide the body directly following this math-cell-heading."
  1385.  
  1386.   (progn
  1387.     (goto-math-cell math-cell-index)
  1388.  
  1389.     ;; explicitly show the label
  1390.     (math-back-to-cell-label)
  1391.     (math-ensure-blank-line)
  1392.     (forward-char -1)
  1393.  
  1394.     (math-flag-region (point)
  1395.               (progn
  1396.             (goto-math-cell math-cell-index)
  1397.             (point)
  1398.             )
  1399.               ?\n)
  1400.  
  1401.     (math-label-to-contents)
  1402.     (setq end-of-contents )
  1403.  
  1404.     ;; delete any extra newline at start of contents
  1405.     (delete-region (point) 
  1406.            (progn
  1407.              (skip-chars-forward "\n\r") 
  1408.              (if (looking-at math-cell-label-text-regexp)
  1409.              (skip-chars-backward "\n\r")) ; too far
  1410.              (point)))
  1411.     (insert "\r")            ; hide the first line of the contents
  1412.  
  1413.     (math-flag-region (point)        ; after newline
  1414.               (progn
  1415.             (math-end-of-contents)
  1416.             (point))
  1417.               ?\r))
  1418.   )
  1419.  
  1420.  
  1421. (defun math-show-entry (math-cell-index)
  1422.   "Show the body of MATH-CELL-INDEX."
  1423.   (save-excursion
  1424.     (let ((math-cell-start (goto-math-cell math-cell-index)))
  1425.  
  1426.       (math-label-to-contents)
  1427.  
  1428.       ;; delete extra newlines before content
  1429.       (delete-region (point)
  1430.              (progn
  1431.                (skip-chars-forward "\n\r")
  1432.                (if (looking-at math-cell-label-text-regexp)
  1433.                (skip-chars-backward "\n\r")) ; too far
  1434.                (point)))
  1435.       ;; could delete lines with only whitespace
  1436.       ;; on beginning of contents
  1437.  
  1438.       (math-back-to-cell-label)
  1439.       (math-ensure-blank-line)
  1440.       (if (not (bobp))
  1441.       (forward-char -1))
  1442.  
  1443.       (math-flag-region (point)
  1444.             (progn
  1445.               (forward-char 1)
  1446.               (math-label-to-contents)
  1447.               (math-end-of-contents)
  1448.               (if (not (eobp))
  1449.                   (forward-char 1)) ; include extra newline
  1450.               (math-ensure-blank-line)
  1451.               (if (looking-at "[\n\r][\n\r]")
  1452.                   ;; delete extra newline
  1453.                   (delete-char 1))
  1454.               (point))
  1455.             ?\n)
  1456.       ;; this is needed if labels changed while cell was closed
  1457.       (adjust-math-cell-indent math-cell-index)
  1458.       )))
  1459.  
  1460.  
  1461. (defun show-or-hide-math-cell (math-cell-index)
  1462.   "Show or hide the MATH-CELL depending on its current setting."
  1463.   (if (math-cell-start-group-p math-cell-index)
  1464.       
  1465.       (if (math-cell-group-closed-p math-cell-index)
  1466.       (math-hide-group math-cell-index)
  1467.     (math-show-group math-cell-index)
  1468.     )
  1469.  
  1470.     (if (math-cell-closed-p math-cell-index)
  1471.     (math-hide-entry math-cell-index)
  1472.       (math-show-entry math-cell-index))))
  1473.  
  1474.  
  1475. (defun adjust-math-cell-indent (math-cell-index)
  1476.   "Adjust the indent level of the open output math-cell MATH-CELL-INDEX."
  1477.   (if  (and (not (math-cell-closed-p math-cell-index))
  1478.         (math-cell-output-p math-cell-index))
  1479.       (let ((last-indent-width (or (math-cell-last-indent math-cell-index) 0))
  1480.         (next-indent-width (or (math-cell-next-indent math-cell-index) 0)))
  1481.     (if (/= last-indent-width next-indent-width)
  1482.         (let ((indent-width
  1483.            (- next-indent-width last-indent-width))
  1484.           (math-cell-start (goto-math-cell math-cell-index)))
  1485.           (goto-char math-cell-start)
  1486.       
  1487.           (next-line 1)
  1488.           (beginning-of-line)    ; first line to indent
  1489.  
  1490.           (let* ((first-line (point))
  1491.              (last-line
  1492.               (max first-line
  1493.                (progn
  1494.                  (math-match-cell-label) ; next math-cell
  1495.                  (if (not (eobp))
  1496.                  (math-back-to-cell-label))
  1497.                  (point))))) ; last line to indent
  1498.         (if (< first-line last-line)
  1499.             (indent-rigidly first-line last-line
  1500.                     indent-width)))
  1501.  
  1502.           (set-math-cell math-cell-index
  1503.                  'last-indent-width
  1504.                  next-indent-width)
  1505.           )))))
  1506.  
  1507.  
  1508. (defun math-mark-current-cell ()
  1509.   "Put point at start of math-cell and mark at end."
  1510.   (interactive)
  1511.   (let ((math-cell-region (math-cell-contents-region (current-math-cell))))
  1512.     (goto-char (cdr math-cell-region))
  1513.     (set-mark-command nil)
  1514.     (goto-char (car math-cell-region))
  1515.     ))
  1516.  
  1517. (defun math-copy-backward-cell ()
  1518.   "Copy the contents of the previous sibling into the current math-cell."
  1519.   (interactive)
  1520.   (let* ((backward-math-cell (save-excursion
  1521.                    (math-cell-backward (current-math-cell))))
  1522.      (math-cell-contents (and backward-math-cell
  1523.                   (save-excursion
  1524.                     (math-cell-contents-string
  1525.                      backward-math-cell))))
  1526.      )
  1527.     (and math-cell-contents
  1528.      (insert math-cell-contents))
  1529.     ))
  1530.  
  1531. (defun math-cell-contents-without-indent (math-cell-index)
  1532.   "Return the contents of MATH-CELL-INDEX with no indentation."
  1533.   (let ((last-indent-width (or (math-cell-last-indent math-cell-index) 0))
  1534.     (contents (math-cell-contents-string math-cell-index))
  1535.     )
  1536.     (if (= last-indent-width 0)
  1537.     contents
  1538.       (let ((indent-width
  1539.          (- last-indent-width))
  1540.         (old-buf (current-buffer))
  1541.         (buf (get-buffer-create " *math-cell*"))
  1542.         )
  1543.       
  1544.     (set-buffer buf)
  1545.     (erase-buffer)
  1546.     (insert contents)
  1547.     (goto-char (point-min))
  1548.         
  1549.     (next-line 1)
  1550.     (beginning-of-line)        ; first line to indent
  1551.  
  1552.     (indent-rigidly (point)
  1553.             (progn
  1554.               (goto-char (point-max))
  1555.               (point))    ; last line to indent
  1556.             indent-width)
  1557.  
  1558.     (prog1
  1559.         (buffer-substring (point-min) (point-max))
  1560.       (set-buffer old-buf))
  1561.     ))))
  1562.  
  1563.  
  1564. (defun math-toggle-close-cell ()
  1565.   "Open the math-cell at point if it is closed, close it if open.
  1566. Applies to groups too."
  1567.   (interactive)
  1568.   (save-excursion
  1569.     (let ((math-cell-index (current-math-cell))
  1570.       (before-change-hook nil)    ; allow change anywhere
  1571.       (inhibit-quit t)              ; no quiting in the middle
  1572.       )
  1573.       (buffer-flush-undo (current-buffer)) ; disable undoing of cell changes
  1574.  
  1575.       (unwind-protect
  1576.       (if (math-cell-start-group-p math-cell-index)
  1577.  
  1578.           (if (math-cell-group-closed-p math-cell-index)
  1579.           (progn        ; open it
  1580.             (message "Open group...")
  1581.             (math-show-group math-cell-index)
  1582.             (open-math-group math-cell-index)
  1583.             (message "")
  1584.             )
  1585.         ;; else close it
  1586.         (message "Close group...")
  1587.         (math-hide-group math-cell-index)
  1588.         (set-math-cell math-cell-index 'Cclosed t)
  1589.         (message "")
  1590.         )
  1591.  
  1592.         (if (math-cell-closed-p math-cell-index)
  1593.         (progn            ; open it
  1594.           (math-show-entry math-cell-index)
  1595.           (open-math-cell math-cell-index)
  1596.           )
  1597.           ;; else close it
  1598.           (set-math-cell math-cell-index 'closed t)
  1599.           (math-hide-entry math-cell-index)
  1600.           )
  1601.         )
  1602.     (buffer-enable-undo)
  1603.     (math-check-current-cell nil)
  1604.     ))))
  1605.  
  1606.  
  1607.  
  1608. (defun math-toggle-cell-output ()
  1609.   "Toggle whether math-cell displays input or output form."
  1610.   (interactive)
  1611.   (save-excursion
  1612.     (let ((math-cell-index (current-math-cell))
  1613.       (before-change-hook nil)    ; allow changes
  1614.       (inhibit-quit t)              ; no quiting in the middle
  1615.       )
  1616.       (buffer-flush-undo (current-buffer))
  1617.       (unwind-protect
  1618.       (if (math-cell-start-group-p math-cell-index)
  1619.           (error "Not an output math-cell.")
  1620.  
  1621.         (if (math-cell-output-p math-cell-index)
  1622.  
  1623.         (if (not (math-cell-input-form math-cell-index))
  1624.             (message "No input form available.")
  1625.           
  1626.           ;; show input form
  1627.           (let ((contents-region
  1628.              (math-cell-contents-region math-cell-index)))
  1629.  
  1630.             ;; store output form in cell info and delete it from buffer
  1631.             ;; we wont need this if the input form is changed
  1632.             (set-math-cell math-cell-index 'output-form
  1633.                    (buffer-substring (car contents-region)
  1634.                              (cdr contents-region)))
  1635.             (delete-region (car contents-region) (cdr contents-region))
  1636.         
  1637.             ;; insert the input form from math-cell info
  1638.             (goto-char (car contents-region))
  1639.             (insert (math-cell-input-form math-cell-index))
  1640.             (set-math-cell math-cell-index 'input-form)
  1641.             (set-math-cell math-cell-index 'font '(input))
  1642.  
  1643.             (set-math-cell math-cell-index 'output)
  1644.             (math-check-current-cell nil)
  1645.             (math-hide-entry math-cell-index)
  1646.             (open-math-cell math-cell-index) ; make it showable
  1647.             (math-show-entry math-cell-index)
  1648.             (message "Input form")
  1649.             ))
  1650.     
  1651.           ;; else not an output cell
  1652.           (if (not (math-cell-output-form math-cell-index))
  1653.           (message "No output form available.")
  1654.  
  1655.         ;; show output form (check whether input form was changed??)
  1656.         ;; could just ask mathematica for the output form!!
  1657.         (let ((contents-region
  1658.                (math-cell-contents-region math-cell-index)))
  1659.  
  1660.           ;; store input form in math-cell info and delete it
  1661.           (set-math-cell math-cell-index 'input-form
  1662.                  (buffer-substring (car contents-region)
  1663.                            (cdr contents-region)))
  1664.           (delete-region (car contents-region) (cdr contents-region))
  1665.         
  1666.           ;; insert the output form from cell info
  1667.           (goto-char (car contents-region))
  1668.           (insert (math-cell-output-form math-cell-index))
  1669.           (set-math-cell math-cell-index 'output-form)
  1670.           (set-math-cell math-cell-index 'font '(output))
  1671.  
  1672.           (set-math-cell math-cell-index 'output t)
  1673.           (math-check-current-cell nil)
  1674.           (math-hide-entry math-cell-index)
  1675.           (open-math-cell math-cell-index) ; make it showable
  1676.           (math-show-entry math-cell-index)
  1677.           (message "Output form")
  1678.           ))
  1679.           ))
  1680.     (buffer-enable-undo (current-buffer))
  1681.     ))))
  1682.  
  1683.  
  1684.  
  1685. ;;;----------------------------
  1686. ;;; Setting other attributes
  1687.  
  1688. (defun math-toggle-active ()
  1689.   "Ask whether to toggle active attribute of current cell."
  1690.   (interactive)
  1691.   (let* ((math-cell-index (save-excursion (current-math-cell)))
  1692.      (active (not (math-cell-inactive-p math-cell-index))))
  1693.     (if (y-or-n-p
  1694.      (format "Toggle whether cell is active (currently %s)? "
  1695.          (if active "active" "inactive")))
  1696.     (setq active (not active))
  1697.       )
  1698.     (set-math-cell math-cell-index 'inactive (not active))
  1699.     (message "Cell is %s"
  1700.          (if active "active" "inactive"))
  1701.     ))
  1702.  
  1703. (defun math-toggle-auto-active ()
  1704.   "Ask whether to toggle autoActive attribute of current cell."
  1705.   (interactive)
  1706.   (let* ((math-cell-index (save-excursion (current-math-cell)))
  1707.      (autoActive (math-cell-autoActive-p math-cell-index)))
  1708.     (cond 
  1709.      ((and (not autoActive)
  1710.        (not (math-cell-start-group-p math-cell-index)))
  1711.       (message "Cell must first be the start of a group (and active)."))
  1712.      ((and (not autoActive)
  1713.        (math-cell-inactive-p math-cell-index))
  1714.       (message "Cell must first be active (and the start of a group)."))
  1715.      (t
  1716.       (if (y-or-n-p
  1717.        (format "Toggle whether cell is autoActive (currently %s)? "
  1718.            (if autoActive "autoActive" "not autoActive")))
  1719.       (setq autoActive (not autoActive)))
  1720.     
  1721.       (set-math-cell math-cell-index 'autoActive autoActive)
  1722.       (message "Cell is %s"
  1723.            (if autoActive "autoActive" "not autoActive"))
  1724.       ))))
  1725.  
  1726.  
  1727. (defun math-toggle-initialization ()
  1728.   "Ask whether to toggle initialization attribute of current cell."
  1729.   (interactive)
  1730.   (let* ((math-cell-index (save-excursion (current-math-cell)))
  1731.      (initialization (math-cell-initialization-p math-cell-index)))
  1732.     (if (y-or-n-p
  1733.      (format "Toggle initialization attribute (currently %s)? "
  1734.          (if initialization "on" "off")))
  1735.     (setq initialization (not initialization)))
  1736.     (set-math-cell math-cell-index 'initialization initialization)
  1737.     (message "Cell initialization is %s"
  1738.          (if initialization
  1739.          (if (math-cell-inactive-p math-cell-index)
  1740.              "on; it must also be active to be evaluated." "on")
  1741.            "off"))
  1742.     ))
  1743.  
  1744.  
  1745. (defconst math-style-alist
  1746.   '(("title")
  1747.     ("subtitle")
  1748.     ("subsubtitle")
  1749.     ("section")
  1750.     ("subsection")
  1751.     ("subsubsection")
  1752.     ("text")
  1753.     ("smalltext")
  1754.     ("input")
  1755.     ("output")
  1756.     ("message")
  1757.     ("print")
  1758.     ("info")
  1759.     ("postscript")
  1760.     ("name")
  1761.     ("header")
  1762.     ("footer")
  1763.     ("help")
  1764.     ("clipboard")
  1765.     ("completions")
  1766.     ("network")
  1767.     ("graphlabel")
  1768.     ("special1")
  1769.     ("special2")
  1770.     ("special3")
  1771.     ("special5")))
  1772.  
  1773.  
  1774. (defun math-set-style ()
  1775.   "Ask for style of the current cell."
  1776.   (interactive)
  1777.   (let* ((math-cell-index (save-excursion (current-math-cell)))
  1778.      (font (math-cell-font math-cell-index))
  1779.      (newfont (completing-read
  1780.            (format "Enter style for this cell (Return for %s): "
  1781.                font)
  1782.            math-style-alist nil 'require-match))
  1783.      )
  1784.     (if (< 0 (length newfont))
  1785.     (progn
  1786.       (set-math-cell math-cell-index 'font (list (intern newfont)))))
  1787.     ))
  1788.       
  1789.  
  1790.  
  1791. ;;;------------------------------
  1792. ;;; Inserting and deleting math-cells
  1793.  
  1794. (defun math-cell-empty (math-cell-index)
  1795.   "Test whether cell MATH-CELL-INDEX is empty.
  1796. An empty cell has no non-white chars in content."
  1797.   (let ((next-math-cell (math-cell-next math-cell-index))
  1798.     end-point)
  1799.     (save-excursion
  1800.       (goto-math-cell math-cell-index)
  1801.       (math-label-to-contents)
  1802.  
  1803.       (setq end-point
  1804.         (if (not next-math-cell)
  1805.         (point-max)
  1806.           (save-excursion
  1807.         (goto-math-cell next-math-cell)
  1808.         (math-back-to-cell-label)
  1809.         (point))))
  1810.  
  1811.       (not (re-search-forward "[^ \t\r\n\f]" end-point 'noerror))
  1812.       )))
  1813.  
  1814.  
  1815. (defun math-insert-new-cell (math-cell-index &optional insert-before font name)
  1816.   "Insert a new math-cell after MATH-CELL-INDEX.
  1817. If non-nil INSERT-BEFORE, then insert before MATH-CELL-INDEX instead.  
  1818. Use FONT and NAME if provided.  Return the new math-cell.
  1819. MATH-CELL-INDEX may be nil."
  1820.   (let ((new-math-cell-index (new-math-cell-info)))
  1821.  
  1822.     ;; add empty fields 
  1823.     (set-math-cell new-math-cell-index 'contents "")
  1824.     (if name
  1825.     (set-math-cell new-math-cell-index 'name name))
  1826.     (if font
  1827.     (set-math-cell new-math-cell-index 'font font))
  1828.     (math-yank-cells math-cell-index insert-before new-math-cell-index)
  1829.     (math-move-to-cell new-math-cell-index)
  1830.     new-math-cell-index
  1831.     ))
  1832.  
  1833.  
  1834. (defun math-insert-new-text-cell (arg)
  1835.   "Create and add a math-cell before or after the math-cell at point.
  1836. If non-nil ARG, then insert before."
  1837.   (interactive "P")
  1838.   (let* ((math-cell-index (current-math-cell))
  1839.      (insert-before arg)
  1840.      (before-change-hook nil)    ; allow changes
  1841.      (inhibit-quit t)        ; no quiting in the middle
  1842.      )
  1843.     (buffer-flush-undo (current-buffer))
  1844.     (unwind-protect
  1845.     (progn
  1846.       (if (and (not insert-before)
  1847.            math-cell-index
  1848.            (math-cell-start-group-p math-cell-index))
  1849.           ;; convert to insertion before first offspring
  1850.           (progn        
  1851.         (if (math-cell-group-closed-p math-cell-index)
  1852.             (progn        ; make sure group is visible
  1853.               (open-math-group math-cell-index)
  1854.               (math-show-group math-cell-index)))
  1855.  
  1856.         (setq insert-before t)
  1857.         (setq math-cell-index
  1858.               (math-cell-offspring math-cell-index)) ; first offspring
  1859.         ))
  1860.  
  1861.       (math-insert-new-cell math-cell-index insert-before '(text) nil)
  1862.       )
  1863.       (buffer-enable-undo (current-buffer))
  1864.       )))
  1865.     
  1866.  
  1867.  
  1868.  
  1869. (defun math-kill-current-cell ()
  1870.   "Kill the current math-cell or group."
  1871.   (interactive)
  1872.   (let ((math-cell-index (current-math-cell))
  1873.     (before-change-hook nil)
  1874.     (inhibit-quit t)        ; no quiting in the middle
  1875.     )
  1876.     (buffer-flush-undo (current-buffer))
  1877.     (unwind-protect
  1878.     (progn
  1879.       ;; remove any previously killed math-cells
  1880.       (remove-killed-math-cells)
  1881.       (save-excursion
  1882.         (math-kill-cell math-cell-index)))
  1883.       (buffer-enable-undo (current-buffer)))
  1884.  
  1885. ;;    (math-move-to-current-cell)
  1886.     ))
  1887.  
  1888.  
  1889. (defun math-kill-region (start end)
  1890.   "Kill the cells in the region between mark and point.
  1891. The region is expanded so that all cells that are within the
  1892. enclosing group common between mark and point are killed.
  1893.  
  1894. Not tested!!"
  1895.   (interactive "r")
  1896.   (let ((before-change-hook nil)    ; allow changes
  1897.     (start-math-cell (progn (goto-char start)
  1898.                 (beginning-of-line)
  1899.                 (skip-chars-forward " \t\n\r")
  1900.                 (current-math-cell)))
  1901.     (end-math-cell  (progn (goto-char end)
  1902.                    (current-math-cell)))
  1903.     )
  1904.     (buffer-flush-undo (current-buffer))
  1905.     (unwind-protect
  1906.     (let* ((common (common-math-cell-parent start-math-cell end-math-cell))
  1907.            (first (car common))
  1908.            (last (cdr common))
  1909.            (cell-index first))
  1910.       (remove-killed-math-cells)
  1911.       (while (/= cell-index last)
  1912.         (setq cell-index 
  1913.           (prog1 (math-cell-forward cell-index)
  1914.             (let ((inhibit-quit t)) ; no quiting in the middle
  1915.               (math-kill-cell cell-index)))))
  1916.  
  1917.       )
  1918.       (math-move-to-current-cell)
  1919.       (buffer-enable-undo (current-buffer))
  1920.       )))
  1921.  
  1922.  
  1923. (defun math-kill-cell (math-cell-index)
  1924.   "Kill the MATH-CELL-INDEX math-cell.
  1925. Killing the only member of a group makes the group header into
  1926. a normal math-cell."
  1927.  
  1928.   (let ((parent-math-cell (math-cell-parent math-cell-index))
  1929.     (next-math-cell)
  1930.     (following-math-cell)
  1931.     (previous-math-cell)
  1932.     (backward-math-cell (math-cell-backward math-cell-index))
  1933.     (forward-math-cell (math-cell-forward math-cell-index))
  1934.     (depth)
  1935.  
  1936.     start-point end-point
  1937.     new-math-cell-index        ; index of new math-cell
  1938.     last-math-cell            ; the cell that ends group of math-cell-index
  1939.     last-end-groups            ; how many groups does last-math-cell end
  1940.     end-groups            ; how many groups does math-cell end
  1941.     end-depth
  1942.     )
  1943.  
  1944.     ;; if only one math-cell remains in group, ungroup it
  1945.     (if (and (not backward-math-cell) (not forward-math-cell)
  1946.          parent-math-cell)
  1947.     (progn
  1948.       (math-ungroup-cell parent-math-cell)
  1949.       (setq parent-math-cell (math-cell-parent math-cell-index))
  1950.       (setq backward-math-cell (math-cell-backward math-cell-index))
  1951.       (setq forward-math-cell (math-cell-forward math-cell-index))
  1952.       ))
  1953.  
  1954.     (setq previous-math-cell (math-cell-previous math-cell-index))
  1955.     (setq depth (or (math-cell-depth math-cell-index) 0))
  1956.  
  1957.     (goto-math-cell math-cell-index)
  1958.     (math-back-to-cell-label)
  1959.     (setq start-point (point))        ; point to start of deletion
  1960.  
  1961.     (setq last-math-cell math-cell-index)
  1962.     (if (or (not forward-math-cell) (math-cell-start-group-p math-cell-index))
  1963.     (progn
  1964.       ;; find math-cell that ends the math-cell-index or parent group
  1965.       ;; and how deep it is
  1966.       (setq last-math-cell (find-end-of-math-group math-cell-index))
  1967.       (setq end-depth (- (or (math-cell-depth last-math-cell) 0) depth))
  1968.       ))
  1969.  
  1970.     (if (not forward-math-cell)
  1971.     ;; math-cell-index is the last sibling in a group or in the notebook
  1972.     (progn
  1973.       ;; change the endGroup values accordingly
  1974.       (if backward-math-cell
  1975.           (setq end-groups (math-cell-end-group backward-math-cell)))
  1976.       (setq last-end-groups (math-cell-end-group last-math-cell))
  1977.       (let ((new-backward-depth (+ (or end-groups 0)
  1978.                        (- last-end-groups end-depth)))
  1979.         (new-last-depth (- last-end-groups
  1980.                    (- last-end-groups end-depth)))
  1981.         )
  1982.         (if backward-math-cell
  1983.         (if (< 0 new-backward-depth)
  1984.             (set-math-cell backward-math-cell 'endGroup
  1985.                    new-backward-depth)
  1986.           (set-math-cell backward-math-cell 'endGroup)))
  1987.         (if (< 0 new-last-depth)
  1988.         (set-math-cell last-math-cell 'endGroup new-last-depth)
  1989.           (set-math-cell last-math-cell 'endGroup))
  1990.         )))
  1991.       
  1992.  
  1993.     (setq following-math-cell
  1994.       (math-cell-next last-math-cell)) ; math-cell after last
  1995.  
  1996.     ;; store contents of math-cells in info for each math-cell under the group
  1997.     (let ((math-cell math-cell-index))
  1998.       (while (and math-cell (not (eq math-cell following-math-cell)))
  1999.     ;; put the contents in the math-cell info
  2000.     (set-math-cell math-cell 'contents
  2001.                (math-cell-contents-string math-cell))
  2002.     ;; delete the cell's point field and marker
  2003.     (set-math-cell math-cell 'point)
  2004.     (delete-math-cell-marker math-cell)
  2005.     (setq last-math-cell math-cell)
  2006.     (setq math-cell (math-cell-next math-cell))
  2007.     ))
  2008.  
  2009.     ;; remove the text of the cells
  2010.     (if following-math-cell
  2011.     (progn
  2012.       (goto-math-cell following-math-cell)
  2013.       (math-back-to-cell-label)
  2014.       (setq end-point (point))
  2015.       )
  2016.       (setq end-point (point-max)))
  2017.  
  2018.     (delete-region start-point end-point)
  2019.  
  2020.     ;; disconnect deleted math-cells
  2021.     (set-math-cell math-cell-index 'previous nil)
  2022.     (set-math-cell last-math-cell 'next nil)
  2023.     (set-math-cell math-cell-index 'backward nil)
  2024.     (set-math-cell math-cell-index 'forward nil)
  2025.  
  2026.     (kill-math-cell-info math-cell-index) ; kill the info for the cell or group
  2027.  
  2028.     ;; link around deleted math-cells
  2029.     (if previous-math-cell
  2030.     (set-math-cell previous-math-cell 'next following-math-cell))
  2031.     (if following-math-cell
  2032.     (set-math-cell following-math-cell 'previous previous-math-cell))
  2033.     (if backward-math-cell
  2034.     (set-math-cell backward-math-cell 'forward forward-math-cell))
  2035.     (if forward-math-cell
  2036.     (set-math-cell forward-math-cell 'backward backward-math-cell))
  2037.       
  2038.     ))
  2039.  
  2040.  
  2041. (defun math-cell-contents-region (math-cell-index)
  2042.   "Return a pair of numbers which are the beginning and ending
  2043. points of the contents of the math-cell MATH-CELL-INDEX."
  2044.   (let ((math-cell-start-point)
  2045.     (math-cell-end-point))
  2046.     (goto-math-cell math-cell-index)
  2047.     (math-label-to-contents)
  2048.     (setq math-cell-start-point (point))
  2049.     (math-match-cell-label)        ; find start of next math-cell
  2050.     (if (not (eobp))
  2051.     (math-back-to-cell-label))
  2052.     (skip-chars-backward "\n\r")
  2053.     ;;    (forward-char 1)
  2054.     (setq math-cell-end-point (point))
  2055.     (cons math-cell-start-point math-cell-end-point)
  2056.     ))
  2057.  
  2058.  
  2059. (defun math-cell-contents-string (math-cell-index)
  2060.   "Return the math-cell contents of MATH-CELL-INDEX from the notebook."
  2061.   (let* ((contents-region (math-cell-contents-region math-cell-index))
  2062.      (contents
  2063.       (buffer-substring (car contents-region) (cdr contents-region)))
  2064.      (start 0))
  2065.     (while (string-match "\r" contents start)
  2066.       (aset contents (match-beginning 0) ?\n)
  2067.       (setq start (match-beginning 0)))
  2068.     contents
  2069.     ))
  2070.  
  2071.  
  2072.  
  2073. (defun math-yank-killed-cells (arg)
  2074.   "Yank the last killed math-cell as an insertion
  2075. after (or before if non-nil ARG) current math-cell."
  2076.   (interactive "P")
  2077.   (let* ((math-cell-index (current-math-cell))
  2078.      (insert-before arg)
  2079.      (before-change-hook nil)    ; allow changes
  2080.      (inhibit-quit t)        ; no quiting in the middle
  2081.      )
  2082.     (if (and (not insert-before)
  2083.          math-cell-index
  2084.          (math-cell-start-group-p math-cell-index))
  2085.     ;; convert to insertion before first offspring
  2086.     (progn
  2087.       (if (math-cell-group-closed-p math-cell-index)
  2088.           (progn            ; make sure group is visible
  2089.         (open-math-group math-cell-index)
  2090.         (math-show-group math-cell-index)))
  2091.  
  2092.       (setq insert-before t)
  2093.       (setq math-cell-index
  2094.         (math-cell-offspring math-cell-index)) ; first offspring
  2095.       ))
  2096.  
  2097.     ;; check whether yank is allowed.
  2098.     ;; dont allow yank into any of the structures being yanked
  2099.     (let (parent-math-cell
  2100.       (yank-allowed t))
  2101.       (if (and math-yank-with-copy
  2102.            math-cell-index
  2103.            (eq killed-math-cells-buffer (current-buffer)))
  2104.       (progn
  2105.         ;; from the yank point, check that each parent is not killed
  2106.         (setq parent-math-cell (math-cell-parent math-cell-index))
  2107.         (while (and yank-allowed parent-math-cell)
  2108.           (setq yank-allowed
  2109.             (not (memq parent-math-cell killed-math-cells)))
  2110.           (setq parent-math-cell (math-cell-parent parent-math-cell)))
  2111.         ))
  2112.  
  2113.       (if (not yank-allowed)
  2114.       (message "Cannot yank within cells being yanked.")
  2115.  
  2116.     ;; reverse if inserting before to keep same order
  2117.     (let ((yanked-math-cells (if insert-before
  2118.                      killed-math-cells
  2119.                    (reverse killed-math-cells)))
  2120.           yanked-math-cell)
  2121.  
  2122.       (buffer-flush-undo (current-buffer))
  2123.       (unwind-protect
  2124.           (while yanked-math-cells
  2125.         (setq yanked-math-cell (car yanked-math-cells))
  2126.         (if (or math-yank-with-copy
  2127.             (not (eq killed-math-cells-buffer (current-buffer))))
  2128.             ;; then first copy it
  2129.             (setq yanked-math-cell
  2130.               (math-copy-cells yanked-math-cell 
  2131.                        killed-math-cells-buffer)))
  2132.         (math-yank-cells
  2133.          math-cell-index insert-before yanked-math-cell)
  2134.         (setq yanked-math-cells (cdr yanked-math-cells))
  2135.         )
  2136.         (setq math-yank-with-copy
  2137.           (or math-yank-with-copy
  2138.               (eq killed-math-cells-buffer (current-buffer))))
  2139.         (math-move-to-cell yanked-math-cell) ; last yanked math-cell
  2140.         (buffer-enable-undo (current-buffer))
  2141.         ))))
  2142.     ))
  2143.  
  2144.  
  2145. (defun math-yank-cells (math-cell-index insert-before yanked-math-cell)
  2146.   "Yank math-cells before or after MATH-CELL-INDEX depending on INSERT-BEFORE.
  2147. Yank all math-cells connected to YANKED-MATH-CELL."
  2148.   ;; works with nil math-cell-index for yank of first math-cell.
  2149.  
  2150.   (let ((parent-math-cell 
  2151.      (and math-cell-index (math-cell-parent math-cell-index)))
  2152.     (next-math-cell 
  2153.      (and math-cell-index (math-cell-next math-cell-index)))
  2154.     (previous-math-cell 
  2155.      (and math-cell-index (math-cell-previous math-cell-index)))
  2156.     (backward-math-cell
  2157.      (and math-cell-index (math-cell-backward math-cell-index)))
  2158.     (forward-math-cell 
  2159.      (and math-cell-index (math-cell-forward math-cell-index)))
  2160.     (depth (or (and math-cell-index (math-cell-depth math-cell-index)) 0))
  2161.  
  2162.     yanked-forwardmost-sibling    ; last sibling in yanked group
  2163.     yanked-group-end        ; last cell of yanked group
  2164.     last-math-cell            ; the cell that closes a group
  2165.     following-math-cell        ; the cell following a cell or group
  2166.     end-groups            ; how many groups does cell end
  2167.     end-depth
  2168.     )
  2169.  
  2170.     (if math-cell-index
  2171.     (if insert-before
  2172.  
  2173.         (progn
  2174.           ;; insert before math-cell math-cell-index
  2175.           (setq following-math-cell math-cell-index)
  2176.  
  2177.           ;; for all siblings, set parent and remember forwardmost sibling
  2178.           (let ((math-cell yanked-math-cell))
  2179.         (while math-cell
  2180.           (set-math-cell math-cell 'parent parent-math-cell)
  2181.           (setq yanked-forwardmost-sibling math-cell)
  2182.           (setq math-cell (math-cell-forward math-cell))))
  2183.  
  2184.           ;; find the last math-cell of yanked group
  2185.           (setq yanked-group-end yanked-forwardmost-sibling)
  2186.           (while (math-cell-next yanked-group-end)
  2187.         (setq yanked-group-end (math-cell-next yanked-group-end)))
  2188.  
  2189.           ;; Add other linkage to other math-cells
  2190.  
  2191.           (set-math-cell yanked-math-cell 'previous previous-math-cell)
  2192.           (set-math-cell yanked-group-end 'next following-math-cell)
  2193.           (if following-math-cell
  2194.           (set-math-cell following-math-cell 'previous
  2195.                  yanked-group-end))
  2196.           (if previous-math-cell
  2197.           (set-math-cell previous-math-cell 'next yanked-math-cell))
  2198.   
  2199.           (set-math-cell yanked-math-cell 'backward backward-math-cell)
  2200.           (set-math-cell yanked-forwardmost-sibling 'forward
  2201.                  math-cell-index)
  2202.           (if backward-math-cell
  2203.           (set-math-cell backward-math-cell 'forward yanked-math-cell))
  2204.           (if math-cell-index
  2205.           (set-math-cell math-cell-index
  2206.                  'backward yanked-forwardmost-sibling))
  2207.  
  2208.           ;; goto insertion point
  2209.           (goto-math-cell math-cell-index)
  2210.           (math-back-to-cell-label)
  2211.           )
  2212.  
  2213.       ;; else insert after current math-cell
  2214.  
  2215.       ;; find math-cell that ends the parent group and how deep it is
  2216.       (setq last-math-cell math-cell-index)
  2217.       (if (or (not forward-math-cell)
  2218.           (math-cell-start-group-p math-cell-index))
  2219.           (progn
  2220.         (setq end-depth 0)
  2221.         (setq last-math-cell (find-end-of-math-group last-math-cell))
  2222.         (setq end-depth 
  2223.               (- (or (and last-math-cell 
  2224.                   (math-cell-depth last-math-cell)) 0)
  2225.              depth))
  2226.         ))
  2227.  
  2228.       ;; find math-cell 'after' math-cell-index
  2229.       (setq following-math-cell
  2230.         (or forward-math-cell 
  2231.             (and last-math-cell (math-cell-next last-math-cell))))
  2232.  
  2233.       ;; set the parent of yanked siblings and remember forwardmost sibling
  2234.       (let ((math-cell yanked-math-cell))
  2235.         (while math-cell
  2236.           (set-math-cell math-cell 'parent parent-math-cell)
  2237.           (setq yanked-forwardmost-sibling math-cell)
  2238.           (setq math-cell (math-cell-forward math-cell))))
  2239.  
  2240.       ;; find the last math-cell of yanked group
  2241.       (setq yanked-group-end yanked-forwardmost-sibling)
  2242.       (while (math-cell-next yanked-group-end)
  2243.         (setq yanked-group-end (math-cell-next yanked-group-end)))
  2244.  
  2245.       ;; adjust depths of neighbors
  2246.       (if (not forward-math-cell)
  2247.           ;; math-cell-index is the last cell in a group or in notebook
  2248.           (progn
  2249.         ;; change the endGroup values accordingly
  2250.         (setq end-groups
  2251.               (or (and last-math-cell
  2252.                    (math-cell-end-group last-math-cell)) 0))
  2253.         (if (and last-math-cell (< 0 end-depth))
  2254.             (set-math-cell last-math-cell 'endGroup end-depth)
  2255.           (set-math-cell last-math-cell 'endGroup))
  2256.         ;; add endGroups to end of yanked group
  2257.         (let ((new-depth (- end-groups end-depth)))
  2258.           (set-math-cell yanked-group-end 'endGroup
  2259.                  (+ (math-cell-end-group yanked-group-end) 
  2260.                     new-depth))
  2261.           )))
  2262.  
  2263.       ;; Add linkage to other math-cells
  2264.       
  2265.       (set-math-cell yanked-math-cell 'previous last-math-cell)
  2266.       (set-math-cell yanked-group-end 'next following-math-cell)
  2267.       (if following-math-cell
  2268.           (set-math-cell following-math-cell 'previous yanked-group-end))
  2269.       (if last-math-cell
  2270.           (set-math-cell last-math-cell 'next yanked-math-cell))
  2271.   
  2272.       (set-math-cell yanked-math-cell 'backward math-cell-index)
  2273.       (set-math-cell yanked-forwardmost-sibling 'forward forward-math-cell)
  2274.       (if forward-math-cell
  2275.           (set-math-cell forward-math-cell 
  2276.                  'backward yanked-forwardmost-sibling))
  2277.       (if math-cell-index
  2278.           (set-math-cell math-cell-index 'forward yanked-math-cell))
  2279.  
  2280.  
  2281.       ;; find insertion point
  2282.       (if following-math-cell
  2283.           (progn
  2284.         (goto-math-cell following-math-cell)
  2285.         (math-back-to-cell-label))
  2286.         (goto-char (point-max))
  2287.         (skip-chars-backward "\n\r")
  2288.         (if (looking-at "[\n\r]")
  2289.         (forward-char 1))
  2290.         )
  2291.       )                ; if insert-before
  2292.       )                    ; math-cell-index
  2293.  
  2294.     ;; fix depth, insert label, insert contents of each math-cell
  2295.     (let ((math-cell yanked-math-cell)
  2296.       (delta-depth (- depth (or (math-cell-depth yanked-math-cell) 0))))
  2297.       (while (and math-cell (not (eq math-cell following-math-cell)))
  2298.     (set-math-cell math-cell 'depth (+ (or (math-cell-depth math-cell) 0)
  2299.                        delta-depth))
  2300.     (math-ensure-blank-line)
  2301.     (insert-new-math-cell-label math-cell)
  2302.     (math-label-to-contents)
  2303.     (insert (math-cell-contents math-cell) "\n")
  2304.     (math-ensure-blank-line)
  2305.     (set-math-cell math-cell 'contents)
  2306.     (setq yanked-group-end math-cell)
  2307.     (setq math-cell (math-cell-next math-cell))
  2308.     ))
  2309.     (show-or-hide-math-cell yanked-math-cell)
  2310.  
  2311.     ))
  2312.  
  2313.  
  2314. (defun math-set-current-cell-as-kill ()
  2315.   "Add the current math-cell or group to the killed-math-cells list,
  2316. but dont kill it."
  2317.   (interactive)
  2318.   (save-excursion 
  2319.     (let ((math-cell-index (current-math-cell))
  2320.       (before-change-hook nil)
  2321.       (inhibit-quit t)              ; no quiting in the middle
  2322.       )
  2323.       (buffer-flush-undo (current-buffer))
  2324.       (unwind-protect
  2325.       (progn
  2326.         ;; remove any previously killed math-cells
  2327.         (remove-killed-math-cells)
  2328.         ;; Add math-cell-index to killed-math-cells, 
  2329.         ;; but specify yank-with-copy.
  2330.         (setq killed-math-cells-buffer (current-buffer))
  2331.         (setq math-yank-with-copy t) ; copies cannot be relinked
  2332.         (setq killed-math-cells (cons math-cell-index killed-math-cells))
  2333.         )
  2334.     (buffer-enable-undo (current-buffer)))
  2335.       (message "Set current math-cell as kill")
  2336.       )))
  2337.  
  2338.  
  2339. (defun math-copy-cells (copied-math-cell copied-buffer)
  2340.   "Copy the math-cell structure COPIED-MATH-CELL from COPIED-BUFFER
  2341. to the math-cell vector in the current buffer.
  2342. If copied-math-cell is a group, all math-cells in the group are copied."
  2343.  
  2344.   (save-excursion
  2345.     (let (math-cell-index
  2346.       new-math-cell
  2347.       copied-math-cell-index
  2348.       copied-math-cell-info
  2349.       copied-math-cell-contents
  2350.       next-math-cell
  2351.       previous-math-cell
  2352.       backward-math-cell
  2353.       parent-math-cell
  2354.       ancestry
  2355.       (depth 0)
  2356.       depth-difference
  2357.       (copy-to-buffer (current-buffer)) ; the buffer to copy to
  2358.       )
  2359.  
  2360.       (set-buffer copied-buffer)
  2361.       ;; find the math-cell after the math-cell(s) to be copied
  2362.       (setq following-copied-math-cell 
  2363.         (if (math-cell-start-group-p copied-math-cell)
  2364.         (find-math-cell-after-group copied-math-cell)
  2365.           (math-cell-next copied-math-cell)))
  2366.  
  2367.       (setq copied-math-cell-index copied-math-cell)
  2368.       (setq depth-difference (math-cell-depth copied-math-cell-index))
  2369.     
  2370.       (while (not (eq copied-math-cell-index following-copied-math-cell))
  2371.     (setq copied-math-cell-info 
  2372.           (copy-sequence
  2373.            (aref math-cell-vector copied-math-cell-index)))
  2374.     (setq copied-math-cell-contents
  2375.           (or (math-cell-contents copied-math-cell-index)
  2376.           (math-cell-contents-string copied-math-cell-index)))
  2377.     (set-buffer copy-to-buffer)
  2378.  
  2379.     (setq math-cell-index (new-math-cell-info copied-math-cell-info))
  2380.     ;; remember the first new math-cell
  2381.     (setq new-math-cell (or new-math-cell math-cell-index))
  2382.     (set-math-cell math-cell-index 'contents copied-math-cell-contents)
  2383.     (set-math-cell math-cell-index 'point nil)
  2384.  
  2385.     ;; Set depth
  2386.     (set-math-cell math-cell-index 'depth
  2387.           (- (math-cell-depth math-cell-index) depth-difference))
  2388.  
  2389.     ;; Set linkage to other math-cells
  2390.     (set-math-cell math-cell-index 'parent parent-math-cell)
  2391.  
  2392.     (set-math-cell math-cell-index 'next nil)
  2393.     (set-math-cell math-cell-index 'previous previous-math-cell)
  2394.     (if previous-math-cell
  2395.         (set-math-cell previous-math-cell 'next math-cell-index))
  2396.     (setq previous-math-cell math-cell-index)
  2397.     
  2398.     (set-math-cell math-cell-index 'forward nil)
  2399.     (set-math-cell math-cell-index 'backward backward-math-cell)
  2400.     (if backward-math-cell
  2401.         (set-math-cell backward-math-cell 'forward math-cell-index))
  2402.     (setq backward-math-cell math-cell-index)
  2403.  
  2404.     ;; if it starts a group, remember parent
  2405.     (if (math-cell-start-group-p math-cell-index)
  2406.         (progn
  2407.           (setq ancestry (cons math-cell-index ancestry))
  2408.           (setq parent-math-cell math-cell-index) ; eq (car ancestry)
  2409.           (setq backward-math-cell nil)
  2410.           )
  2411.       )
  2412.  
  2413.     (let* ((end-groups (or (math-cell-end-group-p math-cell-index) 0))
  2414.            (end-depth (- depth end-groups)))
  2415.        
  2416.       (if (/= end-depth depth)
  2417.           (progn
  2418.         (setq backward-math-cell (nth (1- end-groups) ancestry))
  2419.         (setq ancestry (nthcdr end-groups ancestry))
  2420.  
  2421.         (setq depth end-depth)
  2422.         (setq parent-math-cell (car ancestry))
  2423.         )))
  2424.       
  2425.     (set-buffer copied-buffer)
  2426.     (setq copied-math-cell-index (math-cell-next copied-math-cell-index))
  2427.     )                ; while
  2428.       (set-buffer copy-to-buffer)
  2429.       new-math-cell            ; return the first new math-cell
  2430.       )))
  2431.  
  2432.  
  2433.  
  2434. ;;;------------------------------------
  2435. ;;; Grouping and Ungrouping
  2436.  
  2437. (defun math-group-region (start end)
  2438.   "Group the math-cells within the region START to END.
  2439. Group the math-cells within the common enclosing group
  2440. or at the top level."
  2441.  
  2442.   (interactive "r")
  2443.   (let ((before-change-hook nil)    ; allow changes
  2444.     (inhibit-quit t)        ; no quiting in the middle
  2445.     (start-math-cell (progn (goto-char start)
  2446.                 (beginning-of-line)
  2447.                 (skip-chars-forward " \t\n\r")
  2448.                 (current-math-cell)))
  2449.     (end-math-cell  (progn (goto-char end)
  2450.                    (current-math-cell)))
  2451.     )
  2452.     (buffer-flush-undo (current-buffer))
  2453.     (unwind-protect
  2454.     (let ((common (common-math-cell-parent start-math-cell end-math-cell)))
  2455.       (math-group-cells (car common) (cdr common)))
  2456.       (math-move-to-cell start-math-cell)
  2457.       (buffer-enable-undo (current-buffer))
  2458.       )))
  2459.  
  2460.  
  2461. (defun math-group-cells (start-of-group end-offspring)
  2462.   "Group the math-cells between start-of-group and end-offspring."
  2463.   (let (group-math-cell-index
  2464.     end-depth
  2465.     last-math-cell next-math-cell
  2466.     preface)
  2467.  
  2468.     ;; Check whether grouping is allowed
  2469.     (if (or (= start-of-group end-offspring)
  2470.         (math-cell-start-group-p start-of-group))
  2471.     (setq start-of-group
  2472.           (math-insert-new-cell start-of-group 'insert-before
  2473.                     '(section))))
  2474.  
  2475.     ;; Make start-of-group into start of group
  2476.  
  2477.     (goto-math-cell start-of-group)
  2478.  
  2479.     (set-math-cell start-of-group 'startGroup t)
  2480.  
  2481.     ;; find math-cell that ends the new group
  2482.     (setq last-math-cell (find-end-of-math-group end-offspring))
  2483.  
  2484.     ;; make last math-cell end one more group
  2485.     (let ((new-last-depth (1+ (math-cell-end-group last-math-cell))))
  2486.       (if (< 0 new-last-depth)
  2487.       (set-math-cell last-math-cell 'endGroup new-last-depth)
  2488.     (set-math-cell last-math-cell 'endGroup)))
  2489.  
  2490.     ;; Add linkage to other math-cells
  2491.     (let ((next-math-cell (math-cell-next end-offspring))
  2492.       (previous-math-cell (math-cell-previous start-of-group))
  2493.       (backward-math-cell (math-cell-backward start-of-group))
  2494.       (forward-math-cell (math-cell-forward end-offspring))
  2495.       (depth (math-cell-depth start-of-group))
  2496.       )
  2497.  
  2498.       (set-math-cell start-of-group 'forward forward-math-cell)
  2499.       (set-math-cell end-offspring 'forward nil)
  2500.       (if forward-math-cell
  2501.       (set-math-cell forward-math-cell 'backward start-of-group))
  2502.  
  2503.       (setq next-math-cell (math-cell-next start-of-group))
  2504.       (set-math-cell next-math-cell 'backward nil)
  2505.  
  2506.       ;; set parents of offspring to new parent
  2507.       (setq last-math-cell
  2508.         (math-cell-next last-math-cell)) ; reuse last-math-cell var
  2509.       (while (and next-math-cell (not (eq next-math-cell last-math-cell)))
  2510.     (set-math-cell next-math-cell 'parent start-of-group)
  2511.     (setq next-math-cell (math-cell-forward next-math-cell)))
  2512.  
  2513.       ;; set the depths of all submath-cells to one deeper and fix labels
  2514.       (setq next-math-cell (math-cell-next start-of-group))
  2515.       (while (and next-math-cell (not (eq next-math-cell last-math-cell)))
  2516.     (set-math-cell next-math-cell
  2517.                'depth (1+ (math-cell-depth next-math-cell)))
  2518.     (delete-math-cell-label next-math-cell)
  2519.     (insert-new-math-cell-label next-math-cell)
  2520.     (setq next-math-cell (math-cell-next next-math-cell)))
  2521.  
  2522.       (show-or-hide-math-cell start-of-group)
  2523.       (delete-math-cell-label start-of-group)
  2524.       (insert-new-math-cell-label start-of-group)
  2525.       )))
  2526.  
  2527.  
  2528. (defun math-ungroup-current-group ()
  2529.   "Ungroup the math-cells within the group around point."
  2530.   (interactive)
  2531.   (let ((before-change-hook nil)    ; allow changes
  2532.     (inhibit-quit t)        ; no quiting in the middle
  2533.     (math-cell-index (current-math-cell))
  2534.     (group-math-cell-index))
  2535.     (setq group-math-cell-index
  2536.       (if (math-cell-start-group-p math-cell-index)
  2537.           math-cell-index
  2538.         (math-cell-parent math-cell-index)))
  2539.     (buffer-flush-undo (current-buffer))
  2540.     (unwind-protect
  2541.     (save-excursion
  2542.       (math-ungroup-cell group-math-cell-index))
  2543.       (math-move-to-cell math-cell-index)
  2544.       (buffer-enable-undo (current-buffer)))
  2545.     ))
  2546.  
  2547.  
  2548. (defun math-ungroup-cell (math-cell-index)
  2549.   "Ungroup the group MATH-CELL-INDEX."
  2550.   (let ((group-math-cell-index math-cell-index)
  2551.     last-child-math-cell        ; last cell at one level below group
  2552.     end-group-math-cell        ; cell which ends the group
  2553.     )
  2554.  
  2555.     (if (math-cell-group-closed-p group-math-cell-index)
  2556.     (progn
  2557.       (open-math-group group-math-cell-index)
  2558.       (math-show-group group-math-cell-index)
  2559.       ))
  2560.       
  2561.     ;; find the math-cell that ends this group
  2562.     (setq end-group-math-cell (find-end-of-math-group group-math-cell-index))
  2563.  
  2564.     ;; make last math-cell end one less group
  2565.     (let ((new-end-depth  (1- (math-cell-end-group end-group-math-cell))))
  2566.       (if (< 0 new-end-depth)
  2567.       (set-math-cell end-group-math-cell 'endGroup new-end-depth)
  2568.     (set-math-cell end-group-math-cell 'endGroup)))
  2569.  
  2570.     ;; make it not a group
  2571.     (set-math-cell group-math-cell-index 'startGroup)
  2572.  
  2573.     ;; Fix linkage to other math-cells
  2574.     (let ((next-math-cell (math-cell-next group-math-cell-index))
  2575.       (previous-math-cell (math-cell-previous group-math-cell-index))
  2576.       (backward-math-cell (math-cell-backward group-math-cell-index))
  2577.       (forward-math-cell (math-cell-forward group-math-cell-index))
  2578.       (parent (math-cell-parent group-math-cell-index))
  2579.       (last-math-cell
  2580.        (math-cell-next end-group-math-cell))
  2581.       )
  2582.  
  2583.       (setq last-child-math-cell
  2584.         (find-last-child-math-cell group-math-cell-index))
  2585.       (set-math-cell group-math-cell-index 'forward next-math-cell)
  2586.       (set-math-cell last-child-math-cell 'forward forward-math-cell)
  2587.       (if forward-math-cell
  2588.       (set-math-cell forward-math-cell 'backward last-child-math-cell))
  2589.  
  2590.       (set-math-cell next-math-cell 'backward group-math-cell-index)
  2591.  
  2592.       ;; set parents of offspring to new parent
  2593.       (let ((index next-math-cell))
  2594.     (while (and index
  2595.             (not (eq index last-math-cell)))
  2596.       (set-math-cell index 'parent parent)
  2597.       (setq index (math-cell-forward index))))
  2598.  
  2599.       ;; set the depths of all sub-cells to one less and fix labels
  2600.       (while (and next-math-cell (not (eq next-math-cell last-math-cell)))
  2601.     (set-math-cell next-math-cell 'depth
  2602.                (1- (math-cell-depth next-math-cell)))
  2603.     (delete-math-cell-label next-math-cell)
  2604.     (insert-new-math-cell-label next-math-cell)
  2605.     (setq next-math-cell (math-cell-next next-math-cell)))
  2606.  
  2607.       (let ((index group-math-cell-index))
  2608.     (while (and index
  2609.             (not (eq index last-math-cell)))
  2610.       (show-or-hide-math-cell index)
  2611.       (setq index (math-cell-forward index))))
  2612.  
  2613.       (delete-math-cell-label group-math-cell-index)
  2614.       (insert-new-math-cell-label group-math-cell-index)
  2615.       )))
  2616.  
  2617.  
  2618. (defun find-last-child-math-cell (math-cell)
  2619.   "Find the last child of the group MATH-CELL."
  2620.   (let ((forward-math-cell (math-cell-next math-cell)))
  2621.     (while (and forward-math-cell
  2622.         (setq math-cell (math-cell-forward forward-math-cell)))
  2623.       (setq forward-math-cell math-cell))
  2624.     forward-math-cell))
  2625.  
  2626.  
  2627. (defun find-end-of-math-group (math-cell)
  2628.   "Find the math-cell that ends the group MATH-CELL
  2629. or return the math-cell itself if it is not a group."
  2630.   (let ((forward-math-cell (find-math-cell-after-group math-cell)))
  2631.     (if forward-math-cell
  2632.     (math-cell-previous forward-math-cell)
  2633.       ;; no more math-cells, so find last math-cell in file
  2634.       (let ((last-math-cell))
  2635.     (while math-cell
  2636.       (setq last-math-cell math-cell)
  2637.       (setq math-cell (math-cell-next math-cell)))
  2638.     last-math-cell
  2639.     ))))
  2640.  
  2641.  
  2642. (defun find-math-cell-after-group (math-cell)
  2643.   "Climb the tree until a parent of MATH-CELL has a forward-math-cell.
  2644. Return nil if MATH-CELL is nil, or if it has no forward-math-cell."
  2645.   (let ((forward-math-cell math-cell))
  2646.     (while (and math-cell 
  2647.         (not (setq forward-math-cell (math-cell-forward math-cell))))
  2648.       (setq math-cell (math-cell-parent math-cell)))
  2649.     forward-math-cell))
  2650.  
  2651.  
  2652. (defun common-math-cell-parent (math-cell1 math-cell2)
  2653.   "Return a cons of the lowest math-cells above math-cell1 and math-cell2
  2654. that have the same parent.
  2655. One math-cell might be the ancestor of the other."
  2656.   (let* ((depth1 (math-cell-depth math-cell1))
  2657.      (depth2 (math-cell-depth math-cell2))
  2658.      (i (- depth1 depth2))
  2659.      )
  2660.     (while (< i 0)            ; depth1 < depth2
  2661.       (setq math-cell2 (math-cell-parent math-cell2))
  2662.       (setq i (1+ i)))
  2663.     (while (> i 0)            ; depth1 > depth2
  2664.       (setq math-cell1 (math-cell-parent math-cell1))
  2665.       (setq i (1- i)))
  2666.  
  2667.     ;; now math-cell1 and math-cell2 are at same depth
  2668.     (let ((p1 math-cell1)
  2669.       (p2 math-cell2))
  2670.       (while (and p1 p2 (/= p1 p2))
  2671.     (setq math-cell1 p1)
  2672.     (setq p1 (math-cell-parent p1))
  2673.     (setq math-cell2 p2)
  2674.     (setq p2 (math-cell-parent p2))
  2675.     )
  2676.       (cons math-cell1 math-cell2)
  2677.       )))
  2678.  
  2679.  
  2680.  
  2681. ;;;-------------------------------
  2682. ;;; Splitting and Joining
  2683.  
  2684. (defun math-split-group ()
  2685.   "Split the current group by dropping the current math-cell and all
  2686. following math-cells in the group to the next lower level."
  2687.   (interactive)
  2688.   (let* ((math-cell-index (current-math-cell))
  2689.      (parent-math-cell (math-cell-parent math-cell-index))
  2690.      (before-change-hook nil)
  2691.      (inhibit-quit t)        ; no quiting in the middle
  2692.      )
  2693.     (buffer-flush-undo (current-buffer))
  2694.     (unwind-protect
  2695.     (if (not parent-math-cell)
  2696.         (message "Top level already")
  2697.  
  2698.       (let (;;(last-math-cell (find-last-child-math-cell parent-math-cell))
  2699.         (backward-math-cell (math-cell-backward math-cell-index)))
  2700.         (math-ungroup-cell parent-math-cell)
  2701.         (if backward-math-cell
  2702.         (math-group-cells parent-math-cell backward-math-cell))
  2703.         ;;        (check-math-cell math-cell-index)
  2704.         ;;        (check-math-cell backward-math-cell)
  2705.         ;;        (check-math-cell parent-math-cell)
  2706.         )
  2707.       )
  2708.       (math-move-to-cell math-cell-index)
  2709.       (buffer-enable-undo (current-buffer)))
  2710.     ))
  2711.  
  2712.  
  2713. (defun math-drop-cell ()
  2714.   "Drop the current math-cell from the parent group.  not tested!!"
  2715.   (interactive)
  2716.   (let* ((math-cell-index (current-math-cell))
  2717.      (parent-math-cell (math-cell-parent math-cell-index))
  2718.      (killed-math-cells)        ; protect global killed-math-cells
  2719.      (killed-math-cells-buffer)
  2720.      (math-yank-with-copy)
  2721.      (before-change-hook nil)
  2722.      (inhibit-quit t)        ; no quiting in the middle
  2723.      )
  2724.     (buffer-flush-undo (current-buffer))
  2725.     (unwind-protect
  2726.     (if parent-math-cell
  2727.         (progn            ; trick to move math-cells
  2728.           (math-kill-cell math-cell-index)
  2729.           (math-yank-cells parent-math-cell nil
  2730.                    (car killed-math-cells)) ; == math-cell-index
  2731.           )
  2732.       (message "Top level already"))
  2733.       (math-move-to-cell math-cell-index)
  2734.       (buffer-enable-undo (current-buffer)))
  2735.     ))
  2736.  
  2737.  
  2738. (defun math-join-cell ()
  2739.   "Join the current math-cell with the previous group, or create a group
  2740. if the previous math-cell is not the end of a group."
  2741.   (interactive)
  2742.   (let* ((math-cell-index (current-math-cell))
  2743.      (previous-math-cell (math-cell-previous math-cell-index))
  2744.      (killed-math-cells)        ; protect killed math-cells
  2745.      (killed-math-cells-buffer)
  2746.      (math-yank-with-copy)
  2747.      (before-change-hook nil)
  2748.      (inhibit-quit t)        ; no quiting in the middle
  2749.      )
  2750.     (buffer-flush-undo (current-buffer))
  2751.     (unwind-protect
  2752.     (if (not previous-math-cell)
  2753.         (message "Nothing to join with.")
  2754.  
  2755.       (if (not (< 0 (math-cell-end-group previous-math-cell)))
  2756.           (if (math-cell-start-group-p previous-math-cell)
  2757.           (message "Can't join with start of group.")
  2758.         (math-group-cells previous-math-cell math-cell-index))
  2759.         ;;        (check-math-cell math-cell-index)
  2760.         ;;        (check-math-cell previous-math-cell)
  2761.         (math-kill-cell math-cell-index)
  2762.         (math-yank-cells previous-math-cell nil
  2763.                  (car killed-math-cells)) ; == math-cell-index
  2764.         ;;        (check-math-cell math-cell-index)
  2765.         ;;        (check-math-cell previous-math-cell)
  2766.         ))
  2767.       (math-move-to-cell math-cell-index)
  2768.       (buffer-enable-undo (current-buffer))
  2769.       )))
  2770.  
  2771.  
  2772.  
  2773. ;;;---------------------------------
  2774. ;;; Evaluation
  2775.  
  2776. (defun math-eval-current-cell ()
  2777.   "Evaluate the current math-cell."
  2778.   (interactive)
  2779.   (let ((math-cell-index (save-excursion (current-math-cell)))
  2780.     (before-change-hook nil)
  2781.     (inhibit-quit t)        ; no quiting in the middle
  2782.     )
  2783.     (message "eval current math-cell")
  2784.     (if (math-cell-inactive-p math-cell-index)
  2785.     (message "Cannot evaluate inactive math-cell.  Make it active first.")
  2786.       (buffer-flush-undo (current-buffer))
  2787.       (unwind-protect
  2788.     (progn
  2789.       (if (not (eq math-last-input-cell math-cell-index))
  2790.           (math-autodelete-last-input-cell))
  2791.       (eval-math-cells math-cell-index math-cell-index)
  2792.       ;; assume math-cell-index is still the input cell
  2793.       ;; may be after the wrong math-cell !!
  2794.       (if (not (math-cell-empty math-cell-index))
  2795.           (math-insert-new-input-cell math-cell-index))
  2796.       )
  2797.     (buffer-enable-undo (current-buffer)))
  2798.       )))
  2799.  
  2800.  
  2801. (defun math-eval-region (start end)
  2802.   "Evaluate all active math-cells in region."
  2803.   (interactive "r")
  2804.   (let ((before-change-hook nil)    ; allow changes
  2805.     (inhibit-quit t)        ; no quiting in the middle
  2806.     (start-math-cell (progn (goto-char start)
  2807.                 (beginning-of-line)
  2808.                 (skip-chars-forward " \t\n\r")
  2809.                 (current-math-cell)))
  2810.     (end-math-cell  (progn (goto-char end)
  2811.                    (current-math-cell)))
  2812.     )
  2813.     (buffer-flush-undo (current-buffer))
  2814.     (unwind-protect
  2815.     (progn
  2816.       (eval-math-cells start-math-cell end-math-cell)
  2817.       )
  2818.       (buffer-enable-undo (current-buffer)))
  2819.     ))
  2820.  
  2821.  
  2822. (defun eval-math-cells (start-math-cell end-math-cell)
  2823.   "Evaluate all the active cells between start-math-cell and end-math-cell.
  2824. Return t if anything is evaluated; nil otherwise."
  2825.   (let ((active-math-cells
  2826.      (find-math-cells
  2827.       (function (lambda (math-cell)
  2828.               (not (math-cell-inactive-p math-cell))))
  2829.       start-math-cell end-math-cell)))
  2830.     ;; first find all math-cells that need to be evaled
  2831.     (setq active-math-cells
  2832.       (find-eval-math-cells active-math-cells))
  2833.  
  2834.     ;; now loop through all the math-cells and evaluate them
  2835.     (mapcar 'eval-math-cell active-math-cells)
  2836.     ))
  2837.  
  2838.  
  2839. (defun find-eval-math-cells (active-math-cells)
  2840.   "Find all the math-cells that need to be evaluated in active-math-cells list.
  2841. If any autoActive group is found above an active math-cell, then add all
  2842. active math-cells in the group to the evaluation list."
  2843.   (let ((autoActive-parents nil)
  2844.     (math-cell-list active-math-cells))
  2845.     ;;  For each cell in ACTIVE-MATH-CELLS, find the outermost autoActive group
  2846.     (while math-cell-list
  2847.       (let* ((autoActive-parent nil)
  2848.          (math-cell-index  (car math-cell-list))
  2849.          (parent (math-cell-parent math-cell-index)))
  2850.     (setq math-cell-list (cdr math-cell-list))
  2851.     (set-math-cell math-cell-index 'eval t)
  2852.  
  2853.     ;; find the outermost parent that is autoActive
  2854.     (while parent
  2855.       (if (math-cell-autoActive-p parent)
  2856.           (setq autoActive-parent parent))
  2857.       (setq parent (math-cell-parent parent))
  2858.       )
  2859.  
  2860.     (if (and autoActive-parent
  2861.          (not (memq autoActive-parent autoActive-parents)))
  2862.  
  2863.         ;; eval every active math-cell under this parent 
  2864.         (let ((following-math-cell
  2865.            (find-math-cell-after-group autoActive-parent))
  2866.           (math-cell))
  2867.           (setq autoActive-parents
  2868.             (cons autoActive-parent autoActive-parents))
  2869.           (while (and math-cell (not (eq math-cell following-math-cell)))
  2870.         (if (not (math-cell-inactive-p math-cell))
  2871.             (set-math-cell math-cell 'eval t))
  2872.         (setq math-cell (math-cell-next math-cell)))))))
  2873.  
  2874.     ;; if any autoActive parents found
  2875.     (if autoActive-parents
  2876.     ;; then need to search for all eval math-cells.
  2877.     (progn
  2878.       (find-math-cells
  2879.        (function (lambda (math-cell)
  2880.                (math-cell-eval-p math-cell)))))
  2881.       active-math-cells)
  2882.     ))
  2883.       
  2884.  
  2885.  
  2886. (defun math-eval-init-cells ()
  2887.   "Evaluate all the active initialization math-cells."
  2888.   (let ((init-math-cells
  2889.      (find-math-cells
  2890.       (function (lambda (math-cell)
  2891.               (and (math-cell-initialization-p math-cell)
  2892.                (not (math-cell-inactive-p math-cell)))))
  2893.       )))
  2894.     ;; now loop through all the math-cells and evaluate the active ones
  2895.     ;; should this be EVALONLY ??
  2896.     (mapcar 'eval-only-math-cell init-math-cells)
  2897.     ))
  2898.  
  2899.  
  2900. (defun find-math-cells (pred &optional start-math-cell end-math-cell)
  2901.   "Return a list of all math-cells that match a predicate between
  2902. start-math-cell and end-math-cell."
  2903.  
  2904.   (if (not start-math-cell)
  2905.       (setq start-math-cell (first-math-cell)))
  2906.   (let ((math-cell start-math-cell)
  2907.     (math-cell-list nil))
  2908.     (while (not (eq math-cell end-math-cell) )
  2909.       (if (funcall pred math-cell)
  2910.       (setq math-cell-list (cons math-cell math-cell-list))
  2911.     )
  2912.       (setq math-cell (math-cell-next math-cell))
  2913.       )
  2914.     ;; check end-math-cell
  2915.     (if (and end-math-cell (funcall pred math-cell))
  2916.     (setq math-cell-list (cons math-cell math-cell-list))
  2917.       )
  2918.     (nreverse math-cell-list)
  2919.     ))
  2920.  
  2921.  
  2922. (defun eval-math-cell (math-cell-index)
  2923.   "Evaluate the contents of math-cell-index.
  2924. Return nil if there was a syntax error."
  2925.   ;; needs to work with closed math-cells too!!
  2926.   (let ((contents
  2927.      (if (math-cell-output-p math-cell-index)
  2928.          (math-cell-input-form math-cell-index)
  2929.        (math-cell-contents-string math-cell-index)))
  2930.     )
  2931.  
  2932.     ;; cancel eval field
  2933.     (set-math-cell math-cell-index 'eval nil)
  2934.  
  2935.     (if (not (string-match "[^ \t\f\n\r]" contents))
  2936.     (progn
  2937.       (message "Empty cell")
  2938.       (ding) (sit-for 1))
  2939.       
  2940.       (if (not math-process)
  2941.       (run-math))            ; do this now to get input prompt
  2942.  
  2943.       (setq math-this-input-cell math-cell-index)
  2944.  
  2945.       ;; relabel the cell to be evaluated and set font to input
  2946.       (set-math-cell math-cell-index 'name (list math-input-prompt))
  2947.       (set-math-cell math-cell-index 'font '(input))
  2948.       (delete-math-cell-label math-cell-index)
  2949.       (insert-new-math-cell-label math-cell-index)
  2950.  
  2951.       (math-reset-pagewidth)
  2952.  
  2953.       (setq math-message-blocks nil)    ; remove previous messages before eval
  2954.  
  2955.       (math-send-string-action contents 'aEVAL)
  2956.       (math-kernel-loop)
  2957.       
  2958.       
  2959.       ;; check whether syntax error occurred
  2960.       (if (eq 'syntax-error math-eval-result)
  2961.       ;; goto beginning of math-cell in error and move to error
  2962.       (progn
  2963.         (math-move-to-cell math-cell-index)
  2964.         (forward-char math-error-offset)
  2965.         (error "Syntax Error at this position")
  2966.         nil
  2967.         )
  2968.  
  2969.     (insert-math-result math-cell-index)
  2970.     t)
  2971.       )))
  2972.  
  2973.  
  2974. (defun eval-only-math-cell (math-cell-index)
  2975.   "Evaluate the contents of math-cell-index with EVALONLY."
  2976.   ;; needs to work with closed math-cells too!!
  2977.   (let ((contents
  2978.      (if (math-cell-output-p math-cell-index)
  2979.          (math-cell-input-form math-cell-index)
  2980.        (math-cell-contents-string math-cell-index)))
  2981.     )
  2982.  
  2983.     (if (not (string-match "[^ \t\f\n\r]" contents))
  2984.     (progn
  2985.       (message "Empty cell")
  2986.       (ding) (sit-for 1))
  2987.       
  2988.       ;; relabel the math-cell to be evaluated
  2989. ;;;      (set-math-cell math-cell-index 'name (list math-input-prompt))
  2990.  
  2991.       (math-send-string-action contents 'aEVALONLY)
  2992.       (math-kernel-loop)
  2993.       )))
  2994.  
  2995.  
  2996. (defun insert-math-result (math-cell-index)
  2997.   "Insert a math-cell that represents the mathematica output of evaluating
  2998. the contents of math-cell-index.
  2999. Group the new math-cell with math-cell-index, unless math-cell-index is nil.
  3000. If the input math-cell was the start of a group, kill the members
  3001. of the group that are output math-cells from a previous evaluation."
  3002.  
  3003.   (let ((next-math-cell math-cell-index)) ; insert cells after input cell
  3004.     
  3005.     (if (and math-cell-index (math-cell-start-group-p math-cell-index))
  3006.     (progn
  3007.       (remove-killed-math-cells)
  3008.       (math-ungroup-cell math-cell-index)
  3009.  
  3010.       ;; delete any intervening print, info, and message cells
  3011.       (setq next-math-cell (math-cell-next next-math-cell))
  3012.       (while (and next-math-cell
  3013.               (memq (math-cell-font next-math-cell)
  3014.                 '(message print info)))
  3015.         (math-kill-cell (prog1 next-math-cell
  3016.                   (setq next-math-cell
  3017.                     (math-cell-next next-math-cell)))))
  3018.       
  3019.       ;; delete the output math-cell
  3020.       (if (and next-math-cell
  3021.            (math-cell-output-p next-math-cell))
  3022.           (math-kill-cell next-math-cell))
  3023.       ))
  3024.  
  3025.     (setq next-math-cell math-cell-index)
  3026.     ;; first insert any info, print, and message output
  3027.  
  3028.     (setq math-info-blocks
  3029.       (nreverse math-info-blocks))
  3030.     (if math-info-blocks
  3031.     (let ((info-block (apply 'concat math-info-blocks)))
  3032.       (setq next-math-cell
  3033.         (math-insert-output-cell info-block next-math-cell 'print))
  3034.       ))
  3035.  
  3036.     (setq math-print-blocks 
  3037.       (nreverse math-print-blocks))
  3038.     (if math-print-blocks
  3039.     (let ((print-block (apply 'concat math-print-blocks)))
  3040.       (setq next-math-cell
  3041.         (math-insert-output-cell print-block next-math-cell 'print))
  3042.       ))
  3043.     
  3044.     ;; each message gets its own math-cell
  3045.     (setq math-message-blocks
  3046.       (nreverse math-message-blocks))
  3047.     (while math-message-blocks
  3048.       (setq next-math-cell
  3049.         (math-insert-output-cell (car math-message-blocks)
  3050.                      next-math-cell 'message))
  3051.       (setq math-message-blocks (cdr math-message-blocks))
  3052.       )
  3053.  
  3054.     ;; add output math-cells
  3055.     (if math-output-form
  3056.     (let ((output-math-cell-index (new-math-cell-info)))
  3057.  
  3058.       (set-math-cell output-math-cell-index 'contents math-output-form)
  3059.       (if math-input-form
  3060.           (set-math-cell output-math-cell-index
  3061.                  'input-form math-input-form))
  3062.       (set-math-cell output-math-cell-index 'name
  3063.              (list (concat math-output-prompt " ")))
  3064.       (set-math-cell output-math-cell-index 'last-indent-width 0)
  3065.       (set-math-cell output-math-cell-index 'inactive t)
  3066.       (set-math-cell output-math-cell-index 'output t)
  3067.       (set-math-cell output-math-cell-index 'font '(output))
  3068.  
  3069.       ;; insert the output math-cell after math-cell-index
  3070.       (math-yank-cells next-math-cell nil output-math-cell-index)
  3071.       ;; ensure correct indentation
  3072.       (adjust-math-cell-indent output-math-cell-index)
  3073.  
  3074.       (setq next-math-cell output-math-cell-index)
  3075.       ))
  3076.  
  3077.     ;; group the input with all the output math-cells
  3078.     (if (and math-cell-index 
  3079.          (not (eq math-cell-index next-math-cell)))
  3080.     (math-group-cells math-cell-index next-math-cell)
  3081.       ;; set up for insertion of new math-cell.
  3082.       (setq math-cell-index next-math-cell)
  3083.       )))
  3084.  
  3085.  
  3086. (defun math-insert-output-cell (contents last-math-cell font)
  3087.   "Insert an output math-cell with CONTENTS after LAST-MATH-CELL.
  3088. Set the font of the math-cell to FONT.
  3089. Return the new math-cell index."
  3090.   (let ((math-cell-index (new-math-cell-info))
  3091.     math-cell-name)
  3092.     
  3093.     ;; add fields to output math-cell
  3094.     (if (string-match (concat "^" math-cell-message-label) contents)
  3095.     (progn
  3096.       (setq math-cell-name (substring contents
  3097.                       (match-beginning 0)
  3098.                       (match-end 0)))
  3099.       (setq contents (substring contents (1+ (match-end 0))))))
  3100.       
  3101.     (set-math-cell math-cell-index 'contents contents)
  3102.     (if math-cell-name
  3103.     (set-math-cell math-cell-index 'name
  3104.                (list (concat math-cell-name " "))))
  3105.     (set-math-cell math-cell-index 'inactive t)
  3106.     (set-math-cell math-cell-index 'font
  3107.            (list font))
  3108.     (math-yank-cells last-math-cell nil math-cell-index)
  3109.     math-cell-index
  3110.     )
  3111.   )
  3112.  
  3113.  
  3114. (defvar math-last-input-cell nil
  3115.   "Last input math-cell - used to autodelete if empty.")
  3116.  
  3117. (defvar math-this-input-cell nil
  3118.   "This input cell - used to avoid autodeleting name.")
  3119.  
  3120.  
  3121. (defun math-autodelete-last-input-cell ()
  3122.   "Autodelete last input math-cell if empty.  Remove its name anyway."
  3123.  
  3124.   (if (and math-last-input-cell
  3125.        (aref math-cell-vector math-last-input-cell)
  3126.        ;; killed or dead cells have no point, no need to delete them
  3127.        (math-cell-point math-last-input-cell))
  3128.            
  3129.       (if (and (math-cell-empty math-last-input-cell)
  3130.            (not (math-cell-start-group-p math-last-input-cell)))
  3131.       (save-excursion
  3132.         (remove-killed-math-cells)
  3133.         (math-kill-cell math-last-input-cell)
  3134.         (remove-killed-math-cells)
  3135.         )
  3136.  
  3137.     ;; not empty
  3138.     (if (not (eq math-last-input-cell math-this-input-cell))
  3139.         (progn            ; remove the old input prompt anyway
  3140.           (set-math-cell math-last-input-cell 'name nil)
  3141.           (delete-math-cell-label math-last-input-cell)
  3142.           (insert-new-math-cell-label math-last-input-cell)))
  3143.     ))
  3144.   (setq math-last-input-cell nil)
  3145.   )
  3146.  
  3147.  
  3148.  
  3149. (defun math-insert-new-input-cell (math-cell-index)
  3150.   "Insert a new input math-cell after MATH-CELL-INDEX."
  3151.   (setq math-last-input-cell
  3152.     (math-insert-new-cell math-cell-index
  3153.             nil
  3154.             '(input)
  3155.             (list math-input-prompt))))
  3156.  
  3157.  
  3158.  
  3159. ;;;------------------
  3160. ;;; Completion
  3161.  
  3162. (defun math-complete-symbol ()
  3163.   ;; adapted from lisp-complete-symbol
  3164.   ;; should remove the window afterwards!!
  3165.   "Perform completion on Mathematica symbol preceding point.
  3166. That symbol is compared against the symbols that exist
  3167. and any additional characters determined by what is there
  3168. are inserted.
  3169. If the symbol starts just after an open-parenthesis,
  3170. only symbols with function definitions are considered.
  3171. Otherwise, all symbols with function definitions, values
  3172. or properties are considered."
  3173.   (interactive)
  3174.   (let* ((end (point))
  3175.      (beg (save-excursion
  3176.         (skip-chars-backward "a-zA-Z0-9")
  3177.         (backward-prefix-chars)
  3178.         (math-check-insertion (point) (- end (point)))
  3179.         (point)))
  3180.      (pattern (buffer-substring beg end))
  3181.               
  3182.      math-symbol-list
  3183.      completion)
  3184.     
  3185.     (if (= 0 (length pattern))
  3186.     (message "Nothing to complete.")
  3187.  
  3188.       (setq math-symbol-list (math-get-completion pattern))
  3189.       (setq completion (try-completion pattern math-symbol-list))
  3190.  
  3191.       (cond ((eq completion t)
  3192.          (message "You got it already."))
  3193.         ((null completion)
  3194.          (message "Can't find completion for \"%s\"" pattern)
  3195.          (ding))
  3196.         ((not (string= pattern completion))
  3197.          (delete-region beg end)
  3198.          (insert completion))
  3199.         (t
  3200.          (message "Making completion list...")
  3201.          (let ((list (all-completions pattern math-symbol-list)))
  3202.            (with-output-to-temp-buffer "*Completions*"
  3203.          (display-completion-list list)))
  3204.          (message "Making completion list...%s" "done"))))))
  3205.  
  3206.  
  3207.  
  3208. ;;;--------------------------------
  3209. ;;; Converting the notebook to internal and external form
  3210.  
  3211.  
  3212. (defun math-next-preface ()
  3213.   "Skip forward to just before the next math-cell-heading line.
  3214. If no next preface then move to after last non-whitespace and return nil"
  3215.   (if (re-search-forward math-cell-heading-start-regexp
  3216.                          nil 'move)
  3217.       (goto-char (match-beginning 0))
  3218.     (goto-char (point-max))
  3219. ;;    (skip-chars-backward " \t\n\r\f")  ; should be last non-whitespace
  3220. ;;    (re-search-backward "[\n\r]")
  3221. ;;    (if (looking-at math-cell-marking-regexp)
  3222. ;;      (goto-char (match-end 0)))
  3223.     nil
  3224.     ))
  3225.  
  3226.  
  3227. ;;(defun math-next-cell-heading ()
  3228. ;;  "Move to just inside the beginning of the next math-cell-heading line."
  3229. ;;  (interactive)
  3230. ;;  (re-search-forward math-cell-heading-start-regexp
  3231. ;;                     nil 'move))
  3232.  
  3233.  
  3234. ;;(defun math-end-of-cell-heading ()
  3235. ;;  "Move to just after the end of the current or next math-cell-heading line."
  3236. ;;  (re-search-forward math-cell-heading-end-regexp
  3237. ;;                         nil 'move)
  3238. ;;;      (goto-char (match-beginning 0))
  3239. ;;  )
  3240.  
  3241.  
  3242.  
  3243. (defvar math-nb-control nil
  3244.   "The heading for the notebook.")
  3245.  
  3246.  
  3247. (defun print-math-cell-value (field value)
  3248.   (if value
  3249.       (progn
  3250.     (princ (format "%s" field))
  3251.     (if (listp value)
  3252.         (if (not (eq (car value) t)) ; kluge
  3253.         (progn
  3254.           (princ "=")
  3255.           (while value
  3256.             (princ (format "%s" (car value)))
  3257.             (setq value (cdr value))
  3258.             (if value (princ ", ")))))
  3259.       (if (not (eq value t))
  3260.           (progn
  3261.         (princ "=")
  3262.         (princ (format "%s" value))))
  3263.       ))))
  3264.  
  3265.  
  3266. (defun write-macnb-math-cell (info contents)
  3267.   "Write out the heading info in INFO with content CONTENTS."
  3268.   (let (output-form
  3269.     styles
  3270.     (init (and math-cell-index  ; from write-notebook
  3271.            (math-cell-initialization-p math-cell-index)
  3272.            (not (math-cell-inactive-p math-cell-index))))
  3273.     )
  3274.  
  3275. ;;;    (princ "\n") ; to be sure
  3276.     (if (not contents)
  3277.     (princ ":"))            ; extra colon for notebook control
  3278.     (princ ":[")
  3279.     
  3280.     (if info
  3281.     (let ((i 0)
  3282.           (field-list math-cell-fields)
  3283.           field
  3284.           value)
  3285.       (while (< i math-cell-standard-fields)
  3286.         (setq field (car field-list))
  3287.         (setq field-list (cdr field-list))
  3288.         (setq value (aref info i))
  3289.         (setq i (1+ i))
  3290.     
  3291.         (if value
  3292.         (progn
  3293.           (cond
  3294.            ((and (eq field 'endGroup) value)
  3295.                     ; unravel endGroups
  3296.             (while (> value 1)
  3297.               (setq value (1- value))
  3298.               (princ "endGroup; "))
  3299.             (princ "endGroup"))
  3300.  
  3301.            ((eq field 'name)
  3302.             (princ (format "%s=\"%s\"" field (car value)))
  3303.             )
  3304.  
  3305.            ((eq field 'input-form)
  3306.             (setq output-form contents)
  3307.             (setq contents value))
  3308.  
  3309.            ((eq field 'output-form)
  3310.             (setq output-form value))
  3311.  
  3312.            ((eq field 'styles)
  3313.             (setq styles value))
  3314.      
  3315.            ((eq field 'extras)
  3316.             (while value
  3317.               (print-math-cell-value
  3318.                (car (car value)) (cdr (car value)))
  3319.               (setq value (cdr value))
  3320.               (if value (princ ";\n\t"))
  3321.               ))
  3322.           
  3323.            (t            ; any other field
  3324.             (print-math-cell-value field value)
  3325.             ))
  3326.           ;; if more to follow, append semi
  3327.           (if (< i number-of-math-cell-fields)
  3328.               (princ ";\n\t"))
  3329.           )))))
  3330.     (princ "]\n")
  3331.  
  3332.     ;; if an init math-cell, uncomment the contents
  3333.     (if init
  3334.     (princ "*)\n"))
  3335.     (if contents
  3336.     (princ contents))
  3337.     (princ "\n")
  3338.     (if init
  3339.     (princ "(*\n"))
  3340.     
  3341.     (if output-form
  3342.     (progn
  3343.       (princ ";[o]\n")
  3344.       (princ output-form)
  3345.       (princ "\n")))
  3346.  
  3347.     (if styles
  3348.     (progn
  3349.       (princ ";[s]")
  3350.       (princ styles)
  3351. ;;;      (princ "\n")
  3352.       ))
  3353.     ))
  3354.  
  3355.  
  3356. (defun write-math-mac-notebook ()
  3357.   "Write the current math buffer as a Mac-style notebook."
  3358.   (interactive)
  3359.   (let ((filename (buffer-file-name))
  3360.     (buf (get-buffer-create "*notebook*"))
  3361.     (math-cell-index 0)
  3362.     (vector-length math-cell-vector-length)
  3363. ;;    (temp-buffer-show-hook 'write-notebook-file) ; kludgy
  3364.     )
  3365.     (save-excursion
  3366.       (remove-killed-math-cells)
  3367.  
  3368.       (with-output-to-temp-buffer (buffer-name buf)
  3369.  
  3370.     (princ "(*^\n")
  3371.     
  3372.     ;; print notebook math-cell
  3373.     (write-macnb-math-cell 
  3374.      (math-cell-alist-to-vector math-nb-control) nil)
  3375.  
  3376.     (setq math-cell-index (first-math-cell))
  3377.     
  3378.     (while math-cell-index
  3379.       (if math-show-debug (progn
  3380.                 (message "") (sit-for 0)
  3381.                 (message "Writing notebook...")))
  3382.       ;; dont modify the actual math-cell info
  3383.       (let ((math-cell-info (aref math-cell-vector math-cell-index)))
  3384.         (if (not math-cell-info)
  3385.         nil
  3386.           (write-macnb-math-cell
  3387.            math-cell-info
  3388.            (math-cell-contents-without-indent math-cell-index))
  3389.           )
  3390.         )                ; let
  3391.       (setq math-cell-index (math-cell-next math-cell-index))
  3392.       )
  3393.  
  3394.     (princ "\n^*)\n")
  3395.     )                ; with-output
  3396.  
  3397.       (set-buffer buf)
  3398.       (math-flag-region (point-min) (point-max) ?\n) ; make all readable
  3399.       (write-file (concat (math-file-name-root filename) math-nb-suffix))
  3400.  
  3401.       (kill-buffer buf)
  3402.       filename
  3403.       ))
  3404. ;;  (clear-visited-file-modtime)
  3405.   )
  3406.  
  3407.  
  3408. (defun write-math-package ()
  3409.   "Write the current math buffer as a math package."
  3410.   (interactive)
  3411.   (let ((filename (buffer-file-name))
  3412.     (buf (get-buffer-create "*package*"))
  3413.     (math-cell-index 0)
  3414.     (vector-length math-cell-vector-length)
  3415.     )
  3416.     (save-excursion
  3417.       (remove-killed-math-cells)
  3418.  
  3419.       (with-output-to-temp-buffer (buffer-name buf)
  3420.  
  3421.     (setq math-cell-index (first-math-cell))
  3422.     
  3423.     (while math-cell-index
  3424.       (if (eq 'input (math-cell-font math-cell-index))
  3425.           (progn
  3426.         (princ (math-cell-contents-without-indent math-cell-index))
  3427.         (princ "\n\n"))
  3428.         (princ "(*\n")
  3429.         (princ (math-cell-contents-without-indent math-cell-index))
  3430.         (princ "\n*)\n\n"))
  3431.       (setq math-cell-index (math-cell-next math-cell-index))
  3432.       )
  3433.     )                ; with-output
  3434.  
  3435.       (set-buffer buf)
  3436.       (math-flag-region (point-min) (point-max) ?\n) ; make all readable
  3437.       (write-file (concat (math-file-name-root filename) math-package-suffix))
  3438.  
  3439.       (kill-buffer buf)
  3440.       filename
  3441.       ))
  3442. ;;  (clear-visited-file-modtime)
  3443.   )
  3444.  
  3445.  
  3446. (defun write-math-lisp-notebook ()
  3447.   "Write the notebook as an emacs lisp notebook file.
  3448. The file name is the same as the current buffer's filename."
  3449.   (let ((filename (buffer-file-name))  ; used by write-notebook-lisp-file
  3450.     (notebook-buf (current-buffer))
  3451.     (notebook-len (buffer-size))
  3452.     (buf (get-buffer-create " *math-cell-vector*"))
  3453.     )
  3454.     (save-excursion
  3455.       (remove-killed-math-cells)
  3456.  
  3457.       (set-buffer buf)
  3458.       (set-visited-file-name nil)
  3459.  
  3460.       ;; insert the contents of the notebook buffer
  3461.       (erase-buffer)
  3462.       (insert-buffer-substring notebook-buf 1 notebook-len)
  3463.  
  3464.       ;; create the external lisp representation
  3465.       (set-buffer notebook-buf)
  3466.  
  3467.       (let ((nbl)
  3468.         ;; a vector of all math-cells with marks converted to points
  3469.         (math-cells (make-vector math-cell-vector-length nil))
  3470.         (math-cell-index 0)
  3471.         (point-field (get 'point 'math-cell-field))
  3472.         )
  3473.  
  3474.     ;; loop through each member of math-cell-vector
  3475.     (while (< math-cell-index math-cell-vector-length)
  3476.       (if (aref math-cell-vector math-cell-index)
  3477.           
  3478.           ;; build a copy of the math-cell
  3479.           (let ((info-vector
  3480.              (copy-sequence (aref math-cell-vector math-cell-index))))
  3481.         ;; convert mark to point
  3482.         (aset info-vector point-field
  3483.               (marker-position (aref info-vector point-field)))
  3484.         (aset math-cells math-cell-index info-vector)  ; store it
  3485.         ))
  3486.       (setq math-cell-index (1+ math-cell-index)))
  3487.  
  3488.     ;; now build the structure
  3489.     (setq nbl (` (progn
  3490.                (setq math-mode-version 1)
  3491.                (setq math-use-structure-labels
  3492.                  (, math-use-structure-labels))
  3493.                (setq free-cells (quote (, free-math-cells)) )
  3494.                (setq math-last-input-cell
  3495.                  (, math-last-input-cell))
  3496.                (setq notebook-control 
  3497.                  (quote (, math-nb-control)))
  3498.                ;; write out the fields used so future changes work
  3499.                (setq notebook-cell-fields
  3500.                  (quote (, math-cell-fields)))
  3501.                (setq cell-vector (, math-cells))
  3502.                )))
  3503.  
  3504.     ;; append the structure to the new buffer
  3505.     (set-buffer buf)
  3506.     (goto-char (point-max))
  3507.     (print nbl (current-buffer))
  3508.     (write-region (point-min) (point-max) 
  3509.               filename nil t)
  3510.     ))
  3511.  
  3512.     (kill-buffer buf)
  3513.     (set-buffer notebook-buf)
  3514.     (not-modified)
  3515.     (clear-visited-file-modtime)
  3516.     ))
  3517.  
  3518.  
  3519. ;;(defun pairify (names values)
  3520. ;;  "Return an alist of NAMES and VALUES using
  3521. ;;pairwise elements of those lists.  If there are not enough VALUES, use nil."
  3522. ;;  (mapcar (function (lambda (name)
  3523. ;;              (cons name (prog1 (car values)
  3524. ;;                   (setq values (cdr values))))))
  3525. ;;      names))
  3526.   
  3527.  
  3528.  
  3529. (defun convert-math-notebook-file ()
  3530.   "Convert a buffer containing Mac-style notebook.
  3531. First convert it to lisp forms using the external converter.
  3532. Then convert the lisp forms into internal form."
  3533.   (message "Reading notebook...")
  3534.  
  3535.   ;; first replace any odd chars with octal equivalent
  3536.   (goto-char (point-min))
  3537.   (while (re-search-forward "[^\n\r\b\t -~]" nil t)
  3538.     (replace-match (format "\\\\%o" (char-after (match-beginning 0)))))
  3539.  
  3540.   ;; now send through converter to get lisp forms.
  3541.   (call-process-region (point-min) (point-max) math-macnb2nbl t t)
  3542.   
  3543.   (let ((before-change-hook nil)
  3544.     (inhibit-quit t)
  3545.     (first-math-cell 0)
  3546.     math-cell-index
  3547.     (i 0)
  3548.     )
  3549.     
  3550.     (let (math-mode-version
  3551.       free-cells
  3552.       ;;        math-last-input-cell  ; same
  3553.       notebook-control
  3554.       notebook-cell-fields
  3555.       cell-vector)
  3556.  
  3557.       (eval-current-buffer)        ; buffer of elisp representing notebook
  3558.  
  3559.       ;; do version specific conversion here
  3560.       (setq free-math-cells free-cells)
  3561.       (setq math-nb-control notebook-control)
  3562.       (setq math-cell-vector cell-vector)
  3563.       )
  3564.     (setq math-cell-vector-length (length math-cell-vector))
  3565.  
  3566.     ;; convert the math-cells from alists to vectors
  3567.     (while (< i math-cell-vector-length)
  3568.       (aset math-cell-vector i
  3569.         (math-cell-alist-to-vector (aref math-cell-vector i)))
  3570.       (setq i (1+ i)))
  3571.  
  3572.     ;; add the linkage between math-cells
  3573.     (add-math-cell-structure)
  3574.  
  3575.     (setq first-math-cell (first-math-cell))
  3576.  
  3577.     (erase-buffer)            ; erase the lisp forms
  3578.  
  3579.  
  3580.     ;; insert contents of all math-cells
  3581.     (math-yank-cells nil nil first-math-cell)
  3582.  
  3583.     (if (not first-math-cell)
  3584.     (math-insert-new-input-cell nil)  ; no cells, so make one
  3585.       (save-excursion
  3586.     ;; loop through all top level math-cells and show or hide them
  3587.     (setq math-cell-index first-math-cell)
  3588.     (while math-cell-index
  3589.       (show-or-hide-math-cell math-cell-index)
  3590.       (setq math-cell-index (math-cell-forward math-cell-index))
  3591.       )))
  3592.  
  3593.     (message "")
  3594.     ))
  3595.  
  3596.  
  3597.  
  3598. (defun math-cell-alist-to-vector (info)
  3599.   "Convert the math-cell heading alist INFO to a vector, if non-nil."
  3600.   (if info
  3601.       (let ((heading-vector (make-vector number-of-math-cell-fields nil))
  3602.         (extra-index (get 'extras 'math-cell-field)))
  3603.     (mapcar (function
  3604.          (lambda (item)
  3605.            (let* ((index (get (car item) 'math-cell-field))
  3606.               (value (and index (aref heading-vector index))))
  3607.              (if index
  3608.              (aset heading-vector index
  3609.                    ;; if already has a value
  3610.                    (if value
  3611.                    ;; cons new value with old
  3612.                    (cons (cdr item) value)
  3613.                  (cdr item)))
  3614.                (aset heading-vector extra-index
  3615.                  (cons item
  3616.                    (aref heading-vector extra-index)))))
  3617.            ))
  3618.         info)
  3619.     heading-vector
  3620.     )))
  3621.  
  3622.  
  3623. (defun add-math-cell-structure ()
  3624.   "Add the math-cell structure to the list of math-cells."
  3625.  
  3626.   (let (math-cell-index
  3627.     first-math-cell
  3628.     next-math-cell
  3629.     previous-math-cell
  3630.     backward-math-cell
  3631.     parent-math-cell
  3632.     ancestry
  3633.     (depth 0)
  3634.     )
  3635.  
  3636.     (message "Converting notebook...")
  3637.  
  3638.     (setq math-cell-index 0)
  3639.     (while (< math-cell-index math-cell-vector-length)
  3640.  
  3641.       ;; Add depth
  3642.       (set-math-cell math-cell-index 'depth depth)
  3643.  
  3644.       ;; Add linkage to other math-cells
  3645.       (set-math-cell math-cell-index 'previous previous-math-cell)
  3646.       (if previous-math-cell
  3647.       (set-math-cell previous-math-cell 'next math-cell-index))
  3648.       (setq previous-math-cell math-cell-index)
  3649.       (set-math-cell math-cell-index 'parent parent-math-cell)
  3650.     
  3651.       (if backward-math-cell
  3652.       (set-math-cell backward-math-cell 'forward math-cell-index))
  3653.       (set-math-cell math-cell-index 'backward backward-math-cell)
  3654.       (setq backward-math-cell math-cell-index)
  3655.  
  3656.     
  3657.       (if (math-cell-start-group-p math-cell-index)
  3658.       (progn
  3659.         (setq depth (1+ depth))
  3660.         (setq ancestry (cons math-cell-index ancestry))
  3661.         (setq parent-math-cell math-cell-index) ; eq (car ancestry)
  3662.         (setq backward-math-cell nil)
  3663.         )
  3664.     )
  3665.  
  3666.       (let ((end-depth depth)
  3667.         (end-groups (math-cell-end-group-p math-cell-index))) ; a list of nils
  3668.     ;; count endGroups to collect into one field
  3669.     (while end-groups
  3670.       (setq backward-math-cell (car ancestry))
  3671.       (setq ancestry (cdr ancestry))
  3672.       (setq end-depth (1- end-depth))
  3673.       (setq end-groups (and (listp end-groups) (cdr end-groups))))
  3674.        
  3675.     (if (/= end-depth depth)
  3676.         (progn
  3677.           (set-math-cell math-cell-index 'endGroup (- depth end-depth))
  3678.           (setq depth end-depth)
  3679.           (setq parent-math-cell (car ancestry))
  3680.           )))
  3681.     
  3682.       (setq math-cell-index (1+ math-cell-index))
  3683.       )                    ; while
  3684.     ))
  3685.  
  3686.  
  3687. (defun convert-math-mode-lisp-to-internal ()
  3688.   "Convert a buffer containing math-mode notebook form into internal form."
  3689.   (let ((before-change-hook nil)
  3690.     (filename (buffer-file-name))
  3691.     (first-math-cell 0)
  3692.     math-cell-index
  3693.     (i 0)
  3694.     )
  3695.     (message "Reading math-mode notebook...")
  3696.  
  3697.     ;; evaluate elisp representing math-cell structure
  3698.     (goto-char (point-max))
  3699.     (skip-chars-backward " \n\t")
  3700.     (backward-sexp 1)
  3701.     (save-excursion
  3702.       (let (math-mode-version
  3703.         free-cells
  3704. ;;        math-last-input-cell  ; same
  3705.         notebook-control
  3706.         notebook-cell-fields
  3707.         cell-vector)
  3708.     (eval (read (current-buffer)))
  3709.     
  3710.     ;; do version specific conversion here
  3711.     (setq free-math-cells free-cells)
  3712.     (setq math-nb-control notebook-control)
  3713.     (setq math-cell-vector cell-vector)
  3714.     ))
  3715.     (delete-region (point) (point-max))
  3716.  
  3717.     (setq math-cell-vector-length (length math-cell-vector))
  3718.  
  3719.     ;; future versions should check that math-cell-fields is correct
  3720.     ;; and convert math-cells if needed
  3721.     (let ((point-field (get 'point 'math-cell-field)))
  3722.       (setq math-cell-index 0)
  3723.       (while (< math-cell-index math-cell-vector-length)
  3724.     (if (aref math-cell-vector math-cell-index)
  3725.         ;; convert points to marks
  3726.         (let ((math-cell-marker
  3727.            (progn
  3728.              (goto-char (math-cell-point math-cell-index))
  3729.              (point-marker))))
  3730.           (set-math-cell math-cell-index 'point math-cell-marker)
  3731.           (add-math-cell-marker math-cell-index math-cell-marker)
  3732.           ))
  3733.     (setq math-cell-index (1+ math-cell-index))
  3734.     ))
  3735.  
  3736.     (setq first-math-cell (first-math-cell))
  3737.  
  3738.     (if (not first-math-cell)
  3739.     (math-insert-new-input-cell nil)  ;no cells, so make one
  3740.       (save-excursion
  3741.     ;; loop through all top level math-cells and show or hide them
  3742.     ;; this is redundant with the show/hide routine
  3743.     (setq math-cell-index first-math-cell)
  3744.     (while math-cell-index
  3745.         (if (math-cell-start-group-p math-cell-index)
  3746.  
  3747.         (if (math-cell-group-closed-p math-cell-index)
  3748.             (math-hide-group math-cell-index)
  3749.           (math-show-group math-cell-index)
  3750.           )
  3751.  
  3752.           (if (math-cell-closed-p math-cell-index)
  3753.           (math-hide-entry math-cell-index)
  3754.         (math-show-entry math-cell-index)))
  3755.         (setq math-cell-index (math-cell-forward math-cell-index))
  3756.         )))
  3757.  
  3758.     (message "")
  3759.     ))
  3760.  
  3761.  
  3762. (defun convert-math-package ()
  3763.   "Convert the package format Mathematica expressions in current buffer."
  3764.   ;; Make a cell out of every group of lines separated by a blank line.
  3765.   ;; Remove any cell labels at the start of each line (or each group?)
  3766.   ;; This can be used to recover a notebook file that got messed up.
  3767.  
  3768.   ;; Could make this work for insertion of a package in a file!!
  3769.   
  3770.   ;; Test if in math-mode?
  3771.  
  3772.  
  3773.   (goto-char (point-min))
  3774.   (skip-chars-forward " \t\n\r")
  3775.   (delete-region (point-min) (point))  ; delete extra whitespace
  3776.   (insert "\n")
  3777.  
  3778.   (let ((paragraph-separator-regexp "[\n\r][ \t\n\r]*[\n\r]") ; at least 2
  3779.     (current-cell nil)
  3780.     (before-change-hook nil))
  3781.  
  3782.     (message "Converting Mathematica package...")
  3783.  
  3784.     (while (not (= (point) (point-max)))
  3785.       (forward-char -1)  ; at start of label?
  3786.       (if (looking-at math-cell-label-regexp)
  3787.       ;; delete any existing cell label
  3788.       (delete-region (point)
  3789.              (progn
  3790.                (re-search-forward math-cell-label-regexp)
  3791.                (point))))
  3792.       (save-restriction
  3793.     (narrow-to-region (point-min) (point))
  3794.     (setq current-cell (math-insert-new-input-cell current-cell)))
  3795.  
  3796.       ;; delete the whitespace between new cell label and start of next text
  3797.       (delete-region (point)
  3798.              (progn
  3799.                (skip-chars-forward " \t\n\r")
  3800.                (point)))
  3801.  
  3802.       ;; find start of next cell
  3803.       (re-search-forward paragraph-separator-regexp (point-max) 'move)
  3804.       )
  3805.     (math-goto-first-cell)
  3806.     ))
  3807.  
  3808.  
  3809. (defun math-save-buffer ()
  3810.   "Save a math buffer by saving the lisp file instead.
  3811. Called as a write-file-hooks function."
  3812.  
  3813.   (if math-mode
  3814.       (progn
  3815.         (if math-show-debug
  3816.             (to-math-debug (format "Save math buffer: %s\n" (current-buffer))))
  3817.  
  3818.     (let* ((filename (file-name-nondirectory (buffer-file-name)))
  3819.            (start-with-nbl (string-match math-nbl-regexp filename))
  3820.            (filename-root (math-file-name-root filename))
  3821.            (nb-filename (concat filename-root math-nb-suffix))
  3822.            (nbl-filename (concat filename-root math-nbl-suffix)))
  3823.  
  3824.       (set-visited-file-name nbl-filename)
  3825.       (if (not start-with-nbl)  ; this should never be true
  3826.           (write-math-mac-notebook))
  3827.       ;; write as lisp-notebook anyway
  3828.       (write-math-lisp-notebook)
  3829.       )
  3830.  
  3831.     (set-buffer-modified-p nil)
  3832.     t ; dont save the buffer text
  3833.         ;; note: even if the buffer text is not saved, the visited file will
  3834.     ;; still have been copied to the backup file.
  3835.     ))
  3836.   )
  3837.  
  3838.  
  3839.  
  3840.  
  3841. ;;;---------------------------------------
  3842. ;;; Math-Cell labels
  3843.  
  3844.  
  3845. (defun delete-math-cell-label (math-cell-index)
  3846.   "Delete the math-cell label before MATH-CELL-INDEX.
  3847. If nil, then delete math-cell label before the last math-cell.
  3848. Leave point at the deletion."
  3849.  
  3850.   (if (not math-cell-index)
  3851.       (error "delete-math-cell-label")
  3852.     (goto-math-cell math-cell-index)
  3853.     (math-back-to-cell-label)
  3854.     )
  3855.  
  3856.   (let ((where (point)))
  3857.     (delete-region
  3858.      where
  3859.      (progn
  3860.        (math-match-cell-label)
  3861.        (point))
  3862.      ))
  3863.  
  3864.   ;; delete the math-cell marker since we will need to create another one
  3865.   (delete-math-cell-marker math-cell-index)
  3866.   )
  3867.    
  3868.  
  3869.  
  3870. (defun math-toggle-structure-labels ()
  3871.   "Toggle whether the math-cell structure is shown for math-cell labels."
  3872.   ;; works ok, but messes up with closed math-cells!!
  3873.   (interactive)
  3874.   (message "Relabeling...")
  3875.   (setq math-use-structure-labels (not math-use-structure-labels))
  3876.   (let ((math-cell-index (first-math-cell))
  3877.     ;;      (current-math-cell (current-math-cell))
  3878.     (before-change-hook nil)
  3879.     (inhibit-quit t)        ; no quiting in the middle
  3880.     )
  3881.     (buffer-flush-undo (current-buffer)) ; better not fail
  3882.     (unwind-protect
  3883.     (save-excursion
  3884.       (while (and math-cell-index (not quit-flag)) ; allow quiting
  3885.         (delete-math-cell-label math-cell-index)
  3886.         (insert-new-math-cell-label math-cell-index)
  3887.         (setq math-cell-index (math-cell-next math-cell-index))
  3888.         ;;    (sit-for 0)
  3889.         )
  3890.       (setq math-cell-index (first-math-cell))
  3891.       (while math-cell-index
  3892.         (show-or-hide-math-cell math-cell-index)
  3893.         (setq math-cell-index (math-cell-forward math-cell-index)))
  3894.       )
  3895.       (buffer-enable-undo (current-buffer))))
  3896.   (message "")
  3897.   )
  3898.       
  3899.   
  3900.  
  3901. (defun insert-new-math-cell-label (math-cell-index)
  3902.   "Insert label for math-cell MATH-CELL-INDEX.  
  3903. If nil, insert label at end of file."
  3904.  
  3905.   (let ((before-change-hook nil))
  3906.  
  3907.     (if (not math-cell-index)
  3908.     (error "Called insert-new-math-cell-label with nil argument."))
  3909.     
  3910.     (let* ((depth (or (math-cell-depth math-cell-index) 0))
  3911.        (group (math-cell-start-group-p math-cell-index))
  3912.        (where (math-cell-point math-cell-index))
  3913.        (name (math-cell-name math-cell-index)))
  3914.  
  3915.       (if (not where)            ; assume we are in the right place.
  3916.       (setq where (point)))
  3917.       (goto-char where)
  3918.  
  3919.       (insert "\n")            ; necessary to match label
  3920.       (if (or (not name) math-use-structure-labels)
  3921.       (insert (if group
  3922.               math-group-beginning-char
  3923.             math-cell-beginning-char)
  3924.           (make-string (1+ depth) math-cell-depth-char) " "))
  3925.       (if name (insert name))
  3926.       
  3927.       ;; remember the length of the label for the next indentation
  3928.       (set-math-cell math-cell-index 'next-indent-width
  3929.         (- (point) where 1))
  3930.  
  3931.       ;; mark second char of math-cell label
  3932.       (beginning-of-line)
  3933.       (forward-char 1)
  3934.       (let ((math-cell-marker (point-marker)))
  3935.     (set-math-cell math-cell-index 'point math-cell-marker)
  3936.     (replace-math-cell-marker math-cell-index math-cell-marker))
  3937.       )))
  3938.  
  3939.  
  3940.  
  3941. ;;;--------------------------------
  3942. ;;; Parsing math-cell headings
  3943. ;;; This is only done when a notebook is converted to internal form.
  3944. ;;;  **not used since it is too slow.  use macnb2nbl instead
  3945.  
  3946. (defun math-list-string (list)
  3947.   "Convert the elements of the LIST into a string."
  3948.   (substring (prin1-to-string list) 1 -1))
  3949.  
  3950. (defun math-parse-cell-heading (heading-string)
  3951.   "Parse the HEADING-STRING and return an alist representation of its
  3952. contents where each element is a control/token-list pair.  The
  3953. HEADING-STRING does not include the enclosing brackets."
  3954.  
  3955.   (let ((heading nil)
  3956.     (heading-start 0)
  3957.     (heading-length (length heading-string))
  3958.     (next-token nil)
  3959.     )
  3960.     (math-next-cell-heading-token) ; get first token
  3961.     (while (eq next-token 'semi)
  3962.       (math-next-cell-heading-token))
  3963.     (while next-token
  3964. ;;      (message "next token: %s" next-token) (sit-for 1)
  3965.       (let ((control next-token)
  3966.         (value-list nil)
  3967.         (value nil)
  3968.         )
  3969.     (math-next-cell-heading-token)
  3970.     (while (eq next-token 'semi)
  3971.         (math-next-cell-heading-token))
  3972.     (if (eq next-token 'equal)
  3973.         (progn  ; get list of values
  3974.           (setq next-token 'comma) ; hack
  3975.  
  3976.           (while (eq next-token 'comma)
  3977.         (setq value nil)
  3978.         (math-next-cell-heading-token)
  3979. ;;        (message "next value: %s" next-token) (sit-for 1)
  3980.         (while (not (memq next-token '(comma semi nil)))
  3981.           (setq value (cons next-token value))
  3982.           (math-next-cell-heading-token)
  3983.           )
  3984.         (if (< 1 (length value))  ; convert to string of elements
  3985.             (setq value (math-list-string value))
  3986.           (setq value (car value)))
  3987.         (setq value-list (cons value value-list))
  3988.         )))
  3989.     (setq heading
  3990.           (cons (cons control (or (nreverse value-list) t))
  3991.             heading))
  3992.     (while (eq next-token 'semi)
  3993.         (math-next-cell-heading-token))
  3994.     ))
  3995.     heading
  3996.     )
  3997.   )
  3998.  
  3999.   
  4000.  
  4001. (defconst math-cell-heading-token-regexp  ; dont put anything after next lines
  4002.   "^\\([,;=]\\|\
  4003. \"[^\"\n]*\"\\|\
  4004. In\\[[0-9]+\\] ?:= ?\\|\
  4005. Out\\[[0-9]+\\]= ?\\|\
  4006. \\w+\\)"
  4007.   "Regexp that matches the next token in the input string.
  4008. Probably wrong for In and/or Out prompts.")
  4009.  
  4010.  
  4011. ;; (defconst math-end-of-comment "\\*)")
  4012.  
  4013.  
  4014. (defun math-next-cell-heading-token ()
  4015.   "Get the next math-cell heading token."
  4016.   ;; too slow!!
  4017.   ;;   (message "heading-start = %d" heading-start) (sit-for 1)
  4018.  
  4019.   (if (string-match "^[ \t\n\r\f]+" heading-string heading-start)
  4020.       (progn
  4021.     ;;    (message "skipping: %s" heading-string) (sit-for 2)
  4022.     ;; skip whitespace
  4023.     ;;    (setq heading-start (match-end 0))
  4024.     ;; stick newline in string so ^ matches on the next string-match
  4025.     (aset heading-string (1- (match-end 0)) ?\n)
  4026.     ))
  4027.  
  4028.   ;; no comments allowed inside headers
  4029.   ;;  (if (string-match "^(\\*" heading-string heading-start)
  4030.   ;;    (setq heading-start (match-end 0))
  4031.   ;;    (aset heading-string (1- heading-start) ?\n)
  4032.   ;;    (string-match math-end-of-comment
  4033.   ;;          heading-string heading-start) ; eat comment
  4034.   ;;    (setq heading-start (match-end 0))
  4035.   ;;    (aset heading-string (1- heading-start) ?\n)
  4036.   ;;    )
  4037.  
  4038.  
  4039.   (if (< (1+ heading-start) heading-length)
  4040.       (if (string-match math-cell-heading-token-regexp
  4041.             heading-string heading-start)
  4042.       (let ((token (substring heading-string
  4043.                   (match-beginning 0)
  4044.                   (match-end 0))))
  4045.         (setq heading-start (match-end 0))
  4046.         (aset heading-string (1- heading-start) ?\n)
  4047.         ;;        (message "token: %s" token) (sit-for 1)
  4048.         (setq next-token
  4049.           (cond
  4050.            ((string-equal token ",") 'comma)
  4051.            ((string-equal token ";") 'semi)
  4052.            ((string-equal token "=") 'equal)
  4053.            ((string-match "^[0-9]+$" token) (string-to-int token))
  4054.            ((string-match "\"[^\"\n]*\"" token)
  4055.             (car (read-from-string token)))
  4056.            (t (intern token))))
  4057.         )
  4058.     ;; (error "Bad heading: %s" heading-string)
  4059.     (setq next-token nil)
  4060.     )
  4061.     (setq next-token nil)        ; end of tokens
  4062.     )
  4063.   )
  4064.  
  4065.  
  4066.  
  4067. ;;;-------------------
  4068. ;;; Editing constraints
  4069. ;;; These use the before-change-hook, if implemented, to check
  4070. ;;; that editing does not destroy math-cell labels and hidden marks.
  4071.  
  4072.  
  4073. (defvar current-math-cell-start nil
  4074.   "Buffer local.  A mark at the start position of current math-cell in current
  4075. buffer.")
  4076.  
  4077. (defvar current-math-cell-end nil
  4078.   "Buffer local.  A mark at the end position of current math-cell in current
  4079. buffer.")
  4080.  
  4081. (defvar current-math-cell-index nil
  4082.   "Buffer local.  The index of the current math-cell.")
  4083.  
  4084.  
  4085. (defun math-check-deletion (pos len)
  4086.   "Check that deletion is within a math-cell."
  4087.   (if (or (< pos current-math-cell-start)
  4088.       (> (+ pos len) current-math-cell-end))
  4089.       (progn
  4090.     (math-check-current-cell t)
  4091.     (if (or (< pos current-math-cell-start)
  4092.         (> (+ pos len) current-math-cell-end))
  4093.         (error "Deletion outside of cell contents is not allowed."))
  4094.     )))
  4095.  
  4096.  
  4097. (defun math-check-insertion (pos len)
  4098.   "Check that start of insertion is within a math-cell."
  4099.   (if (or (< pos current-math-cell-start)
  4100.       (> pos current-math-cell-end))
  4101.       (progn
  4102.     (math-check-current-cell t)
  4103.     (if (or (< pos current-math-cell-start)
  4104.         (> pos current-math-cell-end))
  4105.         (error "Insertion outside of a math-cell is not allowed."))
  4106.     )))
  4107.  
  4108.   
  4109. (defun math-check-current-cell (error-out)
  4110.   "Put internal marks at start and end of current math-cell. 
  4111. If ERROR-OUT non-nil and (closed and not group) or output
  4112. then give error."
  4113.   ;; it would be handy to have two kinds of mark.  The end mark
  4114.   ;; should be an insert-before mark!!
  4115.   (save-restriction
  4116.     (widen)                ; just in case
  4117.     (let ((math-match-data (match-data)) ; save since we have to search
  4118.       ;; find currently visible math-cell
  4119.       next-math-cell
  4120.       )
  4121.  
  4122.       (save-excursion
  4123.     (setq current-math-cell-index (current-math-cell))
  4124.  
  4125.     ;; find the start
  4126.     (math-label-to-contents)
  4127.     (skip-chars-backward " ")
  4128.     (set-marker current-math-cell-start (point))
  4129.  
  4130.     ;; find the end
  4131.     (if (setq next-math-cell (math-cell-next current-math-cell-index))
  4132.         (progn
  4133.           (goto-math-cell next-math-cell)
  4134.           (forward-char -1)        ; mark is on char 2
  4135.           (set-marker current-math-cell-end (1- (point)))
  4136.           )
  4137.       ;; no next math-cell, so set to end of buffer
  4138.       (set-marker current-math-cell-end (point-max))
  4139.       (goto-char (point-max))
  4140.       (let ((before-change-hook nil)) ; dont check recursively
  4141.         ;; put extra char at end to speed up inserts
  4142.         (insert "\n")
  4143.         )))
  4144.  
  4145.       (store-match-data math-match-data)
  4146.  
  4147.       (if (and error-out
  4148.            (< (point) current-math-cell-start))
  4149.       (error "Don't edit cell labels.")
  4150.  
  4151.     (let ((output))
  4152.       (if (or (setq output (math-cell-output-p current-math-cell-index))
  4153.           (math-cell-closed-p current-math-cell-index))
  4154.  
  4155.           (progn            ; not supposed to modify
  4156.         (set-marker current-math-cell-end
  4157.                 (1- current-math-cell-start))
  4158.         (if error-out
  4159.             (error "Can't modify %s cell.  %s it first."
  4160.                (if output "output" "closed")
  4161.                (if output "Unformat" "Open") ; give key commands.
  4162.                )))
  4163.         )))
  4164.       )))
  4165.  
  4166.  
  4167. (defun math-check-before-change (kind pos len)
  4168.   "Check that hidden text and math-cell label are not going to be modified."
  4169.   (cond
  4170.    ((= kind 0) (math-check-deletion pos len))
  4171.    ((= kind 1) (math-check-insertion pos len))
  4172.    ((= kind 2) (math-check-deletion pos len)) ; replacement is same
  4173.    (t
  4174.     (error (concat "Math-check-before-change: " kind " " pos " " len))
  4175.     (sit-for 2))            ; this should never happen
  4176.    ))
  4177.  
  4178. (defun math-no-check (kind pos len)
  4179.   "Dont do anything."
  4180.   )
  4181.  
  4182.  
  4183.  
  4184.  
  4185. ;;;------------------
  4186. ;;; Substitutes for common deletion and insertion commands.
  4187. ;;; Used if before-change-hook is not available
  4188.  
  4189. (defun math-delete-char (arg &optional killflag)
  4190.   "delete-char for math-mode.  Check if deletion is ok first."
  4191.   (interactive "*p")
  4192.   ;;  (message "delete-char arg: %s" arg)
  4193.   (if (> 0 arg)
  4194.       (math-delete-backward-char (- arg) killflag)
  4195.     (or    (not before-change-hook)
  4196.     (not math-mode)
  4197.     (math-check-deletion (point) arg))
  4198.     (emacs-delete-char arg killflag))
  4199.   )
  4200.  
  4201.  
  4202. (defun math-delete-backward-char (arg &optional killflag)
  4203.   "delete-backward-char for math-mode.  Check if deletion is ok first."
  4204.   (interactive "*p")
  4205.   ;;  (message "delete-backward-char")
  4206.   (if (> 0 arg)
  4207.       (math-delete-char (- arg) killflag)
  4208.     (or (not before-change-hook)
  4209.     (not math-mode)
  4210.     (math-check-deletion (- (point) arg) arg))
  4211.     (emacs-delete-backward-char arg killflag))
  4212.   )
  4213.  
  4214.  
  4215. (defun math-delete-region (start end)
  4216.   "delete-region for math-mode.  Check if deletion is ok first."
  4217.   (interactive "*r")
  4218.   (or (not before-change-hook)
  4219.       (not math-mode)
  4220.       (math-check-deletion start (- end start)))
  4221.   (emacs-delete-region start end)
  4222.   )
  4223.  
  4224.  
  4225. (defun math-self-insert-command (arg)
  4226.   "Do self-insert-command after checking if it is OK."
  4227.   ;; this doesnt work as a substitute for self-insert-command
  4228.   ;; but if all keys that do self-insert-command are rebound, it works fine.
  4229.   (interactive "*p")
  4230.   (or (not before-change-hook)
  4231. ;;;      (not math-mode)
  4232.       (math-check-insertion (point) 0))
  4233.   (emacs-self-insert-command arg))
  4234.  
  4235.  
  4236. (defun math-yank (arg)
  4237.   "Do yank after checking if it is OK."
  4238.   ;; could also check that text doesnt look like label!!
  4239.   (interactive "*p")
  4240.   (or (not before-change-hook)
  4241.       (not math-mode)
  4242.       (math-check-insertion (point) 0))
  4243.   (emacs-yank arg))
  4244.  
  4245.  
  4246. ;;(defun change-hooks-available-p ()
  4247. ;;  "Test whether the change hooks are available in this version
  4248. ;;of emacs."
  4249. ;;  ;; doesnt seem to work!!  dont use it
  4250. ;;  (let* ((new-buf (set-buffer
  4251. ;;           (get-buffer-create "test-hooks")))
  4252. ;;     before-change-hook)
  4253. ;;    (setq before-change-hook t)
  4254. ;;    (prog1
  4255. ;;    (assq 'before-buffer-hook
  4256. ;;          (buffer-local-variables))
  4257. ;;      (kill-buffer new-buf)
  4258. ;;      )))
  4259.  
  4260. ;; only do this once.  save standard defs so they may be referred to.
  4261. (if (not (fboundp 'emacs-delete-char))
  4262.     (progn
  4263.       (fset 'emacs-delete-char (symbol-function 'delete-char))
  4264.       (fset 'emacs-delete-backward-char (symbol-function 'delete-backward-char))
  4265.       (fset 'emacs-delete-region (symbol-function 'delete-region))
  4266.       (fset 'emacs-self-insert-command (symbol-function 'self-insert-command))
  4267.       (fset 'emacs-yank (symbol-function 'yank))
  4268.       ))
  4269.  
  4270. (defconst change-hooks-available nil
  4271.   "If non-nil, before-change-hook and after-change-hook are implemented.
  4272. These are not part of standard Emacs.")
  4273.  
  4274. (defun math-setup-change-hooks ()
  4275.   "Substitute math- commands for the common emacs insertion and delection commands"
  4276.   (if change-hooks-available
  4277.       (setq before-change-hook 'math-check-before-change)
  4278.     (setq before-change-hook 'math-no-check)
  4279.     (make-variable-buffer-local 'before-change-hook)
  4280.     (fset 'delete-char 'math-delete-char)
  4281.     (fset 'delete-backward-char 'math-delete-backward-char)
  4282.     (fset 'delete-region 'math-delete-region)
  4283. ;;;    (fset 'self-insert-command 'math-self-insert-command)  ; dont do this
  4284.     (fset 'yank (symbol-function 'math-yank))
  4285.     ))
  4286.  
  4287.  
  4288. (if nil;; for debugging only
  4289.     (progn
  4290.       (fset 'delete-char (symbol-function 'emacs-delete-char))
  4291.       (fset 'delete-backward-char (symbol-function 'emacs-delete-backward-char))
  4292.       (fset 'delete-region (symbol-function 'emacs-delete-region))
  4293. ;;;      (fset 'self-insert-command (symbol-function 'emacs-self-insert-command))
  4294.       (fset 'yank (symbol-function 'emacs-yank))
  4295.       ))
  4296.  
  4297.  
  4298.  
  4299.  
  4300. ;;-------------------
  4301. ;; Indentation
  4302. ;; Modified from lisp-mode indentation code
  4303.  
  4304.  
  4305. (defun math-newline-and-indent ()
  4306.   "Do newline-and-indent if in active math-cell,
  4307. otherwise redo command without math-newline-and-indent."
  4308.   (interactive)
  4309.   (if (or (< (point) current-math-cell-start)
  4310.       (> (point) current-math-cell-end))
  4311.       (math-check-current-cell nil))
  4312.   (if (eq 'input (math-cell-font current-math-cell-index))
  4313.       (newline-and-indent)
  4314.  
  4315.     ;; redo key without math-newline-and-indent
  4316.     (let ((indent-line-function 'indent-to-left-margin) ; from text mode
  4317.       (local-keymap (current-local-map)) ; math-mode-map
  4318.       )
  4319.       (use-local-map text-mode-map)
  4320.       (unwind-protect
  4321.       (progn
  4322.         ;; (setq current-prefix-arg arg)
  4323.         (command-execute (this-command-keys)))
  4324.     (use-local-map local-keymap))
  4325.       )))
  4326.  
  4327.  
  4328.  
  4329. (defun math-maybe-indent-line (&optional arg)
  4330.   "Indent current line as Math code, if in an active math-cell.
  4331. Otherwise redo command without math-maybe-indent-line.
  4332. With argument, indent any additional lines of the same expression
  4333. rigidly along with this one."
  4334.   (interactive "P")
  4335.   (if (or (< (point) current-math-cell-start)
  4336.       (> (point) current-math-cell-end))
  4337.       (math-check-current-cell nil))
  4338.   (if (eq 'input (math-cell-font current-math-cell-index))
  4339.       (math-indent-line arg)
  4340.  
  4341.     ;; redo key without math-maybe-indent-line
  4342.     (let ((indent-line-function 'indent-to-left-margin) ; from text mode
  4343.       (local-keymap (current-local-map)) ; math-mode-map
  4344.       )
  4345.       (use-local-map text-mode-map)
  4346.       (unwind-protect
  4347.       (progn
  4348.         (setq current-prefix-arg arg)
  4349.         (command-execute (this-command-keys)))
  4350.     (use-local-map local-keymap))
  4351.       )))
  4352.  
  4353.  
  4354.  
  4355. (defconst math-indent-offset nil "")
  4356. (defconst math-indent-hook 'math-indent-hook "")
  4357.  
  4358. ;; should use restriction around current cell to limit scope!!
  4359.  
  4360. (defun math-indent-line (&optional whole-exp)
  4361.   "Indent current line as Math code.
  4362. With argument, indent any additional lines of the same expression
  4363. rigidly along with this one."
  4364.   (let ((indent (calculate-math-indent)) shift-amt beg end
  4365.     (pos (- (point-max) (point))))
  4366.     (beginning-of-line)
  4367.     (setq beg (point))
  4368.     (skip-chars-forward " \t")
  4369.     (if (looking-at "(\\*\\*")
  4370.     (progn
  4371.       (indent-for-comment)
  4372.       (forward-char -1))
  4373.       (if (listp indent)
  4374.       (setq indent (car indent)))
  4375.       (setq shift-amt (- indent (current-column)))
  4376.       (if (zerop shift-amt)
  4377.       nil
  4378.     (delete-region beg (point))
  4379.     (indent-to indent))
  4380.       )
  4381.  
  4382.     ;; If initial point was within line's indentation,
  4383.     ;; position after the indentation.  Else stay at same point in text.
  4384.     (if (> (- (point-max) pos) (point))
  4385.     (goto-char (- (point-max) pos)))
  4386.     ;; If desired, shift remaining lines of expression the same amount.
  4387.     (and whole-exp (not (zerop shift-amt))
  4388.      (save-excursion
  4389.        (goto-char beg)
  4390.        (forward-sexp 1)
  4391.        (setq end (point))
  4392.        (goto-char beg)
  4393.        (forward-line 1)
  4394.        (setq beg (point))
  4395.        (> end beg))
  4396.      (indent-code-rigidly beg end shift-amt)
  4397.      )))
  4398.  
  4399. (defun calculate-math-indent (&optional parse-start)
  4400.   "Return appropriate indentation for current line as Math code.
  4401. In usual case returns an integer: the column to indent to.
  4402. Can instead return a list, whose car is the column to indent to.
  4403. This means that following lines at the same level of indentation
  4404. should not necessarily be indented the same way.
  4405. The second element of the list is the buffer position
  4406. of the start of the containing expression."
  4407.   (save-excursion
  4408.     (beginning-of-line)
  4409.     (let ((indent-point (point))
  4410.           state paren-depth
  4411.           ;; setting this to a number inhibits calling hook
  4412.           (desired-indent nil)
  4413.           (retry t)
  4414.           last-sexp containing-sexp
  4415.       start-of-expr            ; point where current expression starts
  4416.       expr-char            ; the char that is before this expression
  4417.       )
  4418.       (if parse-start
  4419.           (goto-char parse-start)
  4420.     (if (and (boundp 'math-mode)
  4421.          math-mode)
  4422.         (math-move-to-cell (current-math-cell))
  4423.       ;; math-package
  4424.       (beginning-of-line)
  4425.       (if (not (bobp))
  4426.           (forward-char -1))
  4427.       (re-search-backward "^[ \t]*$\\|\\`")
  4428.       ))
  4429.       (setq containing-sexp (1- (point)))
  4430.  
  4431.       ;; Find outermost containing sexp
  4432.       (while (< (point) indent-point)
  4433.         (setq state (parse-partial-sexp (point) indent-point 0)))
  4434.  
  4435.       ;; Find innermost containing sexp () [] or {}.
  4436.       (while (and retry
  4437.           state
  4438.                   (> (setq paren-depth (elt state 0)) 0))
  4439.         (setq retry nil)
  4440.         (setq last-sexp (elt state 2))
  4441.         (setq containing-sexp (or (elt state 1) containing-sexp))
  4442.  
  4443.         ;; Position following last unclosed open.
  4444.         (goto-char (1+ containing-sexp))
  4445.  
  4446.         ;; Is there a complete sexp since then?
  4447.         (if (and last-sexp (> last-sexp (point)))
  4448.             ;; Yes, but is there a containing sexp after that?
  4449.             (let ((peek (parse-partial-sexp last-sexp indent-point 0)))
  4450.               (if (setq retry (car (cdr peek)))
  4451.           (setq state peek)))))
  4452.  
  4453.       (if (not desired-indent)
  4454.       (progn
  4455.         ;; find innermost comma or semi seperated expression
  4456.         (goto-char indent-point)
  4457.         (math-back-to-previous-expression (1+ containing-sexp))
  4458.         (setq expr-char (preceding-char)) ; remember which kind of expr
  4459.         (save-excursion
  4460.           (math-skip-whitespace)
  4461.           (setq start-of-expr (point)))
  4462.             
  4463.         ;; Innermost containing sexp found
  4464.         (if (save-excursion
  4465.           (goto-char start-of-expr)
  4466.           (forward-line 1)
  4467.           (<= (point) indent-point))
  4468.         ;; Unfinished expression
  4469.         ;; Indent beneath start of current expression + some
  4470.         (progn
  4471.           (goto-char start-of-expr)
  4472.           (setq desired-indent (+ (current-column) math-body-indent)))
  4473.  
  4474.           (if (eq expr-char ?\;)
  4475.           (progn
  4476.             ;; Indent beneath first expression in semi list + some
  4477.             (forward-char -1)
  4478.             (math-back-to-previous-expression
  4479.              (1+ containing-sexp) '(?\,))
  4480.             (math-skip-whitespace)
  4481.             (setq desired-indent (+ (current-column) math-body-indent))
  4482.             )
  4483.         (goto-char (1+ containing-sexp)))
  4484.           )))
  4485.  
  4486.       ;; Point is at the point to indent under unless we are inside a string.
  4487.       ;; Call indentation hook except when overriden by math-indent-offset
  4488.       ;; or if the desired indentation has already been computed.
  4489.       (let ((normal-indent (current-column)))
  4490.     (cond ((elt state 3)
  4491.            ;; Inside a string, don't change indentation.
  4492.            (goto-char indent-point)
  4493.            (skip-chars-forward " \t")
  4494.            (current-column))
  4495.  
  4496.           ((and (integerp math-indent-offset) containing-sexp)
  4497.            ;; Indent by constant offset
  4498.            (goto-char containing-sexp)
  4499.            (+ normal-indent math-indent-offset))
  4500.  
  4501.           (desired-indent)
  4502.  
  4503.           ((and (boundp 'math-indent-hook)
  4504.             math-indent-hook
  4505.             (not retry))
  4506.            (or (funcall math-indent-hook containing-sexp indent-point)
  4507.            normal-indent))
  4508.           (t
  4509.            normal-indent)))
  4510.       )))
  4511.  
  4512.  
  4513. (defun math-indent-hook (containing-sexp indent-point)
  4514.   "Check whether special indenting is required.
  4515. Assume point is after opening paren of containing expression."
  4516.   (if (eq (preceding-char) ?\[)
  4517.       (let ((normal-indent (current-column))
  4518.         (starting-point (point)))
  4519.         
  4520.     (let* ((function-name
  4521.         (progn
  4522.           (if (not (bobp))
  4523.               (forward-char -1))
  4524.           (if (= ?\[ (preceding-char)) ; looking at \[\[
  4525.               (list)
  4526.             (math-skip-whitespace-backwards)
  4527.             (if (and (not (bobp))
  4528.                  (string-match "\\s_"
  4529.                        (char-to-string (preceding-char))))
  4530.             (buffer-substring (point)
  4531.                       (progn           
  4532.                         (forward-sexp -1) 
  4533.                         (point)) ; leave point here 
  4534.                       )))))
  4535.            (start-of-header (progn (point) (current-column)))
  4536.            (method (and function-name
  4537.                 (get (intern-soft function-name) 
  4538.                  'math-indent-hook))))
  4539.  
  4540.       (cond ((integerp method)
  4541.          (goto-char (1+ containing-sexp))
  4542.          (math-indent-specform method
  4543.                        indent-point
  4544.                        (+ start-of-header math-body-indent)))
  4545.         ;; should be a function - not used
  4546.         (method
  4547.          (funcall method indent-point))
  4548.  
  4549.         (t
  4550.          ;; test if function-name is an unknown header
  4551.          ;; or an expression
  4552.          ;; First, does it have any funny chars in it?
  4553.          (if (or (null function-name)
  4554.              (string-match "[#%_$\(\[\{]" function-name))
  4555.              normal-indent
  4556.            ;; starting at beginning of symbol before []
  4557.            ;; check if there is a preceeding :: or ?
  4558.            (math-skip-whitespace-backwards)
  4559.            (forward-char -1)
  4560.            (if (or (= (following-char) ?\?)
  4561.                (and (= (following-char) ?\:)
  4562.                 (= (preceding-char) ?\:)))
  4563.                normal-indent
  4564.              (+ start-of-header math-body-indent)
  4565.              ))
  4566.          )))
  4567.     )))
  4568.  
  4569.  
  4570. (defconst math-body-indent 2
  4571.   "How much to indent body of math expressions.")
  4572.  
  4573. (defun math-indent-specform (count indent-point normal-indent)
  4574.   "Return the column to indent to given the number, COUNT, of the
  4575. first distinguished expression, the INDENT-POINT of the line to indent,
  4576. and the NORMAL-INDENT column."
  4577.   (let ((containing-form-start (point))
  4578.         (i count)
  4579.         body-indent 
  4580.     containing-form-column)
  4581.     ;; Move to the start of containing form, calculate indentation
  4582.     ;; to use for non-distinguished forms (> count).
  4583.     ;; math-indent-hook guarantees that there is at
  4584.     ;; least one expression following open paren of containing
  4585.     ;; form.
  4586.     (goto-char containing-form-start)
  4587.     ;;    (setq containing-form-column (current-column))
  4588.     (setq body-indent (+ math-body-indent normal-indent))
  4589.  
  4590.     ;; Now count the number of expressions up to count
  4591.     (while (and (< (point) indent-point)
  4592.         (<= 0 (setq count (1- count))))
  4593.       (math-forward-to-next-expression indent-point '(?\,))
  4594.       (skip-chars-forward ",")
  4595.       (math-skip-whitespace)
  4596.       )
  4597.       
  4598.     ;; Point is sitting on first character of last (or count) expression.
  4599.     (if (> count 0)
  4600.         ;; A distinguished form.  If it is before the method'th form use double
  4601.         ;; math-body-indent, else just normal-indent. 
  4602.     (list (+ normal-indent math-body-indent)
  4603.           (+ normal-indent math-body-indent))
  4604.  
  4605.       ;; A non-distinguished form.  Use body-indent if there are no
  4606.       ;; distinguished forms and this is the first undistinguished form,
  4607.       ;; or if this is the first undistinguished form and the preceding
  4608.       ;; distinguished form has indentation at least as great as body-indent.
  4609.       (if (or (and (= i 0) (= count 0))
  4610.               (and (= count 0) (<= body-indent normal-indent)))
  4611.           normal-indent
  4612.     normal-indent            ; was normal-indent
  4613.     ))))
  4614.  
  4615. (put 'Block 'math-indent-hook 1)
  4616. (put 'For 'math-indent-hook 3)
  4617. (put 'While 'math-indent-hook 1)
  4618. (put 'Do 'math-indent-hook 1)
  4619. (put 'Next 'math-indent-hook 2)
  4620. (put 'FixedPoint 'math-indent-hook 1)
  4621. (put 'If 'math-indent-hook 2)
  4622. (put 'Switch 'math-indent-hook 1)
  4623. (put 'Which 'math-indent-hook 0)
  4624. (put 'Check 'math-indent-hook 1)
  4625.  
  4626.  
  4627. (defun math-indent-exp ()
  4628.   "Indent each line of the expression starting just after point."
  4629.   (interactive)
  4630.   (if (or (< (point) current-math-cell-start)
  4631.       (> (point) current-math-cell-end))
  4632.       (math-check-current-cell nil))
  4633.   (if (not (eq 'input (math-cell-font current-math-cell-index)))
  4634.       (undefined))
  4635.   (let* ((start-of-exp (point))
  4636.      (end-of-exp (save-excursion
  4637.                (math-forward-expression 1)
  4638.                (skip-chars-backward " \t\n\r")
  4639.                (point-marker))))
  4640.     (save-excursion
  4641.       (forward-line)
  4642.       (while (< (point) end-of-exp)
  4643.     (math-indent-line)
  4644.     (forward-line)
  4645.     ))
  4646.     ))
  4647.  
  4648.  
  4649.  
  4650. (defun math-back-to-previous-expression (limit-point &optional term-chars)
  4651.   "Move point back to previous expression at the same level.
  4652. Dont move past LIMIT-POINT, or past the start of a list.
  4653. If optional TERM-CHARS is non-nil, it is a list of characters that
  4654. may terminate the search.  If nil, use ',' and ';'.
  4655. Leave point after the term char."
  4656.   (or term-chars (setq term-chars '(?\; ?\,)))
  4657.   (while (and (> (point) limit-point)
  4658.           (not (or (memq (preceding-char) term-chars)
  4659.                (memq (preceding-char) '(?\( ?\[ ?\{)))))
  4660.     (if (memq (preceding-char) '(?\) ?\] ?\} ?\"))
  4661.     (forward-sexp -1)
  4662.       (forward-char -1)            ; skip single char
  4663.       (if (looking-at "\\s_")
  4664.       (progn
  4665.         (forward-char 1)
  4666.         (forward-sexp -1)        ; skip the whole symbol
  4667.         ))
  4668.       )
  4669.     (skip-chars-backward " \t\n\r")
  4670.     )
  4671.   (if (> limit-point (point))
  4672.       (goto-char limit-point)        ; too far    
  4673.     ;; else found something
  4674.     ))
  4675.  
  4676.  
  4677. (defun math-forward-to-next-expression (limit-point &optional term-chars)
  4678.   "Move point forward to next expression at the same level.
  4679. Dont move past LIMIT-POINT, or past the start of a list.
  4680. If optional TERM-CHARS is non-nil, it is a list of characters that
  4681. may terminate the search.  If nil, use ',' and ';'.
  4682. Leave point after the term char."
  4683.   (or term-chars (setq term-chars '(?\; ?\,)))
  4684.   (while (and (< (point) limit-point)
  4685.           (not (or (memq (following-char) term-chars)
  4686.                (memq (following-char) '(?\) ?\] ?\})))))
  4687.     (if (memq (following-char) '(?\( ?\[ ?\{ ?\"))
  4688.     (forward-sexp 1)
  4689.       (if (looking-at "\\s_")
  4690.       (forward-sexp 1)        ; skip the whole symbol
  4691.     (forward-char 1)
  4692.     )
  4693.       )
  4694.     (skip-chars-forward " \t\n\r")
  4695.     )
  4696.   (if (< limit-point (point))
  4697.       (goto-char limit-point)        ; too far    
  4698.     ;; else found something
  4699.     ))
  4700.  
  4701.  
  4702.  
  4703. (defun math-skip-whitespace ()
  4704.   "Skip forward skipping comments and whitespace."
  4705.   (skip-chars-forward " \t\n\r")
  4706.   (while (looking-at "(\\*")        ; skip leading comments
  4707.     (forward-sexp 1)
  4708.     (skip-chars-forward " \t\n\r")
  4709.     ))
  4710.  
  4711. (defun math-skip-whitespace-backwards ()
  4712.   "Skip backwards skipping comments and whitespace."
  4713.   (skip-chars-backward " \t\n\r")
  4714.   (while (save-excursion 
  4715.        (forward-char -2)
  4716.        (looking-at "(\\*")        ; skip leading comments
  4717.        )
  4718.     (backward-sexp 1)
  4719.     (skip-chars-backward " \t\n\r")
  4720.     ))
  4721.  
  4722.  
  4723. (defun math-forward-expression (arg)
  4724.   "Move forward across one balanced math expression.
  4725. With argumment, do this that many times."
  4726.   (interactive "p")
  4727.   (if (or (< (point) current-math-cell-start)
  4728.       (> (point) current-math-cell-end))
  4729.       (math-check-current-cell nil))
  4730.   (or (and arg (> arg 0))
  4731.       (setq arg 1))
  4732.   (while (> arg 0)
  4733.     (setq arg (1- arg))
  4734.     (if (memq (following-char) '(?\, ?\;))
  4735.     (forward-char 1))
  4736.     (math-forward-to-next-expression current-math-cell-end)
  4737.     )
  4738.   )
  4739.  
  4740.  
  4741. (defun math-backward-expression (arg)
  4742.   "Move backward across one balanced math expression.
  4743. With argumment, do this that many times."
  4744.   (interactive "p")
  4745.   (if (or (< (point) current-math-cell-start)
  4746.       (> (point) current-math-cell-end))
  4747.       (math-check-current-cell nil))
  4748.   (or (and arg (> arg 0))
  4749.       (setq arg 1))
  4750.   (math-back-to-previous-expression 0)
  4751.   (while (> arg 0)
  4752.     (setq arg (1- arg))
  4753.     (if (memq (preceding-char) '(?\, ?\;))
  4754.     (forward-char -1))
  4755.     (math-back-to-previous-expression current-math-cell-start)
  4756.     )
  4757.   (math-skip-whitespace)
  4758.   )
  4759.  
  4760. ;; This is used by indent-for-comment
  4761. ;; to decide how much to indent a comment in math code
  4762. ;; based on its context.
  4763. (defun math-comment-indent ()
  4764.   (if (looking-at "(\\*\\*")
  4765.       0                ;Existing comment at bol stays there.
  4766.     (save-excursion
  4767.       (skip-chars-backward " \t")
  4768.       (max (1+ (current-column))    ;Else indent at comment column
  4769.        comment-column))))    ; except leave at least one space.
  4770.  
  4771.  
  4772.