1 ;;;; imaxima.el --- Maxima mode with images
3 ;; Copyright (C) 2001, 2002, 2003, 2004 Jesper Harder
5 ;; Author: Jesper Harder <harder@ifa.au.dk>
6 ;; Created: 14 Nov 2001
10 ;; Copyright (C) 2006 Stephen Eglen (imaxima-print-buffer)
11 ;; Copyright (C) 2007, 2008 Yasuaki Honda (imaxima-to-html, inline graph)
13 ;; $Id: imaxima.el,v 1.7 2009-02-22 09:18:27 yasu-honda Exp $
15 ;; This program is free software; you can redistribute it and/or
16 ;; modify it under the terms of the GNU General Public License as
17 ;; published by the Free Software Foundation; either version 2 of
18 ;; the License, or (at your option) any later version.
20 ;; This program is distributed in the hope that it will be
21 ;; useful, but WITHOUT ANY WARRANTY; without even the implied
22 ;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
23 ;; PURPOSE. See the GNU General Public License for more details.
25 ;; You should have received a copy of the GNU General Public
26 ;; License along with this program; if not, write to the Free
27 ;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
33 ;; This file (and imaxima.lisp) provides image support for interacting
34 ;; with the computer algebra system Maxima
35 ;; <http://maxima.sourceforge.net/>
37 ;; The command `imaxima' (M-x imaxima) provides a simple comint
40 ;; To use imaxima with the Maxima mode from the Maxima distribution
41 ;; set `imaxima-use-maxima-mode-flag' to `t'.
43 ;; To turn off images, evaluate "display2d:true" in Maxima. To turn
44 ;; them on again, evaluate "display2d:imaxima".
46 ;; The command `imaxima-latex' prepares a LaTeX version of the Maxima
49 ;; The package requires Emacs 21 with image support.
51 ;; A fairly recent version of Ghostscript is recommended (at least
52 ;; newer than v. 8.56). If your version is too old, you can either set
53 ;; `imaxima-image-type' to 'ps or remove the options
54 ;; "-dTextAlphaBits=4" and "-dGraphicsAlphaBits=4" from
55 ;; `imaxima-gs-options'. The images won't look nearly as attractive,
56 ;; though -- the text looks ragged because it isn't anti aliased.
58 ;; The file "imaxima.lisp" is a slightly modified version of
59 ;; "texmacs.lisp" in the TeXmacs distribution. Several of the image
60 ;; routines are borrowed from David Kastrup's preview-latex.el.
62 ;; Version 1.0 beta and later supports inline graph. You can use
63 ;; the following six maxima commands.
64 ;; wxplot2d(), wxplot3d(), wxdraw2d(), wxdraw3d(), wximplicit_plot(),
66 ;; GNUPLOT 4.2 or later is needed for this to work. The resulted image
67 ;; generated by gnuplot will be inserted as the output of the command.
71 ;; Take a look at the README file which comes with this file.
76 ;; modified to remove eval-when-compile form. Surrounding
77 ;; the eval-when-compile prevernts imaxima from running
78 ;; properly in the xemacs on cygwin environment.
79 (require 'imaxima-autoconf-variables
)
87 (defalias 'imaxima-image-type-available-p
88 (if (fboundp 'image-type-available-p
)
89 'image-type-available-p
92 (defalias 'imaxima-display-pixel-width
93 (if (fboundp 'display-pixel-width
)
97 (defalias 'imaxima-display-pixel-height
98 (if (fboundp 'display-pixel-height
)
100 'device-pixel-height
))
102 (defalias 'imaxima-display-mm-width
103 (if (fboundp 'display-mm-width
)
107 (defalias 'imaxima-display-mm-height
108 (if (fboundp 'display-mm-height
)
112 (defalias 'imaxima-get-window-width
113 (if (featurep 'xemacs
)
114 'imaxima-get-window-width-xemacs
115 'imaxima-get-window-width-emacs
))
117 (defalias 'imaxima-color-values
118 (if (fboundp 'color-values
)
120 '(lambda (color) (color-rgb-components
122 (make-color-specifier color
)
125 (defun imaxima-get-bg-color ()
126 (if (featurep 'xemacs
)
127 (face-property 'default
'background
)
128 (frame-parameter nil
'background-color
)))
130 (defun imaxima-get-fg-color ()
131 (if (featurep 'xemacs
)
132 (face-property 'default
'foreground
)
133 (frame-parameter nil
'foreground-color
)))
135 ;; XEmacs doesn't have subst-char-in-string (sigh!).
137 (defun imaxima-subst-char-in-string (fromchar tochar string
&optional inplace
)
138 "Replace FROMCHAR with TOCHAR in STRING each time it occurs.
139 Unless optional argument INPLACE is non-nil, return a new string."
140 (let ((i (length string
))
141 (newstr (if inplace string
(copy-sequence string
))))
144 (if (eq (aref newstr i
) fromchar
)
145 (aset newstr i tochar
)))
149 (defconst imaxima-mouse2
(if (featurep 'xemacs
)
153 (defconst imaxima-mouse3 (if (featurep 'xemacs)
159 (defgroup imaxima nil
160 "Image support for Maxima."
162 :link '(url-link "http://purl.org/harder/imaxima.html")
163 :link '(custom-manual "(imaxima)")
167 (defvar process-connection-type-flag
168 (if (eql system-type 'darwin) t nil))
170 (defvar imaxima-image-types '(png postscript jpeg tiff))
172 (defcustom imaxima-image-type 'png
173 "Image type to used in Maxima buffer."
176 (mapcar (lambda (type) (list 'const type))
177 (remove-if-not 'imaxima-image-type-available-p
178 imaxima-image-types))))
180 (defcustom imaxima-pt-size 11
181 "*Point size used in LaTeX."
183 :type '(choice (const 9)
188 (defcustom imaxima-fnt-size "normalsize"
189 "*Default size of font."
191 :type '(choice (const "small")
199 (defcustom imaxima-scale-factor 1.0
200 "*All images are scaled by this factor."
204 (defcustom imaxima-label-color "red"
205 "*Color used in output labels."
209 (defcustom imaxima-equation-color (imaxima-get-fg-color)
210 "*Color used for equations."
214 (defcustom imaxima-bg-color nil
215 "Background color of imaxima buffer."
217 :type '(choice (color)
218 (const :tag "None" nil)))
220 (defcustom imaxima-fg-color nil
221 "Foreground color of imaxima buffer."
223 :type '(choice (color)
224 (const :tag "None" nil)))
226 (defcustom imaxima-latex-preamble ""
227 "*String inserted at the start of the document preamble.
228 This can be used to change, say, the document font.
229 E.g. `\\usepackage{concrete}' will use the Euler math fonts."
233 (defcustom imaxima-max-scale 0.85
234 "Maximum amount of scaling allowed to fit wide equations in the buffer.
235 nil means no scaling at all, t allows any scaling."
239 (defcustom imaxima-linearize-flag t
240 "Non-nil means that equations too wide to fit in the buffer are linearized."
244 (defcustom imaxima-use-maxima-mode-flag nil
245 "Non-nil means that the major mode from `maxima.el' is used."
249 (defcustom imaxima-maxima-program "maxima"
255 (defcustom imaxima-initex-option "-ini"
256 "Option passed to TeX to start initex."
260 (defcustom imaxima-tex-program "latex"
265 (defcustom imaxima-gs-program "gs"
266 "Ghostscript executable."
270 (defcustom imaxima-gs-options '("-q" "-dNOPAUSE"
273 "-DNOPLATFONTS" "-dTextAlphaBits=4"
274 "-dGraphicsAlphaBits=4")
275 "Options passed to gs for conversion from EPS."
277 :type '(repeat string))
279 (defcustom imaxima-dvips-program "dvips"
284 (defcustom imaxima-cp-program "cp"
289 (defcustom imaxima-dvips-options '("-E" "-R")
290 "Options passed to dvips for conversion from DVI to EPS."
292 :type '(repeat string))
294 (defcustom imaxima-tmp-dir
295 (cond ((featurep 'xemacs)
297 ((eql system-type 'cygwin)
299 (t temporary-file-directory))
300 "*Directory used for temporary TeX and image files."
304 (defcustom imaxima-startup-hook nil
305 "A hook called at startup.
306 This hook is called after imaxima has started Maxima."
310 (defcustom imaxima-exit-hook nil
311 "Hook called when exiting imaxima."
315 (defvar imaxima-tmp-subdir ""
316 "Subdirectory for temporary files.")
318 (defcustom imaxima-lisp-file
319 (if (eq system-type 'windows-nt)
320 (imaxima-subst-char-in-string ?\\ ?/ (locate-library "imaxima.lisp"))
321 (locate-library "imaxima.lisp"))
322 "Location of `imaxima.lisp'."
326 (defcustom imaxima-maxima-options
327 (if (eq system-type 'windows-nt)
328 ;; in this case the appropriate value is the empty string.
330 (format "--preload-lisp=%s" imaxima-lisp-file))
331 "Arguments passed to Maxima."
335 (defface imaxima-latex-error-face
336 '((t (:foreground "Blue" :underline t)))
337 "Face used for LaTeX errors."
340 (defvar imaxima-image-creators
342 (png ("-sDEVICE=png16m"))
343 (jpeg ("-sDEVICE=jpeg"))
344 (tiff ("-sDEVICE=tiffpack")))
345 "Define functions for generating images.
346 Argument list is passed to gs.")
348 (defvar imaxima-resolution nil
349 "Screen resolution where rendering started.
350 Cons-cell of x and y resolution, given in
351 dots per inch. Buffer-local to rendering buffer.")
352 (make-variable-buffer-local 'imaxima-resolution)
354 (defvar imaxima-output ""
355 "Accumulator for `imaxima-filter'.")
357 (defvar imaxima-gs-output ""
358 "Accumulator for `imaxima-gs-filter'.")
360 (defvar imaxima-process nil)
361 (defvar imaxima-gs-process nil)
362 (defvar imaxima-gs-computing-p nil)
363 (defvar imaxima-gs-7.05-is-broken nil)
365 (defvar imaxima-error-map (make-sparse-keymap)
366 "Keymap for mouse clicks on LaTeX errors.")
368 (defvar imaxima-old-bg-color nil
369 "Old background color.")
371 (defvar imaxima-old-fg-color nil
372 "Old foreground color.")
374 (defvar imaxima-file-counter 0
375 "Counter used for naming temp files.")
377 (defvar imaxima-html-dir "~/")
379 ;; This piece of TeX is `mylatex.ltx' by David Carlisle. The license is:
381 ;; "There are no restrictions on the distribution or modification of
382 ;; this file, except that other people should not attempt to alter
383 ;; the master copy on the ctan archives."
385 (defconst imaxima-mylatex
386 "\\makeatletter\\let\\MYLATEXdocument\\document
387 \\let\\MYLATEXopenout\\openout\\def\\document{\\endgroup
388 {\\setbox\\z@\\hbox{\\normalfont% normal
389 {\\ifx\\large\\@undefined\\else\\large\\fi
390 \\ifx\\footnotesize\\@undefined\\else\\footnotesize\\fi}%
391 {\\bfseries\\itshape}% bold and bold italic
392 {\\itshape}\\ttfamily\\sffamily}}%
393 \\let\\document\\MYLATEXdocument\\let\\openout\\MYLATEXopenout
394 \\makeatother\\everyjob\\expandafter{\\the\\everyjob
395 \\begingroup\\listfiles\\expandafter\\MYLATEXcustomised\\@dofilelist
396 \\endgroup}\\@addtofilelist{.}\\catcode`\\\\=13\\relax
397 \\catcode`\\#=12\\relax\\catcode`\\ =9\\relax\\dump}
398 \\def\\openout#1 {\\g@addto@macro\\MYLATEXopens{\\immediate\\openout#1 }}
399 \\let\\MYLATEXopens\\@empty\\def\\MYLATEXbegin{\\begin{document}}
400 \\def\\MYLATEXcomment{mylatex}\\def\\MYLATEXcustomised#1#2#3\\typeout#4{%
401 \\typeout{CUSTOMISED FORMAT. Preloaded files:^^J\\@spaces\\@spaces.}#3}
402 {\\catcode`\\^^M=\\active\\catcode`\\/=0 %
403 /catcode`\\\\=13 /gdef\\{/catcode`/\\=0 /catcode`/^^M=13 /catcode`/%=9 ^^M}%
404 /long/gdef^^M#1^^M{/def/MYLATEXline{#1}%
405 /ifx/MYLATEXline/MYLATEXcomment/let/MYLATEXbegin/relax%
406 /let/MYLATEXline/relax/fi/ifx/MYLATEXline/MYLATEXbegin%
407 /catcode`/^^M=5/relax/let^^M/par/catcode`/#=6/relax%
408 /catcode`/%=14/relax/catcode`/ =10/relax%
409 /expandafter/MYLATEXopens/expandafter/MYLATEXbegin%
410 /else/expandafter^^M/fi}}\\expandafter\\input\\endinput%"
411 "TeX code for dumping a format file.")
417 (defun imaxima-version ()
418 "Print the package name and the version in the mini buffer"
420 (message "%s %s" *imaxima-autoconf-package* *imaxima-autoconf-version*))
426 (defun reinit-imaxima ()
427 "Re-initialize imaxima"
429 (setq imaxima-filter-running nil
437 (defun imaxima-get-geometry (buffer)
438 "Transfer display geometry parameters from current display.
439 Those are put in local variable `imaxima-resolution'. Calculation is done
440 in source buffer specified by BUFF."
442 (with-current-buffer buffer
443 (setq res (cons (/ (* 25.4 (imaxima-display-pixel-width))
444 (imaxima-display-mm-width))
445 (/ (* 25.4 (imaxima-display-pixel-height))
446 (imaxima-display-mm-height)))))
447 (setq imaxima-resolution res)))
449 (defun imaxima-get-window-width-xemacs ()
450 "Return window width in mm.
452 (/ (* (window-text-area-pixel-width) (imaxima-display-mm-width))
453 (imaxima-display-pixel-width)))
455 (defun imaxima-get-window-width-emacs ()
456 "Return window width in mm.
458 (/ (* (- (window-width) 1) (frame-char-width))
459 (/ (float (imaxima-display-pixel-width))
460 (imaxima-display-mm-width))))
462 (defun imaxima-bp-to-mm (bp)
463 "Convert PostScript big points to mm. BP is size in big points."
466 (defun imaxima-color-to-rgb (str)
467 "Convert color name STR to rgb values understood by TeX."
468 (mapcar #'(lambda (x) (/ x 65535.0)) (imaxima-color-values str)))
470 (defmacro imaxima-with-temp-dir (dir &rest body)
471 "Change to DIR temporarily and execute BODY."
472 (let ((wd (make-symbol "wd")))
473 `(let ((,wd default-directory))
484 (defun imaxima-gs-filter (process str)
485 "Set `imaxima-gs-computing-p' to t when gs is done."
486 (setq imaxima-gs-output (concat imaxima-gs-output str))
487 (when (string-match "GS\\(<[0-9+]\\)?>" imaxima-gs-output)
488 (setq imaxima-gs-computing-p nil)
489 (setq imaxima-gs-output "")))
491 (defun imaxima-gs-wait ()
492 "Wait for gs to finish."
493 (while (and imaxima-gs-computing-p
494 (eq (process-status imaxima-gs-process) 'run))
495 (accept-process-output imaxima-gs-process 1)))
497 (defun imaxima-start-gs ()
498 "Start Ghostscript as an asynchronyous process."
499 ;; Are we using the broken GNU Ghostscript 7.05?
500 (setq imaxima-gs-7.05-is-broken
501 (string-match "\\(GNU\\|ESP\\) Ghostscript 7.05"
502 (shell-command-to-string
503 (concat imaxima-gs-program " --help"))))
505 (type (cadr (assq imaxima-image-type imaxima-image-creators)))
506 (gs-args (append imaxima-gs-options
508 (list (format "-r%gx%g" (car imaxima-resolution)
509 (cdr imaxima-resolution))))))
510 (when (and imaxima-gs-process
511 (processp imaxima-gs-process))
512 (delete-process imaxima-gs-process))
513 (setq imaxima-gs-computing-p t)
515 (setq imaxima-gs-process (apply 'start-process "imaxima-gs"
516 " *imaxima gs output*"
517 imaxima-gs-program gs-args))
519 "Sorry, Ghostscript could not be started. Please check
520 that you have gs in your path or customize the value of
521 `imaxima-gs-program' (current values is \"%s\").
524 (if (imaxima-image-type-available-p 'postscript)
525 "If Ghostscript isn't installed you can set `imaxima-image-type' to `ps'."
526 ;; don't offer this advice in XEmacs, which doesn't support ps.
528 (set-process-filter imaxima-gs-process 'imaxima-gs-filter)
530 (set-process-query-on-exit-flag imaxima-gs-process nil)
531 (unless (eq (process-status imaxima-gs-process) 'run)
532 (setq output (shell-command-to-string (concat imaxima-gs-program " -h")))
534 ((null (string-match (car type) output))
536 "Your version Ghostscript does not appear to support the image type %s.
537 The command \"gs -h\" lists the available devices.
538 You can change the image type in `imaxima-image-type' or the device name
539 associated with an image type in `imaxma-image-creators'" (car type)))
541 "Some of the options passed to Ghostscript are probably not supported
542 by your version. In particular \"-dTextAlphaBits=4\" and \"-dGraphicsAlphaBits=4\"
543 are not supported by gs 5.5 or earlier. Please edit `imaxima-gs-options'"))))))
545 (defun imaxima-extract-bb (filename)
546 "Extract EPS bounding box vector from FILENAME.
547 Returns a list of bounding box, width, and height."
549 (insert-file-contents-literally filename nil 0 1024 t)
550 (goto-char (point-min))
551 (when (search-forward-regexp "%%BoundingBox:\
555 +\\([-+]?[0-9.]+\\)" nil t)
558 (floor (string-to-number (match-string 1)))
559 (floor (string-to-number (match-string 2)))
560 (ceiling (string-to-number (match-string 3)))
561 (ceiling (string-to-number (match-string 4))))))
563 (- (aref bb 2) (aref bb 0))
564 (- (aref bb 3) (aref bb 1)))))))
566 (defun imaxima-eps-scale (file bb scale)
567 "Scale the eps image in FILE with factor SCALE.
568 BB is the bounding box of the image. Returns a list of new bounding
569 box, width, and height."
570 (multiple-value-bind (llx lly urx ury) (append bb nil)
571 (let ((x (round (* (- urx llx) scale)))
572 (y (round (* (- ury lly) scale)))
573 (buff (find-file-noselect file)))
575 (with-current-buffer buff
576 (goto-char (point-min))
577 (search-forward "%%BoundingBox")
578 (delete-region (line-beginning-position) (line-end-position))
579 (insert (format "%%%%BoundingBox: 0 0 %d %d\n" x y))
580 (search-forward "%%EndComments")
582 (insert "%%BeginProcSet: imaxima 1 0\ngsave\n")
583 (insert (format "%f %f translate\n"
586 (insert (format "%f %f scale\n" scale scale))
587 (insert "%%EndProcSet\n")
588 (goto-char (point-max))
589 (insert "\ngrestore\n")
592 (list (vector 0 0 x y) x y))))
594 (defun imaxima-latex ()
595 "Convert Maxima buffer to LaTeX.
596 This command does not work in XEmacs."
598 (let (pos2 label (pos (make-marker))
599 (buf (generate-new-buffer "*imaxima-latex*"))
600 (oldbuf (current-buffer)))
602 (insert-buffer oldbuf)
603 ;; ;; Remove copyright notice
604 ;; (goto-char (point-min))
605 ;; (search-forward "(%i1)" nil t 2)
606 ;; (search-backward "(%i1)" nil t)
607 ;; (delete-region (point-min) (point))
608 ;; (goto-char (point-min))
609 (insert "\\documentclass[leqno]{article}
610 \\usepackage{verbatim}
611 \\usepackage[cmbase]{flexisym}
614 \\setkeys{breqn}{compact}
616 \\setlength{\\textwidth}{180mm}
617 \\setlength{\\oddsidemargin}{15mm}
618 \\addtolength{\\oddsidemargin}{-1in}
619 \\setlength{\\evensidemargin}{15mm}
620 \\addtolength{\\evensidemargin}{-1in}
622 \\newcommand{\\ifrac}[2]{\\frac{#1}{#2}}
623 \\newcommand{\\ifracd}[2]{\\frac{#1}{#2}}
624 \\newcommand{\\ifracn}[2]{\\frac{#1}{#2}}
625 \\newcommand{\\isubscript}[2]{{#1}_{#2}}
626 \\newcommand{\\iexpt}[2]{{#1}^{#2}}
627 \\newcommand{\\isqrt}[1]{\\sqrt{#1}}
628 \\begin{document}\n")
629 ;; (while (and (not (eobp))
630 ;; (setq pos (next-single-property-change (point) 'display)))
632 ;; (insert "\\end{verbatim}\n\n")
633 ;; (setq pos (copy-marker (next-single-property-change (point) 'display)))
634 ;; (remove-text-properties (point) pos '(display nil))
635 ;; (setq pos2 (point))
636 ;; (re-search-forward "(\\([^)]*\\))")
637 ;; (setq label (match-string 1))
638 ;; (delete-region pos2 (point))
639 ;; (insert (format "\\begin{dmath}[number={%s}]\n" label))
641 ;; (insert "\\end{dmath}\n\n\\begin{verbatim}"))
642 ;; (goto-char (point-max))
643 ;; (insert "\n\\end{verbatim}\n\\end{document}")
645 (let* ((region-start (copy-marker (point)))
646 (region-end (copy-marker (next-single-property-change (point) 'display nil (point-max))))
647 (text-prop (get-text-property region-start 'display)))
650 (goto-char region-start)
651 (remove-text-properties region-start region-end '(display nil))
652 (goto-char region-end)
653 (goto-char region-start)
654 (re-search-forward "(\\([^)]*\\))")
655 (setq label (match-string 1))
656 (delete-region region-start (point))
657 (goto-char region-start)
658 (insert (format "\\begin{dmath}[number={%s}]\n" label))
659 (goto-char region-end)
660 (insert "\\end{dmath}\n\n"))
662 (goto-char region-start)
663 (insert "\\begin{verbatim}")
664 (goto-char region-end)
665 (insert "\\end{verbatim}\n\n")))))
666 (insert "\n\\end{document}")
667 (switch-to-buffer-other-window buf)
670 (defun imaxima-process-sentinel (process event)
671 "Process sentinel for Maxima process."
672 (message "Process %s %s" process event)
673 (unless (eq (process-status process) 'run)
676 (defun imaxima-ps-to-image (psfilename filename bb width height)
677 "Convert eps file PSFILENAME to a bitmap image file FILENAME.
678 BB is the bounding box for eps image. WIDTH and HEIGHT are the
679 dimensions of the image."
680 (setq imaxima-gs-computing-p t)
681 (when (eq system-type 'windows-nt)
682 (setq psfilename (imaxima-subst-char-in-string ?\\ ?/ psfilename))
683 (setq filename (imaxima-subst-char-in-string ?\\ ?/ filename)))
684 (process-send-string imaxima-gs-process
686 (if imaxima-gs-7.05-is-broken
687 "clear /imaxima-state save def \
688 << /PageSize [%d %d] /PageOffset [%d %d] /OutputFile (%s) >> \
689 setpagedevice (%s) run imaxima-state restore\n"
692 /PageSize [%d %d] /PageOffset [%d %d] /OutputFile (%s) \
693 >> setpagedevice [save] (%s) (r) file cvx \
694 systemdict /.runandhide known revision 700 ge and {.setsafe {.runandhide}} if \
695 stopped {handleerror quit} if count 1 ne {quit} if \
696 cleardictstack 0 get restore\n")
705 (defun imaxima-check-plot-output (str)
706 "If the str is in the form ^Wpompt^W\\verb|plotfile filename|, then
707 filename is returned. Else, nil is returned."
708 ;; (if (string-match "\x17[^\x17]*\x17\\\\mathrm{wxxmltag}\\\\left\(\\\\verb|\\([^|]*\\)|.*" str)
709 ;; (if (string-match "\x17[^\x17]*\x17\\\\mathrm{wxxmltag}\\\\left[^/]*\\(.*\.eps\\).*" str)
710 ;; (if (string-match "\x17[^\x17]*\x17\\\\mathrm{wxxmltag}\\\\left\(\\\\verb|*\\(.*\.eps\\).*" str)
711 (if (string-match "\x17[^\x17]*\x17\\\\mathrm{wxxmltag}\\\\left\(\\(\\\\verb|\\)*\\(.*\.eps\\).*" str)
715 (defun imaxima-make-image (str eps-or-latex &optional no-label-p)
716 "Make image from STR. If no-label-p is specified t,
717 label becomes nil and passed to imaxima-tex-to-dvi."
718 (let ((res (imaxima-check-plot-output str)))
723 (let* ((filename (expand-file-name
724 (number-to-string (incf imaxima-file-counter))
726 (psfilename (concat filename ".ps"))
729 (cond ((eql eps-or-latex 'latex)
730 (when (string-match "\\(\x17\\([^\x17]*\\)\x17\\)" str)
731 (setq label (match-string 2 str))
732 (setq str (replace-match "" t t str 1)))
733 (if no-label-p (setq label nil)) ;; override label to nil if no-label-p
734 (imaxima-tex-to-dvi str label (concat filename ".tex"))
735 (imaxima-dvi-to-ps filename)
737 ((eql eps-or-latex 'eps)
738 (copy-file str psfilename)
742 (if (not (file-exists-p psfilename))
743 (imaxima-latex-error str filename)
744 (multiple-value-bind (bb width height)
745 (imaxima-extract-bb psfilename)
746 (let ((ratio (/ (imaxima-get-window-width)
747 (imaxima-bp-to-mm width))))
749 ;; image is wider than the buffer
750 (if (or (eql eps-or-latex 'eps)
751 (and imaxima-max-scale
752 (or (eq imaxima-max-scale t)
753 (> ratio imaxima-max-scale))))
755 (multiple-value-setq (bb width height)
756 (imaxima-eps-scale psfilename bb ratio))
757 (when imaxima-linearize-flag
759 (imaxima-tex-to-dvi str label (concat filename ".tex") t)
760 (imaxima-dvi-to-ps filename)
761 (multiple-value-setq (bb width height)
762 (imaxima-extract-bb psfilename))))))
763 (unless (eq imaxima-image-type 'postscript)
764 (imaxima-ps-to-image psfilename filename bb width height))
765 (cond ((featurep 'xemacs)
766 (when (eq system-type 'windows-nt)
767 ;;(setq filename (imaxima-subst-char-in-string ?\\ ?/ filename))
769 ;; Ghostscript on Windows doesn't flush the image to the file.
770 ;; So we have to kill the process and restart. What a kludge!
771 (kill-process imaxima-gs-process)
773 (xemacs-set-imagefile-properties filename imaxima-image-type str))
775 (propertize (concat "(" label ") " str) 'display
776 (if (eq imaxima-image-type 'postscript)
777 (create-image psfilename
779 :pt-width width :pt-height height
780 :bounding-box bb :ascent 'center
781 :mask '(heuristic (color-values imaxima-bg-color)))
782 (create-image filename
783 imaxima-image-type nil
786 (color-values imaxima-bg-color)))))))))))
789 (defun imaxima-latex-error (str filename)
790 "Make clickable error message.
791 STR is offending LaTeX expression. FILENAME is name of the LaTeX file."
792 (let* ((msg "LaTeX error in: ")
793 (delim (if (featurep 'xemacs)
797 (error-text (concat "mouse-2: view LaTeX error log" delim
798 "mouse-3: view LaTeX source")))
799 (fset 'imaxima-error-2
802 (view-file-other-window (concat ,filename ".log"))))
803 (fset 'imaxima-error-3
806 (view-file-other-window (concat ,filename ".tex"))))
807 (define-key imaxima-error-map imaxima-mouse2 'imaxima-error-2)
808 (define-key imaxima-error-map [(return)] 'imaxima-error-2)
809 (define-key imaxima-error-map imaxima-mouse3 'imaxima-error-3)
810 (define-key imaxima-error-map [(meta return)] 'imaxima-error-3)
811 (set-text-properties 0 14 `(face imaxima-latex-error-face
813 help-echo ,error-text
814 keymap ,imaxima-error-map)
819 (defun imaxima-dump-tex ()
820 "Dump a TeX format file preloaded with the required packages."
821 (with-temp-file (expand-file-name "mylatex.ltx" imaxima-tmp-subdir)
822 (insert imaxima-mylatex))
823 (with-temp-file (expand-file-name "format.tex" imaxima-tmp-subdir)
826 (format "\\documentclass[%dpt,leqno]{article}\n" imaxima-pt-size)
827 imaxima-latex-preamble
828 "\\usepackage{color}\n"
829 "\\usepackage{exscale}\n"
830 "\\usepackage[cmbase]{flexisym}\n"
831 "\\usepackage{breqn}\n"
832 "\\setkeys{breqn}{compact}\n"
833 "\\setlength{\\textheight}{200cm}\n"
834 ;; define \boxed from amsmath.sty
836 \\providecommand\\boxed{}
837 \\providecommand\\operatorname{}
838 \\renewcommand{\\boxed}[1]{\\fbox{\\m@th$\\displaystyle#1$}}
839 \\renewcommand{\\operatorname}[1]{%
840 \\mathop{\\relax\\kern\\z@\\operator@font{#1}}}
842 \\newcommand{\\ifrac}[2]{\\frac{#1}{#2}}
843 \\newcommand{\\ifracd}[2]{\\frac{#1}{#2}}
844 \\newcommand{\\ifracn}[2]{\\frac{#1}{#2}}
845 \\newcommand{\\isubscript}[2]{{#1}_{#2}}
846 \\newcommand{\\iexpt}[2]{{#1}^{#2}}
847 \\newcommand{\\isqrt}[1]{\\sqrt{#1}}\n
851 (imaxima-with-temp-dir
853 (apply 'call-process imaxima-tex-program nil nil nil
854 (list imaxima-initex-option "&latex" "mylatex.ltx" "format"))))
855 ;; (format "\\input{%s}" "format.tex")))))
857 (defun imaxima-tex-to-dvi (str label filename &optional linear)
859 Argument LABEL is used as equation label. FILENAME is used for
860 temporary files. Use linearized form if LINEAR is non-nil."
861 (with-temp-file filename
864 (format "\\documentclass[%dpt,leqno]{article}\n" imaxima-pt-size)
866 (format "\\setlength{\\textwidth}{%dmm}\n"
867 (round (/ (imaxima-get-window-width)
868 imaxima-scale-factor)))
871 ;; braces in both denominator and numerator
872 "\\renewcommand{\\ifrac}[2]{\\left(#1\\right)/\\left(#2\\right)}"
873 ;; only braces denominator
874 "\\renewcommand{\\ifracd}[2]{#1/\\left(#2\\right)}"
875 ;; only braces in numerator
876 "\\renewcommand{\\ifracn}[2]{\\left(#1\\right)/#2}"
877 "\\renewcommand{\\isubscript}[2]{\\mathrm{subscript}\\left(#1,#2\\right)}"
878 "\\renewcommand{\\iexpt}[2]{\\mathrm{expt}\\left(#1,#2\\right)}"
879 "\\renewcommand{\\isqrt}[1]{\\left(#1\\right)^{1/2}}\n")
881 "\\begin{document}\n"
882 (apply 'format "\\pagecolor[rgb]{%f,%f,%f}"
883 (imaxima-color-to-rgb (imaxima-get-bg-color)))
884 "\\pagestyle{empty}\n"
885 (format "\\begin{%s}\n" imaxima-fnt-size)
886 (apply 'format "\\color[rgb]{%f,%f,%f}"
887 (imaxima-color-to-rgb imaxima-label-color))
891 (format "\\begin{dmath}[number={%s}]\n" label)
892 (apply 'format "\\color[rgb]{%f,%f,%f}"
893 (imaxima-color-to-rgb imaxima-equation-color))
894 str (format "\\end{dmath}\n"))
896 (apply 'format "\\color[rgb]{%f,%f,%f}"
897 (imaxima-color-to-rgb imaxima-equation-color))
898 "\\begin{math} \\displaystyle " str (format " \\end{math}\n")))
899 (format "\\end{%s}\n" imaxima-fnt-size)
901 (imaxima-with-temp-dir imaxima-tmp-subdir
902 (apply 'call-process imaxima-tex-program nil nil nil
903 (list "&mylatex" filename))))
905 (defun imaxima-dvi-to-ps (filename)
906 "Convert dvi file FILENAME to PostScript."
907 (let ((dvips-args (append
908 imaxima-dvips-options
909 (list "-x" (format "%s" (* imaxima-scale-factor 1000))
910 "-y" (format "%s" (* imaxima-scale-factor 1000))
911 (concat filename ".dvi") "-o"))))
912 (imaxima-with-temp-dir imaxima-tmp-subdir
913 (apply 'call-process imaxima-dvips-program nil nil nil dvips-args))))
915 (defun imaxima-clean-up ()
916 "Kill gs process, delete temporary files and restore colors if applicable."
919 (kill-process imaxima-gs-process))
920 (mapc 'delete-file (directory-files imaxima-tmp-subdir t "^[^.].*"))
921 (delete-directory imaxima-tmp-subdir)
922 (if (featurep 'xemacs)
923 (ad-deactivate 'comint-output-filter)
924 ;; restore frame colors in Emacs
925 (when imaxima-fg-color
926 (modify-frame-parameters
927 nil (list (cons 'foreground-color imaxima-old-fg-color))))
928 (when imaxima-bg-color
929 (modify-frame-parameters
930 nil (list (cons 'background-color imaxima-old-bg-color)))))
931 (run-hooks 'imaxima-exit-hook))
933 ;;; Continuation is used between maxima-to-latex function and
934 ;;; get-image-from-imaxima. The value is either nil or a list of
935 ;;; function, buffer, pos1, and pos2, where pos1 and pos2 are the beginning and
936 ;;; end of current maxima formula.
937 ;; (func buffer pos1 pos2)
939 (defvar continuation nil)
941 ;;; if *debug-imaxima-filter* is set to t, the str is
942 ;;; appended to the last of buffer *imaxima-work*.
943 (defvar *debug-imaxima-filter* nil)
945 (defun debug-imaxima-filter (str)
946 (if *debug-imaxima-filter*
947 (with-current-buffer (get-buffer-create "*imaxima-work*")
950 (defvar imaxima-filter-running nil)
952 (defun* imaxima-filter (str)
953 "Parse output from Maxima and make image from TeX parts.
954 Argument STR contains output received from Maxima.
956 imaxima-filter needs to be written in re-entrant manner.
957 This is because during the creation of latex image, there
958 observed a reentrant call of imaxima-filter. yhonda"
959 (if imaxima-filter-running
961 (setq imaxima-output (concat imaxima-output str))
962 (debug-imaxima-filter "reenter")
963 (return-from imaxima-filter "")))
964 (setq imaxima-filter-running t)
965 (debug-imaxima-filter str)
966 (let* ((len (length str))
970 (setq imaxima-filter-running nil)
971 (return-from imaxima-filter ""))
972 (setq imaxima-output (concat imaxima-output str))
973 (let ((lastchar (aref str (1- len)))
975 (when (and (char-equal lastchar ?\n) (> len 1))
976 (setq lastchar (aref str (- len 2))))
978 (message "Processing Maxima output...")
979 (while (not (string= imaxima-output ""))
980 (let ((1stchar (substring imaxima-output 0 1)))
981 (cond ((string= 1stchar "\x03")
982 (if (string-match "\x03\\([^\x03\x04]*\\)\x04\\(\\(.\\|\n\\)*\\)" imaxima-output)
983 (let ((iprompt (match-string 1 imaxima-output))
984 (rest (match-string 2 imaxima-output)))
985 (setq imaxima-output rest)
986 (setq output (concat output iprompt))
987 ;; All the output for a maxima command are processed.
988 ;; We can call continuation if necessary.
989 (cond ((and continuation main-output)
990 (funcall (car continuation) main-output))
991 ((and continuation (null main-output))
992 (funcall (car continuation) ""))))
993 ;; imaxima-output is incomplete.
994 (setq imaxima-filter-running nil)
995 (return-from imaxima-filter output)))
996 ((string= 1stchar "\x02")
997 (if (string-match "\x02\\([^\x02\x05]*\\)\x05\\(\\(.\\|\n\\)*\\)" imaxima-output)
998 (let ((match (match-string 1 imaxima-output))
999 (rest (match-string 2 imaxima-output))
1001 (setq imaxima-output rest)
1002 (setq output (concat output (setq image (imaxima-make-image match 'latex))))
1003 ;; Remember the image into main-output if this is the first output.
1004 ;; This will be passed to continuation
1005 (if (null main-output)
1006 (setq main-output image)))
1007 ;; imaxima-output is incomplete.
1008 (setq imaxima-filter-running nil)
1009 (return-from imaxima-filter output)))
1010 ((string= 1stchar "\x15")
1011 (if (string-match "\x15\\([^\x15\x16]*\\)\x16\\(\\(.\\|\n\\)*\\)" imaxima-output)
1012 (let ((match (match-string 1 imaxima-output))
1013 (rest (match-string 2 imaxima-output)))
1014 (setq imaxima-output rest)
1015 (setq output (concat output (imaxima-make-image match 'latex))))
1016 ;; imaxima-output is incomplete.
1017 (setq imaxima-filter-running nil)
1018 (return-from imaxima-filter output)))
1019 (t (if (string-match "\\([^\x02\x03\x15]*\\)\\(\\(.\\|\n\\)*\\)" imaxima-output)
1020 (let ((match (match-string 1 imaxima-output))
1021 (rest (match-string 2 imaxima-output)))
1022 (setq imaxima-output rest)
1023 (setq output (concat output match)))
1024 ;; This should not happen.
1025 (message "Unexpected error encountered in imaxima-filter"))))))
1026 (message "Processing Maxima output...done")
1027 (setq imaxima-filter-running nil)
1028 (return-from imaxima-filter output)))))
1030 (defun imaxima-filter1 (str)
1031 "Parse output from Maxima and make image from TeX parts.
1032 Argument STR contains output received from Maxima."
1033 (if *debug-imaxima-filter*
1034 (with-current-buffer (get-buffer-create "*imaxima-work*")
1035 (insert "****new string****
1038 (let* ((len (length str)))
1041 (setq imaxima-output (concat imaxima-output str))
1042 (let ((lastchar (aref str (1- len))))
1043 (when (and (char-equal lastchar ?\n) (> len 1))
1044 (setq lastchar (aref str (- len 2))))
1047 ((string-match "\\`[^\x02\x05\x03\x04\x15\x16]+\\'" imaxima-output)
1048 (prog1 imaxima-output
1049 (setq imaxima-output "")))
1050 ((or (char-equal lastchar ?\x04) (char-equal lastchar ?\x05))
1055 (rest imaxima-output)
1057 (message "Processing Maxima output...")
1058 (if (string-match "\\([^\x03\x04]*\\)\x03\\([^\x03\x04]*\\)\x04$" imaxima-output)
1059 (setq prompt (concat "" (match-string 2 imaxima-output))
1060 rest (match-string 1 imaxima-output)))
1061 (while (string-match "\\(\\([^\x02\x05]*\\)\x02\\([^\x02\x05]*\\)\x05\\)"
1063 (setq text (match-string 2 rest))
1064 (setq match (match-string 3 rest))
1065 (setq rest (replace-match "" t t rest 1))
1066 (setq output (concat output (if (equal output "") "" newline-char) text (imaxima-make-image match 'latex))))
1067 (setq imaxima-output "")
1068 (message "Processing Maxima output...done")
1070 (funcall (car continuation) output))
1071 (concat output rest prompt)))
1072 ;; Special prompt for demo() function.
1074 ((char-equal lastchar ?_)
1075 (let ((newline-char "
1078 (rest (substring imaxima-output 0 -1))
1080 (message "Processing Maxima output...")
1081 (while (string-match "\\(\\([^\x02\x05]*\\)\x02\\([^\x02\x05]*\\)\x05\\)"
1083 (setq text (match-string 2 rest))
1084 (setq match (match-string 3 rest))
1085 (setq rest (replace-match "" t t rest 1))
1086 (setq output (concat output (if (equal output "") "" newline-char) text (imaxima-make-image match 'latex))))
1087 (setq imaxima-output "")
1088 (message "Processing Maxima output...done")
1090 (funcall (car continuation) output))
1091 (concat " " output rest newline-char "_")))
1092 ;; Special prompt, question.
1093 ((char-equal lastchar ?\x16)
1094 (string-match "\x15\\([^\x16]*\\)\x16" imaxima-output)
1095 (prog1 (imaxima-make-image (match-string 1 imaxima-output) 'latex)
1096 (setq imaxima-output "")))
1099 (defun xemacs-set-imagefile-properties (filename img-type str)
1100 (let ((ext (make-extent 0 (length str) str)))
1101 (set-extent-property ext 'duplicable t)
1102 (set-extent-end-glyph ext
1103 (make-glyph (vector img-type
1105 (set-extent-property ext 'invisible t)
1106 (set-extent-property ext 'atomic t))
1113 (defun imaxima-setup-preoutput-filter ()
1114 "Set up `comint-preoutput-filter-functions' or the equivalent."
1115 (cond ((featurep 'xemacs)
1116 ;; XEmacs does not have comint-preoutput-filter-functions, so
1117 ;; we have to advice comint-output-filter instead
1118 (defadvice comint-output-filter (before preoutput-filter)
1119 "Run comint-preoutput-filter-functions."
1120 (ad-set-arg 1 (imaxima-filter (ad-get-arg 1))))
1121 (ad-activate 'comint-output-filter))
1123 (make-local-variable 'comint-preoutput-filter-functions)
1124 ;; This doesn't work due to a bug in comint.el
1125 ;; (add-hook 'comint-preoutput-filter-functions 'imaxima-filter nil t)
1126 (add-hook 'comint-preoutput-filter-functions 'imaxima-filter t))))
1128 (defun imaxima-change-color (buf)
1129 "Change background and foreground color if applicable.
1130 BUF is imaxima buffer."
1133 (when imaxima-bg-color
1134 (set-face-background 'default imaxima-bg-color buf))
1135 (when imaxima-fg-color
1136 (set-face-foreground 'default imaxima-fg-color buf)))
1138 (when imaxima-bg-color
1139 (setq imaxima-old-bg-color (frame-parameter nil 'background-color))
1140 (modify-frame-parameters
1141 nil (list (cons 'background-color imaxima-bg-color))))
1142 (when imaxima-fg-color
1143 (setq imaxima-old-fg-color (frame-parameter nil 'foreground-color))
1144 (modify-frame-parameters
1145 nil (list (cons 'foreground-color imaxima-fg-color)))))))
1147 (defun imaxima-setup ()
1148 "Image support for maxima.el."
1149 (let ((mbuf (process-buffer inferior-maxima-process)))
1150 (with-current-buffer mbuf
1151 (imaxima-change-color mbuf)
1152 (imaxima-get-geometry mbuf)
1154 (unless (eq imaxima-image-type 'postscript)
1156 (add-hook 'kill-buffer-hook 'imaxima-clean-up t t)
1157 (imaxima-setup-preoutput-filter)
1158 (maxima-single-string
1159 ;; (format "?load(?subseq(?symbol\\-name(\"%s\"), 1));\n" imaxima-lisp-file))
1160 (format "block(load((\"%s\")), linenum:0)$\n" imaxima-lisp-file))
1161 ;; maxima mode tries to run inferior-maxima-mode-hook twice
1162 ;; due to changes made in 5.9.2 release. To prevent this,
1163 ;; the following hook must be removed earlier than before.
1165 (remove-hook 'inferior-maxima-mode-hook 'imaxima-setup)
1166 (goto-char (point-max)))))
1168 (defun* imaxima-delete-maxima-hooks ()
1169 (remove-hook 'comint-output-filter-functions 'inferior-maxima-output-filter)
1170 (remove-hook 'comint-output-filter-functions 'inferior-maxima-remove-double-input-prompt)
1171 (remove-hook 'comint-output-filter-functions 'inferior-maxima-remove-double-prompt))
1174 "Image support for Maxima.
1175 \"display2d:true\" in Maxima turns images off, \"display2d:imaxima\"
1176 turns them on. Set `imaxima-use-maxima-mode-flag' to t to use
1179 (if (not window-system)
1180 (error "Emacs in terminal is not supported by Imaxima. You need to run Emacs in a window system, such as X window, Mac OS X, and Microsoft Windows OS."))
1181 (let ((imaxima-buffer))
1182 (setq imaxima-buffer
1183 (get-buffer (if imaxima-use-maxima-mode-flag
1186 (when imaxima-buffer
1188 (switch-to-buffer imaxima-buffer)
1189 (set-buffer imaxima-buffer))
1190 (return-from imaxima t)))
1192 (unless (imaxima-image-type-available-p imaxima-image-type)
1193 (error "Your version of Emacs does not support the image type %s"
1194 imaxima-image-type))
1195 (unless imaxima-lisp-file
1196 (error "The file imaxima.lisp could not be found.
1197 Please customize the option `imaxima-lisp-file'."))
1198 (setq imaxima-file-counter 0)
1200 (setq imaxima-tmp-subdir
1201 (make-temp-name (expand-file-name "imaxima" imaxima-tmp-dir))) t)
1202 (set-file-modes imaxima-tmp-subdir 448) ; 700 in octal
1203 (let ((process-connection-type process-connection-type-flag))
1204 (if imaxima-use-maxima-mode-flag
1207 (setq inferior-maxima-prompt
1208 (concat "\\(^ ?(" maxima-inchar
1209 "[0-9]*) \\)\\|\\(^MAXIMA>+\\)\\|\\(^(dbm:[0-9]*) \\)"))
1210 (add-hook 'inferior-maxima-mode-hook 'imaxima-setup t)
1212 (remove-hook 'inferior-maxima-mode-hook 'imaxima-setup))
1213 (imaxima-delete-maxima-hooks)
1214 (setq imaxima-output "")
1218 imaxima-maxima-program
1221 imaxima-maxima-options))))
1224 (setq imaxima-process (get-buffer-process mbuf))
1225 (imaxima-get-geometry mbuf)
1226 (imaxima-change-color mbuf)
1228 (set-process-sentinel imaxima-process 'imaxima-process-sentinel)
1229 (imaxima-setup-preoutput-filter)
1230 (unless (eq imaxima-image-type 'postscript)
1231 (imaxima-start-gs)))
1232 (when (eq system-type 'windows-nt)
1235 (format "block(load(\"%s\"), linenum:0)$\n" imaxima-lisp-file)))
1236 (switch-to-buffer mbuf))))
1237 (run-hooks 'imaxima-startup-hook))
1239 (defcustom imaxima-print-tex-file "imax"
1240 "Name of the LaTeX file name to be created by `imaxima-print-buffer'.
1241 Do not include \".tex\" suffix. This file will be stored in the
1242 directory `imaxima-temp-dir'."
1246 (defcustom imaxima-print-tex-command
1247 "latex %s; dvips -o imax.ps %s; gv imax.ps"
1248 ;;"latex %s; xdvi %s"
1249 ;;"latex %s; dvipdf %s.dvi imax.pdf; open imax.pdf" for Mac OS X users.
1250 "Command to run LaTeX on the file created by `imaxima-print-buffer'.
1251 In the string %s is replaced by the name of the tex file. e.g.
1252 \"latex %s; xdvi %s\"
1257 (defun imaxima-print-buffer ()
1258 "Run LaTeX on the current buffer and show output.
1259 See `imaxima-print-tex-command' for how latex is run on the latex output."
1261 (let (( tex-file (concat imaxima-tmp-dir
1262 imaxima-print-tex-file ".tex"))
1268 (write-file tex-file)
1269 (setq buf (current-buffer))
1271 ;; Convert all %s into the tex file name.
1272 (setq cmd imaxima-print-tex-command)
1273 (while (string-match "%s" cmd)
1274 (setq cmd (replace-match imaxima-print-tex-file t nil cmd)))
1277 (kill-buffer buf) ;kill the temp tex buffer
1281 ;;; The following codes implements export imath text to HTML.
1283 (defvar html-template
1286 <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; CHARSET=UTF-8\">
1296 (defun* prepare-for-translation ()
1297 "If error occurs inside this function, multiple values nil nil
1301 (let (original-buffer text current-buffer-file-name filename image-folder html-buffer)
1302 (setq original-buffer (current-buffer))
1303 (setq text (buffer-substring (point-min) (point-max)))
1304 (if (or (string= (buffer-name original-buffer)
1306 (string= (buffer-name original-buffer)
1309 (setq current-buffer-file-name "")
1310 (setq filename (concat imaxima-html-dir "session.html"))
1311 (setq image-folder "session-images"))
1312 (setq current-buffer-file-name
1313 (if (buffer-file-name)
1315 (return-from prepare-for-translation (values nil nil))))
1316 (setq filename (concat (file-name-sans-extension
1317 (file-name-nondirectory current-buffer-file-name))
1319 (setq image-folder (concat (file-name-sans-extension
1320 (file-name-nondirectory current-buffer-file-name))
1322 ;; HTML buffer preparation
1323 (setq html-buffer (find-file filename))
1324 (set-buffer html-buffer)
1325 ;; create image folder
1327 (if (file-exists-p image-folder)
1328 ;; since image-folder already exists, let's reuse it.
1332 (setq old-files (directory-files image-folder nil "\\.png$"))
1333 ;; we need to delete all the files already there.
1334 (dolist (f old-files)
1335 (delete-file (concat image-folder "/" f))))
1336 (file-error (return-from prepare-for-translation (values nil nil)))))
1337 ;; since image-folder doest not exist, let's create it.
1339 (make-directory image-folder)
1340 (file-error (return-from prepare-for-translation (values nil nil))))))
1341 ;; buffer preparation
1342 (if buffer-read-only
1343 (return-from prepare-for-translation (values nil nil)))
1345 (insert html-template)
1346 (goto-char (point-min))
1347 (search-forward "<BODY>")
1350 (values html-buffer image-folder))))
1352 (defun* imath-to-html()
1353 "Translate imath minor mode buffer contents into HTML format."
1356 (multiple-value-bind (html-buffer image-folder)
1357 (prepare-for-translation)
1358 (if (not (and html-buffer image-folder))
1360 (message "Error during HTML buffer preparation.")
1361 (return-from imath-to-html)))
1362 (set-buffer html-buffer)
1363 (goto-char (point-min))
1366 (multiple-value-bind (ftype start-pos end-pos)
1368 (if (not (and ftype start-pos end-pos))
1370 (let (filename dest-name)
1371 ;; copy image file to image sub folder
1372 (if (null (setq filename (get-image-filename (1- (point)))))
1374 (message "Error: all formulas must be converted to images first.")
1375 (return-from imath-to-html)))
1376 (setq dest-name (concat
1378 (file-name-sans-extension
1379 (file-name-nondirectory filename))
1382 (copy-file filename dest-name)
1383 ;; replace imath formula with HTML IMG tag
1384 (delete-region start-pos end-pos)
1385 (insert (concat "<IMG SRC=\""
1387 "\" style=\"vertical-align:middle;\"> "))))))
1388 ;; "\" align=\"middle\"> "))))))
1392 (message "Error: File manipulation failed during processing.")
1393 (return-from imath-to-html))))
1395 (let (start-mark end-mark)
1396 (goto-char (point-min))
1397 (search-forward "<BODY>")
1400 (setq start-mark (point-marker))
1401 (search-forward "</BODY>")
1402 (setq end-mark (point-marker))
1403 (goto-char start-mark)
1405 (re-search-forward "$" end-mark)
1406 (replace-match "<br>\n")
1408 (search-failed nil)))))
1410 (defun* imaxima-to-html ()
1411 "Translate the imaxima buffer contents into HTML format."
1415 (defun* original-find-next-formula ()
1416 "Find next formula and return multiple values of
1417 formula type, start position and end position.
1418 If search failed, error search-failed is signaled."
1420 (let (start-pos end-pos tmp found-string ftype)
1421 (re-search-forward (concat maxima-start "\\|" latex-start))
1422 (setq found-string (match-string 0))
1423 (cond ((string= found-string latex-start)
1424 (setq start-pos (- (point) (length latex-start)))
1425 (search-forward latex-end)
1426 (setq end-pos (point) ftype 'latex))
1427 ((string= found-string maxima-start)
1428 (setq start-pos (- (point) (length maxima-start)))
1429 (search-forward maxima-end)
1431 (if (string= (buffer-substring tmp
1433 (length latex-start)))
1434 (concat "&" latex-start))
1436 (search-forward latex-end)
1437 (setq end-pos (point) ftype 'both))
1438 (setq end-pos tmp ftype 'maxima)))
1439 (t (error "Syntax Error in Imath buffer.")))
1440 (values ftype start-pos end-pos)))
1442 (defun* find-next-formula ()
1443 "Find next formula and return multiple values of
1444 formula type, start position and end position.
1445 If search failed, error search-failed is signaled."
1447 (if (equal (point) (point-max))
1448 (return-from find-next-formula (values nil nil nil)))
1449 (let* ((region-start (copy-marker (point)))
1450 (region-end (copy-marker (next-single-property-change (point) 'display nil (point-max))))
1451 (text-prop (get-text-property region-start 'display)))
1452 (goto-char region-end)
1454 (return-from find-next-formula (values 'any region-start region-end))
1455 (find-next-formula))))
1459 (defun* get-image-filename (pos)
1460 "If the pos of the buffer is associated with text a display property,
1461 it is obtained. Then image filename of the display property is
1462 extracted and returned."
1467 (if (setq filename (memq :file (get-text-property pos 'display)))
1468 (second filename))))
1472 ;;; imaxima.el ends here