Subject: bug#15900: 24.3.50; foreground-color-at-point returns wrong results

From: Eli Zaretskii <[email-masked]>
Date: Sat, 16 Nov 2013 20:18:12 +0200

> Date: Sat, 16 Nov 2013 09:47:29 -0800 (PST)
> From: Drew Adams <[email-masked]>
> Cc: [email-masked], [email-masked]
> 
> > > Please be specific.  Just what, in the current context, cannot
> > > be done?
> > 
> > What foreground-color-at-point tries to do.
> 
> Please be specific.

This is silly.  You do know the purpose of foreground-color-at-point,
don't you?  Here's a scoop in case you didn't: it's trying to return
the foreground color of the character at point.  This is what I say
cannot be reliably done in Lisp: you cannot reliably determine the
colors of any specific character at any specific buffer position.

Now, how more specific than that can one be??

> > It is much better to ask the display engine to provide that
> > information directly.
> 
> What information?

The color of the character at point, of course.

> > > please describe the Lisp-level function(s) that you propose to
> > > provide in C
> > 
> > foreground-color-at-point, obviously.
> 
> I see.  And what is the spec of what that function would do?

Same one as the Lisp implementation, except that it will do that
correctly and reliably.  IOW, the implementation will change
completely, while the API will remain unchanged, and the contract will
also remain unchanged, except that it will now be always honored.

> What would it do differently?

It would simulate the display, as if Emacs actually did display the
character at point, and return the color produced by that.  You cannot
do that in Lisp.

> Just what is the problem you would be trying to solve by moving the
> implementation of this function to C?

The current Lisp code collects face information at or around point,
and tries to deduce from that how the character will be displayed.
Instead, the C implementation will actually display it (without
putting the result on the glass).  The result is guaranteed to be
correct.  By contrast, the Lisp implementation cannot promise such
correctness, because it in effect tries to reproduce the logic used by
the display engine, and the result is a different implementation, that
cannot possibly be 100% compatible with what the display does.

> I'm sure that if you do that I will understand, and will likely be
> convinced.  But so far you have just been hand-waving, and its
> hard to learn anything from that.

There's a lot of experience in hacking the display engine behind that
hand-waving, so you may wish to accept what I'm saying.  Or not, I
really don't care much.

> Clearly, if Lisp code cannot be used to accomplish something that
> C code can, then we want to that something in C.  So far, you have
> said nothing about what that something is.  Except for generalities:
> get the foreground color at point or some such.  Speak about the
> specific differences, please.

I can't: you lack too much knowledge for me to discuss the details.
Just read xdisp.c, if you really want to know.  I assure you that once
you've done that, it will become crystal clear to you that producing
the color at point is almost trivial on the C level, since code that
simulates display is readily available and widely used by many Emacs
features.  Reimplementing that in Lisp is waste of energy.

> The lisp code for `foreground-color-at-point' uses `face-at-point'
> (which you say you don't see as the problem) and text properties
> `read-face-name' and `face'.  That is the design - simple, and
> perhaps too simple for all purposes.

Except that a face of a character can come from many different places,
and there could be several different faces in effect at a given buffer
position, some coming from text properties, others from overlays,
still others from display strings, etc. etc.  And what if the
character at point is not even displayed, e.g. if it's covered by some
invisibility spec?  Why try to untangle all this complexity, when the
display engine already does?

> But I don't see obfuscation there - it's pretty clear what is
> going on.

It's wrong, for starters -- this is why this discussion started.  And
it's nowhere near clear, either; but I'm not going to try to convince
you in that.

> It would be clearer perhaps if the doc string said explicitly that
> the foreground color returned, if any, is taken from `face-at-point'
> or text property `read-face-name' or `face', in that order.

As a user of this API, I don't really care.  I want to know the
foreground color of the character at point, and I don't care how the
implementation does that.  So any clarifications in the doc string
about implementation details will not help me, as a user, to
understand the answer to a simple question: does this API produce what
it promises, or doesn't it?

> I'm certainly willing to believe that those three things will not
> always provide all possible information about the foreground
> color at point.

I'm trying to explain that you shouldn't even _try_ doing that in
Lisp.  If you do, you will just waste effort, and likely come up with
unreliable results, because what the display engine does cannot be
reliably reimplemented in Lisp, not with the current design.