Subject: bug#29279: Sharing the margins

From: Eli Zaretskii <[email-masked]>
Date: Mon, 13 Nov 2017 20:15:36 +0200

> Cc: [email-masked]
> From: Dmitry Gutov <[email-masked]>
> Date: Mon, 13 Nov 2017 19:24:21 +0200
> 
> >> - Text alignment within the column (left or right)
> > 
> > Why does this need to be a separate property?  We don't have anything
> > like that for any other kind of text.
> 
> IDK, why not? Will we always align to the right?

No, to the left.  If a Lisp program wants to align to the right, it
should insert white space before the actual text.

> > I think we need to agree on the model of the display in the margins.
> > The fact that you use "columns" in your proposal hints that each
> > "user" of the margin (a Lisp program which displays there) will have a
> > separate "column" in the margin, and that column will be of the same
> > pixel width for each screen line.
> 
> Yes.
> 
> > If this is the model, then it makes
> > little sense to have different display specs regarding the "column"
> > width for each buffer position where display in the margin is
> > requested, because the resulting column width will be the same for all
> > such displays.
> 
> The width of the string inside the margin display specs can very, can't it?

The width can change, but the column width will not change.  That
means the column width should be specified only once, not multiple
times.

> > If we specify these in each display spec, we are in
> > effect wasting Lisp storage, and potentially also working against the
> > fundamental design of the display engine (more about that below).
> 
> Sorry, specify what? The margin display spec will continue to be
> 
>    ((margin column-name) spec)
> 
> where SPEC is a text string, most of the time.

I thought you wanted all the other parameters in the spec as well.

But if you didn't mean that, then what kind of scanning and
calculations are you talking about here:

> >> The display engine would scan the contents of the current window, process said specs, calculate which lines fit the window and which do not, set the total margin width appropriately, and display all columns in it. Some reflowing might be required.

If everything is already spelled out in a variable
left-margin-columns-alist, then why do we need to scan the contents of
the window?

> > So what you suggest can only be implemented by displaying each window
> > twice.  On top of that, it will disable important redisplay
> > optimizations, which refrain from examining all of the screen lines
> > and the corresponding buffer text -- since you require to scan all of
> > the display specs in the window to dynamically compute the margin
> > dimensions.
> 
> I was hoping that we might consider some parts of redisplay to be "fast 
> enough" by now (posn-at-point is fast enough for ~500 FPS on my machine, 
> for instance), but indeed it should require some smart programming.

posn-at-point goes _once_ from window-start to the specified position,
so on average it traverses half a window, once.  By contrast, we are
now talking about redisplaying the window twice, and one of these 2
times must traverse the entire window.  So we are talking about
threefold slow-down on the average.

> What your description tells me, foremost, is that it should be 
> impossible to "perfectly" make these decisions in Lisp, too.
> 
> Like, what can linum-mode do? After scrolling, it would look at the 
> window-start, its height, and calculate the _approximate_ physical line 
> at the end of the window.

linum uses window-end (which could be nil in some cases).  window-end
is updated by redisplay when it ends successfully.  linum then updates
the width of the window margins if needed, and updates all the
overlays with line numbers, which triggers an immediate additional
redisplay.  That's why it is slow.

So yes, if the margin display depends heavily on what is in the
window, especially on how many lines/characters are in the window, it
will have hard time being Speedy Gonzales; such features are better
implemented in C as an integral part of redisplay.  But not all uses
of the margins are like that.  I will even risk saying that most of
them aren't.  For that majority, calculating the maximum width they
need from the margin at the end of a command is not a big deal, and
could probably change relatively rarely.

> I guess more accurately, it would disallow dynamic *sizing* of the 
> margins by the display engine.

With the current design of the display engine, dynamic resizing is not
a good idea.  Any such resizing is painful: it requires throwing away
the window's glyph matrices, reallocating them anew with the new
dimensions, and then completely redrawing the entire window.  It's
expensive and should be avoided.

> Column widths will be accessible for manipulation from e.g. 
> pre-redisplay-functions, but like described above, it doesn't seem like 
> choosing margin width precisely is feasible in Lisp, even in the use 
> case of showing line numbers.

I think it's feasible in many cases.  Linum and its ilk are a rare use
case, although the resulting feature is very popular (which is why we
now have the native line numbers).