unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
@ 2012-10-07 23:03 Christoph Scholtes
  2012-10-08  7:31 ` Eli Zaretskii
  2012-10-15  9:40 ` martin rudalics
  0 siblings, 2 replies; 34+ messages in thread
From: Christoph Scholtes @ 2012-10-07 23:03 UTC (permalink / raw)
  To: 12600

emacs -Q

Load large file, e.g. emacs.c. Buffer content must exceed one
screen.

Enable linum mode with `M-x linum-mode'.

Shrink frame. Maximize frame. Fringe on the left side is missing line 
numbers.

Move cursor down with `C-n' and the fringe refreshes and displays all 
line numbers.


In GNU Emacs 24.2.50.1 (x86_64-unknown-linux-gnu, GTK+ Version 2.24.10)
of 2012-10-07 on marvin
Bzr revision: 110431 fabian@anue.biz-20121007193737-y7fsm9ts74jks2so
Windowing system distributor `The X.Org Foundation', version 11.0.11103000
System Description: Ubuntu 12.04.1 LTS

Configured using:
`configure 'CC=clang''

Important settings:
value of $LANG: en_US.UTF-8
locale-coding-system: utf-8-unix
default enable-multibyte-characters: t

Major mode: C/l

Minor modes in effect:
linum-mode: t
tooltip-mode: t
mouse-wheel-mode: t
tool-bar-mode: t
menu-bar-mode: t
file-name-shadow-mode: t
global-font-lock-mode: t
font-lock-mode: t
blink-cursor-mode: t
auto-composition-mode: t
auto-encryption-mode: t
auto-compression-mode: t
line-number-mode: t
transient-mark-mode: t
abbrev-mode: t

Recent input:
M-x C-g C-x C-f e m c a s . <backspace> <backspace>
<backspace> <backspace> a c s . c <return> M-x l i
n u m <tab> <return> C-n C-p M-x r e p o r t <tab>
<return>

Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
Quit
emacs.c has auto save data; consider M-x recover-this-file
Loading cc-langs...done
Loading vc-bzr...done
Linum mode enabled

Load-path shadows:
None found.

Features:
(shadow sort gnus-util mail-extr emacsbug message cl-macs gv format-spec
rfc822 mml mml-sec mm-decode mm-bodies mm-encode mail-parse rfc2231
mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums
mm-util mail-prsvr mail-utils linum vc-bzr cc-langs cl cl-lib cc-mode
cc-fonts easymenu cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine
cc-vars cc-defs time-date tooltip ediff-hook vc-hooks lisp-float-type
mwheel x-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list newcomment lisp-mode register page menu-bar rfn-eshadow
timer select scroll-bar mouse jit-lock font-lock syntax facemenu
font-core frame cham georgian utf-8-lang misc-lang vietnamese tibetan
thai tai-viet lao korean japanese hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese case-table epa-hook
jka-cmpr-hook help simple abbrev minibuffer loaddefs button faces
cus-face macroexp files text-properties overlay sha1 md5 base64 format
env code-pages mule custom widget hashtable-print-readable backquote
make-network-process dbusbind dynamic-setting system-font-setting
font-render-setting move-toolbar gtk x-toolkit x multi-tty emacs)






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-07 23:03 bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame Christoph Scholtes
@ 2012-10-08  7:31 ` Eli Zaretskii
  2012-10-08  9:17   ` martin rudalics
  2012-10-15  9:40 ` martin rudalics
  1 sibling, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-08  7:31 UTC (permalink / raw)
  To: Christoph Scholtes; +Cc: 12600

> Date: Sun, 07 Oct 2012 17:03:43 -0600
> From: Christoph Scholtes <cschol2112@gmail.com>
> 
> emacs -Q
> 
> Load large file, e.g. emacs.c. Buffer content must exceed one
> screen.
> 
> Enable linum mode with `M-x linum-mode'.
> 
> Shrink frame. Maximize frame. Fringe on the left side is missing line 
> numbers.

What do you mean by "shrink" and "maximize", exactly?  Clicking on the
maximize button on the upper left corner of the Emacs frame (on
MS-Windows) doesn't reproduce the problem.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-08  7:31 ` Eli Zaretskii
@ 2012-10-08  9:17   ` martin rudalics
  2012-10-08 13:59     ` Stefan Monnier
  2012-10-08 15:48     ` Eli Zaretskii
  0 siblings, 2 replies; 34+ messages in thread
From: martin rudalics @ 2012-10-08  9:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 >> emacs -Q
 >>
 >> Load large file, e.g. emacs.c. Buffer content must exceed one
 >> screen.
 >>
 >> Enable linum mode with `M-x linum-mode'.
 >>
 >> Shrink frame. Maximize frame. Fringe on the left side is missing line
 >> numbers.
 >
 > What do you mean by "shrink" and "maximize", exactly?  Clicking on the
 > maximize button on the upper left corner of the Emacs frame (on
 > MS-Windows) doesn't reproduce the problem.

It does so here.  For whatever reason the position reported by
`window-end' in `linum-update-window' is still the same as before the
maximize.  Moving the cursor by one character makes the numbers appear.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-08  9:17   ` martin rudalics
@ 2012-10-08 13:59     ` Stefan Monnier
  2012-10-08 15:48     ` Eli Zaretskii
  1 sibling, 0 replies; 34+ messages in thread
From: Stefan Monnier @ 2012-10-08 13:59 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> It does so here.  For whatever reason the position reported by
> `window-end' in `linum-update-window' is still the same as before the
> maximize.  Moving the cursor by one character makes the numbers appear.

I'd expect that the problem does not affect nlinum.el.


        Stefan





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-08  9:17   ` martin rudalics
  2012-10-08 13:59     ` Stefan Monnier
@ 2012-10-08 15:48     ` Eli Zaretskii
  2012-10-09  9:36       ` martin rudalics
  1 sibling, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-08 15:48 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Mon, 08 Oct 2012 11:17:44 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: Christoph Scholtes <cschol2112@gmail.com>, 12600@debbugs.gnu.org
> 
>  >> emacs -Q
>  >>
>  >> Load large file, e.g. emacs.c. Buffer content must exceed one
>  >> screen.
>  >>
>  >> Enable linum mode with `M-x linum-mode'.
>  >>
>  >> Shrink frame. Maximize frame. Fringe on the left side is missing line
>  >> numbers.
>  >
>  > What do you mean by "shrink" and "maximize", exactly?  Clicking on the
>  > maximize button on the upper left corner of the Emacs frame (on
>  > MS-Windows) doesn't reproduce the problem.
> 
> It does so here.  For whatever reason the position reported by
> `window-end' in `linum-update-window' is still the same as before the
> maximize.  Moving the cursor by one character makes the numbers appear.

I don't think we can trust redisplay to have updated the screen before
the hooks used by linum-mode run.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-08 15:48     ` Eli Zaretskii
@ 2012-10-09  9:36       ` martin rudalics
  2012-10-09 17:04         ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-09  9:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 > I don't think we can trust redisplay to have updated the screen before
 > the hooks used by linum-mode run.

So what does

   If UPDATE is non-nil, compute the up-to-date position
   if it isn't already recorded.

in the doc-string of `window-end' really stand for?

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-09  9:36       ` martin rudalics
@ 2012-10-09 17:04         ` Eli Zaretskii
  2012-10-10 10:22           ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-09 17:04 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Tue, 09 Oct 2012 11:36:41 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: cschol2112@gmail.com, 12600@debbugs.gnu.org
> 
>  > I don't think we can trust redisplay to have updated the screen before
>  > the hooks used by linum-mode run.
> 
> So what does
> 
>    If UPDATE is non-nil, compute the up-to-date position
>    if it isn't already recorded.
> 
> in the doc-string of `window-end' really stand for?

That it does whatever it can to retrieve the information.  But if the
info is not there, e.g., if the resize didn't yet cause the glyph
matrices to be reallocated to match the new size, we cannot expect
redisplay to succeed in this case.

When you reproduce the problem, do you see the code conditioned by the
'if' shown below being executed at all?

(Btw, it looks like linum-mode doesn't expect to get nil from
window-end, although the doc string explicitly says it's possible.)

  if (! NILP (update)
      && ! (! NILP (w->window_end_valid)
	    && w->last_modified >= BUF_MODIFF (b)
	    && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b))
      && !noninteractive)





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-09 17:04         ` Eli Zaretskii
@ 2012-10-10 10:22           ` martin rudalics
  2012-10-10 15:45             ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-10 10:22 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 > When you reproduce the problem, do you see the code conditioned by the
 > 'if' shown below being executed at all?

No.

 > (Btw, it looks like linum-mode doesn't expect to get nil from
 > window-end, although the doc string explicitly says it's possible.)

I suppose the doc-string is wrong since otherwise we should have seen
this already reported.  IIUC it returns either

       value = make_number (IT_CHARPOS (it));

or

     XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));

while the nil reporting part was disabled.

 >
 >   if (! NILP (update)
 >       && ! (! NILP (w->window_end_valid)
 > 	    && w->last_modified >= BUF_MODIFF (b)
 > 	    && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b))
 >       && !noninteractive)

Is there anything that has not been set when the frame got resized?

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-10 10:22           ` martin rudalics
@ 2012-10-10 15:45             ` Eli Zaretskii
  2012-10-11  7:12               ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-10 15:45 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Wed, 10 Oct 2012 12:22:56 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: cschol2112@gmail.com, 12600@debbugs.gnu.org
> 
>  > When you reproduce the problem, do you see the code conditioned by the
>  > 'if' shown below being executed at all?
> 
> No.

QED.  Redisplay thinks that nothing's changed, and returns the
previous (wrong) window-end.

>  > (Btw, it looks like linum-mode doesn't expect to get nil from
>  > window-end, although the doc string explicitly says it's possible.)
> 
> I suppose the doc-string is wrong since otherwise we should have seen
> this already reported.  IIUC it returns either
> 
>        value = make_number (IT_CHARPOS (it));
> 
> or
> 
>      XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
> 
> while the nil reporting part was disabled.

It was disabled with a comment saying

  #if 0 /* This change broke some things.  We should make it later.  */
                                           ^^^^^^^^^^^^^^^^^^^^^^^
If everybody agrees that the doc string is wrong, then we should
permanently delete this code when we update the doc.  Otherwise, some
day the function will begin returning nil, and applications should be
prepared for that. 

>  >   if (! NILP (update)
>  >       && ! (! NILP (w->window_end_valid)
>  > 	    && w->last_modified >= BUF_MODIFF (b)
>  > 	    && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b))
>  >       && !noninteractive)
> 
> Is there anything that has not been set when the frame got resized?

I'm guessing it's the window_end_valid flag, since no buffer changes
are involved in the recipe.  Which probably means that the resize did
not yet become known to the display engine by the time this function
is called.

Of course, this is all theory, and I was wrong before.  It would be
best to trace this with a debugger and see what's going on.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-10 15:45             ` Eli Zaretskii
@ 2012-10-11  7:12               ` martin rudalics
  2012-10-11 16:56                 ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-11  7:12 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 > It was disabled with a comment saying
 >
 >   #if 0 /* This change broke some things.  We should make it later.  */
 >                                            ^^^^^^^^^^^^^^^^^^^^^^^
 > If everybody agrees that the doc string is wrong, then we should
 > permanently delete this code when we update the doc.  Otherwise, some
 > day the function will begin returning nil, and applications should be
 > prepared for that.

Looking at the ChangeLogs this apparently changed back and forth two
times with limited success.

 >>  >   if (! NILP (update)
 >>  >       && ! (! NILP (w->window_end_valid)
 >>  > 	    && w->last_modified >= BUF_MODIFF (b)
 >>  > 	    && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b))
 >>  >       && !noninteractive)
 >>
 >> Is there anything that has not been set when the frame got resized?
 >
 > I'm guessing it's the window_end_valid flag, since no buffer changes
 > are involved in the recipe.  Which probably means that the resize did
 > not yet become known to the display engine by the time this function
 > is called.
 >
 > Of course, this is all theory, and I was wrong before.  It would be
 > best to trace this with a debugger and see what's going on.

I have no idea what these window structure members (window_end_valid,
last_modified and last_overlay_modified) stand for in practice, who's
supposed to set them, why and when.  At least setting window_end_valid
to Qnil in window_resize_apply did not help.  But writing

   if (! NILP (update)
/**       && ! (! NILP (w->window_end_valid) **/
/** 	    && w->last_modified >= BUF_MODIFF (b) **/
/** 	    && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)) **/
       && !noninteractive)

makes the problem disappear.

So apparently this can be fixed easily but as long as I don't understand
that cryptic conjunct I won't do it.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-11  7:12               ` martin rudalics
@ 2012-10-11 16:56                 ` Eli Zaretskii
  2012-10-12  7:32                   ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-11 16:56 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Thu, 11 Oct 2012 09:12:50 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: cschol2112@gmail.com, 12600@debbugs.gnu.org
> 
> I have no idea what these window structure members (window_end_valid,
> last_modified and last_overlay_modified) stand for in practice, who's
> supposed to set them, why and when.  At least setting window_end_valid
> to Qnil in window_resize_apply did not help.  But writing
> 
>    if (! NILP (update)
> /**       && ! (! NILP (w->window_end_valid) **/
> /** 	    && w->last_modified >= BUF_MODIFF (b) **/
> /** 	    && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)) **/
>        && !noninteractive)
> 
> makes the problem disappear.
> 
> So apparently this can be fixed easily but as long as I don't understand
> that cryptic conjunct I won't do it.

That 'if' is just an optimization: it tries to avoid a (potentially
expensive) call to move_it_vertically.  It could be expensive with
large windows and/or very long lines, for example.

So if window-end is not supposed to be called in some inner loop, and
we don't mind getting slower on behalf of a package whose design is
known to be flawed anyway, we can disable the optimization.  Disabling
this optimization should never do any harm, AFAIU, except slow down
the function.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-11 16:56                 ` Eli Zaretskii
@ 2012-10-12  7:32                   ` martin rudalics
  2012-10-12  8:52                     ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-12  7:32 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 >>    if (! NILP (update)
 >> /**       && ! (! NILP (w->window_end_valid) **/
 >> /** 	    && w->last_modified >= BUF_MODIFF (b) **/
 >> /** 	    && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)) **/
 >>        && !noninteractive)
 >>
 >> makes the problem disappear.
 >>
 >> So apparently this can be fixed easily but as long as I don't understand
 >> that cryptic conjunct I won't do it.
 >
 > That 'if' is just an optimization: it tries to avoid a (potentially
 > expensive) call to move_it_vertically.  It could be expensive with
 > large windows and/or very long lines, for example.
 >
 > So if window-end is not supposed to be called in some inner loop, and
 > we don't mind getting slower on behalf of a package whose design is
 > known to be flawed anyway, we can disable the optimization.  Disabling
 > this optimization should never do any harm, AFAIU, except slow down
 > the function.

Before doing that, could you please in window.h eventually update the
comments for display related fields like last_modified,
last_overlay_modified, last_point to say who's supposed to (re-)set them
to which value.  I'm afraid the current situation is a mess.

For example, what does the "displayed buffer's text modification events
counter as of last time display completed" mean?  Suppose redisplay has
set this to 37.  Apparently, setting it to 36 means that the next
redisplay will notice that for this window display is not accurate and
has to be redone because 36 < 37.

But why is a flag insufficient to accomplish that?  IIUC it's set only
once by mark_window_display_accurate_1 and everywhere else reset to 0.
Why can't we set it to "accurate" in mark_window_display_accurate_1 and
"inaccurate" everwhere else?

And why do we have additional fields for last_overlay_modified and
window_end_valid?  What sense does it make to handle these separately?
For example, wherever last_modified is reset to 0 last_overlay_modified
is always reset to 0 too.  Isn't that plain overkill?

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-12  7:32                   ` martin rudalics
@ 2012-10-12  8:52                     ` Eli Zaretskii
  2012-10-12  9:35                       ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-12  8:52 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Fri, 12 Oct 2012 09:32:01 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: cschol2112@gmail.com, 12600@debbugs.gnu.org
> 
> Before doing that, could you please in window.h eventually update the
> comments for display related fields like last_modified,
> last_overlay_modified, last_point to say who's supposed to (re-)set them
> to which value.

I would like to, but I need some guidance as to what is unclear, see
below.

> I'm afraid the current situation is a mess.

I can agree to that.  Quite a few struct members related to the
display engine (and I suppose other core structures as well) are
insufficiently, in accurately, or even downright incorrectly
documented.  I try to fix every such problem I bump into, FWIW.

> For example, what does the "displayed buffer's text modification events
> counter as of last time display completed" mean?

This one sounds quite clear, please tell which part needs further
clarifications.  It would be better to say "counter of the displayed
buffer's modification events as of last time display completed", but
somehow I'm guessing it's not what you had in mind.

> Suppose redisplay has set this to 37.  Apparently, setting it to 36
> means that the next redisplay will notice that for this window
> display is not accurate and has to be redone because 36 < 37.

Not necessarily.  It depends on what is recorded in the buffer's
BUF_MODIFF slot.

> But why is a flag insufficient to accomplish that?  IIUC it's set only
> once by mark_window_display_accurate_1 and everywhere else reset to 0.
> Why can't we set it to "accurate" in mark_window_display_accurate_1 and
> "inaccurate" everwhere else?

How would this work when the displayed buffer is modified behind
redisplay's back?  The last_modified slot belongs to the window, which
redisplay controls, but it doesn't control the buffer, which could
well be displayed in other windows as well and modified through there.
The display engine treats each window separately; when it displays
some window, it doesn't use information from other windows.

> And why do we have additional fields for last_overlay_modified and
> window_end_valid?  What sense does it make to handle these separately?

Because changes in overlays do not constitute changes in buffer
contents, and are done via yet another set of primitives, yet they do
require redisplay.  Also because each one of these can allow and
disallow certain distinct redisplay optimizations, at least in
principle.

As for window_end_valid flag, it's there to allow yet another set of
redisplay optimizations.

> For example, wherever last_modified is reset to 0 last_overlay_modified
> is always reset to 0 too.  Isn't that plain overkill?

The potential for separate optimizations is not realized, that's true.
But it exists; I'm not sure we should remove it, and I surely won't
spend any of my personal time trying.  Fixing real bugs in the display
engine is enough to fill my free time already.  Of course, if you feel
like it, and if no one objects, feel free to make these cleanups.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-12  8:52                     ` Eli Zaretskii
@ 2012-10-12  9:35                       ` martin rudalics
  2012-10-12 13:51                         ` Eli Zaretskii
  2012-10-12 14:55                         ` Stefan Monnier
  0 siblings, 2 replies; 34+ messages in thread
From: martin rudalics @ 2012-10-12  9:35 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 > Quite a few struct members related to the
 > display engine (and I suppose other core structures as well) are
 > insufficiently, in accurately, or even downright incorrectly
 > documented.  I try to fix every such problem I bump into, FWIW.

If these concern the display engine exclusively, there's no problem.
Problems arise when the window handling code is supposed to change them.

 >> For example, what does the "displayed buffer's text modification events
 >> counter as of last time display completed" mean?
 >
 > This one sounds quite clear, please tell which part needs further
 > clarifications.  It would be better to say "counter of the displayed
 > buffer's modification events as of last time display completed", but
 > somehow I'm guessing it's not what you had in mind.

That's exactly what I had in mind: Either something that corresponds
textually to what is used in buffer.h or just mention the name of the
corresponding field used in buffer.h.  As it stands currently, I have to
either guess what is meant or go through the comparisons in the code to
find out.

 >> Suppose redisplay has set this to 37.  Apparently, setting it to 36
 >> means that the next redisplay will notice that for this window
 >> display is not accurate and has to be redone because 36 < 37.
 >
 > Not necessarily.  It depends on what is recorded in the buffer's
 > BUF_MODIFF slot.

IIUC this can only increase monotonously (modulo wraparounds, but in
that case ...).

 >> But why is a flag insufficient to accomplish that?  IIUC it's set only
 >> once by mark_window_display_accurate_1 and everywhere else reset to 0.
 >> Why can't we set it to "accurate" in mark_window_display_accurate_1 and
 >> "inaccurate" everwhere else?
 >
 > How would this work when the displayed buffer is modified behind
 > redisplay's back?  The last_modified slot belongs to the window, which
 > redisplay controls, but it doesn't control the buffer, which could
 > well be displayed in other windows as well and modified through there.
 > The display engine treats each window separately; when it displays
 > some window, it doesn't use information from other windows.

When last_modifed_flag is set, the window must be redisplayed.  Now if
someone else (including the display engine) decremented last_modified,
things were different indeed.  But as it stands I don't see any such
assignment.  OTOH when the buffer iself is modified it has to be
redisplayed anyway because we hardly know where the change happened.  So
I don't see why such a comparison of counters is useful.  But maybe I'm
missing something.

 >> And why do we have additional fields for last_overlay_modified and
 >> window_end_valid?  What sense does it make to handle these separately?
 >
 > Because changes in overlays do not constitute changes in buffer
 > contents, and are done via yet another set of primitives, yet they do
 > require redisplay.  Also because each one of these can allow and
 > disallow certain distinct redisplay optimizations, at least in
 > principle.

I doubt whether such optimizations exist.  Suppose we could exclude a
change to happen within the bounds of a window as for example a buffer
displayed with a window starting at M and ending at N and an overlay
modified at some position < M or > N.  Wouldn't this require to
associate each single overlay with a modification counter?

 > As for window_end_valid flag, it's there to allow yet another set of
 > redisplay optimizations.

I think that a correct implementation would have for each window w

(w->last_modified < MODIFF) => (NOT (w->window_end_valid))

but strongly doubt that this implication holds currently.

 >> For example, wherever last_modified is reset to 0 last_overlay_modified
 >> is always reset to 0 too.  Isn't that plain overkill?
 >
 > The potential for separate optimizations is not realized, that's true.
 > But it exists; I'm not sure we should remove it, and I surely won't
 > spend any of my personal time trying.  Fixing real bugs in the display
 > engine is enough to fill my free time already.  Of course, if you feel
 > like it, and if no one objects, feel free to make these cleanups.

I don't intend to make any cleanups.  I'd like to have a simple routine
we can use to reset any such structur members within window.c and have
that DTRT.  Currently, `window-end' is clearly broken and we should fix
it.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-12  9:35                       ` martin rudalics
@ 2012-10-12 13:51                         ` Eli Zaretskii
  2012-10-12 15:42                           ` martin rudalics
  2012-10-12 14:55                         ` Stefan Monnier
  1 sibling, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-12 13:51 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Fri, 12 Oct 2012 11:35:57 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: cschol2112@gmail.com, 12600@debbugs.gnu.org
> 
>  > Quite a few struct members related to the
>  > display engine (and I suppose other core structures as well) are
>  > insufficiently, in accurately, or even downright incorrectly
>  > documented.  I try to fix every such problem I bump into, FWIW.
> 
> If these concern the display engine exclusively, there's no problem.

I think this is why these are there, yes.

> Problems arise when the window handling code is supposed to change them.

Like where and when?

>  >> For example, what does the "displayed buffer's text modification events
>  >> counter as of last time display completed" mean?
>  >
>  > This one sounds quite clear, please tell which part needs further
>  > clarifications.  It would be better to say "counter of the displayed
>  > buffer's modification events as of last time display completed", but
>  > somehow I'm guessing it's not what you had in mind.
> 
> That's exactly what I had in mind: Either something that corresponds
> textually to what is used in buffer.h or just mention the name of the
> corresponding field used in buffer.h.

OK, will do.

>  >> Suppose redisplay has set this to 37.  Apparently, setting it to 36
>  >> means that the next redisplay will notice that for this window
>  >> display is not accurate and has to be redone because 36 < 37.
>  >
>  > Not necessarily.  It depends on what is recorded in the buffer's
>  > BUF_MODIFF slot.
> 
> IIUC this can only increase monotonously

But BUF_MODIFF could also change, no?  And a window can display
another buffer, can't it?

> When last_modifed_flag is set, the window must be redisplayed.

Not exactly, but OK.

> OTOH when the buffer iself is modified it has to be
> redisplayed anyway because we hardly know where the change happened.

If course, we know: we know where the window begins and ends.

> So I don't see why such a comparison of counters is useful.  But
> maybe I'm missing something.

We probably both are, but what's the bottom line here?

>  >> And why do we have additional fields for last_overlay_modified and
>  >> window_end_valid?  What sense does it make to handle these separately?
>  >
>  > Because changes in overlays do not constitute changes in buffer
>  > contents, and are done via yet another set of primitives, yet they do
>  > require redisplay.  Also because each one of these can allow and
>  > disallow certain distinct redisplay optimizations, at least in
>  > principle.
> 
> I doubt whether such optimizations exist.

What, you mean in theory?  That's a strange opinion, as there are any
number of ways of optimizing redisplay.  In fact, there are comments
today in the display code that describe optimizations that could be
implemented, but never were.

> Suppose we could exclude a change to happen within the bounds of a
> window as for example a buffer displayed with a window starting at M
> and ending at N and an overlay modified at some position < M or > N.
> Wouldn't this require to associate each single overlay with a
> modification counter?

Maybe, but I doubt that would allow any gains.  To make use of these
counters, you'd have to examine every overlay; but as soon as you have
an overlay in hand, its buffer position is as easy to access as its
counter.

The problem with overlays is that overlays-at, next-overlay-change,
etc. are slow, not that we lack some info in the overlays themselves.

Anyway, it would seem to be bad design to have a _window_ flag that
would change when some text or overlay in a buffer is modified.  Emacs
separates between display-related structures and buffer-related
structures for a number of good reasons, the most important being that
they are modified and examined independently, and there's no 1:1
relation between buffers and windows.

> I think that a correct implementation would have for each window w
> 
> (w->last_modified < MODIFF) => (NOT (w->window_end_valid))
> 
> but strongly doubt that this implication holds currently.

You could try putting assertions like that in the code and see if they
fire.

> I don't intend to make any cleanups.  I'd like to have a simple routine
> we can use to reset any such structur members within window.c and have
> that DTRT.

Under what circumstances does window.c need to do that?

> Currently, `window-end' is clearly broken and we should fix it.

An optimization that sometimes does the wrong thing is easy to fix:
either discover a condition under which the optimization works, or
simply disable the optimization.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-12  9:35                       ` martin rudalics
  2012-10-12 13:51                         ` Eli Zaretskii
@ 2012-10-12 14:55                         ` Stefan Monnier
  2012-10-12 15:36                           ` Eli Zaretskii
  2012-10-12 15:43                           ` martin rudalics
  1 sibling, 2 replies; 34+ messages in thread
From: Stefan Monnier @ 2012-10-12 14:55 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> When last_modifed_flag is set, the window must be redisplayed.

No: last_modifed_flag is (normally) only set at the end of redisplay, so
the in the future you can check if redisplay is needed by comparing it
with the buffer's modiff.

> assignment.  OTOH when the buffer iself is modified it has to be
> redisplayed anyway because we hardly know where the change happened.

But instead of going through all the windows that display this buffer,
we just change the buffer's modiff, so it will cause all the
(last_modifed_flag == modiff) checks to fail in the windows that display
this buffer.

BTW, I'm interested in display-optimizations because I sometimes suffer
from severe delays, apparently linked to my use of numerous frames.I
haven't dug into yet enough to know really what's going on, but I have
the impression that I hit a pathological case where optimizations end up
completely disabled such that even after as simple commands as C-f (but
which might do more than meets the idea because of things like
hl-line-mode and reveal-mode, maybe) all the windows/frames get
a redisplay.


        Stefan





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-12 14:55                         ` Stefan Monnier
@ 2012-10-12 15:36                           ` Eli Zaretskii
  2012-10-12 15:43                           ` martin rudalics
  1 sibling, 0 replies; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-12 15:36 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 12600

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: Eli Zaretskii <eliz@gnu.org>,  12600@debbugs.gnu.org
> Date: Fri, 12 Oct 2012 10:55:20 -0400
> 
> BTW, I'm interested in display-optimizations because I sometimes suffer
> from severe delays, apparently linked to my use of numerous frames.I
> haven't dug into yet enough to know really what's going on, but I have
> the impression that I hit a pathological case where optimizations end up
> completely disabled such that even after as simple commands as C-f (but
> which might do more than meets the idea because of things like
> hl-line-mode and reveal-mode, maybe) all the windows/frames get
> a redisplay.

If you can come up with a test case, please file a bug report and I
will look into it.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-12 13:51                         ` Eli Zaretskii
@ 2012-10-12 15:42                           ` martin rudalics
  0 siblings, 0 replies; 34+ messages in thread
From: martin rudalics @ 2012-10-12 15:42 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 >> Problems arise when the window handling code is supposed to change them.
 >
 > Like where and when?

Currently it does reset last_modified and last_overlay_modified in
Fset_window_start, set_window_buffer, window_resize_apply,
grow_mini_window, shrink_mini_window, window_scroll_pixel_based,
window_scroll_line_based and Fset_window_configuration.  I meanwhile
assume that I should do that in Fdelete_other_windows_internal too.

OTOH Frecenter, Fset_window_fringes and Fset_window_scroll_bars do set
window_end_valid but leave w->last_modified and w->last_overlay_modified
alone.

 >> That's exactly what I had in mind: Either something that corresponds
 >> textually to what is used in buffer.h or just mention the name of the
 >> corresponding field used in buffer.h.
 >
 > OK, will do.

And if possible add for each of these an advice like "Code that may
change the start/end position of a buffer in the window is supposed to
reset the value of this to Qnil/0". Please keep in mind that not very
many people currently have an idea what these fields are used for.  So
even if your advices are sloppy they will help to keep one's attention.

 >>  > Not necessarily.  It depends on what is recorded in the buffer's
 >>  > BUF_MODIFF slot.
 >>
 >> IIUC this can only increase monotonously
 >
 > But BUF_MODIFF could also change, no?

I meant BUF_MODIFF.

 > And a window can display
 > another buffer, can't it?

This would obviously have to be caught elsewhere since currently you
don't check for buffer identities either when you do

	   && w->last_modified >= MODIFF

in redisplay_internal (you probably did that before, but in some
independent way).  In any case, set_window_buffer would set
last_modifed_flag as well so again there's no reason for a counter.

 >> When last_modifed_flag is set, the window must be redisplayed.
 >
 > Not exactly, but OK.

You mean that in some cases we could get away without redisplaying it?
That's what I tried to address below.

 >> OTOH when the buffer iself is modified it has to be
 >> redisplayed anyway because we hardly know where the change happened.
 >
 > If course, we know: we know where the window begins and ends.

But we don't necessarily know where any buffer change(s) happened at the
time we redisplay.

 >> So I don't see why such a comparison of counters is useful.  But
 >> maybe I'm missing something.
 >
 > We probably both are, but what's the bottom line here?

That I still don't see why comparing last_modifed and MODIFF is useful
and why we have to assign two or three integer/Lisp fields instead of
one boolean.

 >>  > Because changes in overlays do not constitute changes in buffer
 >>  > contents, and are done via yet another set of primitives, yet they do
 >>  > require redisplay.  Also because each one of these can allow and
 >>  > disallow certain distinct redisplay optimizations, at least in
 >>  > principle.
 >>
 >> I doubt whether such optimizations exist.
 >
 > What, you mean in theory?  That's a strange opinion, as there are any
 > number of ways of optimizing redisplay.  In fact, there are comments
 > today in the display code that describe optimizations that could be
 > implemented, but never were.

Could you lay out one possible way where using a counter for
last_overlay_modified would allow an optimization?  I certainly would
not question any other optimizations.

 >> Suppose we could exclude a change to happen within the bounds of a
 >> window as for example a buffer displayed with a window starting at M
 >> and ending at N and an overlay modified at some position < M or > N.
 >> Wouldn't this require to associate each single overlay with a
 >> modification counter?
 >
 > Maybe, but I doubt that would allow any gains.  To make use of these
 > counters, you'd have to examine every overlay; but as soon as you have
 > an overlay in hand, its buffer position is as easy to access as its
 > counter.
 >
 > The problem with overlays is that overlays-at, next-overlay-change,
 > etc. are slow, not that we lack some info in the overlays themselves.
 >
 > Anyway, it would seem to be bad design to have a _window_ flag that
 > would change when some text or overlay in a buffer is modified.  Emacs
 > separates between display-related structures and buffer-related
 > structures for a number of good reasons, the most important being that
 > they are modified and examined independently, and there's no 1:1
 > relation between buffers and windows.

I agree with everything you say here.  Only that my conclusion is that
using a counter in last_overlay_modified is pretty much useless.

 >> I think that a correct implementation would have for each window w
 >>
 >> (w->last_modified < MODIFF) => (NOT (w->window_end_valid))
 >>
 >> but strongly doubt that this implication holds currently.
 >
 > You could try putting assertions like that in the code and see if they
 > fire.

Why bother?  You would have helped me by telling that such an assertion
_should_ hold.  If so, I can easily fill in the details.

 >> I don't intend to make any cleanups.  I'd like to have a simple routine
 >> we can use to reset any such structur members within window.c and have
 >> that DTRT.
 >
 > Under what circumstances does window.c need to do that?

In the cases I cited at the beginning of this post.  And maybe in some
cases I'm not aware of.

 >> Currently, `window-end' is clearly broken and we should fix it.
 >
 > An optimization that sometimes does the wrong thing is easy to fix:
 > either discover a condition under which the optimization works, or
 > simply disable the optimization.

If the underlying implementation defies the optimization, we should fix
that implementation.  But for that I'd have to understand the semantics
of the optimization first.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-12 14:55                         ` Stefan Monnier
  2012-10-12 15:36                           ` Eli Zaretskii
@ 2012-10-12 15:43                           ` martin rudalics
  2012-10-13  8:56                             ` Eli Zaretskii
  1 sibling, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-12 15:43 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 12600

 >> When last_modifed_flag is set, the window must be redisplayed.
 >
 > No: last_modifed_flag is (normally) only set at the end of redisplay, so
 > the in the future you can check if redisplay is needed by comparing it
 > with the buffer's modiff.

last_modifed_flag is a fictitious variable I would set when the window
changes.  When it's set, redisplay must redisplay the window.

 >> assignment.  OTOH when the buffer iself is modified it has to be
 >> redisplayed anyway because we hardly know where the change happened.
 >
 > But instead of going through all the windows that display this buffer,
 > we just change the buffer's modiff, so it will cause all the
 > (last_modifed_flag == modiff) checks to fail in the windows that display
 > this buffer.

We'd obviously have an independent buffer_modified_flag.  A window must
be redisplayed if either buffer_modified_flag is set (modulo any
optimizations which I won't dispute here) or its last_modifed_flag is
set.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-12 15:43                           ` martin rudalics
@ 2012-10-13  8:56                             ` Eli Zaretskii
  2012-10-13  9:51                               ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-13  8:56 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Fri, 12 Oct 2012 17:43:01 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: Eli Zaretskii <eliz@gnu.org>, 12600@debbugs.gnu.org
> 
>  >> When last_modifed_flag is set, the window must be redisplayed.
>  >
>  > No: last_modifed_flag is (normally) only set at the end of redisplay, so
>  > the in the future you can check if redisplay is needed by comparing it
>  > with the buffer's modiff.
> 
> last_modifed_flag is a fictitious variable I would set when the window
> changes.  When it's set, redisplay must redisplay the window.

What do you mean by "window changes"?  And how would any code outside
of the display engine know whether some change requires to redisplay a
window?

Anyway, I don't think the above is right.  Only the display engine
should set this variable.  The display engine should figure out itself
whether to redisplay a window, by using other means.  If it doesn't,
that's a bug.

>  >> assignment.  OTOH when the buffer iself is modified it has to be
>  >> redisplayed anyway because we hardly know where the change happened.
>  >
>  > But instead of going through all the windows that display this buffer,
>  > we just change the buffer's modiff, so it will cause all the
>  > (last_modifed_flag == modiff) checks to fail in the windows that display
>  > this buffer.
> 
> We'd obviously have an independent buffer_modified_flag.  A window must
> be redisplayed if either buffer_modified_flag is set (modulo any
> optimizations which I won't dispute here) or its last_modifed_flag is
> set.

But comparing the buffer's modiff with last_modified already
accomplishes this, so what would be the purpose of converting
last_modified to a boolean flag, and then introducing another struct
member that acts exactly like last_modified does today?





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-13  8:56                             ` Eli Zaretskii
@ 2012-10-13  9:51                               ` martin rudalics
  2012-10-13 12:45                                 ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-13  9:51 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 >> last_modifed_flag is a fictitious variable I would set when the window
 >> changes.  When it's set, redisplay must redisplay the window.
 >
 > What do you mean by "window changes"?  And how would any code outside
 > of the display engine know whether some change requires to redisplay a
 > window?

There are three types of window changes we have to consider:

(1) Change the window's buffer via `set-window-buffer'.

(2) Change the size of the window (including toggling of scrollbars and
     fringes).

(3) Change the buffer's position in the window (usually via scrolling,
     `set-window-point' and `set-window-start').

There might be indirect changes as well (e.g., when setting a window
display property) but let's stick to the three cited above.  All these
require usually a complete redisplay of the buffer in the window.  There
is one exception, namely when `split-window-keep-point' is nil,
`split-window-below' tries to keep the old display (but I doubt that
this works with variable height fonts and it will likely fail as soon as
we split windows pixel-wise).

Now in all of these cases, the respective routines in window.c would set
the window's last_modified_flag to t, marking the window as dirty.  When
resizing or splitting windows, usually more than one window is affected;
for scrolling usually one window is affected.  When the display engine
scans windows, it has to redisplay a window when the flag is set,
resetting the flag when it's done.  Otherwise, it will redisplay the
window iff the buffer's modification flag says so.

Note that the last_modified_flag of the window covers both last_modified
and last_overlay_modified as far as the window's redisplay is concerned.

`window-end' with non-nil UPDATE requires a different treatment anyway
because it inspects a cached value that is invalidated either by a
buffer modification or a window change.  Hence the only simple solution
for this is to reset window_end_pos to nil whenenver we set that
window's last_modified_flag.  `window-end' then would update
window_end_pos either if it is nil or the buffer was modified since the
last redisplay.

 > Anyway, I don't think the above is right.  Only the display engine
 > should set this variable.  The display engine should figure out itself
 > whether to redisplay a window, by using other means.  If it doesn't,
 > that's a bug.

So why do we currently reset last_modified and last_overlay_modified in
window.c?

 >> We'd obviously have an independent buffer_modified_flag.  A window must
 >> be redisplayed if either buffer_modified_flag is set (modulo any
 >> optimizations which I won't dispute here) or its last_modifed_flag is
 >> set.
 >
 > But comparing the buffer's modiff with last_modified already
 > accomplishes this, so what would be the purpose of converting
 > last_modified to a boolean flag, and then introducing another struct
 > member that acts exactly like last_modified does today?

The last_modified_flag struct member would replace three members that
have very obscure semantics IMHO.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-13  9:51                               ` martin rudalics
@ 2012-10-13 12:45                                 ` Eli Zaretskii
  2012-10-13 17:45                                   ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-13 12:45 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Sat, 13 Oct 2012 11:51:46 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org
> 
>  >> last_modifed_flag is a fictitious variable I would set when the window
>  >> changes.  When it's set, redisplay must redisplay the window.
>  >
>  > What do you mean by "window changes"?  And how would any code outside
>  > of the display engine know whether some change requires to redisplay a
>  > window?
> 
> There are three types of window changes we have to consider:
> 
> (1) Change the window's buffer via `set-window-buffer'.

This is taken care of by setting windows_or_buffers_changed.

> (2) Change the size of the window (including toggling of scrollbars and
>      fringes).

Redisplay figures this out already, I think.  Which commands/functions
make these changes?

> (3) Change the buffer's position in the window (usually via scrolling,
>      `set-window-point' and `set-window-start').

These likewise set windows_or_buffers_changed, so they shouldn't be a
problem.

> Now in all of these cases, the respective routines in window.c would set
> the window's last_modified_flag to t, marking the window as dirty.

I don't think this is necessary.  Can you try without setting this
flag, and see if anything breaks?

>  > Anyway, I don't think the above is right.  Only the display engine
>  > should set this variable.  The display engine should figure out itself
>  > whether to redisplay a window, by using other means.  If it doesn't,
>  > that's a bug.
> 
> So why do we currently reset last_modified and last_overlay_modified in
> window.c?

See above.  Maybe I'm missing something, but
windows_or_buffers_changed should take care of all of this.

>  >> We'd obviously have an independent buffer_modified_flag.  A window must
>  >> be redisplayed if either buffer_modified_flag is set (modulo any
>  >> optimizations which I won't dispute here) or its last_modifed_flag is
>  >> set.
>  >
>  > But comparing the buffer's modiff with last_modified already
>  > accomplishes this, so what would be the purpose of converting
>  > last_modified to a boolean flag, and then introducing another struct
>  > member that acts exactly like last_modified does today?
> 
> The last_modified_flag struct member would replace three members that
> have very obscure semantics IMHO.

We are going in circles, so there must be some misunderstanding here.
Can you describe your complete change suggestion, wrt these flags?  In
particular, what about buffer_modified_flag, and how does it enter
this picture?





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-13 12:45                                 ` Eli Zaretskii
@ 2012-10-13 17:45                                   ` martin rudalics
  2012-10-13 18:08                                     ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-13 17:45 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 >> (1) Change the window's buffer via `set-window-buffer'.
 >
 > This is taken care of by setting windows_or_buffers_changed.

windows_or_buffers_changed is a global flag.  How does redisplay find
out _which_ window got a new buffer?  Or does redisplay not care?

 >> (2) Change the size of the window (including toggling of scrollbars and
 >>      fringes).
 >
 > Redisplay figures this out already, I think.  Which commands/functions
 > make these changes?

They all end up calling window_resize_apply.

 >> (3) Change the buffer's position in the window (usually via scrolling,
 >>      `set-window-point' and `set-window-start').
 >
 > These likewise set windows_or_buffers_changed, so they shouldn't be a
 > problem.

But usually they affect only one window.  Again, redisplay might not
care.  But I would be surprised that it doesn't handle such a simple
case of optimization.

 >> Now in all of these cases, the respective routines in window.c would set
 >> the window's last_modified_flag to t, marking the window as dirty.
 >
 > I don't think this is necessary.  Can you try without setting this
 > flag, and see if anything breaks?

I said "would".  last_modified_flag doesn't exist.

 >> So why do we currently reset last_modified and last_overlay_modified in
 >> window.c?
 >
 > See above.  Maybe I'm missing something, but
 > windows_or_buffers_changed should take care of all of this.

OK.  I'll comment them out after the feature freeze and we'll see ;-)

 > We are going in circles, so there must be some misunderstanding here.
 > Can you describe your complete change suggestion, wrt these flags?  In
 > particular, what about buffer_modified_flag, and how does it enter
 > this picture?

Replace the three struct members last_modified, last_overlay_modified
and window_end_valid by one struct member called last_modified_flag -
actually calling it window_modified would be better.  Set
window_modified to t wherever we currently reset one of the three
members.  Redisplay, when fully done, would reset window_modified to nil
for every window it completes instead of setting the other members.

I care about BUF_MODIFF/BUF_OVERLAY_MODIFF only in one place: When
calculating `window-end' after a buffer change but before the next
redisplay, `window-end' with UPDATE non-nil has to consult
BUF_MODIFF/BUF_OVERLAY_MODIFF in order to be sure whether it can reuse
window_end_pos.  window_end_pos would be nil (invalid) initially, set to
a valid value when Fwindow_end updates it, and be reset to nil wherever
we change the value of window_modified.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-13 17:45                                   ` martin rudalics
@ 2012-10-13 18:08                                     ` Eli Zaretskii
  2012-10-14 10:21                                       ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-13 18:08 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Sat, 13 Oct 2012 19:45:20 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org
> 
>  >> (1) Change the window's buffer via `set-window-buffer'.
>  >
>  > This is taken care of by setting windows_or_buffers_changed.
> 
> windows_or_buffers_changed is a global flag.  How does redisplay find
> out _which_ window got a new buffer?  Or does redisplay not care?

It doesn't care, in the sense that it always considers every window.
It _does_ care, in the sense that certain redisplay optimizations are
turned off when windows_or_buffers_changed is non-zero.

E.g., if nothing's changed since the last redisplay, then redisplay
will only enter try_cursor_movement for each window, quickly see that
point didn't move, and exit without doing anything.  But if
windows_or_buffers_changed is non-zero, this optimizations is
disabled.

>  >> (2) Change the size of the window (including toggling of scrollbars and
>  >>      fringes).
>  >
>  > Redisplay figures this out already, I think.  Which commands/functions
>  > make these changes?
> 
> They all end up calling window_resize_apply.

They all also set windows_or_buffers_changed non-zero.  So I think
these cases are already covered, as far as redisplay is concerned.

> 
>  >> (3) Change the buffer's position in the window (usually via scrolling,
>  >>      `set-window-point' and `set-window-start').
>  >
>  > These likewise set windows_or_buffers_changed, so they shouldn't be a
>  > problem.
> 
> But usually they affect only one window.  Again, redisplay might not
> care.  But I would be surprised that it doesn't handle such a simple
> case of optimization.

It tries.  It disables fewer optimizations when last_modified is reset
than when windows_or_buffers_changed is non-zero.  But I doubt that
this difference shows in many important situations.  At least resizing
a window never affects only one window.

>  >> Now in all of these cases, the respective routines in window.c would set
>  >> the window's last_modified_flag to t, marking the window as dirty.
>  >
>  > I don't think this is necessary.  Can you try without setting this
>  > flag, and see if anything breaks?
> 
> I said "would".  last_modified_flag doesn't exist.

The same should be tru for the last_modified and last_overlay_modified
fields, which do exist.

>  >> So why do we currently reset last_modified and last_overlay_modified in
>  >> window.c?
>  >
>  > See above.  Maybe I'm missing something, but
>  > windows_or_buffers_changed should take care of all of this.
> 
> OK.  I'll comment them out after the feature freeze and we'll see ;-)

Thanks.

> Replace the three struct members last_modified, last_overlay_modified
> and window_end_valid by one struct member called last_modified_flag -
> actually calling it window_modified would be better.  Set
> window_modified to t wherever we currently reset one of the three
> members.  Redisplay, when fully done, would reset window_modified to nil
> for every window it completes instead of setting the other members.

And when a buffer is modified or its overlays are modified, what
should we do to indicate to redisplay that the corresponding windows
might need a more thorough redisplay?





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-13 18:08                                     ` Eli Zaretskii
@ 2012-10-14 10:21                                       ` martin rudalics
  2012-10-14 12:06                                         ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-14 10:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 >> Replace the three struct members last_modified, last_overlay_modified
 >> and window_end_valid by one struct member called last_modified_flag -
 >> actually calling it window_modified would be better.  Set
 >> window_modified to t wherever we currently reset one of the three
 >> members.  Redisplay, when fully done, would reset window_modified to nil
 >> for every window it completes instead of setting the other members.
 >
 > And when a buffer is modified or its overlays are modified, what
 > should we do to indicate to redisplay that the corresponding windows
 > might need a more thorough redisplay?

When a window shows a buffer that has been modified since the last
redisplay, that buffer must be redrawn.  More precisely, redisplay would
walk all live windows and for each window

(1) Redraw if something in the window's buffer or a setting affecting
     the display of all buffers (like the cursor type) was modified.

(2) Redraw if the window itself has been modified.

(3) Don't redraw the window otherwise.  This would cover the case where
     `point' was moved in a buffer not shown in this window or another
     window was scrolled.

This would replace checking of windows_or_buffers_changed with a
finer-grained has "this window or its buffer changed".  But after a
cursory look at redisplay_window I doubt that such a change would be
feasible.  And I have no idea to which extent (3) is already covered by
try_window_id.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-14 10:21                                       ` martin rudalics
@ 2012-10-14 12:06                                         ` Eli Zaretskii
  2012-10-14 18:33                                           ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-14 12:06 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Sun, 14 Oct 2012 12:21:15 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org
> 
>  >> Replace the three struct members last_modified, last_overlay_modified
>  >> and window_end_valid by one struct member called last_modified_flag -
>  >> actually calling it window_modified would be better.  Set
>  >> window_modified to t wherever we currently reset one of the three
>  >> members.  Redisplay, when fully done, would reset window_modified to nil
>  >> for every window it completes instead of setting the other members.
>  >
>  > And when a buffer is modified or its overlays are modified, what
>  > should we do to indicate to redisplay that the corresponding windows
>  > might need a more thorough redisplay?
> 
> When a window shows a buffer that has been modified since the last
> redisplay, that buffer must be redrawn.  More precisely, redisplay would
> walk all live windows and for each window
> 
> (1) Redraw if something in the window's buffer or a setting affecting
>      the display of all buffers (like the cursor type) was modified.

How do you know whether the window's buffer was modified, under your
suggestion?  Won't we need some record of "the last buffer state when
this window was displayed"?  E.g., how do we know that point moved
since last full redisplay of the window?

> (2) Redraw if the window itself has been modified.

You mean, its dimensions or start-point?  Or something else?

> (3) Don't redraw the window otherwise.  This would cover the case where
>      `point' was moved in a buffer not shown in this window or another
>      window was scrolled.
> 
> This would replace checking of windows_or_buffers_changed with a
> finer-grained has "this window or its buffer changed".  But after a
> cursory look at redisplay_window I doubt that such a change would be
> feasible.  And I have no idea to which extent (3) is already covered by
> try_window_id.

The normal "do-nothing" route is to call try_cursor_movement, then
"goto done".  try_window_id is called only if there's some change that
requires redisplaying some of the text, not just moving the cursor.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-14 12:06                                         ` Eli Zaretskii
@ 2012-10-14 18:33                                           ` martin rudalics
  2012-10-14 20:01                                             ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-14 18:33 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 > How do you know whether the window's buffer was modified, under your
 > suggestion?  Won't we need some record of "the last buffer state when
 > this window was displayed"?  E.g., how do we know that point moved
 > since last full redisplay of the window?

If we do not know whether point moved in a buffer since its last
redisplay, we probably can't optimize anything at all.  But we already
got MODIFF, CHARS_MODIFF, and OVERLAY_MODIFF.  What are these good for
if we always have to redisplay a window showing a buffer whose point
could have moved since the last redisplay?  But apparently
try_cursor_movement handles this if I understand your text below
correctly.  So why are you asking this?

 >> (2) Redraw if the window itself has been modified.
 >
 > You mean, its dimensions or start-point?  Or something else?

That it shows another buffer.  The window code is not able to
discriminate anything else but these three.

 >> (3) Don't redraw the window otherwise.  This would cover the case where
 >>      `point' was moved in a buffer not shown in this window or another
 >>      window was scrolled.
 >>
 >> This would replace checking of windows_or_buffers_changed with a
 >> finer-grained has "this window or its buffer changed".  But after a
 >> cursory look at redisplay_window I doubt that such a change would be
 >> feasible.  And I have no idea to which extent (3) is already covered by
 >> try_window_id.
 >
 > The normal "do-nothing" route is to call try_cursor_movement,

So try_cursor_movement cares about the no buffer change, no overlay
change, no window change, no font change, ... only point movement case.

 > then
 > "goto done".  try_window_id is called only if there's some change that
 > requires redisplaying some of the text, not just moving the cursor.

That's what I meant earlier where you replied by asking "how do we know
that point moved".  The various MODIFFs should tell me whether the
buffer changed.  Some other settings tell me whether some font or the
cursor type changed.  And window_modified tells me whether something in
the window changed that requires to execute try_window_id.  If none of
these changed, the window can stay alone.  All this would work only if
point movement has been handled already.

This would mean that try_cursor_movement had instead of

       && !windows_or_buffers_changed

check

       && !w->window_modified

and the respective MODIFF conjuncts for w's buffer.

BTW, couldn't we instead of

       && !(!NILP (Vtransient_mark_mode)
	   && !NILP (BVAR (current_buffer, mark_active)))

use the more human

       && (NILP (Vtransient_mark_mode)
	   || NILP (BVAR (current_buffer, mark_active)))

here?

martin






^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-14 18:33                                           ` martin rudalics
@ 2012-10-14 20:01                                             ` Eli Zaretskii
  2012-10-15  9:41                                               ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-14 20:01 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Sun, 14 Oct 2012 20:33:39 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org
> 
>  > How do you know whether the window's buffer was modified, under your
>  > suggestion?  Won't we need some record of "the last buffer state when
>  > this window was displayed"?  E.g., how do we know that point moved
>  > since last full redisplay of the window?
> 
> If we do not know whether point moved in a buffer since its last
> redisplay, we probably can't optimize anything at all.

We do know, but only because we record that (in w->last_point).

> But we already
> got MODIFF, CHARS_MODIFF, and OVERLAY_MODIFF.  What are these good for
> if we always have to redisplay a window showing a buffer whose point
> could have moved since the last redisplay?

Those MODIFF features record actual changes, not cursor motion.

> But apparently
> try_cursor_movement handles this if I understand your text below
> correctly.  So why are you asking this?

Because I don't understand your plan to redesign these variables and
flags.  I don't see the big picture.

>  >> (3) Don't redraw the window otherwise.  This would cover the case where
>  >>      `point' was moved in a buffer not shown in this window or another
>  >>      window was scrolled.
>  >>
>  >> This would replace checking of windows_or_buffers_changed with a
>  >> finer-grained has "this window or its buffer changed".  But after a
>  >> cursory look at redisplay_window I doubt that such a change would be
>  >> feasible.  And I have no idea to which extent (3) is already covered by
>  >> try_window_id.
>  >
>  > The normal "do-nothing" route is to call try_cursor_movement,
> 
> So try_cursor_movement cares about the no buffer change, no overlay
> change, no window change, no font change, ... only point movement case.

No, it is only _called_ when there are no changes of the kind you
mention above.  If any of these changes are detected,
try_cursor_movement is bypassed, since it is known that it will not do
the job.  Here:

  /* Handle case where text has not changed, only point, and it has
     not moved off the frame, and we are not retrying after hscroll.
     (current_matrix_up_to_date_p is nonzero when retrying.)  */
  if (current_matrix_up_to_date_p
      && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
	  rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
    {
      switch (rc)
	{
	case CURSOR_MOVEMENT_SUCCESS:
	  used_current_matrix_p = 1;
	  goto done;   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

	case CURSOR_MOVEMENT_MUST_SCROLL:
	  goto try_to_scroll;

	default:
	  emacs_abort ();
	}
    }

The marked line is the "green channel".  It is taken only if
try_cursor_movement succeeds.

And current_matrix_up_to_date_p is computed thusly:

  current_matrix_up_to_date_p
    = (!NILP (w->window_end_valid)
       && !current_buffer->clip_changed
       && !current_buffer->prevent_redisplay_optimizations_p
       && w->last_modified >= MODIFF
       && w->last_overlay_modified >= OVERLAY_MODIFF);

>  > then
>  > "goto done".  try_window_id is called only if there's some change that
>  > requires redisplaying some of the text, not just moving the cursor.
> 
> That's what I meant earlier where you replied by asking "how do we know
> that point moved".  The various MODIFFs should tell me whether the
> buffer changed.  Some other settings tell me whether some font or the
> cursor type changed.  And window_modified tells me whether something in
> the window changed that requires to execute try_window_id.  If none of
> these changed, the window can stay alone.  All this would work only if
> point movement has been handled already.

I'm not sure I understand where you are getting, but to facilitate
this discussion, let me describe the logic of redisplay_window.  It
goes like this:

  . if nothing changed except possibly point, call
    try_cursor_movement; if that succeeds, we are done

  . otherwise, if the buffer is unchanged, try reusing some of the
    current glyph matrix, assuming that just the window-start has
    changed -- this is what try_window_reusing_current_matrix does

  . if that fails, call try_window_id, which tries reusing of the
    current glyph matrix, assuming that only some lines at the
    beginning or the end of the window have changed

  . if that fails, too, call try_window to redisplay the entire window
    using the previous window-start point

  . if try_window finds that point ends up outside the window,
    "scroll" the window, i.e. find a better window-start point such
    that point enters the window -- this is what try_scrolling does

  . if that fails as well, compute the new window-start and redisplay
    the entire window starting from there

> This would mean that try_cursor_movement had instead of
> 
>        && !windows_or_buffers_changed
> 
> check
> 
>        && !w->window_modified
> 
> and the respective MODIFF conjuncts for w's buffer.

What would we gain by this change?

> BTW, couldn't we instead of
> 
>        && !(!NILP (Vtransient_mark_mode)
> 	   && !NILP (BVAR (current_buffer, mark_active)))
> 
> use the more human
> 
>        && (NILP (Vtransient_mark_mode)
> 	   || NILP (BVAR (current_buffer, mark_active)))
> 
> here?

It depends on how you reason about logic.  To me, the condition

    !NILP (Vtransient_mark_mode)
     && !NILP (BVAR (current_buffer, mark_active))

is clear, whereas its reverse is less so.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-07 23:03 bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame Christoph Scholtes
  2012-10-08  7:31 ` Eli Zaretskii
@ 2012-10-15  9:40 ` martin rudalics
  2012-11-09  9:49   ` martin rudalics
  1 sibling, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-15  9:40 UTC (permalink / raw)
  To: Christoph Scholtes; +Cc: 12600

 > emacs -Q
 >
 > Load large file, e.g. emacs.c. Buffer content must exceed one
 > screen.
 >
 > Enable linum mode with `M-x linum-mode'.
 >
 > Shrink frame. Maximize frame. Fringe on the left side is missing line
 > numbers.

I checked in a fix for this in revision 110551.  Please try again.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-14 20:01                                             ` Eli Zaretskii
@ 2012-10-15  9:41                                               ` martin rudalics
  2012-10-15 19:39                                                 ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-15  9:41 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 >>  > How do you know whether the window's buffer was modified, under your
 >>  > suggestion?  Won't we need some record of "the last buffer state when
 >>  > this window was displayed"?  E.g., how do we know that point moved
 >>  > since last full redisplay of the window?
 >>
 >> If we do not know whether point moved in a buffer since its last
 >> redisplay, we probably can't optimize anything at all.
 >
 > We do know, but only because we record that (in w->last_point).
 >
 >> But we already
 >> got MODIFF, CHARS_MODIFF, and OVERLAY_MODIFF.  What are these good for
 >> if we always have to redisplay a window showing a buffer whose point
 >> could have moved since the last redisplay?
 >
 > Those MODIFF features record actual changes, not cursor motion.
 >
 >> But apparently
 >> try_cursor_movement handles this if I understand your text below
 >> correctly.  So why are you asking this?
 >
 > Because I don't understand your plan to redesign these variables and
 > flags.  I don't see the big picture.

I never proposed to redesign the handling of w->last_point.  All I cared
about were last_modified, last_overlay_modified, and window_end_valid.

 >> So try_cursor_movement cares about the no buffer change, no overlay
 >> change, no window change, no font change, ... only point movement case.
 >
 > No, it is only _called_ when there are no changes of the kind you
 > mention above.  If any of these changes are detected,
 > try_cursor_movement is bypassed, since it is known that it will not do
 > the job.

Sorry for being unclear.  That's what I tried to describe with my
sentence above.  Maybe "bothers" would have been a better term ...

 > And current_matrix_up_to_date_p is computed thusly:
 >
 >   current_matrix_up_to_date_p
 >     = (!NILP (w->window_end_valid)
 >        && !current_buffer->clip_changed
 >        && !current_buffer->prevent_redisplay_optimizations_p
 >        && w->last_modified >= MODIFF
 >        && w->last_overlay_modified >= OVERLAY_MODIFF);
 >
 >>  > then
 >>  > "goto done".  try_window_id is called only if there's some change that
 >>  > requires redisplaying some of the text, not just moving the cursor.

I got the impression that the big conjunct below

   if (/* Point may be in this window.  */
       PT >= CHARPOS (startp)
       /* Selective display hasn't changed.  */
       && !current_buffer->clip_changed
       /* Function force-mode-line-update is used to force a thorough
	 redisplay.  It sets either windows_or_buffers_changed or
	 update_mode_lines.  So don't take a shortcut here for these
	 cases.  */
       && !update_mode_lines
       && !windows_or_buffers_changed
       && !cursor_type_changed
       /* Can't use this case if highlighting a region.  When a
          region exists, cursor movement has to do more than just
          set the cursor.  */
       && !(!NILP (Vtransient_mark_mode)
	   && !NILP (BVAR (current_buffer, mark_active)))
       && NILP (w->region_showing)
       && NILP (Vshow_trailing_whitespace)
       /* This code is not used for mini-buffer for the sake of the case
	 of redisplaying to replace an echo area message; since in
	 that case the mini-buffer contents per se are usually
	 unchanged.  This code is of no real use in the mini-buffer
	 since the handling of this_line_start_pos, etc., in redisplay
	 handles the same cases.  */
       && !EQ (window, minibuf_window)
       /* When splitting windows or for new windows, it happens that
	 redisplay is called with a nil window_end_vpos or one being
	 larger than the window.  This should really be fixed in
	 window.c.  I don't have this on my list, now, so we do
	 approximately the same as the old redisplay code.  --gerd.  */
       && INTEGERP (w->window_end_vpos)
       && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
       && (FRAME_WINDOW_P (f)
	  || !overlay_arrow_in_current_buffer_p ()))

indicates all the cases where try_cursor_movement fails immediately.

 > I'm not sure I understand where you are getting, but to facilitate
 > this discussion, let me describe the logic of redisplay_window.  It
 > goes like this:
 >
 >   . if nothing changed except possibly point, call
 >     try_cursor_movement; if that succeeds, we are done

But you clumsily check there whether "nothing changed".  So I'd move
this to the end.  I'd start checking conditions like
windows_or_buffers_changed and do the through redisplay immediately.

 >   . otherwise, if the buffer is unchanged, try reusing some of the
 >     current glyph matrix, assuming that just the window-start has
 >     changed -- this is what try_window_reusing_current_matrix does

What happens when the window width has changed?  Is the glyph matrix
still OK?  In that case not even the window-start position might have
changed.

 >   . if that fails, call try_window_id, which tries reusing of the
 >     current glyph matrix, assuming that only some lines at the
 >     beginning or the end of the window have changed
 >
 >   . if that fails, too, call try_window to redisplay the entire window
 >     using the previous window-start point

Provided the window-start position is still the same, I assume.  Do we
assume that the buffer has changed from here on?

 >   . if try_window finds that point ends up outside the window,
 >     "scroll" the window, i.e. find a better window-start point such
 >     that point enters the window -- this is what try_scrolling does

I suppose this could be called by the next as well?

 >   . if that fails as well, compute the new window-start and redisplay
 >     the entire window starting from there

OK.  I suppose the order is due to the fact that if applying step N
fails, you continue with step N + 1.  I thought there are enough cases
where one decided statically (that is, when redisplay starts) that the
last step doing the full redisplay is needed anyway and it doesn't pay
to try another step first.

 >> This would mean that try_cursor_movement had instead of
 >>
 >>        && !windows_or_buffers_changed
 >>
 >> check
 >>
 >>        && !w->window_modified
 >>
 >> and the respective MODIFF conjuncts for w's buffer.
 >
 > What would we gain by this change?

That for certain windows we could exclude that a redisplay is needed
because the window's size or the buffer's start position in the window
changed.  But if you can't use this information there's obviously no
need providing it.

BTW, I meanwhile discovered that the update_mode_line field (with a
misleading comment IIUC) is the canonical approach to ask for
redisplaying a specific window.  Or am I wrong again and
`force-window-update' never discriminates between updating a single or
all windows of a frame.

 > It depends on how you reason about logic.  To me, the condition
 >
 >     !NILP (Vtransient_mark_mode)
 >      && !NILP (BVAR (current_buffer, mark_active))
 >
 > is clear, whereas its reverse is less so.

... doubling the negation is even less clear ;-)


Ayway, I now checked in a fix for this bug based on the assumption that
all involved routines set windows_or_buffers_changed.  Some, like the
frame resizing functions, never did so and I changed that as well.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-15  9:41                                               ` martin rudalics
@ 2012-10-15 19:39                                                 ` Eli Zaretskii
  2012-10-16  9:39                                                   ` martin rudalics
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-15 19:39 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Mon, 15 Oct 2012 11:41:05 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org
> 
>  > And current_matrix_up_to_date_p is computed thusly:
>  >
>  >   current_matrix_up_to_date_p
>  >     = (!NILP (w->window_end_valid)
>  >        && !current_buffer->clip_changed
>  >        && !current_buffer->prevent_redisplay_optimizations_p
>  >        && w->last_modified >= MODIFF
>  >        && w->last_overlay_modified >= OVERLAY_MODIFF);
>  >
>  >>  > then
>  >>  > "goto done".  try_window_id is called only if there's some change that
>  >>  > requires redisplaying some of the text, not just moving the cursor.
> 
> I got the impression that the big conjunct below
> 
>    if (/* Point may be in this window.  */
>        PT >= CHARPOS (startp)
>        /* Selective display hasn't changed.  */
>        && !current_buffer->clip_changed
>        /* Function force-mode-line-update is used to force a thorough
> 	 redisplay.  It sets either windows_or_buffers_changed or
> 	 update_mode_lines.  So don't take a shortcut here for these
> 	 cases.  */
>        && !update_mode_lines
>        && !windows_or_buffers_changed
>        && !cursor_type_changed
>        /* Can't use this case if highlighting a region.  When a
>           region exists, cursor movement has to do more than just
>           set the cursor.  */
>        && !(!NILP (Vtransient_mark_mode)
> 	   && !NILP (BVAR (current_buffer, mark_active)))
>        && NILP (w->region_showing)
>        && NILP (Vshow_trailing_whitespace)
>        /* This code is not used for mini-buffer for the sake of the case
> 	 of redisplaying to replace an echo area message; since in
> 	 that case the mini-buffer contents per se are usually
> 	 unchanged.  This code is of no real use in the mini-buffer
> 	 since the handling of this_line_start_pos, etc., in redisplay
> 	 handles the same cases.  */
>        && !EQ (window, minibuf_window)
>        /* When splitting windows or for new windows, it happens that
> 	 redisplay is called with a nil window_end_vpos or one being
> 	 larger than the window.  This should really be fixed in
> 	 window.c.  I don't have this on my list, now, so we do
> 	 approximately the same as the old redisplay code.  --gerd.  */
>        && INTEGERP (w->window_end_vpos)
>        && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
>        && (FRAME_WINDOW_P (f)
> 	  || !overlay_arrow_in_current_buffer_p ()))
> 
> indicates all the cases where try_cursor_movement fails immediately.

This is inside try_cursor_movement.  Some simple checks (which are
also useful for considering other optimizations) are done before
try_cursor_movement is called.

>  > I'm not sure I understand where you are getting, but to facilitate
>  > this discussion, let me describe the logic of redisplay_window.  It
>  > goes like this:
>  >
>  >   . if nothing changed except possibly point, call
>  >     try_cursor_movement; if that succeeds, we are done
> 
> But you clumsily check there whether "nothing changed".

The name of the variable, current_matrix_up_to_date_p, is revealing.
If these conditions are true, the current glyph matrix is reusable.
There's nothing clumsy about that.  This variable is used further down
the code.

> So I'd move this to the end.  I'd start checking conditions like
> windows_or_buffers_changed and do the through redisplay immediately.

Conceptually, the order doesn't matter.  Practically, it is better to
first check the feasibility of optimizations that allow us to get away
with cheaper redisplay, because (a) thorough redisplay anyway takes
significantly more time, so there's no need to rush doing it, and 
(b) the tests for the best optimization are faster and cheaper than
those for slower alternatives.

>  >   . otherwise, if the buffer is unchanged, try reusing some of the
>  >     current glyph matrix, assuming that just the window-start has
>  >     changed -- this is what try_window_reusing_current_matrix does
> 
> What happens when the window width has changed?  Is the glyph matrix
> still OK?

No, the glyph matrix needs to be reallocated in that case, which
causes a thorough redisplay (AFAIR).

>  >   . if that fails, call try_window_id, which tries reusing of the
>  >     current glyph matrix, assuming that only some lines at the
>  >     beginning or the end of the window have changed
>  >
>  >   . if that fails, too, call try_window to redisplay the entire window
>  >     using the previous window-start point
> 
> Provided the window-start position is still the same, I assume.

If this assumptions proves false, we call try_scrolling, see below.

> Do we assume that the buffer has changed from here on?

Yes.

>  >   . if try_window finds that point ends up outside the window,
>  >     "scroll" the window, i.e. find a better window-start point such
>  >     that point enters the window -- this is what try_scrolling does
> 
> I suppose this could be called by the next as well?
> 
>  >   . if that fails as well, compute the new window-start and redisplay
>  >     the entire window starting from there

Not normally.  The new window-start is computed so as to make sure
point will appear.  But there are a couple of obscure fallbacks if it
doesn't (e.g., if the whole window shows one very high line, or
there's a lot of invisible text at window-start, etc.).

> OK.  I suppose the order is due to the fact that if applying step N
> fails, you continue with step N + 1.

Right.  And the flags are designed so that testing for potential
applicability of step N is cheaper than for step N+1.

> I thought there are enough cases where one decided statically (that
> is, when redisplay starts) that the last step doing the full
> redisplay is needed anyway and it doesn't pay to try another step
> first.

Some tests are expensive, so we postpone them as much as possible.

>  >> This would mean that try_cursor_movement had instead of
>  >>
>  >>        && !windows_or_buffers_changed
>  >>
>  >> check
>  >>
>  >>        && !w->window_modified
>  >>
>  >> and the respective MODIFF conjuncts for w's buffer.
>  >
>  > What would we gain by this change?
> 
> That for certain windows we could exclude that a redisplay is needed
> because the window's size or the buffer's start position in the window
> changed.  But if you can't use this information there's obviously no
> need providing it.

You can't use it easily.  There are just too many conditions when
redisplay, or at least some part of it, cannot be avoided.

> BTW, I meanwhile discovered that the update_mode_line field (with a
> misleading comment IIUC) is the canonical approach to ask for
> redisplaying a specific window.

That's not my reading of the code.  The w->update_mode_line flag, if
non-zero, forces redisplay of the mode line, and also of the menu bar
and the tool bar, of that window.  Where did you see that its effect
is to redisplay the whole window?

> Or am I wrong again and `force-window-update' never discriminates
> between updating a single or all windows of a frame.

force-window-update with a nil argument sets update_mode_lines and
also windows_or_buffers_changed.  The latter prevents redisplay
optimizations; the former just causes redisplay to consider all
windows, but does not prevent optimizations for each and every window,
if these optimizations are otherwise possible.

force-window-update with a window as its argument just marks that one
window's display "inaccurate", requests redisplay of its mode-line,
and prevents optimizations of any other window displaying the same
buffer.  Windows that don't display this buffer can still avoid some
or all of redisplay through optimizations.

>  > It depends on how you reason about logic.  To me, the condition
>  >
>  >     !NILP (Vtransient_mark_mode)
>  >      && !NILP (BVAR (current_buffer, mark_active))
>  >
>  > is clear, whereas its reverse is less so.
> 
> ... doubling the negation is even less clear ;-)

It's not doubling the negation, it negates a condition with a clear
and easy interpretation.

> Ayway, I now checked in a fix for this bug based on the assumption that
> all involved routines set windows_or_buffers_changed.  Some, like the
> frame resizing functions, never did so and I changed that as well.

Thanks.  I think resizing requests a thorough redisplay anyway, but
setting windows_or_buffers_changed cannot hurt.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-15 19:39                                                 ` Eli Zaretskii
@ 2012-10-16  9:39                                                   ` martin rudalics
  2012-10-16 17:35                                                     ` Eli Zaretskii
  0 siblings, 1 reply; 34+ messages in thread
From: martin rudalics @ 2012-10-16  9:39 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 12600

 >> BTW, I meanwhile discovered that the update_mode_line field (with a
 >> misleading comment IIUC) is the canonical approach to ask for
 >> redisplaying a specific window.
 >
 > That's not my reading of the code.  The w->update_mode_line flag, if
 > non-zero, forces redisplay of the mode line, and also of the menu bar
 > and the tool bar, of that window.  Where did you see that its effect
 > is to redisplay the whole window?

Because the doc-string for Fforce_window_update says "If optional arg
OBJECT is a window, force redisplay of that window only." but the code
does

       mark_window_display_accurate (object, 0);
       w->update_mode_line = 1;
       if (BUFFERP (w->buffer))
	XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
       ++update_mode_lines;

and does not set windows_or_buffers_changed.  So apparently the above
(and not only setting w->update_mode_line to 1 as I concluded
incorrectly) are sufficient to force the redisplay of a single window
(including all windows showing the same buffer).

 > force-window-update with a window as its argument just marks that one
 > window's display "inaccurate", requests redisplay of its mode-line,
 > and prevents optimizations of any other window displaying the same
 > buffer.  Windows that don't display this buffer can still avoid some
 > or all of redisplay through optimizations.

That's the case I had in mind.  So if I follow you correctly,
set_window_buffer could instead of doing

   windows_or_buffers_changed++;

call Fforce_window_update with the window whose buffer gets set as its
argument.

 > I think resizing requests a thorough redisplay anyway,

Resizing a frame almost certainly does.  change_frame_size_1 does

   adjust_glyphs (f);
   calculate_costs (f);
   SET_FRAME_GARBAGED (f);
   f->resized_p = 1;

but none of these seem useful for Fwindow_end (are they useful anywhere
at all?), so ...

 > setting windows_or_buffers_changed cannot hurt.

... I _had to_ set this in order to make the check in Fwindow_end fail.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-16  9:39                                                   ` martin rudalics
@ 2012-10-16 17:35                                                     ` Eli Zaretskii
  0 siblings, 0 replies; 34+ messages in thread
From: Eli Zaretskii @ 2012-10-16 17:35 UTC (permalink / raw)
  To: martin rudalics; +Cc: 12600

> Date: Tue, 16 Oct 2012 11:39:37 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org
> 
>  >> BTW, I meanwhile discovered that the update_mode_line field (with a
>  >> misleading comment IIUC) is the canonical approach to ask for
>  >> redisplaying a specific window.
>  >
>  > That's not my reading of the code.  The w->update_mode_line flag, if
>  > non-zero, forces redisplay of the mode line, and also of the menu bar
>  > and the tool bar, of that window.  Where did you see that its effect
>  > is to redisplay the whole window?
> 
> Because the doc-string for Fforce_window_update says "If optional arg
> OBJECT is a window, force redisplay of that window only." but the code
> does
> 
>        mark_window_display_accurate (object, 0);
>        w->update_mode_line = 1;
>        if (BUFFERP (w->buffer))
> 	XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
>        ++update_mode_lines;
> 
> and does not set windows_or_buffers_changed.  So apparently the above
> (and not only setting w->update_mode_line to 1 as I concluded
> incorrectly) are sufficient to force the redisplay of a single window
> (including all windows showing the same buffer).

Yes.  The prevent_redisplay_optimizations_p flag is the crucial detail
here.

>  > force-window-update with a window as its argument just marks that one
>  > window's display "inaccurate", requests redisplay of its mode-line,
>  > and prevents optimizations of any other window displaying the same
>  > buffer.  Windows that don't display this buffer can still avoid some
>  > or all of redisplay through optimizations.
> 
> That's the case I had in mind.  So if I follow you correctly,
> set_window_buffer could instead of doing
> 
>    windows_or_buffers_changed++;
> 
> call Fforce_window_update with the window whose buffer gets set as its
> argument.

Yes, I think so.





^ permalink raw reply	[flat|nested] 34+ messages in thread

* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame
  2012-10-15  9:40 ` martin rudalics
@ 2012-11-09  9:49   ` martin rudalics
  0 siblings, 0 replies; 34+ messages in thread
From: martin rudalics @ 2012-11-09  9:49 UTC (permalink / raw)
  To: Christoph Scholtes; +Cc: 12600-done

> I checked in a fix for this in revision 110551.  Please try again.

Bug closed.

martin





^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2012-11-09  9:49 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-07 23:03 bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame Christoph Scholtes
2012-10-08  7:31 ` Eli Zaretskii
2012-10-08  9:17   ` martin rudalics
2012-10-08 13:59     ` Stefan Monnier
2012-10-08 15:48     ` Eli Zaretskii
2012-10-09  9:36       ` martin rudalics
2012-10-09 17:04         ` Eli Zaretskii
2012-10-10 10:22           ` martin rudalics
2012-10-10 15:45             ` Eli Zaretskii
2012-10-11  7:12               ` martin rudalics
2012-10-11 16:56                 ` Eli Zaretskii
2012-10-12  7:32                   ` martin rudalics
2012-10-12  8:52                     ` Eli Zaretskii
2012-10-12  9:35                       ` martin rudalics
2012-10-12 13:51                         ` Eli Zaretskii
2012-10-12 15:42                           ` martin rudalics
2012-10-12 14:55                         ` Stefan Monnier
2012-10-12 15:36                           ` Eli Zaretskii
2012-10-12 15:43                           ` martin rudalics
2012-10-13  8:56                             ` Eli Zaretskii
2012-10-13  9:51                               ` martin rudalics
2012-10-13 12:45                                 ` Eli Zaretskii
2012-10-13 17:45                                   ` martin rudalics
2012-10-13 18:08                                     ` Eli Zaretskii
2012-10-14 10:21                                       ` martin rudalics
2012-10-14 12:06                                         ` Eli Zaretskii
2012-10-14 18:33                                           ` martin rudalics
2012-10-14 20:01                                             ` Eli Zaretskii
2012-10-15  9:41                                               ` martin rudalics
2012-10-15 19:39                                                 ` Eli Zaretskii
2012-10-16  9:39                                                   ` martin rudalics
2012-10-16 17:35                                                     ` Eli Zaretskii
2012-10-15  9:40 ` martin rudalics
2012-11-09  9:49   ` martin rudalics

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).