1 ;;; w3-latex.el --- Emacs-W3 printing via LaTeX
3 ;; Created: 1996/06/30 18:08:34
5 ;; Keywords: hypermedia, printing, typesetting
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; Copyright (c) 1996, 1997 by Stephen Peters <speters@cygnus.com>
10 ;;; This file is part of GNU Emacs.
12 ;;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;;; it under the terms of the GNU General Public License as published by
14 ;;; the Free Software Foundation; either version 2, or (at your option)
15 ;;; any later version.
17 ;;; GNU Emacs is distributed in the hope that it will be useful,
18 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;;; GNU General Public License for more details.
22 ;;; You should have received a copy of the GNU General Public License
23 ;;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;;; Boston, MA 02111-1307, USA.
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27 ;;; Elisp code to convert a W3 parse tree into a LaTeX buffer.
29 ;;; Heavily hacked upon by William Perry <wmperry@cs.indiana.edu> to add more
30 ;;; bells and whistles.
33 ;;; 1) This does not use stylesheets to get the formatting information
34 ;;; 2) This means that the new drawing routines need to be abstracted
35 ;;; further so that the same main engine can be used for either
36 ;;; text-output (standard stuff in w3-draw), LaTeX output (this file),
37 ;;; Postscript (to-be-implemented), etc., etc.
38 ;;; 3) This still doesn't handle tables.
40 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
44 ;; Internal variables - do not touch!
45 (defvar w3-latex-current-url nil "What URL we are formatting")
46 (defvar w3-latex-verbatim nil "Whether we are in a {verbatim} block or not")
47 (defvar w3-latex-links-list nil "List of links for endnote usage")
49 (defvar w3-latex-entities
59 (copy . "\\copyright ")
78 (frac14 . "$\frac{1}{4}$")
79 (frac12 . "$\frac{1}{2}$")
80 (frac34 . "$\frac{3}{4}$")
105 (times . "$\\times$")
146 "Defines mappings between `w3-html-entities' and LaTeX characters.")
148 (defun w3-latex-replace-entities (str)
150 (while (string-match "[\200-\377]" str start)
151 ; get the character code, and then search for a match in
152 ; w3-html-entities. If one is found, use it to perform a lookup
153 ; in w3-latex-entities, and use the resulting match to replace
155 (let* ((match (rassq (aref str (match-beginning 0))
158 (assq (car match) w3-latex-entities))))
160 (setq str (replace-match (cdr replace) t t str)))
161 (setq start (match-end 0))))
164 (defun w3-latex-insert-string (str)
165 ;;; convert string to a LaTeX-compatible one.
166 (let ((todo (list (cons "\\\\" "-BaCkSlAsH-")
167 (cons "[%&#_{}$]" "\\\\\\&")
168 (cons "\\^" "{\\\\textasciicircum}")
169 (cons "~" "{\\\\textasciitilde}")
171 (cons "[><|]" "$\\&$")
172 (cons "-BaCkSlAsH-" "$\\\\backslash$"))))
173 (if w3-latex-verbatim
174 (setq todo (append todo '(("\n" . "\\\\newline\\\\nullspace\n")
177 (set-buffer (get-buffer-create " *w3-latex-munging*"))
181 (goto-char (point-min))
182 (while (re-search-forward (caar todo) nil t)
183 (replace-match (cdar todo)))
184 (setq todo (cdr todo)))
185 (setq str (w3-latex-replace-entities (buffer-string))))
188 (defun w3-latex-ignore (tree)
189 ;;; ignores any contents of this tree.
192 (defun w3-latex-contents (tree)
193 ;;; passes contents of subtree through to the latex-subtree
194 (let ((contents (car (cdr (cdr tree)))))
196 (w3-latex-subtree (car contents))
197 (setq contents (cdr contents)))))
199 (defun w3-latex-html (tree)
200 (insert "% This document automatically generated by Emacs-W3 v"
201 w3-version-number "\n")
202 (if w3-latex-current-url
203 (insert "% from <URL:" w3-latex-current-url ">\n"))
205 "\\batchmode\n\\begin{document}\n")
206 (insert "\\setlength{\\parindent}{0pt}\n"
207 "\\setlength{\\parskip}{1.5ex}\n")
208 (insert "\\newcommand{\\nullspace}{\\rule{0pt}{0pt}}")
209 (w3-latex-contents tree)
210 (if w3-latex-links-list (w3-latex-endnotes))
211 (insert "\\end{document}\n"))
213 (defun w3-latex-title (tree)
214 (if w3-latex-use-maketitle
216 (insert "\\section*{\\centering "))
217 (w3-latex-contents tree)
219 (if w3-latex-use-maketitle
220 (insert "\\author{}\\date{}\n\\maketitle")))
222 (defun w3-latex-heading (tree)
223 ;; look through the additional markup to see if an align=right or
224 ;; align=center is in here...
225 (let ((align (assq 'align (car (cdr tree))))
228 (cond ((and align (string-equal (cdr align) "center"))
229 (insert "\\begin{center}\n"))
230 ((and align (string-equal (cdr align) "right"))
231 (insert "\\begin{flushright}\n")))
232 (cond ((eq sym 'h1) (insert "\\section*{"))
233 ((eq sym 'h2) (insert "\\subsection*{"))
234 ((eq sym 'h3) (insert "\\subsubsection*{"))
235 ((eq sym 'h4) (insert "\\subsubsection*{"))
236 ((eq sym 'h5) (insert "\\paragraph*{"))
237 ((eq sym 'h6) (insert "\\subparagraph*{")))
238 (w3-latex-contents tree)
240 (cond ((and align (string-equal (cdr align) "center"))
241 (insert "\\end{center}\n"))
242 ((and align (string-equal (cdr align) "right"))
243 (insert "\\end{flushright}\n")))))
245 (defun w3-latex-bold (tree)
247 (w3-latex-contents tree)
249 (defun w3-latex-italic (tree)
251 (w3-latex-contents tree)
253 (defun w3-latex-typewriter (tree)
255 (w3-latex-contents tree)
258 (defun w3-latex-list (tree)
259 (let* ((sym (car tree))
260 (list-type (cond ((eq sym 'ol) "enumerate")
261 ((eq sym 'dl) "description")
263 (insert (concat "\n\\begin{" list-type "}\n"))
264 (w3-latex-contents tree)
265 (insert (concat "\n\\end{" list-type "}\n"))))
267 (defun w3-latex-list-item (tree)
268 (let ((sym (car tree)))
270 (insert "\n\\item["))
272 ;; don't do anything for dd -- the item is handled by dt.
274 (t (insert "\n\\item")))
275 (w3-latex-contents tree)
279 (defun w3-latex-center (tree)
280 (insert "\\begin{center}")
281 (w3-latex-contents tree)
282 (insert "\\end{center}"))
284 (defun w3-latex-rule (tree)
285 ; use \par to make paragraph division clear.
286 (insert "\n\\par\\noindent\\rule{\\textwidth}{.01in}\n"))
288 (defun w3-latex-para (tree)
289 ;; look through the additional markup to see if an align=right or
290 ;; align=center is in here...
291 (let ((align (assq 'align (car (cdr tree)))))
293 (string-equal (cdr align) "center"))
294 (w3-latex-center tree))
296 (string-equal (cdr align) "right"))
297 (insert "\\begin{flushright}")
298 (w3-latex-contents tree)
299 (insert "\\end{flushright}"))
301 (w3-latex-contents tree)))))
303 (defun w3-latex-quote (tree)
304 (insert "\\begin{quote}\n")
305 (w3-latex-contents tree)
306 (insert "\\end{quote}\n"))
308 (defun w3-latex-break (tree)
309 ;; no content allowed
310 (insert "\\newline "))
312 (defun w3-latex-endnotes ()
314 (insert "\\begin{thebibliography}{99}\n")
315 (while w3-latex-links-list
316 (insert (concat "\\bibitem{ref" (number-to-string i) "}"))
317 (w3-latex-insert-string (car w3-latex-links-list))
319 (setq w3-latex-links-list (cdr w3-latex-links-list))
321 (insert "\\end{thebibliography}\n")))
323 (defun w3-latex-href (tree)
324 (let ((href (cdr-safe (assq 'href (cadr tree))))
325 (name (cdr-safe (assq 'name (cadr tree)))))
327 ((not w3-latex-print-links) ; No special treatment
328 (w3-latex-contents tree))
330 (w3-latex-contents tree)
331 (insert (concat "\\label{" name "}")))
332 (href ; Special treatment requested
333 ; (insert "\\underline{") ; and we have a URL - underline
334 (w3-latex-contents tree) ; it.
337 ((char-equal ?# (aref href 0))
338 (insert (concat " (see page~\\pageref{"
341 ((eq w3-latex-print-links 'footnote)
342 (insert "\\footnote{") ; Request to prepare footnote
343 (w3-latex-insert-string href)
345 (t ; Otherwise, prepare endnotes
346 (let ((mem (member href w3-latex-links-list))
347 (i (1+ (length w3-latex-links-list))))
349 (setq i (- i (length mem)))
350 (setq w3-latex-links-list
351 (append w3-latex-links-list (cons href nil))))
352 (insert (concat "~\\cite{ref" (number-to-string i) "}"))))))
353 (t ; Special treatment requested, but
354 (w3-latex-contents tree))))) ; no URL - do nothing.
356 (defun w3-latex-preformatted (tree)
357 (let ((w3-latex-verbatim t))
358 (insert "\\par\\noindent\\begin{tt}")
359 (w3-latex-contents tree)
360 (insert "\\end{tt}\\par")
363 (defun w3-latex-xmp (tree)
364 (insert "\\begin{verbatim}")
365 (w3-latex-contents tree)
366 (insert "\\end{verbatim}"))
368 (let ((todo '((title . w3-latex-title)
369 (html . w3-latex-html)
370 (pre . w3-latex-preformatted)
372 (h1 . w3-latex-heading)
373 (h2 . w3-latex-heading)
374 (h3 . w3-latex-heading)
375 (h4 . w3-latex-heading)
376 (h5 . w3-latex-heading)
377 (h6 . w3-latex-heading)
379 (strong . w3-latex-bold)
381 (dfn . w3-latex-bold)
382 (em . w3-latex-italic)
383 (i . w3-latex-italic)
384 (address . w3-latex-italic)
385 (code . w3-latex-typewriter)
386 (samp . w3-latex-typewriter)
387 (tt . w3-latex-typewriter)
388 (kbd . w3-latex-typewriter)
389 (var . w3-latex-typewriter)
393 (menu . w3-latex-list)
394 (dir . w3-latex-list)
395 (li . w3-latex-list-item)
396 (dt . w3-latex-list-item)
397 (dd . w3-latex-list-item)
398 (center . w3-latex-center)
401 (br . w3-latex-break)
402 (blockquote . w3-latex-quote))))
404 (put (caar todo) 'w3-latex-formatter (cdar todo))
405 (setq todo (cdr todo))))
407 (defun w3-latex-subtree (tree)
410 (w3-latex-insert-string tree))
411 ((stringp (car-safe tree))
413 (w3-latex-insert-string (car tree))
414 (setq tree (cdr tree))))
415 ((symbolp (car tree))
416 (let ((proc (get (car tree) 'w3-latex-formatter)))
417 (if (and proc (fboundp proc))
419 ;; anything else gets passed through unchanged
420 (w3-latex-contents tree))))
422 (w3-latex-contents tree))))
424 ;; Fixme: url-working-buffer is never defined.
426 (defun w3-parse-tree-to-latex (tree &optional url)
427 ; assumes that url-working-buffer exists.
428 (set-buffer (get-buffer-create url-working-buffer))
429 (setq w3-latex-current-url url)
431 (goto-char (point-min))
432 (if w3-latex-use-latex2e
433 (insert (concat "\\documentclass" w3-latex-docstyle "\n"))
434 (insert (concat "\\documentstyle" w3-latex-docstyle "\n")))
435 (if (and w3-latex-use-latex2e
437 (insert (apply 'concat
438 (mapcar (lambda (x) (concat "\\usepackage{" x "}\n"))
439 w3-latex-packages))))
441 (w3-latex-subtree (car tree))
442 (setq tree (cdr tree))))
445 (defun w3-show-dvi ()
446 "Uses xdvi to show DVI file created from `w3-parse-tree-to-latex'."
448 (w3-parse-tree-to-latex w3-current-parse)
449 (save-window-excursion
450 (set-buffer url-working-buffer)
451 (let ((coding-system-for-write 'binary))
453 (point-min) (point-max)
454 (expand-file-name "w3-tmp.latex"
455 w3-temporary-directory) nil 5))
458 "(cd %s ; latex w3-tmp.latex ; latex w3-tmp.latex ; xdvi w3-tmp.dvi ; rm -f w3-tmp*) &"
459 w3-temporary-directory))))