[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: before- and after-string issues

From: martin rudalics
Subject: Re: before- and after-string issues
Date: Mon, 23 May 2005 11:43:45 +0200
User-agent: Mozilla Thunderbird 1.0 (Windows/20041206)

>     (let ((B (make-overlay (point) (1+ (point))))
>       (A (make-overlay (point) (1+ (point)))))
>        (overlay-put B 'before-string "B")
>        (overlay-put A 'after-string "A"))
>     should get you two overlays covering one character with "B" appearing
>     before and "A" after the character.  Deleting that character will cause
>     the overlays to change places resulting in something like "AB".
> Now I see what you mean.  However, I am coming to the conclusion
> that the problem is overdetermined--that there is no solution
> that will DTRT in all the cases we have considered.
> In most cases we want after-strings to come before before-strings.
> The after-strings are associated with the previous character(s) while
> the before-strings are associated with the following character(s).

Conceptually, overlays and their properties have no association with
surrounding text - at least no such association is mentioned anywhere.
An overlay property - be it a face or a before-string - is associated
with an overlay and nothing else.  An overlay is specified by two buffer
positions which may stand for a stretch of characters in the buffer.
For zero-length overlays there are no such characters.  In fact, the
associated buffer may be even empty.

Moreover, your argument fails to explain the following behavior of
current Emacs: For one and the same zero-length overlay an associated
before-string appears before the after-string.  For two distinct
zero-length overlays residing at the same position the after-string
appears in front of the before-string.  Consider an empty buffer:

(let ((B (make-overlay (point-min) (point-min)))
      (A (make-overlay (point-min) (point-min))))
  (overlay-put B 'before-string "B")
  (overlay-put A 'after-string "A"))

will display "AB" while

(let ((O (make-overlay (point-min) (point-min))))
  (overlay-put O 'before-string "B")
  (overlay-put O 'after-string "A"))

displays "BA".  If I understand the commentary of `overlay_strings'

"Normally all of the after-strings come first, but zero-sized overlays
have their after-strings ride along with the before-strings because it
would look strange to print them inside-out."

correctly, "BA" would have to appear in both cases.  I believe that the
current solution has been adopted because it was simpler - and more
elegant - to code.  Any good programmer would have written it that way.

> In your case, we would like the before-string to come first because of
> history which is not represented in the actual buffer status.  I don't
> see how we could DTRT in this case based on current buffer status
> without making the behavior incorrect for other cases.
> Consider this code:
>     (let ((B (make-overlay (point) (1+ (point))))
>       (A (make-overlay (1- (point)) (point))))
>        (overlay-put B 'before-string "B")
>        (overlay-put A 'after-string "A"))
> Here it is proper for A to precede B.  If we delete the two
> characters around point, we get a situation of exactly the same
> sort that your example produces.  Except that in this case
> we would want A to still precede B.

History nowhere should come into play here.  The - probably C-incorrect
- solution I sent to Kim uses five simple rules and straightforward
state-based reasoning.  In your example, after all characters have been
deleted both overlays are empty and reside at the same position.  Hence,
DTRT in the resulting state will have B precede A.  If you really wanted
history to influence state, you would have to resort to text properties.
I'd definitely keep history-based reasoning out of any implementation of

However, your "counterexample" is implausible for another reason: In
your code, overlay A clearly precedes B at the time of creation where
"precedes" alludes to the somewhat diffuse concept implemented by
`recenter_overlay_lists'.  A certainly precedes B if you can specify at
least one buffer position POS such that A resides before POS and B after
it.  In your example such a position exists initially - `point'.  You
break precedence when you delete the characters.  Whatever criterion you
apply now, A and B must end up at the same side of any buffer position.
Consequently, overlays may get reordered - moved between the respective
`overlays_before' and `overlays_after' lists in `buffer.c' parlance.
Any such reordering should result in an according reordering during

In my example there is never any precedence with respect to any buffer
position - the overlays always start and begin at the same position
regardless of whether and where you insert or delete a character.  Hence
there should not be any reordering on the screen.

> I think this proves that the only way to get "correct" results
> in all cases involving empty overlays is to record something about
> their history when they were nonempty.  Exactly what sort of
> history information would do the job, I am not sure.

I think your example does not prove that.

> Would you like to start experimenting with such solutions,
> and report back later if you find one that seems to work?

No.  Kim would justly kill me if came up with such a solution and asked
him to implement it.  (Let's rather have him kill me for my complaints
about face inheritance.)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]