> (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 overlays. 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 redisplay. 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.) _______________________________________________ Emacs-pretest-bug mailing list Emacs-pretest-bug@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-pretest-bug