1 ;;; preview.el --- embed preview LaTeX images in source buffer
3 ;; Copyright (C) 2001-2006, 2010, 2012 Free Software Foundation, Inc.
5 ;; Author: David Kastrup
6 ;; Keywords: tex, wp, convenience
8 ;; This file is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; This file is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GNU Emacs; see the file COPYING. If not, write to
20 ;; the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 ;; Boston, MA 02110-1301, USA.
25 ;; $Id: preview.el,v 1.286 2011/01/23 18:53:55 angeli Exp $
27 ;; This style is for the "seamless" embedding of generated images
28 ;; into LaTeX source code. Please see the README and INSTALL files
29 ;; for further instruction.
31 ;; Please use the usual configure script for installation: more than
32 ;; just Elisp files are involved: a LaTeX style, icon files, startup
35 ;; Quite a few things with regard to preview-latex's operation can be
36 ;; configured by using
37 ;; M-x customize-group RET preview RET
39 ;; Please report bugs with M-x preview-report-bug RET
52 (file-error (message "Missing desktop package:
53 preview-latex buffers will not survive across sessions.")))
56 (file-error (message "Missing reporter library, probably from the mail-lib package:
57 preview-latex's bug reporting commands will probably not work.")))
61 ;; we need the compatibility macros which do _not_ get byte-compiled.
63 (if (featurep 'xemacs)
64 (load-library "prv-xemacs.el")))
66 ;; if the above load-library kicked in, this will not cause anything
68 (require (if (featurep 'xemacs)
69 'prv-xemacs 'prv-emacs))
71 (defgroup preview nil "Embed Preview images into LaTeX buffers."
74 :link '(custom-manual "(preview-latex)Top")
75 :link '(info-link "(preview-latex)The Emacs interface")
76 :link '(url-link :tag "Homepage" "http://www.gnu.org/software/auctex/"))
78 (defgroup preview-gs nil "Preview's Ghostscript renderer."
82 (defgroup preview-appearance nil "Preview image appearance."
86 (defconst preview-specs-type
88 (list :tag "Image spec"
89 ;; Use an extra :value keyword to avoid a bug in
90 ;; `widget-convert' of XEmacs 21.4 and Emacs 21.
91 ;; Analogously for the following `const' statements.
92 (const :format "" :value :type)
93 (choice :tag "Image type"
96 (symbol :tag "Other"))
97 (set :inline t :tag "Minimum font size"
98 (list :inline t :tag ""
99 (const :format "" :value :min)
100 (integer :tag "pixels")))
101 (const :format "" :value :file) (string :tag "Filename")
102 (set :inline t :tag "Ascent ratio"
103 (list :inline t :tag ""
104 (const :format "" :value :ascent)
105 (integer :tag "percent of image"
108 (defun preview-specs-setter (symbol value)
109 "Set SYMBOL to VALUE and clear `preview-min-alist' property.
110 This is used in icon specs, so that customizing will
112 (put symbol 'preview-min-alist nil)
113 (set-default symbol value))
115 (defcustom preview-nonready-icon-specs
116 '((:type xpm :min 26 :file "prvwrk24.xpm" :ascent 90)
117 (:type xpm :min 22 :file "prvwrk20.xpm" :ascent 90)
118 (:type xpm :min 17 :file "prvwrk16.xpm" :ascent 90)
119 (:type xpm :min 15 :file "prvwrk14.xpm" :ascent 90)
120 (:type xpm :file "prvwrk12.xpm" :ascent 90)
121 (:type xbm :file "prvwrk24.xbm" :ascent 90))
122 "The icon used for previews to be generated.
123 The spec must begin with `:type'. File names are relative to
124 `load-path' and `data-directory', a spec `:min' requires a
125 minimal pixel height for `preview-reference-face' before the spec
126 will be considered. Since evaluating the `:file' spec takes
127 considerable time under XEmacs, it should come after the `:min'
128 spec to avoid unnecessary evaluation time."
129 :group 'preview-appearance
130 :type preview-specs-type
131 :set #'preview-specs-setter)
133 (defvar preview-nonready-icon)
135 (defcustom preview-error-icon-specs
136 '((:type xpm :min 22 :file "prverr24.xpm" :ascent 90)
137 (:type xpm :min 18 :file "prverr20.xpm" :ascent 90)
138 (:type xpm :file "prverr16.xpm" :ascent 90)
139 (:type xbm :file "prverr24.xbm" :ascent 90))
140 "The icon used for PostScript errors.
141 The spec must begin with `:type'. File names are relative to
142 `load-path' and `data-directory', a spec `:min' requires a
143 minimal pixel height for `preview-reference-face' before the spec
144 will be considered. Since evaluating the `:file' spec takes
145 considerable time under XEmacs, it should come after the `:min'
146 spec to avoid unnecessary evaluation time."
147 :group 'preview-appearance
148 :type preview-specs-type
149 :set #'preview-specs-setter
152 (defvar preview-error-icon)
154 (defcustom preview-icon-specs
155 '((:type xpm :min 24 :file "prvtex24.xpm" :ascent 75)
156 (:type xpm :min 20 :file "prvtex20.xpm" :ascent 75)
157 (:type xpm :min 16 :file "prvtex16.xpm" :ascent 75)
158 (:type xpm :file "prvtex12.xpm" :ascent 75)
159 (:type xbm :min 24 :file "prvtex24.xbm" :ascent 75)
160 (:type xbm :min 16 :file "prvtex16.xbm" :ascent 75)
161 (:type xbm :file "prvtex12.xbm" :ascent 75))
162 "The icon used for an open preview.
163 The spec must begin with `:type'. File names are relative to
164 `load-path' and `data-directory', a spec `:min' requires a
165 minimal pixel height for `preview-reference-face' before the spec
166 will be considered. Since evaluating the `:file' spec takes
167 considerable time under XEmacs, it should come after the `:min'
168 spec to avoid unnecessary evaluation time."
169 :group 'preview-appearance
170 :type preview-specs-type
171 :set #'preview-specs-setter)
173 (defvar preview-icon)
175 (defgroup preview-latex nil "LaTeX options for preview."
179 (defcustom preview-image-creators
181 (open preview-gs-open preview-dvipng-process-setup)
182 (place preview-gs-place)
183 (close preview-dvipng-close))
184 (png (open preview-gs-open)
185 (place preview-gs-place)
186 (close preview-gs-close))
187 (jpeg (open preview-gs-open)
188 (place preview-gs-place)
189 (close preview-gs-close))
190 (pnm (open preview-gs-open)
191 (place preview-gs-place)
192 (close preview-gs-close))
193 (tiff (open preview-gs-open)
194 (place preview-gs-place)
195 (close preview-gs-close)))
196 "Define functions for generating images.
197 These functions get called in the process of generating inline
198 images of the specified type. The open function is called
199 at the start of a rendering pass, the place function for
200 placing every image, the close function at the end of
201 the pass. Look at the documentation of the various
202 functions used here for the default settings, and at
203 the function `preview-call-hook' through which those are
204 called. Additional argument lists specified in here
205 are passed to the functions before any additional
206 arguments given to `preview-call-hook'.
208 Not all of these image types may be supported by your copy
209 of Ghostscript, or by your copy of Emacs."
211 :type '(alist :key-type (symbol :tag "Preview's image type")
213 (alist :tag "Handler" :key-type (symbol :tag "Operation:")
214 :value-type (list :tag "Handler"
215 (function :tag "Handler function")
216 (repeat :tag "Additional \
217 function args" :inline t sexp))
218 :options (open place close))))
220 (defcustom preview-gs-image-type-alist
221 '((png png "-sDEVICE=png16m")
222 (dvipng png "-sDEVICE=png16m")
223 (jpeg jpeg "-sDEVICE=jpeg")
224 (pnm pbm "-sDEVICE=pnmraw")
225 (tiff tiff "-sDEVICE=tiff12nc"))
226 "*Alist of image types and corresponding Ghostscript options.
227 The `dvipng' and `postscript' (don't use) entries really specify
228 a fallback device when images can't be processed by the requested
229 method, like when PDFTeX was used."
231 :type '(repeat (list :tag nil (symbol :tag "preview image-type")
232 (symbol :tag "Emacs image-type")
233 (repeat :inline t :tag "Ghostscript options" string))))
235 (defcustom preview-image-type 'png
236 "*Image type to be used in images."
238 :type (append '(choice)
239 (mapcar (lambda (symbol) (list 'const (car symbol)))
240 preview-image-creators)
241 '((symbol :tag "Other"))))
243 (defun preview-call-hook (symbol &rest rest)
244 "Call a function from `preview-image-creators'.
245 This looks up SYMBOL in the `preview-image-creators' entry
246 for the image type `preview-image-type' and calls the
247 hook function given there with the arguments specified there
248 followed by REST. If such a function is specified in there,
250 (let ((hook (cdr (assq symbol
251 (cdr (assq preview-image-type
252 preview-image-creators))))))
254 (apply (car hook) (append (cdr hook) rest)))))
257 (defvar TeX-active-tempdir nil
258 "List of directory name, top directory name and reference count.")
259 (make-variable-buffer-local 'TeX-active-tempdir)
261 (defcustom preview-bb-filesize 1024
262 "Size of file area scanned for bounding box information."
263 :group 'preview-gs :type 'integer)
265 (defcustom preview-preserve-indentation t
266 "*Whether to keep additional whitespace at the left of a line."
267 :group 'preview-appearance :type 'boolean)
269 (defun preview-extract-bb (filename)
270 "Extract EPS bounding box vector from FILENAME."
272 (insert-file-contents-literally filename nil 0 preview-bb-filesize
274 (goto-char (point-min))
275 (when (search-forward-regexp "%%BoundingBox:\
279 +\\([-+]?[0-9.]+\\)" nil t)
281 (if preview-preserve-indentation
282 (min 72 (string-to-number (match-string 1)))
283 (string-to-number (match-string 1)))
284 (string-to-number (match-string 2))
285 (string-to-number (match-string 3))
286 (string-to-number (match-string 4))
289 (defcustom preview-prefer-TeX-bb nil
290 "*Prefer TeX bounding box to EPS one if available.
291 If `preview-fast-conversion' is set, this option is not
292 consulted since the TeX bounding box has to be used anyway."
296 (defcustom preview-TeX-bb-border 0.5
297 "*Additional space in pt around Bounding Box from TeX."
301 (defvar preview-coding-system nil
302 "Coding system used for LaTeX process.")
303 (make-variable-buffer-local 'preview-coding-system)
304 (defvar preview-parsed-font-size nil
305 "Font size as parsed from the log of LaTeX run.")
306 (make-variable-buffer-local 'preview-parsed-font-size)
307 (defvar preview-parsed-magnification nil
308 "Magnification as parsed from the log of LaTeX run.")
309 (make-variable-buffer-local 'preview-parsed-magnification)
310 (defvar preview-parsed-pdfoutput nil
311 "PDFoutput as parsed from the log of LaTeX run.")
312 (make-variable-buffer-local 'preview-parsed-pdfoutput)
313 (defvar preview-parsed-counters nil
314 "Counters as parsed from the log of LaTeX run.")
315 (make-variable-buffer-local 'preview-parsed-counters)
316 (defvar preview-parsed-tightpage nil
317 "Tightpage as parsed from the log of LaTeX run.")
318 (make-variable-buffer-local 'preview-parsed-tightpage)
320 (defun preview-get-magnification ()
321 "Get magnification from `preview-parsed-magnification'."
322 (if preview-parsed-magnification
323 (/ preview-parsed-magnification 1000.0) 1.0))
325 (defun preview-TeX-bb (list)
326 "Calculate bounding box from (ht dp wd).
327 LIST consists of TeX dimensions in sp (1/65536 TeX point)."
330 (let* ((dims (vconcat (mapcar
332 (/ x 65781.76)) list)))
335 (+ 72 (min 0 (aref dims 2)))
336 (+ 720 (min (aref dims 0) (- (aref dims 1)) 0))
337 (+ 72 (max 0 (aref dims 2)))
338 (+ 720 (max (aref dims 0) (- (aref dims 1)) 0))))
339 (border (if preview-parsed-tightpage
342 (/ x 65781.76)) preview-parsed-tightpage))
343 (vector (- preview-TeX-bb-border)
344 (- preview-TeX-bb-border)
345 preview-TeX-bb-border
346 preview-TeX-bb-border))))
348 (aset box i (+ (aref box i) (aref border i)))))))
350 (defcustom preview-gs-command (if (eq system-type 'windows-nt)
353 "*How to call gs for conversion from EPS. See also `preview-gs-options'."
357 (defcustom preview-gs-options '("-q" "-dDELAYSAFER" "-dNOPAUSE"
358 "-DNOPLATFONTS" "-dPrinted"
360 "-dGraphicsAlphaBits=4")
361 "*Options with which to call gs for conversion from EPS.
362 See also `preview-gs-command'."
364 :type '(repeat string))
366 (defvar preview-gs-queue nil
367 "List of overlays to convert using gs.
368 Buffer-local to the appropriate TeX process buffer.")
369 (make-variable-buffer-local 'preview-gs-queue)
371 (defvar preview-gs-outstanding nil
372 "Overlays currently processed.")
373 (make-variable-buffer-local 'preview-gs-outstanding)
375 (defcustom preview-gs-outstanding-limit 2
376 "*Number of requests allowed to be outstanding.
377 This is the number of not-yet-completed requests we
378 might at any time have piped into Ghostscript. If
379 this number is larger, the probability of Ghostscript
380 working continuously is higher when Emacs is rather
381 busy. If this number is smaller, redisplay will
382 follow changes in the displayed buffer area faster."
384 :type '(restricted-sexp
386 ((lambda (value) (and
390 :tag "small number"))
392 (defvar preview-gs-answer nil
393 "Accumulated answer of Ghostscript process.")
394 (make-variable-buffer-local 'preview-gs-answer)
396 (defvar preview-gs-image-type nil
397 "Image type for gs produced images.")
398 (make-variable-buffer-local 'preview-gs-image-type)
400 (defvar preview-gs-sequence nil
401 "Pair of sequence numbers for gs produced images.")
402 (make-variable-buffer-local 'preview-gs-sequence)
404 (defvar preview-scale nil
405 "Screen scale of images.
406 Magnify by this factor to make images blend with other
407 screen content. Buffer-local to rendering buffer.")
408 (make-variable-buffer-local 'preview-scale)
410 (defvar preview-colors nil
412 An array with elements 0, 1 and 2 for background,
413 foreground and border colors, respectively. Each element
414 is a list of 3 real numbers between 0 and 1, or NIL
415 of nothing special should be done for the color")
416 (make-variable-buffer-local 'preview-colors)
418 (defvar preview-gs-init-string nil
419 "Ghostscript setup string.")
420 (make-variable-buffer-local 'preview-gs-init-string)
422 (defvar preview-ps-file nil
423 "PostScript file name for fast conversion.")
424 (make-variable-buffer-local 'preview-ps-file)
426 (defvar preview-gs-dsc nil
427 "Parsed DSC information.")
428 (make-variable-buffer-local 'preview-gs-dsc)
430 (defvar preview-resolution nil
431 "Screen resolution where rendering started.
432 Cons-cell of x and y resolution, given in
433 dots per inch. Buffer-local to rendering buffer.")
434 (make-variable-buffer-local 'preview-resolution)
436 (defun preview-gs-resolution (scale xres yres)
437 "Generate resolution argument for gs.
438 Calculated from real-life factor SCALE and XRES and
439 YRES, the screen resolution in dpi."
441 (/ (* scale xres) (preview-get-magnification))
442 (/ (* scale yres) (preview-get-magnification))))
444 (defun preview-gs-behead-outstanding (err)
445 "Remove leading element of outstanding queue after error.
446 Return element if non-nil. ERR is the error string to
447 show as response of Ghostscript."
448 (let ((ov (pop preview-gs-outstanding)))
450 (preview-gs-flag-error ov err)
451 (overlay-put ov 'queued nil))
454 (defvar preview-gs-command-line nil)
455 (make-variable-buffer-local 'preview-gs-command-line)
456 (defvar preview-gs-file nil)
457 (make-variable-buffer-local 'preview-gs-file)
459 (defcustom preview-fast-conversion t
460 "*Set this for single-file PostScript conversion.
461 This will have no effect when `preview-image-type' is
462 set to `postscript'."
463 :group 'preview-latex
466 (defun preview-string-expand (arg &optional separator)
467 "Expand ARG as a string.
468 It can already be a string. Or it can be a list, then it is
469 recursively evaluated using SEPARATOR as separator. If a list
470 element is in itself a CONS cell, the CAR of the list (after symbol
471 dereferencing) can evaluate to either a string, in which case it is
472 used as a separator for the rest of the list,
473 or a boolean (t or nil) in which case the rest of the list is
474 either evaluated and concatenated or ignored, respectively.
475 ARG can be a symbol, and so can be the CDR
476 of a cell used for string concatenation."
487 (while (and (symbolp sep)
488 (not (memq sep '(t nil))))
489 (setq sep (symbol-value sep)))
491 (preview-string-expand (cdr x) sep)
493 (preview-string-expand (cdr x)))))
494 (preview-string-expand x)))
497 ((and (symbolp arg) (not (memq arg '(t nil))))
498 (preview-string-expand (symbol-value arg) separator))
499 (t (error "Bad string expansion"))))
501 (defconst preview-expandable-string
502 ((lambda (f) (funcall f (funcall f 'sexp)))
506 (repeat :tag "Concatenate"
509 (cons :tag "Separated list"
510 (choice (string :tag "Separator")
511 (symbol :tag "Indirect separator or flag"))
513 (symbol :tag "Indirect variable (no separator)")))
514 (symbol :tag "Indirect variable (with separator)"))))
515 "Type to be used for `preview-string-expand'.
516 Just a hack until we get to learn how to do this properly.
517 Recursive definitions are not popular with Emacs,
518 so we define this type just two levels deep. This
519 kind of expandible string can either be just a string, or a
520 cons cell with a separator string in the CAR, and either
521 an explicit list of elements in the CDR, or a symbol to
522 be consulted recursively.")
524 (defcustom preview-dvipng-command
525 "dvipng -picky -noghostscript %d -o \"%m/prev%%03d.png\""
526 "*Command used for converting to separate PNG images.
528 You might specify options for converting to other image types,
529 but then you'll need to adapt `preview-dvipng-image-type'."
530 :group 'preview-latex
533 (defcustom preview-dvipng-image-type
535 "*Image type that dvipng produces.
537 You'll need to change `preview-dvipng-command' too,
538 if you customize this."
539 :group 'preview-latex
540 :type '(choice (const png)
542 (symbol :tag "Other" :value png)))
544 (defcustom preview-dvips-command
545 "dvips -Pwww -i -E %d -o %m/preview.000"
546 "*Command used for converting to separate EPS images."
547 :group 'preview-latex
550 (defcustom preview-fast-dvips-command
551 "dvips -Pwww %d -o %m/preview.ps"
552 "*Command used for converting to a single PS file."
553 :group 'preview-latex
556 (defcustom preview-pdf2dsc-command
557 "pdf2dsc %s.pdf %m/preview.dsc"
558 "*Command used for generating dsc from a PDF file."
559 :group 'preview-latex
562 (defun preview-gs-queue-empty ()
563 "Kill off everything remaining in `preview-gs-queue'."
564 (mapc #'preview-delete preview-gs-outstanding)
565 (dolist (ov preview-gs-queue)
566 (if (overlay-get ov 'queued)
567 (preview-delete ov)))
568 (setq preview-gs-outstanding nil)
569 (setq preview-gs-queue nil))
571 (defvar preview-error-condition nil
572 "Last error raised and to be reported.")
574 (defun preview-log-error (err context &optional process)
575 "Log an error message to run buffer.
576 ERR is the caught error syndrome, CONTEXT is where it
577 occured, PROCESS is the process for which the run-buffer
579 (when (or (null process) (buffer-name (process-buffer process)))
580 (with-current-buffer (or (and process
581 (process-buffer process))
584 (goto-char (or (and process
585 (process-buffer process)
586 (marker-buffer (process-mark process))
587 (process-mark process))
589 (insert-before-markers
591 context (error-message-string err)))
592 (display-buffer (current-buffer)))))
593 (setq preview-error-condition err))
595 (defun preview-reraise-error (&optional process)
596 "Raise an error that has been logged.
597 Makes sure that PROCESS is removed from the \"Compilation\"
598 tag in the mode line."
599 (when preview-error-condition
601 (signal (car preview-error-condition) (cdr preview-error-condition))
602 (setq preview-error-condition nil
603 compilation-in-progress (delq process compilation-in-progress)))))
605 (defun preview-gs-sentinel (process string)
606 "Sentinel function for rendering process.
607 Gets the default PROCESS and STRING arguments
608 and tries to restart Ghostscript if necessary."
610 (let ((status (process-status process)))
611 (when (memq status '(exit signal))
612 (setq compilation-in-progress (delq process compilation-in-progress)))
613 (when (buffer-name (process-buffer process))
614 (with-current-buffer (process-buffer process)
615 (goto-char (point-max))
616 (insert-before-markers "\n" mode-name " " string)
619 (substring (current-time-string) 0 -5))
621 (TeX-command-mode-line process)
622 (when (memq status '(exit signal))
624 ;; Throw away culprit, go on.
625 (let* ((err (concat preview-gs-answer "\n"
626 (process-name process) " " string))
627 (ov (preview-gs-behead-outstanding err)))
628 (when (and (null ov) preview-gs-queue)
630 (goto-char (if (marker-buffer (process-mark process))
631 (process-mark process)
633 (insert-before-markers err)))
634 (delete-process process)
637 ;; if process was killed explicitly by signal, or if nothing
638 ;; was processed, we give up on the matter altogether.
640 (when preview-ps-file
642 (preview-delete-file preview-ps-file)
644 (preview-gs-queue-empty))
646 ;; restart only if we made progress since last call
648 (dolist (ov preview-gs-outstanding)
649 (setq filenames (overlay-get ov 'filenames))
651 (preview-delete-file (nth 1 filenames))
653 (setcdr filenames nil)))
654 (setq preview-gs-queue (nconc preview-gs-outstanding
656 (setq preview-gs-outstanding nil)
657 (preview-gs-restart)))))))
658 (error (preview-log-error err "Ghostscript" process)))
659 (preview-reraise-error process))
661 (defun preview-gs-filter (process string)
662 "Filter function for processing Ghostscript output.
663 Gets the usual PROCESS and STRING parameters, see
664 `set-process-filter' for a description."
665 (with-current-buffer (process-buffer process)
666 (setq preview-gs-answer (concat preview-gs-answer string))
667 (while (string-match "GS\\(<[0-9]+\\)?>" preview-gs-answer)
668 (let* ((pos (match-end 0))
669 (answer (substring preview-gs-answer 0 pos)))
670 (setq preview-gs-answer (substring preview-gs-answer pos))
672 (preview-gs-transact process answer)
673 (error (preview-log-error err "Ghostscript filter" process))))))
674 (preview-reraise-error))
676 (defun preview-gs-restart ()
677 "Start a new Ghostscript conversion process."
678 (when preview-gs-queue
679 (if preview-gs-sequence
680 (setcar preview-gs-sequence (1+ (car preview-gs-sequence)))
681 (setq preview-gs-sequence (list 1)))
682 (setcdr preview-gs-sequence 1)
683 (let* ((process-connection-type nil)
684 (outfile (format "-dOutputFile=%s"
685 (preview-ps-quote-filename
686 (format "%s/pr%d-%%d.%s"
687 (car TeX-active-tempdir)
688 (car preview-gs-sequence)
689 preview-gs-image-type))))
691 (apply #'start-process
692 "Preview-Ghostscript"
696 preview-gs-command-line)))
697 (goto-char (point-max))
698 (insert-before-markers "Running `Preview-Ghostscript' with ``"
699 (mapconcat #'shell-quote-argument
701 (list preview-gs-command
703 preview-gs-command-line)
705 (setq preview-gs-answer "")
706 (process-kill-without-query process)
707 (set-process-sentinel process #'preview-gs-sentinel)
708 (set-process-filter process #'preview-gs-filter)
709 (process-send-string process preview-gs-init-string)
710 (setq mode-name "Preview-Ghostscript")
711 (push process compilation-in-progress)
712 (TeX-command-mode-line process)
713 (set-buffer-modified-p (buffer-modified-p))
716 (defun preview-gs-open (&optional setup)
717 "Start a Ghostscript conversion pass.
718 SETUP may contain a parser setup function."
719 (let ((image-info (assq preview-image-type preview-gs-image-type-alist)))
720 (setq preview-gs-image-type (nth 1 image-info))
721 (setq preview-gs-sequence nil)
722 (setq preview-gs-command-line (append
724 (nthcdr 2 image-info))
725 preview-gs-init-string
726 (format "{DELAYSAFER{.setsafe}if}stopped pop\
727 /.preview-BP currentpagedevice/BeginPage get dup \
728 null eq{pop{pop}bind}if def\
729 <</BeginPage{currentpagedevice/PageSize get dup 0 get 1 ne exch 1 get 1 ne or\
730 {.preview-BP %s}{pop}ifelse}bind/PageSize[1 1]>>setpagedevice\
731 /preview-do{[count 3 roll save]3 1 roll dup length 0 eq\
732 {pop}{setpagedevice}{ifelse .runandhide}\
733 stopped{handleerror quit}if \
734 aload pop restore}bind def "
735 (preview-gs-color-string preview-colors)))
736 (preview-gs-queue-empty)
737 (preview-parse-messages (or setup #'preview-gs-dvips-process-setup))))
739 (defun preview-gs-color-value (value)
740 "Return string to be used as color value for an RGB component.
741 Conversion from Emacs color numbers (0 to 65535) in VALUE
742 to Ghostscript floats."
743 (format "%g" (/ value 65535.0)))
745 (defun preview-pdf-color-string (colors)
746 "Return a string that patches PDF foreground color to work properly."
747 ;; Actually, this is rather brutal. It will only be invoked in
748 ;; cases, however, where previously it was not expected that
749 ;; anything readable turned up, anyway.
750 (let ((fg (aref colors 1)))
753 "/GS_PDF_ProcSet GS_PDF_ProcSet dup maxlength dict copy dup begin\
754 /graphicsbeginpage{//graphicsbeginpage exec "
755 (mapconcat #'preview-gs-color-value fg " ")
756 " 3 copy rg RG}bind store end readonly store "))))
758 (defun preview-gs-color-string (colors)
759 "Return a string setting up colors"
760 (let ((bg (aref colors 0))
762 (mask (aref colors 2))
763 (border (aref colors 3)))
765 (and (or (and mask border) (and bg (not fg)))
769 (mapconcat #'preview-gs-color-value bg " ")
770 " setrgbcolor clippath fill "))
772 (format "%s setrgbcolor false setstrokeadjust %g \
773 setlinewidth clippath strokepath \
774 matrix setmatrix true \
775 {2 index{newpath}if round exch round exch moveto pop false}\
776 {round exch round exch lineto}{curveto}{closepath}\
777 pathforall pop fill "
778 (mapconcat #'preview-gs-color-value mask " ")
780 ;; I hate antialiasing. Warp border to integral coordinates.
781 (and (or (and mask border) (and bg (not fg)))
785 (mapconcat #'preview-gs-color-value fg " ")
788 (defun preview-dvipng-color-string (colors res)
789 "Return color setup tokens for dvipng.
790 Makes a string of options suitable for passing to dvipng.
791 Pure borderless black-on-white will return an empty string."
793 ((bg (aref colors 0))
795 (mask (aref colors 2))
796 (border (aref colors 3)))
799 (format "--bg 'rgb %s' "
800 (mapconcat #'preview-gs-color-value bg " ")))
802 (format "--fg 'rgb %s' "
803 (mapconcat #'preview-gs-color-value fg " ")))
805 (format "--bd 'rgb %s' "
806 (mapconcat #'preview-gs-color-value mask " ")))
808 (format "--bd %d" (max 1 (round (/ (* res border) 72.0))))))))
810 (defun preview-gs-dvips-process-setup ()
811 "Set up Dvips process for conversions via gs."
812 (unless (preview-supports-image-type preview-gs-image-type)
813 (error "preview-image-type setting '%s unsupported by this Emacs"
814 preview-gs-image-type))
815 (setq preview-gs-command-line (append
816 preview-gs-command-line
817 (list (preview-gs-resolution
818 (preview-hook-enquiry preview-scale)
819 (car preview-resolution)
820 (cdr preview-resolution)))))
821 (if preview-parsed-pdfoutput
822 (preview-pdf2dsc-process-setup)
823 (let ((process (preview-start-dvips preview-fast-conversion)))
824 (setq TeX-sentinel-function #'preview-gs-dvips-sentinel)
825 (list process (current-buffer) TeX-active-tempdir preview-ps-file
826 preview-gs-image-type))))
828 (defun preview-dvipng-process-setup ()
829 "Set up dvipng process for conversion."
830 (setq preview-gs-command-line (append
831 preview-gs-command-line
832 (list (preview-gs-resolution
833 (preview-hook-enquiry preview-scale)
834 (car preview-resolution)
835 (cdr preview-resolution)))))
836 (if preview-parsed-pdfoutput
837 (if (preview-supports-image-type preview-gs-image-type)
838 (preview-pdf2dsc-process-setup)
839 (error "preview-image-type setting '%s unsupported by this Emacs"
840 preview-gs-image-type))
841 (unless (preview-supports-image-type preview-dvipng-image-type)
842 (error "preview-dvipng-image-type setting '%s unsupported by this Emacs"
843 preview-dvipng-image-type))
844 (let ((process (preview-start-dvipng)))
845 (setq TeX-sentinel-function #'preview-dvipng-sentinel)
846 (list process (current-buffer) TeX-active-tempdir t
847 preview-dvipng-image-type))))
850 (defun preview-pdf2dsc-process-setup ()
851 (let ((process (preview-start-pdf2dsc)))
852 (setq TeX-sentinel-function #'preview-pdf2dsc-sentinel)
853 (list process (current-buffer) TeX-active-tempdir preview-ps-file
854 preview-gs-image-type)))
856 (defun preview-dvips-abort ()
858 (preview-gs-queue-empty)
861 (let ((gsfile preview-gs-file))
862 (with-current-buffer TeX-command-buffer
863 (funcall (car gsfile) "dvi"))))
865 (when preview-ps-file
867 (preview-delete-file preview-ps-file)
869 (setq TeX-sentinel-function nil))
871 (defalias 'preview-dvipng-abort 'preview-dvips-abort)
872 ; "Abort a DviPNG run.")
874 (defun preview-gs-dvips-sentinel (process command &optional gsstart)
875 "Sentinel function for indirect rendering DviPS process.
876 The usual PROCESS and COMMAND arguments for
877 `TeX-sentinel-function' apply. Starts gs if GSSTART is set."
879 (let ((status (process-status process))
880 (gsfile preview-gs-file))
881 (cond ((eq status 'exit)
882 (delete-process process)
883 (setq TeX-sentinel-function nil)
886 (with-current-buffer TeX-command-buffer
887 (funcall (car gsfile) "dvi")))
890 (preview-prepare-fast-conversion))
894 (when preview-ps-file
896 (preview-delete-file preview-ps-file)
897 (file-error nil))))))
899 (delete-process process)
900 (preview-dvips-abort))))
901 (error (preview-log-error err "DviPS sentinel" process)))
902 (preview-reraise-error process))
904 (defun preview-pdf2dsc-sentinel (process command &optional gsstart)
905 "Sentinel function for indirect rendering PDF process.
906 The usual PROCESS and COMMAND arguments for
907 `TeX-sentinel-function' apply. Starts gs if GSSTART is set."
909 (let ((status (process-status process)))
910 (cond ((eq status 'exit)
911 (delete-process process)
912 (setq TeX-sentinel-function nil)
913 (setq preview-gs-init-string
914 (concat preview-gs-init-string
915 (preview-pdf-color-string preview-colors)))
916 (preview-prepare-fast-conversion)
920 (when preview-ps-file
922 (preview-delete-file preview-ps-file)
923 (file-error nil))))))
925 (delete-process process)
926 (preview-dvips-abort))))
927 (error (preview-log-error err "PDF2DSC sentinel" process)))
928 (preview-reraise-error process))
930 (defun preview-gs-close (process closedata)
931 "Clean up after PROCESS and set up queue accumulated in CLOSEDATA."
932 (setq preview-gs-queue (nconc preview-gs-queue closedata))
935 (if TeX-process-asynchronous
936 (if (and (eq (process-status process) 'exit)
937 (null TeX-sentinel-function))
938 ;; Process has already finished and run sentinel
940 (when preview-ps-file
942 (preview-delete-file preview-ps-file)
944 (preview-gs-restart))
945 (setq TeX-sentinel-function
946 `(lambda (process command)
947 (,(if preview-parsed-pdfoutput
948 'preview-pdf2dsc-sentinel
949 'preview-gs-dvips-sentinel)
953 (TeX-synchronous-sentinel "Preview-DviPS" (cdr preview-gs-file)
955 ;; pathological case: no previews although we sure thought so.
956 (delete-process process)
957 (unless (eq (process-status process) 'signal)
958 (preview-dvips-abort)))))
960 (defun preview-dvipng-sentinel (process command &optional placeall)
961 "Sentinel function for indirect rendering DviPNG process.
962 The usual PROCESS and COMMAND arguments for
963 `TeX-sentinel-function' apply. Places all snippets if PLACEALL is set."
965 (let ((status (process-status process)))
966 (cond ((eq status 'exit)
967 (delete-process process)
968 (setq TeX-sentinel-function nil)
970 (preview-dvipng-place-all)))
972 (delete-process process)
973 (preview-dvipng-abort))))
974 (error (preview-log-error err "DviPNG sentinel" process)))
975 (preview-reraise-error process))
977 (defun preview-dvipng-close (process closedata)
978 "Clean up after PROCESS and set up queue accumulated in CLOSEDATA."
979 (if preview-parsed-pdfoutput
980 (preview-gs-close process closedata)
981 (setq preview-gs-queue (nconc preview-gs-queue closedata))
984 (if TeX-process-asynchronous
985 (if (and (eq (process-status process) 'exit)
986 (null TeX-sentinel-function))
987 ;; Process has already finished and run sentinel
988 (preview-dvipng-place-all)
989 (setq TeX-sentinel-function (lambda (process command)
990 (preview-dvipng-sentinel
994 (TeX-synchronous-sentinel "Preview-DviPNG" (cdr preview-gs-file)
996 ;; pathological case: no previews although we sure thought so.
997 (delete-process process)
998 (unless (eq (process-status process) 'signal)
999 (preview-dvipng-abort))))))
1001 (defun preview-dsc-parse (file)
1002 "Parse DSC comments of FILE.
1003 Returns a vector with offset/length pairs corresponding to
1004 the pages. Page 0 corresponds to the initialization section."
1006 (set-buffer-multibyte nil)
1007 (insert-file-contents-literally file)
1008 (let ((last-pt (point-min))
1015 (while (search-forward-regexp "\
1016 %%\\(?:\\(BeginDocument:\\)\\|\
1017 \\(EndDocument[\n\r]\\)\\|\
1019 \\(Trailer[\n\r]\\)\\)" nil t)
1020 (setq pt (match-beginning 0))
1021 (cond ((null (memq (char-before pt) '(?\C-j ?\C-m nil))))
1022 (trailer (error "Premature %%%%Trailer in `%s' at offsets %d/%d"
1024 ((match-beginning 1)
1026 (setq lastbegin pt))
1027 (setq level (1+ level)))
1028 ((match-beginning 2)
1030 (error "Unmatched %%%%EndDocument in `%s' at offset %d"
1032 (setq level (1- level))))
1034 ((match-beginning 3)
1035 (push (list last-pt (- pt last-pt)) pagelist)
1037 ((match-beginning 4)
1038 (setq trailer pt))))
1039 (unless (zerop level)
1040 (error "Unmatched %%%%BeginDocument in `%s' at offset %d"
1043 (- (or trailer (point-max)) last-pt)) pagelist)
1044 (vconcat (nreverse pagelist)))))
1046 (defun preview-gs-dsc-cvx (page dsc)
1047 "Generate PostScript code accessing PAGE in the DSC object.
1048 The returned PostScript code will need the file on
1049 top of the stack, and will replace it with an executable
1050 object corresponding to the wanted page."
1051 (let ((curpage (aref dsc page)))
1052 (format "dup %d setfileposition %d()/SubFileDecode filter cvx"
1053 (1- (car curpage)) (nth 1 curpage))))
1055 (defun preview-ps-quote-filename (str &optional nonrel)
1056 "Make a PostScript string from filename STR.
1057 The file name is first made relative unless
1059 (unless nonrel (setq str (file-relative-name str)))
1061 (while (setq index (string-match "[\\()]" str index))
1062 (setq str (replace-match "\\\\\\&" t nil str)
1064 (concat "(" str ")")))
1066 (defun preview-prepare-fast-conversion ()
1067 "This fixes up all parameters for fast conversion."
1068 (let* ((file (if (consp (car preview-ps-file))
1069 (if (consp (caar preview-ps-file))
1070 (car (last (caar preview-ps-file)))
1071 (caar preview-ps-file))
1072 (car preview-ps-file)))
1073 (all-files (if (and (consp (car preview-ps-file))
1074 (consp (caar preview-ps-file)))
1075 (caar preview-ps-file)
1077 (setq preview-gs-dsc (preview-dsc-parse file))
1078 (setq preview-gs-init-string
1079 (concat (format "{<</PermitFileReading[%s]>> setuserparams \
1080 .locksafe} stopped pop "
1081 (mapconcat 'preview-ps-quote-filename all-files ""))
1082 preview-gs-init-string
1083 (format "[%s(r)file]aload exch %s .runandhide aload pop "
1084 (preview-ps-quote-filename file)
1085 (preview-gs-dsc-cvx 0 preview-gs-dsc))))))
1087 (defun preview-gs-urgentize (ov buff)
1088 "Make a displayed overlay render with higher priority.
1089 This function is used in fake conditional display properties
1090 for reordering the conversion order to prioritize on-screen
1091 images. OV is the overlay in question, and BUFF is the
1092 Ghostscript process buffer where the buffer-local queue
1094 ;; It does not matter that ov gets queued twice in that process: the
1095 ;; first version to get rendered will clear the 'queued property.
1096 ;; It cannot get queued more than twice since we remove the
1097 ;; conditional display property responsible for requeuing here.
1098 ;; We don't requeue if the overlay has been killed (its buffer made
1099 ;; nil). Not necessary, but while we are checking...
1100 ;; We must return t.
1101 (preview-remove-urgentization ov)
1102 (when (and (overlay-get ov 'queued)
1103 (overlay-buffer ov))
1104 (with-current-buffer buff
1105 (push ov preview-gs-queue)))
1109 (defun preview-gs-place (ov snippet box run-buffer tempdir ps-file imagetype)
1110 "Generate an image placeholder rendered over by Ghostscript.
1111 This enters OV into all proper queues in order to make it render
1112 this image for real later, and returns the overlay after setting
1113 a placeholder image. SNIPPET gives the number of the
1114 snippet in question for the file to be generated.
1115 BOX is a bounding box if we already know one via TeX.
1116 RUN-BUFFER is the buffer of the TeX process,
1117 TEMPDIR is the correct copy of `TeX-active-tempdir',
1118 PS-FILE is a copy of `preview-ps-file', IMAGETYPE is the image type
1119 for the file extension."
1120 (overlay-put ov 'filenames
1121 (unless (eq ps-file t)
1123 (preview-make-filename
1125 (format "preview.%03d" snippet))
1127 (overlay-put ov 'queued
1128 (vector box nil snippet))
1129 (overlay-put ov 'preview-image
1130 (list (preview-icon-copy preview-nonready-icon)))
1131 (preview-add-urgentization #'preview-gs-urgentize ov run-buffer)
1134 (defun preview-mouse-open-error (string)
1135 "Display STRING in a new view buffer on click."
1136 (let ((buff (get-buffer-create
1137 "*Preview-Ghostscript-Error*")))
1138 (with-current-buffer buff
1139 (kill-all-local-variables)
1140 (set (make-local-variable 'view-exit-action) #'kill-buffer)
1141 (setq buffer-undo-list t)
1144 (goto-char (point-min)))
1145 (view-buffer-other-window buff)))
1147 (defun preview-mouse-open-eps (file &optional position)
1148 "Display eps FILE in a view buffer on click.
1149 Place point at POSITION, else beginning of file."
1150 (let ((default-major-mode
1152 (assoc-default "x.ps" auto-mode-alist #'string-match)
1153 default-major-mode))
1154 (buff (get-file-buffer file)))
1157 (pop-to-buffer buff)
1158 (view-file-other-window file))
1159 (goto-char (or position (point-min)))
1160 (if (eq major-mode 'ps-mode) ; Bundled with GNU Emacs
1161 (message "%s" (substitute-command-keys "\
1162 Try \\[ps-run-start] \\[ps-run-buffer] and \
1163 \\<ps-run-mode-map>\\[ps-run-mouse-goto-error] on error offset." )))
1164 (if (eq major-mode 'postscript-mode) ; Bundled with XEmacs, limited
1165 (message "%s" (substitute-command-keys "\
1166 Try \\[ps-shell] and \\[ps-execute-buffer]."))))))
1168 (defun preview-gs-flag-error (ov err)
1169 "Make an eps error flag in overlay OV for ERR string."
1170 (let* ((filenames (overlay-get ov 'filenames))
1171 (file (car (nth 0 filenames)))
1172 (outfile (format "-dOutputFile=%s"
1173 (preview-ps-quote-filename
1174 (car (nth 1 filenames)))))
1176 `(lambda() (interactive "@")
1177 (preview-mouse-open-error
1179 (mapconcat #'shell-quote-argument
1183 preview-gs-command-line)
1186 preview-gs-init-string
1187 (aref (overlay-get ov 'queued) 1)
1190 (preview-make-clickable
1193 "%s views error message
1196 `(lambda() (interactive)
1198 '("PostScript error"
1199 ["View error" ,ps-open]
1201 (lambda () (interactive "@")
1202 ,(if preview-ps-file
1203 `(preview-mouse-open-eps
1204 ,(if (consp (car file))
1207 ,(nth 0 (aref preview-gs-dsc
1208 (aref (overlay-get ov 'queued) 2))))
1209 `(preview-mouse-open-eps ,file)))]))))))
1210 (overlay-put ov 'strings (cons str str))
1211 (preview-toggle ov)))
1213 (defun preview-gs-transact (process answer)
1214 "Work off Ghostscript transaction.
1215 This routine is the action routine called via the process filter.
1216 The Ghostscript process buffer of PROCESS will already be selected, and
1217 and the standard output of Ghostscript up to the next prompt will be
1219 (let ((ov (pop preview-gs-outstanding))
1221 (string-match "\\`GS\\(<[0-9]+\\)?>\\'" answer ))))
1222 (when (and ov (overlay-buffer ov))
1223 (let ((queued (overlay-get ov 'queued)))
1225 (let* ((bbox (aref queued 0))
1226 (filenames (overlay-get ov 'filenames))
1227 (oldfile (nth 0 filenames))
1228 (newfile (nth 1 filenames)))
1230 (preview-gs-flag-error ov answer)
1232 (preview-delete-file oldfile)
1234 (overlay-put ov 'filenames (cdr filenames))
1235 (preview-replace-active-icon
1237 (preview-create-icon (car newfile)
1238 preview-gs-image-type
1239 (preview-ascent-from-bb
1241 (aref preview-colors 2))))
1242 (overlay-put ov 'queued nil)))))
1243 (while (and (< (length preview-gs-outstanding)
1244 preview-gs-outstanding-limit)
1245 (setq ov (pop preview-gs-queue)))
1246 (let ((queued (overlay-get ov 'queued)))
1248 (not (memq ov preview-gs-outstanding))
1249 (overlay-buffer ov))
1250 (let* ((filenames (overlay-get ov 'filenames))
1251 (oldfile (car (nth 0
1254 (preview-make-filename
1255 (format "pr%d-%d.%s"
1256 (car preview-gs-sequence)
1257 (cdr preview-gs-sequence)
1258 preview-gs-image-type)
1259 TeX-active-tempdir))))))
1260 (bbox (aset queued 0
1261 (or (and preview-prefer-TeX-bb
1263 (and (stringp oldfile)
1267 (error "No bounding box"))))
1268 (snippet (aref queued 2))
1271 "%s<<%s>>preview-do\n"
1277 (format "%s(r)file cvx"
1278 (preview-ps-quote-filename
1280 (car (last oldfile))
1282 (if preview-parsed-tightpage
1284 (format "/PageSize[%g %g]/PageOffset[%g \
1285 %g[1 1 dtransform exch]{0 ge{neg}if exch}forall]"
1286 (- (aref bbox 2) (aref bbox 0))
1287 (- (aref bbox 3) (aref bbox 1))
1288 (aref bbox 0) (aref bbox 1))))))
1289 (setcdr preview-gs-sequence (1+ (cdr preview-gs-sequence)))
1290 (setq preview-gs-outstanding
1291 (nconc preview-gs-outstanding
1293 (aset queued 1 gs-line)
1294 ;; ignore errors because of dying processes: they will get
1295 ;; caught by the sentinel, anyway.
1297 (process-send-string
1301 (unless preview-gs-outstanding
1303 (process-send-eof process)
1306 (defun preview-hook-enquiry (hook)
1307 "Gets a value from a configured hook.
1308 HOOK is a list or single item, for which the first resolving to
1309 non-nil counts. Entries can be a callable function, or
1310 a symbol that is consulted, or a value. Lists are evaluated
1312 (cond ((functionp hook)
1316 (while (and (not res) hook)
1317 (setq res (preview-hook-enquiry (car hook))
1320 ((and (symbolp hook) (boundp hook))
1321 (symbol-value hook))
1324 (defcustom preview-scale-function #'preview-scale-from-face
1325 "*Scale factor for included previews.
1326 This can be either a function to calculate the scale, or
1328 :group 'preview-appearance
1329 :type '(choice (function-item preview-scale-from-face)
1332 (function :value preview-scale-from-face)))
1334 (defcustom preview-default-document-pt 10
1335 "*Assumed document point size for `preview-scale-from-face'.
1336 If the point size (such as 11pt) of the document cannot be
1337 determined from the document options itself, assume this size.
1338 This is for matching screen font size and previews."
1339 :group 'preview-appearance
1341 '(choice (const :tag "10pt" 10)
1342 (const :tag "11pt" 11)
1343 (const :tag "12pt" 12)
1344 (number :tag "Other" :value 11.0))
1347 (defcustom preview-document-pt-list '(preview-parsed-font-size
1348 preview-auctex-font-size
1349 preview-default-document-pt)
1350 "*How `preview-document-pt' figures out the document size."
1351 :group 'preview-appearance
1354 ;; This is a bug: type function seems to match variables, too.
1355 (restricted-sexp :match-alternatives (functionp)
1356 :tag "Function" :value preview-auctex-font-size)
1357 (variable :value preview-parsed-font-size)
1358 (number :value 11))))
1360 (defun preview-auctex-font-size ()
1361 "Calculate the default font size of document.
1362 If packages, classes or styles were called with an option
1363 like 10pt, size is taken from the first such option if you
1364 had let your document be parsed by AucTeX."
1365 (catch 'return (dolist (option (TeX-style-list))
1366 (if (string-match "\\`\\([0-9]+\\)pt\\'" option)
1369 (match-string 1 option)))))))
1371 (defsubst preview-document-pt ()
1372 "Calculate the default font size of document."
1373 (preview-hook-enquiry preview-document-pt-list))
1375 (defun preview-scale-from-face ()
1376 "Calculate preview scale from `preview-reference-face'.
1377 This calculates the scale of EPS images from a document assumed
1378 to have a default font size given by function `preview-document-pt'
1379 so that they match the reference face in height."
1381 (/ ,(/ (preview-inherited-face-attribute 'preview-reference-face :height
1383 (preview-document-pt))))
1385 (defvar preview-min-spec)
1387 (defun preview-make-image (symbol)
1388 "Make an image from a preview spec list.
1389 The first spec that is workable (given the current setting of
1390 `preview-min-spec') from the given symbol is used here. The
1391 icon is cached in the property list of the symbol."
1392 (let ((alist (get 'preview-min-alist symbol)))
1394 (assq preview-min-spec alist)
1395 (car (put symbol 'preview-min-alist
1397 (cons preview-min-spec
1398 (preview-filter-specs
1399 (symbol-value symbol)))
1402 (defun preview-filter-specs (spec-list)
1403 "Find the first of the fitting specs and make an image."
1405 (while (and spec-list
1407 (catch 'preview-filter-specs
1408 (preview-filter-specs-1 (car spec-list))))))
1409 (setq spec-list (cdr spec-list)))
1412 (defun preview-filter-specs-1 (specs)
1414 (if (get 'preview-filter-specs (car specs))
1415 (apply (get 'preview-filter-specs (car specs)) specs)
1416 `(,(nth 0 specs) ,(nth 1 specs)
1417 ,@(preview-filter-specs-1 (nthcdr 2 specs))))))
1419 (put 'preview-filter-specs :min
1420 #'(lambda (keyword value &rest args)
1421 (if (> value preview-min-spec)
1422 (throw 'preview-filter-specs nil)
1423 (preview-filter-specs-1 args))))
1425 (defvar preview-datadir (file-name-directory load-file-name)
1426 "The directory relative to which package data may be found.
1427 This should be hardwired into the startup file containing the
1428 autoloads for preview-latex.")
1430 (put 'preview-filter-specs :file
1431 #'(lambda (keyword value &rest args)
1432 `(:file ,(expand-file-name value (expand-file-name "images"
1434 ,@(preview-filter-specs-1 args))))
1436 (defun preview-ascent-from-bb (bb)
1437 "This calculates the image ascent from its bounding box.
1438 The bounding box BB needs to be a 4-component vector of
1439 numbers (can be float if available)."
1440 ;; baseline is at 1in from the top of letter paper (11in), so it is
1441 ;; at 10in from the bottom precisely, which is 720 in PostScript
1442 ;; coordinates. If our bounding box has its bottom not above this
1443 ;; line, and its top above, we can calculate a useful ascent value.
1444 ;; If not, something is amiss. We just use 100 in that case.
1446 (let ((bottom (aref bb 1))
1448 (if (and (<= bottom 720)
1450 (round (* 100.0 (/ (- top 720.0) (- top bottom))))
1453 (defface preview-face '((((background dark))
1454 (:background "dark slate gray"))
1456 (:background "beige")))
1457 "Face to use for the preview source."
1458 :group 'preview-appearance)
1460 (defface preview-reference-face '((t nil))
1461 "Face consulted for colors and scale of active previews.
1462 Fallback to :inherit and 'default implemented."
1463 :group 'preview-appearance)
1465 (defcustom preview-auto-reveal
1466 '(eval (preview-arrived-via (key-binding [left]) (key-binding [right])
1467 'backward-char 'forward-char))
1468 "*Cause previews to open automatically when entered.
1472 a symbol will have its value consulted if it exists,
1473 defaulting to NIL if it doesn't.
1474 An integer will specify a maximum cursor movement distance.
1475 Larger movements won't open the preview.
1476 A CONS-cell means to call a function for determining the value.
1477 The CAR of the cell is the function to call which receives
1478 the CDR of the CONS-cell in the rest of the arguments, while
1479 point and current buffer point to the position in question.
1480 All of the options show reasonable defaults."
1481 :group 'preview-appearance
1482 :type '(choice (const :tag "Off" nil)
1484 (symbol :tag "Indirect variable" :value reveal-mode)
1485 (integer :tag "Maximum distance" :value 1)
1486 (cons :tag "Function call"
1487 :value (eval (preview-arrived-via
1488 (key-binding [left])
1489 (key-binding [right])))
1490 function (list :tag "Argument list"
1491 (repeat :inline t sexp)))))
1493 (defun preview-auto-reveal-p (mode distance)
1494 "Decide whether to auto-reveal.
1495 Returns non-NIL if region should be auto-opened.
1496 See `preview-auto-reveal' for definitions of MODE, which gets
1497 set to `preview-auto-reveal'. DISTANCE specifies the movement
1498 distance with which point has been reached in case it has been
1499 a movement starting in the current buffer."
1500 (cond ((symbolp mode)
1502 (symbol-value mode)))
1504 (and distance (/= 0 distance) (<= (abs distance) mode)))
1506 (apply (car mode) (cdr mode)))
1509 (defun preview-arrived-via (&rest list)
1510 "Indicate auto-opening.
1511 Returns non-NIL if called by one of the commands in LIST."
1512 (memq this-command list))
1514 (defcustom preview-equality-transforms '(identity
1515 preview-canonical-spaces)
1516 "Transformation functions for region changes.
1517 These functions are tried in turn on the strings from the
1518 regions of a preview to decide whether a preview is to be considered
1519 changed. If any transform leads to equal results, the preview is
1520 considered unchanged."
1521 :group 'preview-appearance
1522 :type '(repeat function))
1524 (defun preview-relaxed-string= (&rest args)
1525 "Check for functional equality of arguments.
1526 The arguments ARGS are checked for equality by using
1527 `preview-equality-transforms' on them until it is exhausted
1528 or one transform returns equality."
1529 (let ((lst preview-equality-transforms))
1530 (while (and lst (not (apply #'string= (mapcar (car lst) args))))
1531 (setq lst (cdr lst)))
1534 (defun preview-canonical-spaces (arg)
1535 "Convert ARG into canonical form.
1536 Removes comments and collapses white space, except for multiple newlines."
1538 (while (setq pos (string-match "\\s<.*[\n\r][ \t]*" arg pos))
1539 (setq arg (replace-match "" t t arg 0)))
1540 (while (setq pos (string-match "[ \t]*\\(\\([ \t]\\)\\|[\n\r][ \t]*\\)"
1542 (setq arg (replace-match (if (match-beginning 2) " " "\n") t t arg 0)
1544 (while (setq pos (string-match "\n+" arg pos))
1545 (if (string= "\n" (match-string 0 arg))
1546 (setq arg (replace-match " " t t arg 0)
1548 (setq pos (match-end 0)))))
1551 (defun preview-regenerate (ovr)
1552 "Pass the modified region in OVR again through LaTeX."
1553 (let ((begin (overlay-start ovr))
1554 (end (overlay-end ovr)))
1555 (with-current-buffer (overlay-buffer ovr)
1556 (preview-delete ovr)
1557 (preview-region begin end))))
1559 (defcustom preview-inner-environments '("Bmatrix" "Vmatrix" "aligned"
1560 "array" "bmatrix" "cases"
1561 "gathered" "matrix" "pmatrix"
1562 "smallmatrix" "split"
1563 "subarray" "vmatrix")
1564 "Environments not to be previewed on their own."
1565 :group 'preview-latex
1566 :type '(repeat string))
1569 (defun preview-next-border (backwards)
1570 "Search for the next interesting border for `preview-at-point'.
1571 Searches backwards if BACKWARDS is non-nil."
1572 (let (history preview-state (pt (point)))
1580 (previous-single-char-property-change
1581 pt 'preview-state)) (point-min))
1582 (get-char-property (1- pt) 'preview-state)
1583 (throw 'exit (or history (point-min))))
1585 (next-single-char-property-change
1586 pt 'preview-state)) (point-max))
1587 (get-char-property pt 'preview-state)
1588 (throw 'exit (or history (point-max))))))
1589 '(active inactive)))
1590 (setq history (and (not preview-state) pt)))
1593 (defun preview-at-point ()
1594 "Do the appropriate preview thing at point.
1595 If point is positioned on or inside of an unmodified preview area,
1596 its visibility is toggled.
1598 If not, the surroundings are run through preview. The
1599 surroundings don't extend into unmodified previews or past
1600 contiguous previews invalidated by modifications.
1602 Overriding any other action, if a region is
1603 active (`transient-mark-mode' or `zmacs-regions'), it is run
1604 through `preview-region'."
1606 (if (TeX-active-mark)
1607 (preview-region (region-beginning) (region-end))
1609 (dolist (ovr (overlays-in (max (point-min) (1- (point)))
1610 (min (point-max) (1+ (point)))))
1611 (let ((preview-state (overlay-get ovr 'preview-state)))
1613 (unless (eq preview-state 'disabled)
1614 (preview-toggle ovr 'toggle (selected-window))
1616 (preview-region (preview-next-border t)
1617 (preview-next-border nil)))))
1619 (defun preview-disabled-string (ov)
1620 "Generate a before-string for disabled preview overlay OV."
1621 (concat (preview-make-clickable
1622 (overlay-get ov 'preview-map)
1625 %s regenerates preview
1627 `(lambda() (interactive) (preview-regenerate ,ov)))
1628 ;; icon on separate line only for stuff starting on its own line
1629 (with-current-buffer (overlay-buffer ov)
1633 (goto-char (overlay-start ov))
1634 (if (bolp) "\n" ""))))))
1636 (defun preview-disable (ovr)
1637 "Change overlay behaviour of OVR after source edits."
1638 (overlay-put ovr 'queued nil)
1639 (preview-remove-urgentization ovr)
1640 (overlay-put ovr 'preview-image nil)
1641 (overlay-put ovr 'timestamp nil)
1642 (setcdr (overlay-get ovr 'strings) (preview-disabled-string ovr))
1643 (preview-toggle ovr)
1644 (overlay-put ovr 'preview-state 'disabled)
1645 (dolist (filename (overlay-get ovr 'filenames))
1647 (preview-delete-file filename)
1649 (overlay-put ovr 'filenames nil)))
1651 (defun preview-delete (ovr &rest ignored)
1652 "Delete preview overlay OVR, taking any associated file along.
1653 IGNORED arguments are ignored, making this function usable as
1654 a hook in some cases"
1655 (let ((filenames (overlay-get ovr 'filenames)))
1656 (overlay-put ovr 'filenames nil)
1657 (delete-overlay ovr)
1658 (dolist (filename filenames)
1660 (preview-delete-file filename)
1661 (file-error nil)))))
1663 (defun preview-clearout (&optional start end timestamp)
1664 "Clear out all previews in the current region.
1665 When called interactively, the current region is used.
1666 Non-interactively, the region between START and END is
1667 affected. Those two values default to the borders of
1668 the entire buffer. If TIMESTAMP is non-nil, previews
1669 with a `timestamp' property of it are kept."
1671 (dolist (ov (overlays-in (or start (point-min))
1672 (or end (point-max))))
1673 (and (overlay-get ov 'preview-state)
1675 (equal timestamp (overlay-get ov 'timestamp))))
1676 (preview-delete ov))))
1678 (defun preview-clearout-buffer (&optional buffer)
1679 "Clearout BUFFER from previews, current buffer if nil."
1682 (with-current-buffer buffer (preview-clearout))
1683 (preview-clearout)))
1685 (defun preview-clearout-section ()
1686 "Clearout previews from LaTeX section."
1689 (LaTeX-mark-section)
1690 (preview-clearout (region-beginning) (region-end))))
1692 (defun preview-clearout-at-point ()
1693 "Clearout any preview at point."
1695 (preview-clearout (max (point-min) (1- (point)))
1696 (min (point-max) (1+ (point)))))
1698 (defun preview-walk-document (func)
1699 "Cycle through all buffers belonging to current document.
1700 Each buffer having the same master file as the current file
1701 has FUNC called with its current buffer being set to it."
1702 (let* ((buffers (buffer-list))
1703 (master (expand-file-name (TeX-master-file t)))
1704 (default-buffers (list (current-buffer)
1705 (find-buffer-visiting master))))
1707 (with-current-buffer (pop buffers)
1709 (or (memq (current-buffer) default-buffers)
1710 (and (memq major-mode '(plain-tex-mode latex-mode))
1711 (or (stringp TeX-master)
1713 (string= (expand-file-name (TeX-master-file t))
1717 (defun preview-clearout-document ()
1718 "Clear out all previews in current document.
1719 The document consists of all buffers that have the same master file
1720 as the current buffer. This makes the current document lose
1723 (preview-walk-document #'preview-clearout-buffer))
1725 (defun preview-kill-buffer-cleanup (&optional buf)
1726 "This is a cleanup function just for use in hooks.
1727 Cleans BUF or current buffer. The difference to
1728 `preview-clearout-buffer' is that previews
1729 associated with the last buffer modification time are
1731 (with-current-buffer (or buf (current-buffer))
1734 (preview-clearout (point-min) (point-max) (visited-file-modtime)))))
1736 (add-hook 'kill-buffer-hook #'preview-kill-buffer-cleanup)
1737 (add-hook 'before-revert-hook #'preview-kill-buffer-cleanup)
1739 (defvar preview-last-counter)
1741 (defun preview-extract-counters (ctr)
1742 (setq preview-last-counter
1743 (prog1 (copy-sequence ctr)
1744 (dolist (elt preview-last-counter)
1745 (setq ctr (delete elt ctr)))))
1746 (apply #'concat ctr))
1748 (defun desktop-buffer-preview-misc-data (&rest ignored)
1749 "Hook function that extracts previews for persistent sessions."
1750 (unless (buffer-modified-p)
1751 (setq preview-last-counter nil)
1754 (let (save-info (timestamp (visited-file-modtime)))
1755 (dolist (ov (sort (overlays-in (point-min) (point-max))
1756 (lambda (x y) (< (overlay-start x)
1757 (overlay-start y)))))
1758 (when (and (memq (overlay-get ov 'preview-state) '(active inactive))
1759 (null (overlay-get ov 'queued))
1760 (cdr (overlay-get ov 'preview-image)))
1761 (push (preview-dissect ov timestamp) save-info)))
1763 (cons 'preview (cons timestamp (nreverse save-info))))))))
1765 (eval-after-load "desktop"
1767 'desktop-buffer-misc-functions
1768 #'desktop-buffer-preview-misc-data))
1770 (defvar preview-temp-dirs nil
1771 "List of top level temporary directories in use from preview.
1772 Any directory not in this list will be cleared out by preview
1775 (defun preview-dissect (ov timestamp)
1776 "Extract all persistent data from OV and TIMESTAMP it."
1777 (let ((filenames (butlast (nth 0 (overlay-get ov 'filenames)))))
1778 (overlay-put ov 'timestamp timestamp)
1779 (list (overlay-start ov)
1781 (cdr (overlay-get ov 'preview-image))
1783 (let ((ctr (overlay-get ov 'preview-counters)))
1785 (cons (preview-extract-counters (car ctr))
1786 (preview-extract-counters (cdr ctr))))))))
1788 (defun preview-buffer-restore-internal (buffer-misc)
1789 "Restore previews from BUFFER-MISC if proper.
1790 Remove them if they have expired."
1791 (let ((timestamp (visited-file-modtime)) tempdirlist files)
1792 (setq preview-parsed-counters nil)
1793 (when (eq 'preview (pop buffer-misc))
1794 (preview-get-geometry)
1795 (if (equal (pop buffer-misc) timestamp)
1796 (dolist (ovdata buffer-misc)
1798 (apply #'preview-reinstate-preview tempdirlist
1800 (dolist (ovdata buffer-misc)
1801 (setq files (nth 3 ovdata))
1803 (delete-file (nth 0 files))
1805 (unless (member (nth 1 files) tempdirlist)
1806 (push (nth 1 files) tempdirlist)))
1807 (dolist (dir tempdirlist)
1809 (delete-directory dir)
1810 (file-error nil)))))))
1813 (defun preview-buffer-restore (buffer-misc)
1814 "At end of desktop load, reinstate previews.
1815 This delay is so that minor modes changing buffer positions
1816 \(like `x-symbol-mode' does) will not wreak havoc.
1817 BUFFER-MISC is the appropriate data to be used."
1818 (add-hook 'desktop-delay-hook `(lambda ()
1819 (with-current-buffer ,(current-buffer)
1820 (preview-buffer-restore-internal
1823 (defun desktop-buffer-preview (desktop-buffer-file-name
1825 desktop-buffer-misc)
1826 "Hook function for restoring persistent previews into a buffer."
1827 (when (and desktop-buffer-file-name
1828 (file-readable-p desktop-buffer-file-name))
1829 (let ((buf (find-file-noselect desktop-buffer-file-name)))
1830 (if (eq (car desktop-buffer-misc) 'preview)
1831 (with-current-buffer buf
1832 (preview-buffer-restore desktop-buffer-misc)
1836 (eval-after-load "desktop"
1837 '(if (boundp 'desktop-buffer-mode-handlers)
1838 (add-to-list 'desktop-buffer-mode-handlers
1839 '(latex-mode . desktop-buffer-preview))
1840 (add-hook 'desktop-buffer-handlers '(lambda ()
1841 (desktop-buffer-preview
1842 desktop-buffer-file-name
1844 desktop-buffer-misc)))))
1846 (defcustom preview-auto-cache-preamble 'ask
1847 "*Whether to generate a preamble cache format automatically.
1848 Possible values are nil, t, and `ask'."
1849 :group 'preview-latex
1850 :type '(choice (const :tag "Cache" t)
1851 (const :tag "Don't cache" nil)
1852 (const :tag "Ask" ask)))
1854 (defvar preview-dumped-alist nil
1855 "Alist of dumped masters.
1856 The elements are (NAME . ASSOC). NAME is the master file name
1857 \(without extension), ASSOC is what to do with regard to this
1858 format. Possible values: NIL means no format is available
1859 and none should be generated. T means no format is available,
1860 it should be generated on demand. If the value is a cons cell,
1861 the CAR of the cons cell is the command with which the format
1862 has been generated, and the CDR is some Emacs-flavor specific
1863 value used for maintaining a watch on possible changes of the
1866 (defun preview-cleanout-tempfiles ()
1867 "Clean out all directories and files with non-persistent data.
1868 This is called as a hook when exiting Emacs."
1869 (mapc #'preview-kill-buffer-cleanup (buffer-list))
1870 (mapc #'preview-format-kill preview-dumped-alist))
1872 (defun preview-inactive-string (ov)
1873 "Generate before-string for an inactive preview overlay OV.
1874 This is for overlays where the source text has been clicked
1875 visible. For efficiency reasons it is expected that the buffer
1876 is already selected and unnarrowed."
1878 (preview-make-clickable (overlay-get ov 'preview-map)
1881 %s redisplays preview
1883 ;; icon on separate line only for stuff starting on its own line
1884 (with-current-buffer (overlay-buffer ov)
1888 (goto-char (overlay-start ov))
1889 (if (bolp) "\n" ""))))))
1891 (defun preview-dvipng-place-all ()
1892 "Place all images dvipng has created, if any.
1893 Deletes the dvi file when finished."
1894 (let (filename queued oldfiles snippet)
1895 (dolist (ov (prog1 preview-gs-queue (setq preview-gs-queue nil)))
1896 (when (and (setq queued (overlay-get ov 'queued))
1897 (setq snippet (aref (overlay-get ov 'queued) 2))
1898 (setq filename (preview-make-filename
1899 (format "prev%03d.%s"
1900 snippet preview-dvipng-image-type)
1901 TeX-active-tempdir)))
1902 (if (file-exists-p (car filename))
1904 (overlay-put ov 'filenames (list filename))
1905 (preview-replace-active-icon
1907 (preview-create-icon (car filename)
1908 preview-dvipng-image-type
1909 (preview-ascent-from-bb
1911 (aref preview-colors 2)))
1912 (overlay-put ov 'queued nil))
1913 (push filename oldfiles)
1914 (overlay-put ov 'filenames nil)
1915 (push ov preview-gs-queue))))
1916 (if (setq preview-gs-queue (nreverse preview-gs-queue))
1918 (preview-start-dvips preview-fast-conversion)
1919 (setq TeX-sentinel-function (lambda (process command)
1920 (preview-gs-dvips-sentinel
1924 (dolist (ov preview-gs-queue)
1925 (setq snippet (aref (overlay-get ov 'queued) 2))
1926 (overlay-put ov 'filenames
1928 (preview-make-filename
1930 (format "preview.%03d" snippet))
1931 TeX-active-tempdir))))
1932 (while (setq filename (pop oldfiles))
1934 (preview-delete-file filename)
1937 (let ((gsfile preview-gs-file))
1939 (with-current-buffer TeX-command-buffer
1940 (funcall (car gsfile) "dvi"))))
1941 (file-error nil)))))
1943 (defun preview-active-string (ov)
1944 "Generate before-string for active image overlay OV."
1945 (preview-make-clickable
1946 (overlay-get ov 'preview-map)
1947 (car (overlay-get ov 'preview-image))
1951 (defun preview-make-filename (file tempdir)
1952 "Generate a preview filename from FILE and TEMPDIR.
1953 Filenames consist of a CONS-cell with absolute file name as CAR
1954 and TEMPDIR as CDR. TEMPDIR is a copy of `TeX-active-tempdir'
1955 with the directory name, the reference count and its top directory
1956 name elements. If FILE is already in that form, the file name itself
1957 gets converted into a CONS-cell with a name and a reference count."
1960 (if (consp (car file))
1961 (setcdr (car file) (1+ (cdr (car file))))
1962 (setcar file (cons (car file) 1)))
1964 (setcar (nthcdr 2 tempdir) (1+ (nth 2 tempdir)))
1965 (cons (expand-file-name file (nth 0 tempdir))
1968 (defun preview-attach-filename (attached file)
1969 "Attaches the absolute file name ATTACHED to FILE."
1970 (if (listp (caar file))
1971 (setcar (car file) (cons attached (caar file)))
1972 (setcar (car file) (list attached (caar file))))
1975 (defun preview-delete-file (file)
1976 "Delete a preview FILE.
1977 See `preview-make-filename' for a description of the data
1978 structure. If the containing directory becomes empty,
1979 it gets deleted as well."
1981 (if (consp (car file))
1983 (setcdr (car file) (1- (cdr (car file)))))
1988 (if (listp filename)
1989 (dolist (elt filename) (delete-file elt))
1990 (delete-file filename))
1991 (let ((tempdir (cdr file)))
1993 (if (> (nth 2 tempdir) 1)
1994 (setcar (nthcdr 2 tempdir) (1- (nth 2 tempdir)))
1996 (delete-directory (nth 0 tempdir)))))))))
1998 (defvar preview-buffer-has-counters nil)
1999 (make-variable-buffer-local 'preview-buffer-has-counters)
2001 (defun preview-place-preview (snippet start end
2002 box counters tempdir place-opts)
2003 "Generate and place an overlay preview image.
2004 This generates the filename for the preview
2005 snippet SNIPPET in the current buffer, and uses it for the
2006 region between START and END. BOX is an optional preparsed
2007 TeX bounding BOX passed on to the `place' hook.
2008 COUNTERS is the info about saved counter structures.
2009 TEMPDIR is a copy of `TeX-active-tempdir'.
2010 PLACE-OPTS are additional arguments passed into
2011 `preview-parse-messages'. Returns
2012 a list with additional info from the placement hook.
2013 Those lists get concatenated together and get passed
2015 (preview-clearout start end tempdir)
2016 (let ((ov (make-overlay start end nil nil nil)))
2017 (when (fboundp 'TeX-overlay-prioritize)
2018 (overlay-put ov 'priority (TeX-overlay-prioritize start end)))
2019 (overlay-put ov 'preview-map
2020 (preview-make-clickable
2022 `(lambda(event) (interactive "e")
2023 (preview-toggle ,ov 'toggle event))
2024 `(lambda(event) (interactive "e")
2025 (preview-context-menu ,ov event))))
2026 (overlay-put ov 'timestamp tempdir)
2027 (when (cdr counters)
2028 (overlay-put ov 'preview-counters counters)
2029 (setq preview-buffer-has-counters t))
2030 (prog1 (apply #'preview-call-hook 'place ov snippet box
2032 (overlay-put ov 'strings
2033 (list (preview-active-string ov)))
2034 (preview-toggle ov t))))
2036 ;; The following is a brutal hack. It relies on `begin' being let to
2037 ;; the start of the interesting area when TeX-region-create is being
2040 (defun preview-counter-find (begin)
2041 "Fetch the next preceding or next preview-counters property.
2042 Factored out because of compatibility macros XEmacs would
2044 ;; The following two lines are bug workaround for Emacs < 22.1.
2046 (setq begin (marker-position begin)))
2047 (or (car (get-char-property begin 'preview-counters))
2048 (cdr (get-char-property (max (point-min)
2051 (cdr (get-char-property
2053 (1- (previous-single-char-property-change
2055 'preview-counters)))
2057 (car (get-char-property
2058 (next-single-char-property-change begin 'preview-counters)
2059 'preview-counters))))
2061 (defadvice TeX-region-create (around preview-counters)
2062 "Write out counter information to region."
2063 (let ((TeX-region-extra
2065 (and (boundp 'begin)
2066 preview-buffer-has-counters
2071 (preview-counter-find (symbol-value 'begin)))
2076 (defun preview-reinstate-preview (tempdirlist timestamp start end
2077 image filename &optional counters)
2078 "Reinstate a single preview.
2079 This gets passed TEMPDIRLIST, a list consisting of the kind
2080 of entries used in `TeX-active-tempdir', and TIMESTAMP, the
2081 time stamp under which the file got read in. It returns an augmented
2082 list. START and END give the buffer location where the preview
2083 is to be situated, IMAGE the image to place there, and FILENAME
2084 the file to use: a triple consisting of filename, its temp directory
2085 and the corresponding topdir. COUNTERS is saved counter information,
2088 (or (null filename) (file-readable-p (car filename)))
2090 (unless (equal (nth 1 filename) (car TeX-active-tempdir))
2091 (setq TeX-active-tempdir
2092 (or (assoc (nth 1 filename) tempdirlist)
2093 (car (push (append (cdr filename) (list 0))
2095 (setcar (cdr TeX-active-tempdir)
2096 (car (or (member (nth 1 TeX-active-tempdir)
2099 (add-hook 'kill-emacs-hook
2100 #'preview-cleanout-tempfiles t)
2101 (push (nth 1 TeX-active-tempdir)
2102 preview-temp-dirs))))))
2103 (setcar (nthcdr 2 TeX-active-tempdir)
2104 (1+ (nth 2 TeX-active-tempdir)))
2105 (setcdr filename TeX-active-tempdir)
2106 (setq filename (list filename)))
2107 (let ((ov (make-overlay start end nil nil nil)))
2108 (when (fboundp 'TeX-overlay-prioritize)
2109 (overlay-put ov 'priority (TeX-overlay-prioritize start end)))
2110 (overlay-put ov 'preview-map
2111 (preview-make-clickable
2113 `(lambda(event) (interactive "e")
2114 (preview-toggle ,ov 'toggle event))
2115 `(lambda(event) (interactive "e")
2116 (preview-context-menu ,ov event))))
2119 ov 'preview-counters
2122 (if (string= (car counters) "")
2123 preview-parsed-counters
2124 (setq preview-parsed-counters
2125 (preview-parse-counters (car counters)))))
2127 (if (string= (cdr counters) "")
2128 preview-parsed-counters
2129 (setq preview-parsed-counters
2130 (preview-parse-counters (cdr counters)))))))
2131 (setq preview-buffer-has-counters t))
2132 (overlay-put ov 'filenames filename)
2133 (overlay-put ov 'preview-image (cons (preview-import-image image)
2135 (overlay-put ov 'strings
2136 (list (preview-active-string ov)))
2137 (overlay-put ov 'timestamp timestamp)
2138 (preview-toggle ov t)))
2141 (defun preview-back-command (&optional nocomplex)
2142 "Move backward a TeX token.
2143 If NOCOMPLEX is set, only basic tokens and no argument sequences
2144 will be skipped over backwards."
2145 (let ((oldpos (point)) oldpoint)
2147 (or (search-backward-regexp "\\(\\$\\$?\
2150 \\|\\\\begin[ \t]*{[^}]+}\
2151 \\)\\=" (line-beginning-position) t)
2153 (if (eq ?\) (char-syntax (char-before)))
2156 (setq oldpoint (point))
2158 (and (not (eq oldpoint (point)))
2159 (eq ?\( (char-syntax (char-after))))))
2161 (error (goto-char oldpos)))))
2163 (defcustom preview-required-option-list '("active" "tightpage" "auctex"
2164 (preview-preserve-counters
2166 "Specifies required options passed to the preview package.
2167 These are passed regardless of whether there is an explicit
2168 \\usepackage of that package present."
2169 :group 'preview-latex
2170 :type preview-expandable-string)
2172 (defcustom preview-preserve-counters nil
2173 "Try preserving counters for partial runs if set."
2174 :group 'preview-latex
2177 (defcustom preview-default-option-list '("displaymath" "floats"
2178 "graphics" "textmath" "sections"
2180 "*Specifies default options to pass to preview package.
2181 These options are only used when the LaTeX document in question does
2182 not itself load the preview package, namely when you use preview
2183 on a document not configured for preview. \"auctex\", \"active\",
2184 \"dvips\" and \"delayed\" need not be specified here."
2185 :group 'preview-latex
2186 :type '(list (set :inline t :tag "Options known to work"
2187 :format "%t:\n%v%h" :doc
2188 "The above options are all the useful ones
2189 at the time of the release of this package.
2190 You should not need \"Other options\" unless you
2191 upgraded to a fancier version of just the LaTeX style.
2192 Please also note that `psfixbb' fails to have an effect if
2193 `preview-fast-conversion' or `preview-prefer-TeX-bb'
2195 (const "displaymath")
2201 (const "showlabels")
2203 (set :tag "Expert options" :inline t
2204 :format "%t:\n%v%h" :doc
2205 "Expert options should not be enabled permanently."
2208 (const "tracingall"))
2209 (repeat :inline t :tag "Other options" (string))))
2211 (defcustom preview-default-preamble
2212 '("\\RequirePackage[" ("," . preview-default-option-list)
2213 "]{preview}[2004/11/05]")
2214 "*Specifies default preamble code to add to a LaTeX document.
2215 If the document does not itself load the preview package, that is,
2216 when you use preview on a document not configured for preview, this
2217 list of LaTeX commands is inserted just before \\begin{document}."
2218 :group 'preview-latex
2219 :type preview-expandable-string)
2221 (defcustom preview-LaTeX-command '("%`%l \"\\nonstopmode\\nofiles\
2222 \\PassOptionsToPackage{" ("," . preview-required-option-list) "}{preview}\
2223 \\AtBeginDocument{\\ifx\\ifPreview\\undefined"
2224 preview-default-preamble "\\fi}\"%' %t")
2225 "*Command used for starting a preview.
2226 See description of `TeX-command-list' for details."
2227 :group 'preview-latex
2228 :type preview-expandable-string)
2230 (defun preview-goto-info-page ()
2231 "Read documentation for preview-latex in the info system."
2233 (info "(preview-latex)"))
2235 (eval-after-load 'info '(add-to-list 'Info-file-list-for-emacs
2236 '("preview" . "preview-latex")))
2239 (let ((map (make-sparse-keymap)))
2240 (define-key map "\C-p" #'preview-at-point)
2241 (define-key map "\C-r" #'preview-region)
2242 (define-key map "\C-b" #'preview-buffer)
2243 (define-key map "\C-d" #'preview-document)
2244 (define-key map "\C-f" #'preview-cache-preamble)
2245 (define-key map "\C-c\C-f" #'preview-cache-preamble-off)
2246 (define-key map "\C-i" #'preview-goto-info-page)
2247 ;; (define-key map "\C-q" #'preview-paragraph)
2248 (define-key map "\C-e" #'preview-environment)
2249 (define-key map "\C-s" #'preview-section)
2250 (define-key map "\C-w" #'preview-copy-region-as-mml)
2251 (define-key map "\C-c\C-p" #'preview-clearout-at-point)
2252 (define-key map "\C-c\C-r" #'preview-clearout)
2253 (define-key map "\C-c\C-s" #'preview-clearout-section)
2254 (define-key map "\C-c\C-b" #'preview-clearout-buffer)
2255 (define-key map "\C-c\C-d" #'preview-clearout-document)
2258 (defun preview-copy-text (ov)
2259 "Copy the text of OV into the kill buffer."
2261 (set-buffer (overlay-buffer ov))
2262 (copy-region-as-kill (overlay-start ov) (overlay-end ov))))
2264 (defun preview-copy-mml (ov)
2265 "Copy an MML representation of OV into the kill buffer.
2266 This can be used to send inline images in mail and news when
2268 (when (catch 'badcolor
2269 (let ((str (car (preview-format-mml ov))))
2271 (if (eq last-command 'kill-region)
2272 (kill-append str nil)
2274 (error "No image file available")))
2276 (let (preview-transparent-border)
2277 (preview-regenerate ov))))
2279 (defun preview-copy-region-as-mml (start end)
2281 (when (catch 'badcolor
2282 (let (str lst dont-ask)
2283 (dolist (ov (overlays-in start end))
2284 (when (setq str (preview-format-mml ov dont-ask))
2285 (setq dont-ask (cdr str))
2287 (>= (overlay-start ov) start)
2288 (<= (overlay-end ov) end)
2289 (push (list (- (overlay-start ov) start)
2290 (- (overlay-end ov) start)
2292 (setq str (buffer-substring start end))
2293 (dolist (elt (nreverse (sort lst #'car-less-than-car)))
2294 (setq str (concat (substring str 0 (nth 0 elt))
2296 (substring str (nth 1 elt)))))
2297 (if (eq last-command 'kill-region)
2298 (kill-append str nil)
2301 (let (preview-transparent-border)
2302 (preview-region start end))))
2304 (autoload 'mailcap-extension-to-mime "mailcap")
2306 (defun preview-format-mml (ov &optional dont-ask)
2307 "Return an MML representation of OV as string.
2308 This can be used to send inline images in mail and news when
2309 using MML mode. If there is nothing current available,
2310 NIL is returned. If the image has a colored border and the
2311 user wants it removed when asked (unless DONT-ASK is set),
2312 'badcolor is thrown a t. The MML is returned in the car of the
2313 result, DONT-ASK in the cdr."
2314 (and (memq (overlay-get ov 'preview-state) '(active inactive))
2315 (not (overlay-get ov 'queued))
2316 (let* ((text (with-current-buffer (overlay-buffer ov)
2317 (buffer-substring (overlay-start ov)
2319 (image (cdr (overlay-get ov 'preview-image)))
2321 (cond ((consp image)
2324 (if (y-or-n-p "Replace colored borders? ")
2327 (setq file (car (car (last (overlay-get ov 'filenames))))
2328 type (mailcap-extension-to-mime
2329 (file-name-extension file)))
2336 (format "type=\"%s\" disposition=inline" type)
2337 "disposition=attachment")
2338 (if (string-match "[\n\"]" text)
2339 "preview-latex image"
2341 (if (string-match "[ \n<>]" file)
2342 (concat "\"" file "\"")
2346 (cons image dont-ask))))))
2348 (defun preview-active-contents (ov)
2349 "Check whether we have a valid image associated with OV."
2350 (and (memq (overlay-get ov 'preview-state) '(active inactive)) t))
2352 (defun preview-context-menu (ov ev)
2353 "Pop up a menu for OV at position EV."
2356 ["Toggle" (preview-toggle ,ov 'toggle ',ev)
2357 (preview-active-contents ,ov)]
2358 ["Regenerate" (preview-regenerate ,ov)]
2359 ["Remove" (preview-delete ,ov)]
2360 ["Copy text" (preview-copy-text ,ov)]
2361 ["Copy MIME" (preview-copy-mml ,ov)
2362 (preview-active-contents ,ov)])
2365 (defvar preview-TeX-style-dir)
2367 (defun preview-TeX-style-cooked ()
2368 "Return `preview-TeX-style-dir' in cooked form.
2369 This will be fine for prepending to a `TEXINPUT' style
2370 environment variable, including an initial `.' at the front."
2371 (if (or (zerop (length preview-TeX-style-dir))
2372 (member (substring preview-TeX-style-dir -1) '(";" ":")))
2373 preview-TeX-style-dir
2376 ((stringp TeX-kpathsea-path-delimiter)
2377 TeX-kpathsea-path-delimiter)
2380 (if (file-name-absolute-p preview-TeX-style-dir)
2381 preview-TeX-style-dir
2382 (expand-file-name preview-TeX-style-dir)))
2385 (concat "." sep preview-TeX-style-dir sep))))
2387 (defun preview-set-texinputs (&optional remove)
2388 "Add `preview-TeX-style-dir' into `TEXINPUTS' variables.
2389 With prefix argument REMOVE, remove it again."
2391 (let ((case-fold-search nil)
2392 (preview-TeX-style-dir (preview-TeX-style-cooked))
2396 (setq pattern (concat "\\`\\(TEXINPUTS[^=]*\\)=\\(.*\\)"
2397 (regexp-quote preview-TeX-style-dir)))
2398 (dolist (env (copy-sequence process-environment))
2399 (if (string-match pattern env)
2400 (setenv (match-string 1 env)
2401 (and (or (< (match-beginning 2) (match-end 2))
2402 (< (match-end 0) (length env)))
2403 (concat (match-string 2 env)
2404 (substring env (match-end 0))))))))
2405 (setq pattern (regexp-quote preview-TeX-style-dir))
2406 (dolist (env (cons "TEXINPUTS=" (copy-sequence process-environment)))
2407 (if (string-match "\\`\\(TEXINPUTS[^=]*\\)=" env)
2408 (unless (string-match pattern env)
2409 (setenv (match-string 1 env)
2410 (concat preview-TeX-style-dir
2411 (substring env (match-end 0))))))))))
2413 (defcustom preview-TeX-style-dir nil
2414 "This variable contains the location of uninstalled TeX styles.
2415 If this is nil, the preview styles are considered to be part of
2416 the installed TeX system.
2418 Otherwise, it can either just specify an absolute directory, or
2419 it can be a complete TEXINPUTS specification. If it is the
2420 latter, it has to be followed by the character with which
2421 kpathsea separates path components, either `:' on Unix-like
2422 systems, or `;' on Windows-like systems. And it should be
2423 preceded with .: or .; accordingly in order to have . first in
2426 The `TEXINPUT' environment type variables will get this prepended
2427 at load time calling \\[preview-set-texinputs] to reflect this.
2428 You can permanently install the style files using
2429 \\[preview-install-styles].
2431 Don't set this variable other than with customize so that its
2432 changes get properly reflected in the environment."
2433 :group 'preview-latex
2434 :set (lambda (var value)
2437 (preview-set-texinputs t))
2439 (and (symbol-value var)
2440 (preview-set-texinputs)))
2441 :type '(choice (const :tag "Installed" nil)
2442 (string :tag "Style directory or TEXINPUTS path")))
2445 (defun preview-install-styles (dir &optional force-overwrite
2447 "Installs the TeX style files into a permanent location.
2448 This must be in the TeX search path. If FORCE-OVERWRITE is greater
2449 than 1, files will get overwritten without query, if it is less
2450 than 1 or nil, the operation will fail. The default of 1 for interactive
2453 Similarly FORCE-SAVE can be used for saving
2454 `preview-TeX-style-dir' to record the fact that the uninstalled
2455 files are no longer needed in the search path."
2456 (interactive "DPermanent location for preview TeX styles
2458 (unless preview-TeX-style-dir
2459 (error "Styles are already installed"))
2465 "\\`\\(\\.[:;]\\)?\\(.*?\\)\\([:;]\\)?\\'"
2466 preview-TeX-style-dir)
2467 (match-string 2 preview-TeX-style-dir))
2468 t "\\.\\(sty\\|def\\|cfg\\)\\'")
2470 (error "Can't find files to install")))
2471 (copy-file file dir (cond ((eq force-overwrite 1) 1)
2472 ((numberp force-overwrite)
2473 (> force-overwrite 1))
2474 (t force-overwrite))))
2475 (if (cond ((eq force-save 1)
2476 (y-or-n-p "Stop using non-installed styles permanently "))
2477 ((numberp force-save)
2480 (customize-save-variable 'preview-TeX-style-dir nil)
2481 (customize-set-variable 'preview-TeX-style-dir nil)))
2484 (defun LaTeX-preview-setup ()
2485 "Hook function for embedding the preview package into AUCTeX.
2486 This is called by `LaTeX-mode-hook' and changes AUCTeX variables
2487 to add the preview functionality."
2488 (remove-hook 'LaTeX-mode-hook #'LaTeX-preview-setup)
2489 (add-hook 'LaTeX-mode-hook #'preview-mode-setup)
2490 (define-key LaTeX-mode-map "\C-c\C-p" preview-map)
2491 (easy-menu-define preview-menu LaTeX-mode-map
2492 "This is the menu for preview-latex."
2495 ["(or toggle) at point" preview-at-point]
2496 ["for environment" preview-environment]
2497 ["for section" preview-section]
2498 ["for region" preview-region (preview-mark-active)]
2499 ["for buffer" preview-buffer]
2500 ["for document" preview-document]
2503 ["at point" preview-clearout-at-point]
2504 ["from section" preview-clearout-section]
2505 ["from region" preview-clearout (preview-mark-active)]
2506 ["from buffer" preview-clearout-buffer]
2507 ["from document" preview-clearout-document]
2509 "Turn preamble cache"
2510 ["on" preview-cache-preamble]
2511 ["off" preview-cache-preamble-off]
2515 (customize-group 'preview)]
2519 (customize-menu-create 'preview))])
2520 ["Read documentation" preview-goto-info-page]
2521 ["Report Bug" preview-report-bug]))
2522 (if (eq major-mode 'latex-mode)
2523 (preview-mode-setup))
2524 (if (boundp 'desktop-buffer-misc)
2525 (preview-buffer-restore desktop-buffer-misc)))
2527 (defun preview-clean-subdir (dir)
2528 "Cleans out a temporary DIR with preview image files."
2532 (directory-files dir t "\\`pr" t))
2533 (delete-directory dir))
2534 (error (message "Deletion of `%s' failed: %s" dir
2535 (error-message-string err)))))
2537 (defun preview-clean-topdir (topdir)
2538 "Cleans out TOPDIR from temporary directories.
2539 This does not erase the directory itself since its permissions
2540 might be needed for colloborative work on common files."
2541 (mapc #'preview-clean-subdir
2543 (directory-files topdir t "\\`tmp" t)
2546 (defun preview-create-subdirectory ()
2547 "Create a temporary subdir for the current TeX process.
2548 If necessary, generates a fitting top
2549 directory or cleans out an existing one (if not yet
2550 visited in this session), then returns the name of
2551 the created subdirectory relative to the master directory,
2552 in shell-quoted form. `TeX-active-tempdir' is
2553 set to the corresponding TEMPDIR descriptor as described
2554 in `preview-make-filename'. The directory is registered
2555 in `preview-temp-dirs' in order not to be cleaned out
2556 later while in use."
2557 (let ((topdir (expand-file-name (TeX-active-master "prv"))))
2558 (if (file-directory-p topdir)
2559 (unless (member topdir preview-temp-dirs)
2560 ;; Cleans out the top preview directory by
2561 ;; removing subdirs possibly left from a previous session.
2562 (preview-clean-topdir topdir)
2563 (push topdir preview-temp-dirs))
2564 (make-directory topdir)
2565 (add-to-list 'preview-temp-dirs topdir))
2566 (add-hook 'kill-emacs-hook #'preview-cleanout-tempfiles t)
2567 (setq TeX-active-tempdir
2568 (list (make-temp-file (expand-file-name
2569 "tmp" (file-name-as-directory topdir)) t)
2572 (shell-quote-argument
2573 (concat (file-name-as-directory (file-name-nondirectory topdir))
2574 (file-name-nondirectory (nth 0 TeX-active-tempdir))))))
2576 ;; Hook into TeX immediately if it's loaded, use LaTeX-mode-hook if not.
2577 (if (featurep 'latex)
2578 (LaTeX-preview-setup)
2579 (add-hook 'LaTeX-mode-hook #'LaTeX-preview-setup))
2581 ;;;###autoload (add-hook 'LaTeX-mode-hook #'LaTeX-preview-setup)
2583 (defun preview-parse-counters (string)
2584 "Extract counter information from STRING."
2585 (let ((list preview-parsed-counters) (pos 0))
2586 (while (eq pos (string-match " *\\({\\([^{}]+\\)}{[-0-9]+}\\)" string pos))
2587 (setcdr (or (assoc (match-string 2 string) list)
2588 (car (push (list (match-string 2 string)) list)))
2589 (match-string 1 string))
2590 (setq pos (match-end 1)))
2593 (defun preview-parse-tightpage (string)
2594 "Build tightpage vector from STRING,"
2595 (read (concat "[" string "]")))
2597 (defvar preview-parse-variables
2598 '(("Fontsize" preview-parsed-font-size
2599 "\\` *\\([0-9.]+\\)pt\\'" 1 string-to-number)
2600 ("Magnification" preview-parsed-magnification
2601 "\\` *\\([0-9]+\\)\\'" 1 string-to-number)
2602 ("PDFoutput" preview-parsed-pdfoutput
2604 ("Counters" preview-parsed-counters
2605 ".*" 0 preview-parse-counters)
2606 ("Tightpage" preview-parsed-tightpage
2607 "\\` *\\(-?[0-9]+ *\\)\\{4\\}\\'" 0 preview-parse-tightpage)))
2609 (defun preview-error-quote (string run-coding-system)
2610 "Turn STRING with potential ^^ sequences into a regexp.
2611 To preserve sanity, additional ^ prefixes are matched literally,
2612 so the character represented by ^^^ preceding extended characters
2613 will not get matched, usually."
2614 (let (output case-fold-search)
2615 (when (featurep 'mule)
2616 (setq string (encode-coding-string string run-coding-system)))
2617 (while (string-match "\\^\\{2,\\}\\(\\([@-_?]\\)\\|[8-9a-f][0-9a-f]\\)"
2621 (regexp-quote (substring string
2623 (- (match-beginning 1) 2)))
2624 (if (match-beginning 2)
2626 "\\(?:" (regexp-quote
2628 (- (match-beginning 1) 2)
2632 (logxor (aref string (match-beginning 2)) 64))
2635 (string-to-number (match-string 1 string) 16))))
2636 string (substring string (match-end 0))))
2637 (setq output (concat output (regexp-quote string)))
2638 (if (featurep 'mule)
2639 (decode-coding-string output
2640 (or (and (boundp 'TeX-japanese-process-output-coding-system)
2641 TeX-japanese-process-output-coding-system)
2642 buffer-file-coding-system))
2645 (defun preview-parse-messages (open-closure)
2646 "Turn all preview snippets into overlays.
2647 This parses the pseudo error messages from the preview
2648 document style for LaTeX. OPEN-CLOSURE is called once
2649 it is certain that we have a valid output file, and it has
2650 to return in its CAR the PROCESS parameter for the CLOSE
2651 call, and in its CDR the final stuff for the placement hook."
2652 (with-temp-message "locating previews..."
2653 (let (TeX-error-file TeX-error-offset snippet box counters
2655 (lsnippet 0) lstart (lfile "") lline lbuffer lpoint
2657 string after-string error context-start
2659 parsestate (case-fold-search nil)
2660 (run-buffer (current-buffer))
2661 (run-coding-system preview-coding-system)
2662 (run-directory default-directory)
2668 ;; clear parsing variables
2669 (dolist (var preview-parse-variables)
2670 (set (nth 1 var) nil))
2671 (goto-char (point-min))
2675 (re-search-forward "\
2676 ^\\(!\\|\\(.*?\\):[0-9]+:\\) \\|\
2678 \\(?:\\.+[^()\r\n{} /]*\\|[^()\r\n{} ./]+\
2679 \\(?: [^()\r\n{} ./]+\\)*\\(?:\\.[-0-9a-zA-Z_.]*\\)?\\)\
2680 \\(?:/+\\(?:\\.+[^()\r\n{} /]*\\|[^()\r\n{} ./]+\
2681 \\(?: [^()\r\n{} ./]+\\)*\\(?:\\.[-0-9a-zA-Z_.]*\\)?\\)?\\)*\\)\
2682 )*\\(?: \\|\r?$\\)\\|\
2684 !\\(?:offset(\\([---0-9]+\\))\\|\
2685 name(\\([^)]+\\))\\)\\|\
2686 ^Preview: \\([a-zA-Z]+\\) \\([^\n\r]*\\)\r?$" nil t)
2687 ;;; Ok, here is a line by line breakdown:
2688 ;;; match-alternative 1:
2689 ;;; error indicator for TeX error, either style.
2690 ;;; match-alternative 2:
2691 ;;; The same, but file-line-error-style, matching on file name.
2692 ;;; match-alternative 3:
2693 ;;; Too ugly to describe in detail. In short, we try to catch file
2694 ;;; names built from path components that don't contain spaces or
2695 ;;; other special characters once the file extension has started.
2697 ;;; Position for searching immediately after the file name so as to
2698 ;;; not miss closing parens or something.
2699 ;;; (match-string 3) is the file name.
2700 ;;; match-alternative 4:
2702 ;;; a closing paren followed by the end of line or a space: a just
2704 ;;; match-alternative 5 (wrapped into one shy group with
2705 ;;; match-alternative 6, so that the match on first char is slightly
2707 ;;; !offset(\([---0-9]+\))
2708 ;;; an AUCTeX offset message. (match-string 5) is the offset itself
2709 ;;; !name(\([^)]+\))
2710 ;;; an AUCTeX file name message. (match-string 6) is the file name
2711 ;;; TODO: Actually, the latter two should probably again match only
2712 ;;; after a space or newline, since that it what \message produces.
2713 ;;;disabled in prauctex.def:
2714 ;;;\(?:Ov\|Und\)erfull \\.*[0-9]*--[0-9]*
2717 ;;; This would have caught overfull box messages that consist of
2718 ;;; several lines of context all with 79 characters in length except
2719 ;;; of the last one. prauctex.def kills all such messages.
2720 (setq file (match-string-no-properties 2))
2722 ((match-beginning 1)
2724 \\(?:Preview\\|Package Preview Error\\): Snippet \\([---0-9]+\\) \\(started\\|ended\\(\
2725 \\.? *(\\([---0-9]+\\)\\+\\([---0-9]+\\)x\\([---0-9]+\\))\\)?\\)\\.")
2728 (unless TeX-error-file
2729 (push nil TeX-error-file)
2730 (push nil TeX-error-offset))
2731 (unless (car TeX-error-offset)
2732 (rplaca TeX-error-file file)))
2733 (setq snippet (string-to-number (match-string 1))
2735 (string= (match-string 2) "started")
2736 (if (match-string 4)
2737 (mapcar #'(lambda (x)
2738 (* (preview-get-magnification)
2739 (string-to-number x)))
2745 counters (mapcar #'cdr preview-parsed-counters)
2747 (setq lpoint (point))
2749 (buffer-substring lpoint (point)))
2751 ;; And the context for the help window.
2752 context-start (point)
2754 ;; And the line number to position the cursor.
2755 ;;; variant 1: profiling seems to indicate the regexp-heavy solution
2756 ;;; to be favorable. Removing incomplete characters from the error
2757 ;;; context is an absolute nuisance.
2758 line (and (re-search-forward "\
2759 ^l\\.\\([0-9]+\\) \\(\\.\\.\\.\\(?:\\^*\\(?:[89a-f][0-9a-f]\\|[]@-\\_?]\\)\\|\
2760 \[0-9a-f]?\\)\\)?\\([^\n\r]*?\\)\r?
2761 \\([^\n\r]*?\\)\\(\\(?:\\^+[89a-f]?\\)?\\.\\.\\.\\)?\r?$" nil t)
2762 (string-to-number (match-string 1)))
2763 ;; And a string of the context to search for.
2764 string (and line (match-string 3))
2765 after-string (and line (buffer-substring
2766 (+ (match-beginning 4)
2768 (match-beginning 0)))
2771 ;; And we have now found to the end of the context.
2772 context (buffer-substring context-start (point))
2773 ;; We may use these in another buffer.
2774 offset (or (car TeX-error-offset) 0)
2775 file (car TeX-error-file))
2776 (when (and (stringp file)
2777 (or (string= file "<none>")
2778 (TeX-match-extension file)))
2779 ;; if we are the first time round, check for fast hooks:
2780 (when (null parsestate)
2782 (save-excursion (funcall open-closure))
2783 tempdir TeX-active-tempdir)
2785 (lst (if (listp TeX-translate-location-hook)
2786 TeX-translate-location-hook
2787 (list TeX-translate-location-hook)))
2790 (get lst 'TeX-translate-via-list))))
2793 (nconc fast-hook (list fast)))
2795 (nconc slow-hook (list lst)))))))
2797 (save-excursion (run-hooks 'slow-hook))
2798 (error (preview-log-error err "Translation hook")))
2799 (push (vector file (+ line offset)
2801 snippet box counters) parsestate)))
2802 ;; else normal error message
2804 (re-search-forward "^l\\.[0-9]" nil t)
2806 ((match-beginning 3)
2807 ;; New file -- Push on stack
2808 (push (match-string-no-properties 3) TeX-error-file)
2809 (push nil TeX-error-offset)
2810 (goto-char (match-end 3)))
2811 ((match-beginning 4)
2812 ;; End of file -- Pop from stack
2813 (when (> (length TeX-error-file) 1)
2814 (pop TeX-error-file)
2815 (pop TeX-error-offset))
2816 (goto-char (1+ (match-beginning 0))))
2817 ((match-beginning 5)
2818 ;; Hook to change line numbers
2819 (setq TeX-error-offset
2820 (list (string-to-number (match-string 5)))))
2821 ((match-beginning 6)
2822 ;; Hook to change file name
2823 (setq TeX-error-file (list (match-string-no-properties 6))))
2824 ((match-beginning 7)
2826 (assoc (match-string-no-properties 7)
2827 preview-parse-variables))
2828 (offset (- (match-beginning 0) (match-beginning 8)))
2829 (str (match-string-no-properties 8)))
2830 ;; paste together continuation lines:
2831 (while (= (- (length str) offset) 79)
2832 (search-forward-regexp "^\\([^\n\r]*\\)\r?$")
2833 (setq offset (- (length str))
2834 str (concat str (match-string-no-properties 1))))
2836 (string-match (nth 2 var) str))
2838 (funcall (nth 4 var)
2839 (match-string-no-properties
2842 (when (null parsestate)
2843 (error "LaTeX found no preview images")))
2846 (setq parsestate (nreverse parsestate))
2848 (dolist (fun fast-hook)
2850 (save-excursion (funcall fun parsestate))))
2851 (error (preview-log-error err "Fast translation hook")))
2853 (dolist (state parsestate)
2854 (setq lsnippet snippet
2857 string (aref state 2)
2858 after-string (aref state 3)
2859 snippet (aref state 4)
2861 counters (aref state 6))
2862 (unless (string= lfile file)
2863 (set-buffer (if (string= file "<none>")
2864 (with-current-buffer run-buffer
2867 (expand-file-name file run-directory))))
2872 ;; a fast hook might have positioned us already:
2873 (if (number-or-marker-p string)
2877 (if (number-or-marker-p after-string)
2879 (line-beginning-position))))
2880 (if (and (eq (current-buffer) lbuffer)
2882 ;; while Emacs does the perfectly correct
2883 ;; thing even when when the line differences
2884 ;; get zero or negative, I don't trust this
2885 ;; to be universally the case across other
2886 ;; implementations. Besides, if the line
2887 ;; number gets smaller again, we are probably
2888 ;; rereading the file, and restarting from
2889 ;; the beginning will probably be faster.
2893 (if (eq selective-display t)
2894 (re-search-forward "[\n\C-m]" nil
2897 (forward-line (- line lline)))))
2899 (setq lpoint (point))
2901 ((search-forward (concat string after-string)
2902 (line-end-position) t)
2903 (backward-char (length after-string)))
2904 ;;ok, transform ^^ sequences
2905 ((search-forward-regexp
2908 (preview-error-quote
2913 (preview-error-quote
2915 run-coding-system)))
2916 (line-end-position) t)
2917 (goto-char (match-end 1)))
2918 ((search-forward-regexp
2921 "^[^\0-\177]\\{1,6\\}" string)
2923 (substring string (match-end 0)))
2927 "[^\0-\177]\\{1,6\\}$" after-string)
2929 (substring after-string
2930 0 (match-beginning 0)))))
2931 (line-end-position) t)
2932 (goto-char (match-end 1)))
2933 (t (search-forward-regexp
2935 (line-end-position) t))))
2937 lbuffer (current-buffer))
2940 (if (and lstart (= snippet lsnippet))
2943 (preview-place-preview
2946 (preview-back-command
2952 (preview-TeX-bb box)
2953 (cons lcounters counters)
2957 (with-current-buffer run-buffer
2961 "End of Preview snippet %d unexpected"
2962 snippet)) "Parser")))
2964 ;; else-part of if box
2965 (setq lstart (point) lcounters counters)
2966 ;; >= because snippets in between might have
2967 ;; been ignored because of TeX-default-extension
2968 (unless (>= snippet (1+ lsnippet))
2969 (with-current-buffer run-buffer
2973 "Preview snippet %d out of sequence"
2974 snippet)) "Parser"))))))))
2975 (preview-call-hook 'close (car open-data) close-data))))))
2977 (defun preview-get-geometry ()
2978 "Transfer display geometry parameters from current display.
2979 Returns list of scale, resolution and colors. Calculation
2980 is done in current buffer."
2983 (list (preview-hook-enquiry preview-scale-function)
2984 (cons (/ (* 25.4 (display-pixel-width))
2986 (/ (* 25.4 (display-pixel-height))
2987 (display-mm-height)))
2988 (preview-get-colors)))
2990 (* (cdr (nth 1 geometry))
2992 (preview-inherited-face-attribute
2993 'preview-reference-face :height 'default)
2995 (setq preview-icon (preview-make-image 'preview-icon-specs)
2996 preview-error-icon (preview-make-image
2997 'preview-error-icon-specs)
2998 preview-nonready-icon (preview-make-image
2999 'preview-nonready-icon-specs))
3001 (error (error "Display geometry unavailable: %s"
3002 (error-message-string err)))))
3004 (defun preview-set-geometry (geometry)
3005 "Set geometry variables from GEOMETRY.
3006 Buffer-local `preview-scale', `preview-resolution',
3007 and `preview-colors' are set as given."
3008 (setq preview-scale (nth 0 geometry)
3009 preview-resolution (nth 1 geometry)
3010 preview-colors (nth 2 geometry)))
3012 (defun preview-start-dvipng ()
3013 "Start a DviPNG process.."
3014 (let* ((file preview-gs-file)
3016 (res (/ (* (car preview-resolution)
3017 (preview-hook-enquiry preview-scale))
3018 (preview-get-magnification)))
3019 (resolution (format " -D%d " res))
3020 (colors (preview-dvipng-color-string preview-colors res))
3021 (command (with-current-buffer TeX-command-buffer
3023 (concat (TeX-command-expand preview-dvipng-command
3025 " " colors resolution)
3026 (setq tempdir TeX-active-tempdir))))
3027 (name "Preview-DviPNG"))
3028 (setq TeX-active-tempdir tempdir)
3029 (goto-char (point-max))
3030 (insert-before-markers "Running `" name "' with ``" command "''\n")
3031 (setq mode-name name)
3032 (setq TeX-sentinel-function
3033 (lambda (process name) (message "%s: done." name)))
3034 (if TeX-process-asynchronous
3035 (let ((process (start-process name (current-buffer) TeX-shell
3036 TeX-shell-command-option
3038 (if TeX-after-start-process-function
3039 (funcall TeX-after-start-process-function process))
3040 (TeX-command-mode-line process)
3041 (set-process-filter process 'TeX-command-filter)
3042 (set-process-sentinel process 'TeX-command-sentinel)
3043 (set-marker (process-mark process) (point-max))
3044 (push process compilation-in-progress)
3047 (setq mode-line-process ": run")
3048 (set-buffer-modified-p (buffer-modified-p))
3049 (sit-for 0) ; redisplay
3050 (call-process TeX-shell nil (current-buffer) nil
3051 TeX-shell-command-option
3054 (defun preview-start-dvips (&optional fast)
3055 "Start a DviPS process.
3056 If FAST is set, do a fast conversion."
3057 (let* ((file preview-gs-file)
3059 (command (with-current-buffer TeX-command-buffer
3061 (TeX-command-expand (if fast
3062 preview-fast-dvips-command
3063 preview-dvips-command)
3065 (setq tempdir TeX-active-tempdir))))
3066 (name "Preview-DviPS"))
3067 (setq TeX-active-tempdir tempdir)
3068 (setq preview-ps-file (and fast
3069 (preview-make-filename
3070 (preview-make-filename
3071 "preview.ps" tempdir) tempdir)))
3072 (goto-char (point-max))
3073 (insert-before-markers "Running `" name "' with ``" command "''\n")
3074 (setq mode-name name)
3075 (setq TeX-sentinel-function
3076 (lambda (process name) (message "%s: done." name)))
3077 (if TeX-process-asynchronous
3078 (let ((process (start-process name (current-buffer) TeX-shell
3079 TeX-shell-command-option
3081 (if TeX-after-start-process-function
3082 (funcall TeX-after-start-process-function process))
3083 (TeX-command-mode-line process)
3084 (set-process-filter process 'TeX-command-filter)
3085 (set-process-sentinel process 'TeX-command-sentinel)
3086 (set-marker (process-mark process) (point-max))
3087 (push process compilation-in-progress)
3090 (setq mode-line-process ": run")
3091 (set-buffer-modified-p (buffer-modified-p))
3092 (sit-for 0) ; redisplay
3093 (call-process TeX-shell nil (current-buffer) nil
3094 TeX-shell-command-option
3097 (defun preview-start-pdf2dsc ()
3098 "Start a PDF2DSC process."
3099 (let* ((file preview-gs-file)
3102 (command (with-current-buffer TeX-command-buffer
3104 (TeX-command-expand preview-pdf2dsc-command
3106 (setq tempdir TeX-active-tempdir
3107 pdfsource (funcall `,(car file) "pdf")))))
3108 (name "Preview-PDF2DSC"))
3109 (setq TeX-active-tempdir tempdir)
3110 (setq preview-ps-file (preview-attach-filename
3112 (preview-make-filename
3113 (preview-make-filename
3114 "preview.dsc" tempdir) tempdir)))
3115 (goto-char (point-max))
3116 (insert-before-markers "Running `" name "' with ``" command "''\n")
3117 (setq mode-name name)
3118 (setq TeX-sentinel-function
3119 (lambda (process name) (message "%s: done." name)))
3120 (if TeX-process-asynchronous
3121 (let ((process (start-process name (current-buffer) TeX-shell
3122 TeX-shell-command-option
3124 (if TeX-after-start-process-function
3125 (funcall TeX-after-start-process-function process))
3126 (TeX-command-mode-line process)
3127 (set-process-filter process 'TeX-command-filter)
3128 (set-process-sentinel process 'TeX-command-sentinel)
3129 (set-marker (process-mark process) (point-max))
3130 (push process compilation-in-progress)
3133 (setq mode-line-process ": run")
3134 (set-buffer-modified-p (buffer-modified-p))
3135 (sit-for 0) ; redisplay
3136 (call-process TeX-shell nil (current-buffer) nil
3137 TeX-shell-command-option
3140 (defun preview-TeX-inline-sentinel (process name)
3141 "Sentinel function for preview.
3142 See `TeX-sentinel-function' and `set-process-sentinel'
3143 for definition of PROCESS and NAME."
3144 (if process (TeX-format-mode-line process))
3145 (let ((status (process-status process)))
3146 (if (memq status '(signal exit))
3147 (delete-process process))
3148 (when (eq status 'exit)
3150 (goto-char (point-max))
3152 (if (search-forward "abnormally with code 1" nil t)
3153 (replace-match "as expected with code 1" t t)
3154 (if (search-forward "finished" nil t)
3155 (insert " with nothing to show"))))
3157 (preview-call-hook 'open)
3158 (error (preview-log-error err "LaTeX" process)))
3159 (preview-reraise-error process))))
3161 (defcustom preview-format-extensions '(".fmt" ".efmt")
3162 "Possible extensions for format files.
3163 Those are just needed for cleanup."
3164 :group 'preview-latex
3165 :type '(repeat string))
3167 (defun preview-format-kill (format-cons)
3168 "Kill a cached format.
3169 FORMAT-CONS is intended to be an element of `preview-dumped-alist'.
3170 Tries through `preview-format-extensions'."
3171 (dolist (ext preview-format-extensions)
3173 (delete-file (preview-dump-file-name (concat (car format-cons) ext)))
3176 (defun preview-dump-file-name (file)
3177 "Make a file name suitable for dumping from FILE."
3179 (concat (file-name-directory file)
3182 (setq file (file-name-nondirectory file))
3183 (while (string-match " " file)
3184 (setq file (replace-match "_" t t file)))
3188 (defun preview-do-replacements (string replacements)
3189 "Perform replacements in string.
3190 STRING is the input string, REPLACEMENTS is a list of replacements.
3191 A replacement is a cons-cell, where the car is the match string,
3192 and the cdr is a list of strings or symbols. Symbols get dereferenced,
3193 and strings get evaluated as replacement strings."
3194 (let (rep case-fold-search)
3196 (setq rep (pop replacements))
3197 (cond ((symbolp rep)
3198 (setq string (preview-do-replacements
3199 string (symbol-value rep))))
3200 ((string-match (car rep) string)
3202 (mapconcat (lambda(x)
3205 (replace-match x t nil string)))
3209 (defconst preview-LaTeX-disable-pdfoutput
3210 '(("\\`\\(pdf[^ ]*\\)\
3211 \\(\\( [-&]\\([^ \"]\\|\"[^\"]*\"\\)*\\|\
3212 \"[-&][^\"]*\"\\)*\\)\\(.*\\)\\'"
3213 . ("\\1\\2 \"\\\\pdfoutput=0 \" \\5")))
3214 "This replacement places `\"\\pdfoutput=0 \"' after the options
3215 of any command starting with `pdf'.")
3217 (defcustom preview-LaTeX-command-replacements
3219 "Replacement for `preview-LaTeX-command'.
3220 This is passed through `preview-do-replacements'."
3221 :group 'preview-latex
3224 (symbol :tag "Named replacement" :value preview-LaTeX-disable-pdfoutput)
3225 (cons (string :tag "Matched string")
3226 (repeat :tag "Concatenated elements for replacement"
3227 (choice (symbol :tag "Variable with literal string")
3228 (string :tag "non-literal regexp replacement")))))))
3230 (defvar preview-format-name)
3232 (defcustom preview-dump-replacements
3233 '(preview-LaTeX-command-replacements
3235 \\(\\( +-\\([^ \\\\\"]\\|\\\\\\.\\|\"[^\"]*\"\\)*\\)*\\)\\(.*\\)\\'"
3236 . ("\\1 -ini -interaction=nonstopmode \"&\\1\" " preview-format-name ".ini \\5")))
3237 "Generate a dump command from the usual preview command."
3238 :group 'preview-latex
3240 (choice (symbol :tag "Named replacement")
3241 (cons string (repeat (choice symbol string))))))
3243 (defcustom preview-undump-replacements
3245 .*? \"\\\\input\" \\(.*\\)\\'"
3246 . ("\\1 -interaction=nonstopmode \"&" preview-format-name "\" \\2")))
3247 "Use a dumped format for reading preamble."
3248 :group 'preview-latex
3250 (choice (symbol :tag "Named replacement")
3251 (cons string (repeat (choice symbol string))))))
3254 (defun preview-cache-preamble (&optional format-cons)
3255 "Dump a pregenerated format file.
3256 For the rest of the session, this file is used when running
3257 on the same master file.
3259 Returns the process for dumping, nil if there is still a valid
3262 If FORMAT-CONS is non-nil, a previous format may get reused."
3265 (expand-file-name (preview-dump-file-name (TeX-master-file "ini"))))
3266 (master (TeX-master-file))
3267 (format-name (expand-file-name master))
3268 (preview-format-name (shell-quote-argument
3269 (preview-dump-file-name (file-name-nondirectory
3271 (master-file (expand-file-name (TeX-master-file t)))
3272 (command (preview-do-replacements
3274 (preview-string-expand preview-LaTeX-command)
3276 preview-dump-replacements))
3277 (preview-auto-cache-preamble nil))
3278 (unless (and (consp (cdr format-cons))
3279 (string= command (cadr format-cons)))
3281 (setq format-cons (assoc format-name preview-dumped-alist)))
3283 (preview-cache-preamble-off format-cons)
3284 (setq format-cons (list format-name))
3285 (push format-cons preview-dumped-alist))
3286 ;; mylatex.ltx expects a file name to follow. Bad. `.tex'
3287 ;; in the tools bundle is an empty file.
3288 (write-region "\\ifx\\pdfoutput\\undefined\\else\
3289 \\let\\PREVIEWdump\\dump\\def\\dump{%
3290 \\edef\\next{{\\catcode`\\ 9 \\pdfoutput=\\the\\pdfoutput\\relax\
3291 \\the\\everyjob}}\\everyjob\\next\\catcode`\\ 10 \\let\\dump\\PREVIEWdump\\dump}\\fi\\input mylatex.ltx \\relax\n" nil dump-file)
3292 (TeX-save-document master)
3294 (preview-generate-preview
3295 nil (file-name-nondirectory master)
3297 (add-hook 'kill-emacs-hook #'preview-cleanout-tempfiles t)
3298 (setq TeX-sentinel-function
3299 `(lambda (process string)
3302 (if (and (eq (process-status process) 'exit)
3303 (zerop (process-exit-status process)))
3304 (preview-watch-preamble
3308 (preview-format-kill ',format-cons))
3309 (delete-file ',dump-file))
3310 (error (preview-log-error err "Dumping" process)))
3311 (preview-reraise-error process)))))))
3313 (defun preview-cache-preamble-off (&optional old-format)
3314 "Clear the pregenerated format file.
3315 The use of the format file is discontinued.
3316 OLD-FORMAT may already contain a format-cons as
3317 stored in `preview-dumped-alist'."
3321 (let ((master-file (expand-file-name (TeX-master-file))))
3322 (or (assoc master-file preview-dumped-alist)
3323 (car (push (list master-file) preview-dumped-alist))))))
3324 (preview-unwatch-preamble old-format)
3325 (preview-format-kill old-format)
3326 (setcdr old-format nil))
3328 (defun preview-region (begin end)
3329 "Run preview on region between BEGIN and END."
3331 (TeX-region-create (TeX-region-file TeX-default-extension)
3332 (buffer-substring begin end)
3333 (if buffer-file-name
3334 (file-name-nondirectory buffer-file-name)
3338 (let ((inhibit-point-motion-hooks t)
3339 (inhibit-field-text-motion t))
3340 (+ (count-lines (point-min) begin)
3343 (if (bolp) 0 -1))))))
3344 (preview-generate-preview t (TeX-region-file nil t)
3345 (preview-do-replacements
3347 (preview-string-expand preview-LaTeX-command)
3349 preview-LaTeX-command-replacements)))
3351 (defun preview-buffer ()
3352 "Run preview on current buffer."
3354 (preview-region (point-min) (point-max)))
3356 ;; We have a big problem: When we are dumping preambles, diagnostics
3357 ;; issued in later runs will not make it to the output when the
3358 ;; predumped format skips the preamble. So we have to place those
3359 ;; after \begin{document}. This we can only do if regions never
3360 ;; include the preamble. We could do this in our own functions, but
3361 ;; that would not extend to the operation of C-c C-r g RET. So we
3362 ;; make this preamble skipping business part of TeX-region-create.
3363 ;; This will fail if the region is to contain just part of the
3364 ;; preamble -- a bad idea anyhow.
3366 (defadvice TeX-region-create (before preview-preamble preactivate activate)
3367 "Skip preamble for the sake of predumped formats."
3368 (when (string-match TeX-header-end (ad-get-arg 1))
3370 (prog1 (substring (ad-get-arg 1) (match-end 0))
3373 (insert (substring (ad-get-arg 1)
3376 (count-lines (point-min) (point-max))
3377 (if (bolp) 0 -1))))))))
3379 (defun preview-document ()
3380 "Run preview on master document."
3382 (TeX-save-document (TeX-master-file))
3383 (preview-generate-preview
3384 nil (TeX-master-file nil t)
3385 (preview-do-replacements
3387 (preview-string-expand preview-LaTeX-command)
3389 preview-LaTeX-command-replacements)))
3391 (defun preview-environment (count)
3392 "Run preview on LaTeX environment.
3393 This avoids running environments through preview that are
3394 indicated in `preview-inner-environments'. If you use a prefix
3395 argument COUNT, the corresponding level of outward nested
3396 environments is selected."
3400 (dotimes (i (1- count))
3401 (setq currenv (LaTeX-current-environment))
3402 (if (string= currenv "document")
3403 (error "No enclosing outer environment found"))
3404 (LaTeX-find-matching-begin))
3405 (while (member (setq currenv (LaTeX-current-environment))
3406 preview-inner-environments)
3407 (LaTeX-find-matching-begin))
3408 (if (string= currenv "document")
3409 (error "No enclosing outer environment found"))
3411 (save-excursion (LaTeX-find-matching-begin) (point))
3412 (save-excursion (LaTeX-find-matching-end) (point))))))
3414 (defun preview-section ()
3415 "Run preview on LaTeX section." (interactive)
3417 (LaTeX-mark-section)
3418 (preview-region (region-beginning) (region-end))))
3421 (defun preview-generate-preview (region-p file command)
3422 "Generate a preview.
3423 REGION-P is the region flag, FILE the file (without default
3424 extension and directory), COMMAND is the command to use.
3426 It returns the started process."
3427 (setq TeX-current-process-region-p region-p)
3428 (let* ((geometry (preview-get-geometry))
3429 (commandbuff (current-buffer))
3431 (if TeX-current-process-region-p
3435 (master (TeX-master-file))
3436 (master-file (expand-file-name master))
3437 (dumped-cons (assoc master-file
3438 preview-dumped-alist))
3441 (push (setq dumped-cons (cons master-file
3442 (if (eq preview-auto-cache-preamble 'ask)
3443 (y-or-n-p "Cache preamble? ")
3444 preview-auto-cache-preamble)))
3445 preview-dumped-alist))
3446 (when (cdr dumped-cons)
3447 (let* (TeX-current-process-region-p)
3448 (setq process (preview-cache-preamble dumped-cons))
3450 (setq TeX-sentinel-function
3451 `(lambda (process string)
3452 (funcall ,TeX-sentinel-function process string)
3453 (TeX-inline-preview-internal
3455 ',pr-file ,commandbuff
3459 (buffer-string)))))))
3461 (TeX-inline-preview-internal command file
3466 (defun TeX-inline-preview-internal (command file pr-file
3467 commandbuff dumped-cons master
3470 "Internal stuff for previewing.
3471 COMMAND and FILE should be explained in `TeX-command-list'.
3472 PR-FILE is the target file name in the form for `preview-gs-file'.
3473 COMMANDBUFF, DUMPED-CONS, MASTER, and GEOMETRY are
3474 internal parameters, STR may be a log to insert into the current log."
3475 (set-buffer commandbuff)
3477 ((preview-format-name (shell-quote-argument
3478 (preview-dump-file-name
3479 (file-name-nondirectory master))))
3483 (if (consp (cdr dumped-cons))
3484 (preview-do-replacements
3485 command preview-undump-replacements)
3491 (goto-char (point-min))
3493 (when (= (process-mark process) (point-min))
3494 (set-marker (process-mark process) (point)))))
3495 (preview-set-geometry geometry)
3496 (setq preview-gs-file pr-file)
3497 (setq TeX-sentinel-function 'preview-TeX-inline-sentinel)
3498 (when (featurep 'mule)
3499 (setq preview-coding-system
3500 (or (and (boundp 'TeX-japanese-process-output-coding-system)
3501 TeX-japanese-process-output-coding-system)
3502 (with-current-buffer commandbuff
3503 buffer-file-coding-system)))
3504 (when preview-coding-system
3505 (setq preview-coding-system
3506 (preview-buffer-recode-system
3507 (coding-system-base preview-coding-system))))
3508 (set-process-coding-system
3509 process preview-coding-system))
3511 (setq TeX-parse-function 'TeX-parse-TeX)
3512 (if TeX-process-asynchronous
3514 (TeX-synchronous-sentinel "Preview-LaTeX" file process)))
3515 (error (preview-log-error err "Preview" process)
3516 (delete-process process)
3517 (preview-reraise-error process)))))
3519 (defconst preview-version (eval-when-compile
3520 (let ((name "$Name: release_11_87 $")
3521 (rev "$Revision: 1.286 $"))
3522 (or (when (string-match "\\`[$]Name: *release_\\([^ ]+\\) *[$]\\'" name)
3523 (setq name (match-string 1 name))
3524 (while (string-match "_" name)
3525 (setq name (replace-match "." t t name)))
3527 (if (string-match "\\`[$]Revision: *\\([^ ]+\\) *[$]\\'" rev)
3528 (format "CVS-%s" (match-string 1 rev)))
3531 If not a regular release, CVS revision of `preview.el'.")
3533 (defconst preview-release-date
3535 (let ((date "$Date: 2011/01/23 18:53:55 $"))
3537 "\\`[$]Date: *\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)"
3539 (format "%s.%s%s" (match-string 1 date) (match-string 2 date)
3540 (match-string 3 date))))
3541 "Preview release date.
3542 In the form of yyyy.mmdd")
3544 (defun preview-dump-state (buffer)
3547 (unless (local-variable-p 'TeX-command-buffer)
3548 (setq buffer (with-current-buffer buffer (TeX-active-buffer))))
3549 (when (bufferp buffer)
3550 (insert "\nRun buffer contents:\n\n")
3551 (if (< (buffer-size buffer) 5000)
3552 (insert-buffer-substring buffer)
3553 (insert-buffer-substring buffer 1 2500)
3554 (insert "...\n\n[...]\n\n\t...")
3555 (insert-buffer-substring buffer
3556 (- (buffer-size buffer) 2500)
3557 (buffer-size buffer)))
3562 (defun preview-report-bug () "Report a bug in the preview-latex package."
3564 (let ((reporter-prompt-for-summary-p "Bug report subject: "))
3565 (reporter-submit-bug-report
3566 "bug-auctex@gnu.org"
3567 (if (string-match "^CVS-" preview-version)
3568 (concat "preview-" (substring preview-version 4))
3574 preview-image-creators
3575 preview-dvipng-image-type
3576 preview-dvipng-command
3577 preview-pdf2dsc-command
3580 preview-gs-image-type-alist
3581 preview-fast-conversion
3582 preview-prefer-TeX-bb
3583 preview-dvips-command
3584 preview-fast-dvips-command
3585 preview-scale-function
3586 preview-LaTeX-command
3587 preview-required-option-list
3588 preview-preserve-counters
3589 preview-default-option-list
3590 preview-default-preamble
3591 preview-LaTeX-command-replacements
3592 preview-dump-replacements
3593 preview-undump-replacements
3594 preview-auto-cache-preamble
3595 preview-TeX-style-dir)
3596 `(lambda () (preview-dump-state ,(current-buffer)))
3598 (insert (format "\nOutput from running `%s -h':\n"
3599 preview-gs-command))
3600 (call-process preview-gs-command nil t nil "-h")
3602 "Remember to cover the basics. Including a minimal LaTeX example
3603 file exhibiting the problem might help."
3607 (when (boundp 'preview-compatibility-macros)
3608 (dolist (elt preview-compatibility-macros)
3610 (fset (car elt) (cdr elt))
3611 (fmakunbound elt)))))
3613 (makunbound 'preview-compatibility-macros)
3616 ;;; preview.el ends here