Subject: Re: bug#11068: 24.0.94; Face-remapped background does not extend to end of window

From: martin rudalics <[email-masked]>
Date: Mon, 26 Mar 2012 09:05:43 +0200

>> So you do use an established mechanism but for the fact that these lines
 >> exist only virtually.  Or am I missing something?
 >
 > I don't understand what you mean by "exist only virtually".  We are
 > not talking about lines, we are talking about glyph matrices.  A glyph
 > matrix has at least one glyph for each screen line, no matter if there
 > is or isn't text on these lines; this includes empty lines beyond BOB.
								
With "virtual" I tried to describe the presence of a (space) character
on the screen which has no correspondence to a "real" character in a
buffer.

 > The established mechanism I used was invented for extending the
 > (non-default) face of the last character of a line all the way to the
 > right margin of the window.  I made it do double duty for R2L lines,
 > because these need a stretch glyph at their left, so that the
 > device-specific drawing code could still draw left to right.  Then I
 > made it do triple duty when the default face is remapped, by adding
 > stretch glyphs even on L2R lines beyond EOB.  All it took was to
 > slightly tweak the conditions under which the function
 > extend_face_to_end_of_line is called, and what it does as part of its
 > job.

That's what I thought.  Thanks for the precise explanation.

 >> But when drawing the stretch glyph at a non-EOB line end the display
 >> engine does use the face of the return character.
 >
 > Not the face of the return character, but the face of the last glyph
 > produced for the line.

I still can't follow you.  For years I use:

(defun font-lock-fontify-syntactically-region (start end &optional loudly ppss)
   "Put proper face on each string and comment between START and END.
START should be at the beginning of a line."
   (let (state face from to lep)
     (goto-char start)
     (setq state (or ppss (syntax-ppss start)))
     (while
         (progn
           (when (or (nth 3 state) (nth 4 state))
             (setq face (funcall font-lock-syntactic-face-function state))
             (setq from (max (nth 8 state) start))
             (setq state
                   (parse-partial-sexp (point) end nil nil state 'syntax-table))
             (setq to (point))
             (save-excursion
               (goto-char from)
               (while (< from to)
                 (setq lep (line-end-position))
                 (if (< lep to)
                     (progn
                       (put-text-property from lep 'face face)
                       (remove-text-properties
		       lep (1+ lep) '(face nil)) ; rear-nonsticky t))
                       (goto-char (setq from (1+ lep))))
                   (put-text-property from to 'face face)
                   (setq from to)))))
           (< (point) end))
       (setq state
         (parse-partial-sexp (point) end nil nil state 'syntax-table)))))

(custom-set-faces
  '(font-lock-comment-face ((((class color) (background light)) (:background "Beige" :foreground "Black"))))
  '(font-lock-string-face ((t (:foreground "green4"))))
  '(font-lock-doc-face ((t (:inherit font-lock-string-face :background "grey96")))))

Evaluate these in *scratch* with emacs -Q and redraw.  You will see that
the background of comments and doc-strings does _not_ extend to the
right window margin although the last character on each comment or
doc-string line _does_ have that background.  Now what constitutes "the
last glyph produced" for such a line?  That of the last visible
character on the buffer line?

 >> In my `font-lock-fontify-syntactically-region' function I strip all
 >> face properties from the return character and the rest of the line
 >> has the default background.
 >
 > What that does is force redisplay to change the face at the line
 > boundary.  Normally, the last face used on the line is also used for
 > the first glyph of the next line.  The face of the newline itself has
 > no direct relation to this.

But as you see from my code above, all I do is change the face of the
newline character.  The faces before and after it remain unchanged.  You
can easily verify for yourself in a not font-locked buffer: Change the
background of one newline character only and the value you specifiy
there will be used for drawing the space between the last visible
character on the line and the right window margin and for nothing else.

 >> Couldn't we "clear" using the remapped default color as well?
 >
 > That's possible, but it's a much worse design, IMO, because it would
 > mean this needs to be implemented N times, one each for every terminal
 > type we support (TTY, X, w32, ns).  Worse, there's this:
 >
 >> Does "clearing" care about character heights, for example?
 >
 > No.  It also cannot support faces with a stipple.  So this design
 > isn't really up to the job at all.

Aha.  This clears things up for me.

 >> If you do, for example,
 >>
 >> (let ((overlay (make-overlay (point-max) (point-max))))
 >>    (overlay-put overlay 'after-string "\n\n\n\n"))
 >>
 >> you can't move to the position before the overlay which makes the whole
 >> thing worthless.
 >
 > Try putting a `cursor' text property on the first newline of the
 > string, and if that doesn't work, I might agree it's a bug.
 > Otherwise, Emacs always puts the cursor after the overlay string.

Thanks, that works.  Now if only this had been described in the overlays
manual section ...

martin