Subject: bug#22915: foreground-color-at-point doesn't return the foreground color at point (when overlays are present)

From: Eli Zaretskii <[email-masked]>
Date: Sat, 05 Mar 2016 10:15:58 +0200

> From: Clément Pit--Claudel <[email-masked]>
> Date: Sat, 5 Mar 2016 01:10:37 -0500
> 
> (with-current-buffer (get-buffer-create "*broken*")
>   (require 'cl-lib)
>   (erase-buffer)
>   (delete-all-overlays)
>   (fundamental-mode)
>   (insert "AAAAA")
>   (goto-char (point-min))
> 
>   ;; Add two faces
>   (set-text-properties (point-min) (point-max) '(face font-lock-type-face))
>   (let ((ov (make-overlay (point-min) (point-max))))
>     (overlay-put ov 'face 'font-lock-negation-char-face))
> 
>   ;; This passes, proving that font-lock-negation-char-face is not contributing to the
>   ;; foreground color
>   (cl-assert (eq (face-attribute 'font-lock-negation-char-face :foreground)
>                  'unspecified))
> 
>   ;; This fails: foreground-color-at-point reads the face of the overlay, sees that it's undefined, 
>   ;; and ignores the 'face text property
>   (cl-assert (eq (foreground-color-at-point)
>                  (face-attribute 'font-lock-type-face :foreground)))
> 
>   (pop-to-buffer (current-buffer)))

You are creating a situation where the actual color of the character
is the result of face merging as part of redisplay.  I don't think
there's currently any way of accessing the results of face merging
from Lisp.

By contrast, foreground-color-at-point simply returns the color
specified by the highest-priority overlay/text property at point; in
this case that color is unspecified, so it defaults to the default
face's foreground color.

If I'm right, you expect too much from foreground-color-at-point, or
from any Lisp implementation of this functionality in general.

AFAICT, if we want this kind of functionality supported from Lisp, we
will need first to implement a primitive that would accept a list of
faces and return the fully realized face spec produced by merging
those faces.  Then a Lisp implementation of foreground-color-at-point
could be changed to collect all the relevant text/overlay properties
at point and pass them to that primitive.

Alternatively, an entirely-C implementation, exposed to Lisp as a
primitive, could simulate display of the character at point and return
the resulting color.

If there are other ideas, I'm all ears.  If not, I think this is a
fine subject for a small project, patches are welcome.