;;; w3-latex.el --- Emacs-W3 printing via LaTeX ;;; Last edited on DATE TIME by USER ;; Author: wmperry ;; Created: 1996/06/30 18:08:34 ;; Version: 1.3 ;; See the legal garbage at the end of this file. Hang the lawyers. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Elisp code to convert a W3 parse tree into a LaTeX buffer. ;;; ;;; Heavily hacked upon by William Perry to add more ;;; bells and whistles. ;;; ;;; KNOWN BUGS: ;;; 1) This does not use stylesheets to get the formatting information ;;; 2) This means that the new drawing routines need to be abstracted ;;; further so that the same main engine can be used for either ;;; text-output (standard stuff in w3-draw), LaTeX output (this file), ;;; Postscript (to-be-implemented), etc., etc. ;;; 3) This still doesn't handle tables. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (require 'w3-cus) (require 'w3-print) ;; Internal variables - do not touch! (defvar w3-latex-current-url nil "What URL we are formatting") (defvar w3-latex-verbatim nil "Whether we are in a {verbatim} block or not") (defvar w3-latex-links-list nil "List of links for endnote usage") (defvar w3-latex-entities '((nbsp . "~") (iexcl . "!`") ; (cent . "") (pound . "\\pounds ") ; (curren . "") ; (yen . "") (brvbar . "|") (sect . "\\S") (uml . "\\\"{ }") (copy . "\\copyright ") ; (ordf . "") (laquo . "$\\ll$") (not . "\\neg") (shy . "-") (reg . "(R)") (macr . "\\={ }") (deg . "$\\deg$") (plusmn . "$\\pm$") (sup2 . "$^{2}$") (sup3 . "$^{3}$") (acute . "\\'{ }") (micro . "$\\mu$") (para . "\\P ") (middot . "$\\cdot$") (cedil . "\\c{ }") (sup1 . "$^{1}$") ; (ordm . "") (raquo . "$\\gg$") (frac14 . "$\frac{1}{4}$") (frac12 . "$\frac{1}{2}$") (frac34 . "$\frac{3}{4}$") (iquest . "?`") (Agrave . "\\`{A}") (Aacute . "\\'{A}") (Acirc . "\\^{A}") (Atilde . "\\~{A}") (Auml . "\\\"{A}") (Aring . "\\AA ") (AElig . "\\AE ") (Ccedil . "\\c{C}") (Egrave . "\\`{E}") (Eacute . "\\'{E}") (Ecirc . "\\^{E}") (Euml . "\\\"{E}") (Igrave . "\\`{I}") (Iacute . "\\'{I}") (Icirc . "\\^{I}") (Iuml . "\\\"{I}") ; (ETH . "") (Ntilde . "\\~{N}") (Ograve . "\\`{O}") (Oacute . "\\'{O}") (Ocirc . "\\^{O}") (Otilde . "\\~{O}") (Ouml . "\\\"{O}") (times . "$\\times$") (Oslash . "\\O") (Ugrave . "\\`{U}") (Uacute . "\\'{U}") (Ucirc . "\\^{U}") (Uuml . "\\\"{U}") (Yacute . "\\'{Y}") ; (THORN . "") (szlig . "\\ss ") (agrave . "\\`{a}") (aacute . "\\'{a}") (acirc . "\\^{a}") (atilde . "\\~{a}") (auml . "\\\"{a}") (aring . "\\aa ") (aelig . "\\ae ") (ccedil . "\\c{c}") (egrave . "\\`{e}") (eacute . "\\'{e}") (ecirc . "\\^{e}") (euml . "\\\"{e}") (igrave . "\\`{i}") (iacute . "\\'{i}") (icirc . "\\^{i}") (iuml . "\\\"{i}") ; (eth . "") (ntilde . "\\~{n}") (ograve . "\\`{o}") (oacute . "\\'{o}") (ocirc . "\\^{o}") (otilde . "\\~{o}") (ouml . "\\\"{o}") (divide . "$\\div$") (oslash . "\\o") (ugrave . "\\`{u}") (uacute . "\\'{u}") (ucirc . "\\^{u}") (uuml . "\\\"{u}") (yacute . "\\'{y}") ; (thorn . "") (yuml . "\\\"{y}")) "Defines mappings between `w3-html-entities' and LaTeX characters.") (defun w3-latex-replace-entities (str) (let ((start 0)) (while (string-match "[\200-\377]" str start) ; get the character code, and then search for a match in ; w3-html-entities. If one is found, use it to perform a lookup ; in w3-latex-entities, and use the resulting match to replace ; the character. (let* ((match (rassq (aref str (match-beginning 0)) w3-html-entities)) (replace (and match (assq (car match) w3-latex-entities)))) (if replace (setq str (replace-match (cdr replace) t t str))) (setq start (match-end 0)))) str)) (defun w3-latex-insert-string (str) ;;; convert string to a LaTeX-compatible one. (let ((todo (list (cons "\\\\" "-BaCkSlAsH-") (cons "[%&#_{}$]" "\\\\\\&") (cons "\\^" "{\\\\textasciicircum}") (cons "~" "{\\\\textasciitilde}") (cons "[*]" "{\\&}") (cons "[><|]" "$\\&$") (cons "-BaCkSlAsH-" "$\\\\backslash$")))) (if w3-latex-verbatim (setq todo (append todo '(("\n" . "\\\\newline\\\\nullspace\n") (" " . "\\\\ "))))) (save-excursion (set-buffer (get-buffer-create " *w3-latex-munging*")) (erase-buffer) (insert str) (while todo (goto-char (point-min)) (while (re-search-forward (caar todo) nil t) (replace-match (cdar todo))) (setq todo (cdr todo))) (setq str (w3-latex-replace-entities (buffer-string)))) (insert str))) (defun w3-latex-ignore (tree) ;;; ignores any contents of this tree. nil) (defun w3-latex-contents (tree) ;;; passes contents of subtree through to the latex-subtree (let ((contents (car (cdr (cdr tree))))) (while contents (w3-latex-subtree (car contents)) (setq contents (cdr contents))))) (defun w3-latex-html (tree) (insert "% This document automatically generated by Emacs-W3 v" w3-version-number "\n") (if w3-latex-current-url (insert "% from \n")) (insert "%\n" "\\batchmode\n\\begin{document}\n") (insert "\\setlength{\\parindent}{0pt}\n" "\\setlength{\\parskip}{1.5ex}\n") (insert "\\newcommand{\\nullspace}{\\rule{0pt}{0pt}}") (w3-latex-contents tree) (if w3-latex-links-list (w3-latex-endnotes)) (insert "\\end{document}\n")) (defun w3-latex-title (tree) (if w3-latex-use-maketitle (insert "\\title{") (insert "\\section*{\\centering ")) (w3-latex-contents tree) (insert "}\n") (if w3-latex-use-maketitle (insert "\\author{}\\date{}\n\\maketitle"))) (defun w3-latex-heading (tree) ;; look through the additional markup to see if an align=right or ;; align=center is in here... (let ((align (assq 'align (car (cdr tree)))) (sym (car tree))) (insert "\n\n") (cond ((and align (string-equal (cdr align) "center")) (insert "\\begin{center}\n")) ((and align (string-equal (cdr align) "right")) (insert "\\begin{flushright}\n"))) (cond ((eq sym 'h1) (insert "\\section*{")) ((eq sym 'h2) (insert "\\subsection*{")) ((eq sym 'h3) (insert "\\subsubsection*{")) ((eq sym 'h4) (insert "\\subsubsection*{")) ((eq sym 'h5) (insert "\\paragraph*{")) ((eq sym 'h6) (insert "\\subparagraph*{"))) (w3-latex-contents tree) (insert "}\n") (cond ((and align (string-equal (cdr align) "center")) (insert "\\end{center}\n")) ((and align (string-equal (cdr align) "right")) (insert "\\end{flushright}\n"))))) (defun w3-latex-bold (tree) (insert "{\\bf ") (w3-latex-contents tree) (insert "}")) (defun w3-latex-italic (tree) (insert "{\\em ") (w3-latex-contents tree) (insert "}")) (defun w3-latex-typewriter (tree) (insert "{\\tt ") (w3-latex-contents tree) (insert "}")) (defun w3-latex-list (tree) (let* ((sym (car tree)) (list-type (cond ((eq sym 'ol) "enumerate") ((eq sym 'dl) "description") (t "itemize")))) (insert (concat "\n\\begin{" list-type "}\n")) (w3-latex-contents tree) (insert (concat "\n\\end{" list-type "}\n")))) (defun w3-latex-list-item (tree) (let ((sym (car tree))) (cond ((eq sym 'dt) (insert "\n\\item[")) ((eq sym 'dd) ;; don't do anything for dd -- the item is handled by dt. nil) (t (insert "\n\\item"))) (w3-latex-contents tree) (if (eq sym 'dt) (insert "]")))) (defun w3-latex-center (tree) (insert "\\begin{center}") (w3-latex-contents tree) (insert "\\end{center}")) (defun w3-latex-rule (tree) ; use \par to make paragraph division clear. (insert "\n\\par\\noindent\\rule{\\textwidth}{.01in}\n")) (defun w3-latex-para (tree) ;; look through the additional markup to see if an align=right or ;; align=center is in here... (let ((align (assq 'align (car (cdr tree))))) (cond ((and align (string-equal (cdr align) "center")) (w3-latex-center tree)) ((and align (string-equal (cdr align) "right")) (insert "\\begin{flushright}") (w3-latex-contents tree) (insert "\\end{flushright}")) (t (insert "\\par ") (w3-latex-contents tree))))) (defun w3-latex-quote (tree) (insert "\\begin{quote}\n") (w3-latex-contents tree) (insert "\\end{quote}\n")) (defun w3-latex-break (tree) ;; no content allowed (insert "\\newline ")) (defun w3-latex-endnotes () (let ((i 1)) (insert "\\begin{thebibliography}{99}\n") (while w3-latex-links-list (insert (concat "\\bibitem{ref" (number-to-string i) "}")) (w3-latex-insert-string (car w3-latex-links-list)) (insert "\n") (setq w3-latex-links-list (cdr w3-latex-links-list)) (setq i (1+ i))) (insert "\\end{thebibliography}\n"))) (defun w3-latex-href (tree) (let ((href (cdr-safe (assq 'href (cadr tree)))) (name (cdr-safe (assq 'name (cadr tree))))) (cond ((not w3-latex-print-links) ; No special treatment (w3-latex-contents tree)) (name (w3-latex-contents tree) (insert (concat "\\label{" name "}"))) (href ; Special treatment requested ; (insert "\\underline{") ; and we have a URL - underline (w3-latex-contents tree) ; it. ; (insert "}") (cond ((char-equal ?# (aref href 0)) (insert (concat " (see page~\\pageref{" (substring href 1) "})"))) ((eq w3-latex-print-links 'footnote) (insert "\\footnote{") ; Request to prepare footnote (w3-latex-insert-string href) (insert "}")) (t ; Otherwise, prepare endnotes (let ((mem (member href w3-latex-links-list)) (i (1+ (length w3-latex-links-list)))) (if mem (setq i (- i (length mem))) (setq w3-latex-links-list (append w3-latex-links-list (cons href nil)))) (insert (concat "~\\cite{ref" (number-to-string i) "}")))))) (t ; Special treatment requested, but (w3-latex-contents tree))))) ; no URL - do nothing. (defun w3-latex-preformatted (tree) (let ((w3-latex-verbatim t)) (insert "\\par\\noindent\\begin{tt}") (w3-latex-contents tree) (insert "\\end{tt}\\par") )) (defun w3-latex-xmp (tree) (insert "\\begin{verbatim}") (w3-latex-contents tree) (insert "\\end{verbatim}")) (let ((todo '((title . w3-latex-title) (html . w3-latex-html) (pre . w3-latex-preformatted) (xmp . w3-latex-xmp) (h1 . w3-latex-heading) (h2 . w3-latex-heading) (h3 . w3-latex-heading) (h4 . w3-latex-heading) (h5 . w3-latex-heading) (h6 . w3-latex-heading) (a . w3-latex-href) (strong . w3-latex-bold) (b . w3-latex-bold) (dfn . w3-latex-bold) (em . w3-latex-italic) (i . w3-latex-italic) (address . w3-latex-italic) (code . w3-latex-typewriter) (samp . w3-latex-typewriter) (tt . w3-latex-typewriter) (kbd . w3-latex-typewriter) (var . w3-latex-typewriter) (ol . w3-latex-list) (dl . w3-latex-list) (ul . w3-latex-list) (menu . w3-latex-list) (dir . w3-latex-list) (li . w3-latex-list-item) (dt . w3-latex-list-item) (dd . w3-latex-list-item) (center . w3-latex-center) (hr . w3-latex-rule) (p . w3-latex-para) (br . w3-latex-break) (blockquote . w3-latex-quote)))) (while todo (put (caar todo) 'w3-latex-formatter (cdar todo)) (setq todo (cdr todo)))) (defun w3-latex-subtree (tree) (cond ((stringp tree) (w3-latex-insert-string tree)) ((stringp (car-safe tree)) (while tree (w3-latex-insert-string (car tree)) (setq tree (cdr tree)))) ((symbolp (car tree)) (let ((proc (get (car tree) 'w3-latex-formatter))) (if (and proc (fboundp proc)) (funcall proc tree) ;; anything else gets passed through unchanged (w3-latex-contents tree)))) (t (w3-latex-contents tree)))) ;;;###autoload (defun w3-parse-tree-to-latex (tree &optional url) ; assumes that url-working-buffer exists. (set-buffer (get-buffer-create url-working-buffer)) (setq w3-latex-current-url url) (erase-buffer) (goto-char (point-min)) (if w3-latex-use-latex2e (insert (concat "\\documentclass" w3-latex-docstyle "\n")) (insert (concat "\\documentstyle" w3-latex-docstyle "\n"))) (if (and w3-latex-use-latex2e w3-latex-packages) (insert (apply 'concat (mapcar (lambda (x) (concat "\\usepackage{" x "}\n")) w3-latex-packages)))) (while tree (w3-latex-subtree (car tree)) (setq tree (cdr tree)))) ;;;###autoload (defun w3-show-dvi () "Uses xdvi to show DVI file created from `w3-parse-tree-to-latex'." (interactive) (w3-parse-tree-to-latex w3-current-parse) (save-window-excursion (set-buffer url-working-buffer) (write-region (point-min) (point-max) (expand-file-name "w3-tmp.latex" w3-temporary-directory) nil 5) (shell-command (format "(cd %s ; latex w3-tmp.latex ; latex w3-tmp.latex ; xdvi w3-tmp.dvi ; rm -f w3-tmp*) &" w3-temporary-directory)))) (provide 'w3-latex) ;; Keywords: hypermedia, printing, typesetting ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Copyright (c) 1996, 1997 by Stephen Peters ;;; ;;; This file is not part of GNU Emacs, but the same permissions apply. ;;; ;;; GNU Emacs is free software; you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 2, or (at your option) ;;; any later version. ;;; ;;; GNU Emacs is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with GNU Emacs; see the file COPYING. If not, write to the ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;;; Boston, MA 02111-1307, USA. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;