Subject: bug#39927: 12.2; preview-latex gs treatment off by one

From: [email-masked]
Date: Thu, 5 Mar 2020 13:47:42 +0100 (CET)

Hello,

Funny bug with preview-latex.  I use gs 9.50 with preview-pdf-color-adjust-method = t.

Whenever generating previews, I get error messages for essentially all preview images, such as:
« Cannot find image file ‘.../_region_.prv/.../pr1-1.png’ » 

Then, one preview image (first one in document order, last one to be treated, if I understood things correctly) fails to load, just get a big blank square.
Move the cursor a bit, and it loads as well.  Particularly annoying if you are just refreshing a single preview image and it fails to load.

My diagnosis : in parsing the GS output, preview-gs-transact just assumes that some prompts from GS mean that an image has been treated.  I **guess** the introduction of -dDELAYBIND could have added an extra such prompt, so now it assumes the image is ready before it actually is.  emacs complains it cannot be found.  Then when adding the next image to its overlay, emacs realises that the previous image is there now, and loads it, so in the end, it is only the last image to be loaded that is missing, but error messages are displayed for all.

Possible solution : it **seems** that GS outputs GS<1> when it has treated an image, and GS> when it has, well, done I am not sure what.  So instead of just counting all prompts and just skip one as current code seems to do, I would suggest to ignore the GS> prompts.
The following code does this, and solves the problem (for me).
Cheers,

Itaï.

(defun preview-gs-transact (process answer)
  "Work off Ghostscript transaction.
This routine is the action routine called via the process filter.
The Ghostscript process buffer of PROCESS will already be selected, and
and the standard output of Ghostscript up to the next prompt will be
given as ANSWER."
  (while (and (< (length preview-gs-outstanding)
		 preview-gs-outstanding-limit)
	      (setq ov (pop preview-gs-queue)))
    (let ((queued (overlay-get ov 'queued)))
      (when (and queued
		 (not (memq ov preview-gs-outstanding))
		 (overlay-buffer ov))
	(let* ((filenames (overlay-get ov 'filenames))
	       (oldfile (car (nth 0
				  (nconc filenames
					 (list
					  (preview-make-filename
					   (format "pr%d-%d.%s"
						   (car preview-gs-sequence)
						   (cdr preview-gs-sequence)
						   preview-gs-image-type)
					   TeX-active-tempdir))))))
	       (bbox (aset queued 0
			   (or (and preview-prefer-TeX-bb
				    (aref queued 0))
			       (and (stringp oldfile)
				    (preview-extract-bb
				     oldfile))
			       (aref queued 0)
			       (error "No bounding box"))))
	       (snippet (aref queued 2))
	       (gs-line
		(format
		 "%s<<%s>>preview-do\n"
		 (if preview-ps-file
		     (concat "dup "
			     (preview-gs-dsc-cvx
			      snippet
			      preview-gs-dsc))
		   (format "%s(r)file cvx"
			   (preview-ps-quote-filename
			    (if (listp oldfile)
				(car (last oldfile))
			      oldfile))))
		 (if preview-parsed-tightpage
		     ""
		   (format "/PageSize[%g %g]/PageOffset[%g \
%g[1 1 dtransform exch]{0 ge{neg}if exch}forall]"
			   (- (aref bbox 2) (aref bbox 0))
			   (- (aref bbox 3) (aref bbox 1))
			   (aref bbox 0) (aref bbox 1))))))
	  (setcdr preview-gs-sequence (1+ (cdr preview-gs-sequence)))
	  (setq preview-gs-outstanding
		(nconc preview-gs-outstanding
		       (list ov)))
	  (aset queued 1 gs-line)
	  ;; ignore errors because of dying processes: they will get
	  ;; caught by the sentinel, anyway.
	  (condition-case nil
	      (process-send-string
	       process
	       gs-line)
	    (error nil))))))
  (when (not (string-match "\\`GS>\\'" answer))
    (let ((ov (pop preview-gs-outstanding))
	  (have-error (not
		       (string-match "\\`GS\\(<[0-9]+\\)?>\\'" answer))))
      (when (and ov (overlay-buffer ov))
	(let ((queued (overlay-get ov 'queued)))
	  (when queued
	    (let* ((bbox (aref queued 0))
		   (filenames (overlay-get ov 'filenames))
		   (oldfile (nth 0 filenames))
		   (newfile (nth 1 filenames)))
	      (if have-error
		  (preview-gs-flag-error ov answer)
		(condition-case nil
		    (preview-delete-file oldfile)
		  (file-error nil))
		(overlay-put ov 'filenames (cdr filenames))
		(preview-replace-active-icon
		 ov
		 (preview-create-icon (car newfile)
				      preview-gs-image-type
				      (preview-ascent-from-bb
				       bbox)
				      (aref preview-colors 2))))
	      (overlay-put ov 'queued nil))))))
    (unless preview-gs-outstanding
      (condition-case nil
	  (process-send-eof process)
	(error nil)))))

Emacs  : GNU Emacs 26.3 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.11)
 of 2019-09-22, modified by Debian
Package: 12.2

current state:
==============
(setq
 AUCTeX-date "2019-10-30"
 window-system 'x
 LaTeX-version "2e"
 TeX-style-path '("/var/lib/auctex/emacs/"
		  "/usr/share/emacs/site-lisp/auctex/style"
		  "/home/begnac/.emacs.d/auctex/auto"
		  "/home/begnac/.emacs.d/auctex/style" "auto" "style")
 TeX-auto-save nil
 TeX-parse-self nil
 TeX-master t
 TeX-command-list '(("LaTeX" "%`%l%(mode)%' %t" TeX-run-TeX nil
		     (latex-mode doctex-mode) :help "Run LaTeX")
		    ("BibTeX" "bibtex %s" TeX-run-BibTeX nil t :help
		     "Run BibTeX")
		    ("View" "%V" TeX-run-discard-or-function nil t :help
		     "Run Viewer")
		    ("Index" "makeindex %s" TeX-run-index nil
		     (plain-tex-mode latex-mode doctex-mode ams-tex-mode
		      texinfo-mode)
		     :help "Run makeindex to create index file")
		    ("Clean" "TeX-clean" TeX-run-function nil t :help
		     "Delete generated intermediate files")
		    ("Clean All" "(TeX-clean t)" TeX-run-function nil t :help
		     "Delete generated intermediate and output files")
		    )
 )