Subject: Re: bug#21368: 25.0.50; Core navigation commands fail in a multi-line intangible text with fringe

From: Eli Zaretskii <[email-masked]>
Date: Sat, 29 Aug 2015 10:25:22 +0300

> From: Vitalie Spinu <[email-masked]>
> Cc: [email-masked]
> Date: Sat, 29 Aug 2015 00:02:22 +0200
> 
> >> On Fri, Aug 28 2015 22:45, Eli Zaretskii wrote:
> 
> > The first two do work, you just need to invoke backward-char twice to
> > see the cursor move.  
> 
> This is not happening with `M-x (backward-char 1)`. It does indeed work when
> backward-char is invoked interactively with C-b.
> 
> This is a relatively recent change in behavior (past 2-3 months or so).

What is a relatively recent change?  The C-b part or the M-x part?

> > Is there some important real-life use case that needs this to work?
> > Otherwise, I'm inclined to leave this alone.  After all, it's not a
> > catastrophe: the next call to previous-line will go to the line you
> > want.
> 
> I have encountered this issue in 3 different projects. One is the implementation
> of visual breakpoints in ESS which look like this:
> 
>    https://ess-tracebug.googlecode.com/svn/trunk/img/breakpoint_types.PNG
> 
> For years I used to have a defadvice workaround along the following lines:
>      ...
>      (when (and (eq major-mode 'ess-mode)
>                 (get-text-property (point) 'intangible))
>       (backward-char 1))
>      add-do-it 
>      ...
> 
> With the new emacs dev the backward-char stopped working. That's why I am
> finally reporting this bug.

Can't you use an overlay to show the bitmap on the fringe?  IOW,
instead of the first display property, define an empty overlay
(i.e. overlay whose start and end positions are equal) with a
before-string that is propertized with a 'fringe' display property.
Here's an example, based on your original scenario:

  (defun insert-with-fringe ()
    (let ((pt (point))
	  ov)
      (insert
       "      "
       (propertize "dummy" 'display "AAA\n" 'font-lock-face font-lock-doc-face)
       "some more text")
      (setq ov (make-overlay (+ pt 5) (+ pt 5)))
      (overlay-put ov 'before-string
		   (propertize "fringe"
			       'display
			       (list 'left-fringe
				     'filled-square font-lock-doc-face)))
      (previous-line)))

This produces the same display as in your example, but has none of its
problems, because the situation with 2 consecutive display strings on
adjacent buffer positions is eliminated.

> Another real life use case is the yet unfinished image-display package where I
> attempted to build a grid of images with intangible segments and simply rely on
> emacs motion commands for navigation between cells. This didn't work properly
> because the vertical motion was jumping columns.
> 
> Another example is a spredsheet application for data manipulation where I have
> read-only cells which I want to navigate with standard emacs motion
> commands. Same design as above and the same problem.

OK, but if using overlays as shown above doesn't fill your needs,
please don't hold your breath for a quick solution.  It's a hard
problem, and the code that handles it is already too convoluted.
Visual line movement is a tough nut when there's a lot of invisible
text around.  (Btw, yet another solution is to disable
line-move-visual in these cases -- would that be a good idea in those
real-life examples?)