5

Q:  How to obtain the points at the beginning and ending of each visual line of the current window -- without using vertical-motion -- when word-wrap is t (aka visual-line-mode).

For this experiment, I am using a few of the functions from the section of the manual entitled Accessing Mouse Events: http://www.gnu.org/software/emacs/manual/html_node/elisp/Accessing-Mouse.html

BACKGROUND:  As we all know, vertical-motion is very costly in terms of time. I have a custom minor-mode that is similar to vline.el -- http://www.emacswiki.org/emacs/vline.el -- except that mine works with word-wrap/visual-line-mode. I am searching for a faster method to perform calculations each command loop. At the present time, I make one pass of the current window (every command loop) using vertical-motion to obtain the following information: point at beginning/ending of the whole line; point at the beginning/ending of the visual line; the visual column number at the end of the visual line (which may be different than the actual column number when a line is wrapped at the window edge); point at each location in a vertical line from the cursor position spanning from window-start to window-end; and, various other information based on all of the foregoing -- e.g., colors of foreground/background faces and character codes at the various locations, line numbers, etc.

(setq word-wrap t)

(setq truncate-lines nil)

(progn
  (remove-overlays) ;; after-string properties prevent `posn-at-point` from working right.
  (let* (
      pt
      posn-at-x-y
      (counter 0)
      (window-height (window-height))
      (window-header-line-height (window-header-line-height))
      (frame-char-height (frame-char-height))
      (position (posn-at-point))
      (posn-x-y (nth 2 position))
      (posn-actual-col-row (nth 6 position)))
    (while (<= counter window-height)
      (unless
          (and
            (= counter 0)
            (= 0 window-header-line-height))
        (setq posn-at-x-y (posn-at-x-y (car posn-x-y) (* frame-char-height counter))))
      (setq pt (nth 1 posn-at-x-y))
      (setq counter (1+ counter))
      (message "counter: %s | %s" counter (if (integerp pt) (char-after pt) pt)))))
lawlist
  • 18,826
  • 5
  • 37
  • 118

1 Answers1

2

First Rough Draft

As to x, one pixel less than the (window-body-width nil t) when used in conjunction with posn-at-x-y will yield the point at the end of the visual line. As to x, zero will return the point at the beginning of the visual line. Refer to the diagram in the manual at the section relating to window sizes: https://www.gnu.org/software/emacs/manual/html_node/elisp/Window-Sizes.html

(progn
  (remove-overlays)
  (let* (
      pt
      posn-at-x-y
      (counter 0)
      (window-body-width (window-body-width nil t))
      (last-available-x (1- window-body-width))
      (window-height (window-height))
      (window-header-line-height (window-header-line-height))
      (frame-char-height (frame-char-height))
      (position (posn-at-point))
      (posn-x-y (nth 2 position))
      (posn-actual-col-row (nth 6 position)) ) ;; not presently used
    (while (<= counter window-height)
      (unless
          (and
            (= counter 0)
            (= 0 window-header-line-height))
        (setq posn-at-x-y (posn-at-x-y (car posn-x-y) (* frame-char-height counter)))
        (setq posn-x-y (nth 2 posn-at-x-y)))
      (setq pt (nth 1 posn-at-x-y))
      (message "counter: %s | pt: %s | pbovl: %s | peovl: %s"
        counter
        (if (integerp pt)
          pt ;; (char-after pt) -- not presently used.
          pt)
        (nth 1 (posn-at-x-y 0
          (if (= counter 0)
            (cdr posn-x-y)
            (+ window-header-line-height (cdr posn-x-y)))))
        (nth 1 (posn-at-x-y last-available-x
          (if (= counter 0)
            (cdr posn-x-y)
            (+ window-header-line-height (cdr posn-x-y))))))
      (setq counter (1+ counter)))))
lawlist
  • 18,826
  • 5
  • 37
  • 118