Subject: Re: bug#14567: Scrolling of large images

From: David Engster <[email-masked]>
Date: Sat, 15 Jun 2013 11:02:46 +0200

Eli Zaretskii writes:
>> >> I can't really reproduce the line-move error either in this mode. It
>> >> does show up occasionally but I haven't figured out how to
>> >> explicitly trigger it thus far.
>> >
>> > I'll try reproducing it here.
>> 
>> I also tried the patch on current trunk. I use the following snippet to
>> generate a buffer containing large and small images as well as text:
>
> Thanks.  Unfortunately, using Emacs with Imagemagick support is a
> no-starter for me.

It's only needed for scaling, though. If you have at least libjpeg, then
just download those two images

http://randomsample.de/bigimage.jpg
http://randomsample.de/smallimage.jpg

and use

(with-current-buffer (get-buffer-create "test")
  (erase-buffer)
  (let ((imagelarge (create-image "~/bigimage.jpg"))
	(imagesmall (create-image "~/smallimage.jpg")))
    (dotimes (i 20)
      (insert "\n*** " (number-to-string i)" ***\nThis is a line of text.\nAnd here's a large image:\n")
      (insert-image imagelarge)
      (insert "\nAnd a small image:\n")
      (insert-image imagesmall))
    (goto-char (point-min))))

>However, I tried to cover every possibility of using non-numeric values
>in numeric context.  Please try the patch below (it's relative to the
>current trunk, not to the previous patch), and see if it gives good
>results.  If you still get errors, please manually load simple.el (not
>simple.elc) into your Emacs, run your test snippet, and see if the
>backtrace can pinpoint the place where I missed something.

It fails in line 4789 because 'py' is nil. I attached the backtrace.

-David

Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
  =(nil 4)
  (and vpos (> vpos 0) (= py (min (- (window-text-height) scroll-margin 1) (1- vpos))))
  (cond ((and (or (< (setq vs (window-vscroll nil t)) fch) (null this-height) (<= this-height fch)) (or (null rbot) (= rbot 0))) nil) ((and (or (null this-height) (<= this-height fch)) vpos (> vpos 0) (< (setq py (or (nth 1 this-lh) (let (...) (cdr ...)))) (min (- (window-text-height) scroll-margin 1) (1- vpos)))) nil) ((> vs 0) (if (or (and rbot (> rbot 0)) (and this-height (> this-height fch))) (progn (set-window-vscroll nil (+ vs fch) t)))) ((and vpos (> vpos 0) (= py (min (- (window-text-height) scroll-margin 1) (1- vpos)))) (set-window-vscroll nil (frame-char-height) t) (line-move-1 arg noerror to-end) t) ((and vpos (> vpos 0)) (scroll-up 1) t) (t (set-window-vscroll nil (frame-char-height) t)))
  (progn (if lh nil (let ((wend (pos-visible-in-window-p t nil t))) (setq rbot (nth 3 wend) vpos (nth 5 wend)))) (if this-lh nil (let ((wstart (pos-visible-in-window-p nil nil t))) (setq this-ypos (nth 2 wstart) this-height (nth 4 wstart)))) (cond ((and (or (< (setq vs (window-vscroll nil t)) fch) (null this-height) (<= this-height fch)) (or (null rbot) (= rbot 0))) nil) ((and (or (null this-height) (<= this-height fch)) vpos (> vpos 0) (< (setq py (or (nth 1 this-lh) (let ... ...))) (min (- (window-text-height) scroll-margin 1) (1- vpos)))) nil) ((> vs 0) (if (or (and rbot (> rbot 0)) (and this-height (> this-height fch))) (progn (set-window-vscroll nil (+ vs fch) t)))) ((and vpos (> vpos 0) (= py (min (- (window-text-height) scroll-margin 1) (1- vpos)))) (set-window-vscroll nil (frame-char-height) t) (line-move-1 arg noerror to-end) t) ((and vpos (> vpos 0)) (scroll-up 1) t) (t (set-window-vscroll nil (frame-char-height) t))))
  (if (or (null lh) (>= rbot fch) (<= ypos (- fch)) (null this-lh) (<= this-ypos (- fch))) (progn (if lh nil (let ((wend (pos-visible-in-window-p t nil t))) (setq rbot (nth 3 wend) vpos (nth 5 wend)))) (if this-lh nil (let ((wstart (pos-visible-in-window-p nil nil t))) (setq this-ypos (nth 2 wstart) this-height (nth 4 wstart)))) (cond ((and (or (< (setq vs ...) fch) (null this-height) (<= this-height fch)) (or (null rbot) (= rbot 0))) nil) ((and (or (null this-height) (<= this-height fch)) vpos (> vpos 0) (< (setq py (or ... ...)) (min (- ... scroll-margin 1) (1- vpos)))) nil) ((> vs 0) (if (or (and rbot (> rbot 0)) (and this-height (> this-height fch))) (progn (set-window-vscroll nil (+ vs fch) t)))) ((and vpos (> vpos 0) (= py (min (- ... scroll-margin 1) (1- vpos)))) (set-window-vscroll nil (frame-char-height) t) (line-move-1 arg noerror to-end) t) ((and vpos (> vpos 0)) (scroll-up 1) t) (t (set-window-vscroll nil (frame-char-height) t)))))
  (let* ((lh (window-line-height -1)) (vpos (nth 1 lh)) (ypos (nth 2 lh)) (rbot (nth 3 lh)) (this-lh (window-line-height)) (this-height (nth 0 this-lh)) (this-ypos (nth 2 this-lh)) (fch (frame-char-height)) py vs) (if (or (null lh) (>= rbot fch) (<= ypos (- fch)) (null this-lh) (<= this-ypos (- fch))) (progn (if lh nil (let ((wend (pos-visible-in-window-p t nil t))) (setq rbot (nth 3 wend) vpos (nth 5 wend)))) (if this-lh nil (let ((wstart (pos-visible-in-window-p nil nil t))) (setq this-ypos (nth 2 wstart) this-height (nth 4 wstart)))) (cond ((and (or (< ... fch) (null this-height) (<= this-height fch)) (or (null rbot) (= rbot 0))) nil) ((and (or (null this-height) (<= this-height fch)) vpos (> vpos 0) (< (setq py ...) (min ... ...))) nil) ((> vs 0) (if (or (and rbot ...) (and this-height ...)) (progn (set-window-vscroll nil ... t)))) ((and vpos (> vpos 0) (= py (min ... ...))) (set-window-vscroll nil (frame-char-height) t) (line-move-1 arg noerror to-end) t) ((and vpos (> vpos 0)) (scroll-up 1) t) (t (set-window-vscroll nil (frame-char-height) t))))))
  (if (< arg 0) (let ((vs (window-vscroll nil t))) (if (> vs (frame-char-height)) (progn (set-window-vscroll nil (- vs (frame-char-height)) t)))) (let* ((lh (window-line-height -1)) (vpos (nth 1 lh)) (ypos (nth 2 lh)) (rbot (nth 3 lh)) (this-lh (window-line-height)) (this-height (nth 0 this-lh)) (this-ypos (nth 2 this-lh)) (fch (frame-char-height)) py vs) (if (or (null lh) (>= rbot fch) (<= ypos (- fch)) (null this-lh) (<= this-ypos (- fch))) (progn (if lh nil (let ((wend ...)) (setq rbot (nth 3 wend) vpos (nth 5 wend)))) (if this-lh nil (let ((wstart ...)) (setq this-ypos (nth 2 wstart) this-height (nth 4 wstart)))) (cond ((and (or ... ... ...) (or ... ...)) nil) ((and (or ... ...) vpos (> vpos 0) (< ... ...)) nil) ((> vs 0) (if (or ... ...) (progn ...))) ((and vpos (> vpos 0) (= py ...)) (set-window-vscroll nil (frame-char-height) t) (line-move-1 arg noerror to-end) t) ((and vpos (> vpos 0)) (scroll-up 1) t) (t (set-window-vscroll nil (frame-char-height) t)))))))
  line-move-partial(1 nil nil)
  (and auto-window-vscroll try-vscroll (= (abs arg) 1) (zerop scroll-conservatively) (not defining-kbd-macro) (not executing-kbd-macro) (line-move-partial arg noerror to-end))
  (if (and auto-window-vscroll try-vscroll (= (abs arg) 1) (zerop scroll-conservatively) (not defining-kbd-macro) (not executing-kbd-macro) (line-move-partial arg noerror to-end)) nil (set-window-vscroll nil 0 t) (if (and line-move-visual (not goal-column) (not (> (window-hscroll) 0))) (prog1 (line-move-visual arg noerror) (let ((lh (line-pixel-height))) (if (and (< arg 0) (< (point) (window-start)) (> lh (frame-char-height))) (set-window-vscroll nil (- lh (frame-char-height)) t)))) (line-move-1 arg noerror to-end)))
  (if noninteractive (forward-line arg) (if (and auto-window-vscroll try-vscroll (= (abs arg) 1) (zerop scroll-conservatively) (not defining-kbd-macro) (not executing-kbd-macro) (line-move-partial arg noerror to-end)) nil (set-window-vscroll nil 0 t) (if (and line-move-visual (not goal-column) (not (> (window-hscroll) 0))) (prog1 (line-move-visual arg noerror) (let ((lh (line-pixel-height))) (if (and (< arg 0) (< ... ...) (> lh ...)) (set-window-vscroll nil (- lh ...) t)))) (line-move-1 arg noerror to-end))))
  line-move(1 nil nil 1)
  (condition-case err (line-move arg nil nil try-vscroll) ((beginning-of-buffer end-of-buffer) (signal (car err) (cdr err))))
  (if (called-interactively-p (quote interactive)) (condition-case err (line-move arg nil nil try-vscroll) ((beginning-of-buffer end-of-buffer) (signal (car err) (cdr err)))) (line-move arg nil nil try-vscroll))
  (if (and next-line-add-newlines (= arg 1)) (if (save-excursion (end-of-line) (eobp)) (let ((abbrev-mode nil)) (end-of-line) (insert (if use-hard-newlines hard-newline "\n"))) (line-move arg nil nil try-vscroll)) (if (called-interactively-p (quote interactive)) (condition-case err (line-move arg nil nil try-vscroll) ((beginning-of-buffer end-of-buffer) (signal (car err) (cdr err)))) (line-move arg nil nil try-vscroll)))
  next-line(1 1)
  call-interactively(next-line nil nil)
  (prog1 (call-interactively cmd record-flag keys) (if (and (symbolp cmd) (get cmd (quote byte-obsolete-info)) (not (get cmd (quote command-execute-obsolete-warned)))) (progn (put cmd (quote command-execute-obsolete-warned) t) (message "%s" (macroexp--obsolete-warning cmd (get cmd (quote byte-obsolete-info)) "command")))))
  (cond ((arrayp final) (if record-flag (progn (setq command-history (cons (list (quote execute-kbd-macro) final prefixarg) command-history)) (if (and (numberp history-length) (> history-length 0)) (progn (let (...) (if ... ...)))))) (execute-kbd-macro final prefixarg)) (t (prog1 (call-interactively cmd record-flag keys) (if (and (symbolp cmd) (get cmd (quote byte-obsolete-info)) (not (get cmd (quote command-execute-obsolete-warned)))) (progn (put cmd (quote command-execute-obsolete-warned) t) (message "%s" (macroexp--obsolete-warning cmd (get cmd ...) "command")))))))
  (let ((final cmd)) (while (progn (setq final (indirect-function final)) (if (autoloadp final) (setq final (autoload-do-load final cmd))))) (cond ((arrayp final) (if record-flag (progn (setq command-history (cons (list ... final prefixarg) command-history)) (if (and (numberp history-length) (> history-length 0)) (progn (let ... ...))))) (execute-kbd-macro final prefixarg)) (t (prog1 (call-interactively cmd record-flag keys) (if (and (symbolp cmd) (get cmd (quote byte-obsolete-info)) (not (get cmd ...))) (progn (put cmd (quote command-execute-obsolete-warned) t) (message "%s" (macroexp--obsolete-warning cmd ... "command"))))))))
  (let ((prefixarg (if special nil (prog1 prefix-arg (setq current-prefix-arg prefix-arg) (setq prefix-arg nil))))) (and (symbolp cmd) (get cmd (quote disabled)) (run-hooks (quote disabled-command-function))) (let ((final cmd)) (while (progn (setq final (indirect-function final)) (if (autoloadp final) (setq final (autoload-do-load final cmd))))) (cond ((arrayp final) (if record-flag (progn (setq command-history (cons ... command-history)) (if (and ... ...) (progn ...)))) (execute-kbd-macro final prefixarg)) (t (prog1 (call-interactively cmd record-flag keys) (if (and (symbolp cmd) (get cmd ...) (not ...)) (progn (put cmd ... t) (message "%s" ...))))))))
  command-execute(next-line)