Subject: bug#56682: locked narrowing

From: Eli Zaretskii <[email-masked]>
Date: Wed, 17 Aug 2022 22:19:56 +0300

> From: Stefan Monnier <[email-masked]>
> Cc: [email-masked],  [email-masked],  [email-masked]
> Date: Wed, 17 Aug 2022 15:09:22 -0400
> 
> >> Because I can't find that code.
> > What do you mean? it's in maybe_produce_line_number, obviously...
> 
> My intuition tells me it should be there, but I can't find it.

Really?  I meant this:

      if (!last_line)
	{
	  /* If possible, reuse data cached by line-number-mode.  */
	  if (it->w->base_line_number > 0
	      && it->w->base_line_pos > 0
	      && it->w->base_line_pos <= IT_CHARPOS (*it)
	      /* line-number-mode always displays narrowed line
		 numbers, so we cannot use its data if the user wants
		 line numbers that disregard narrowing, or if the
		 buffer's narrowing has just changed.  */
	      && !(line_numbers_wide
		   && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
	      && !current_buffer->clip_changed)
	    {
	      start_from = CHAR_TO_BYTE (it->w->base_line_pos);
	      last_line = it->w->base_line_number - 1;
	    }
	  else
	    start_from = beg_byte;
	  if (!it->lnum_bytepos)
	    first_time = true;
	}
      else
	start_from = it->lnum_bytepos;

      /* Paranoia: what if someone changes the narrowing since the
	 last time display_line was called?  Shouldn't really happen,
	 but who knows what some crazy Lisp invoked by :eval could do?  */
      if (!(beg_byte <= start_from && start_from <= z_byte))
	{
	  last_line = 0;
	  start_from = beg_byte;
	}

      this_line =
	last_line + display_count_lines_logically (start_from,
						   IT_BYTEPOS (*it),
						   IT_CHARPOS (*it), &bytepos);

> >> Apparently `maybe_produce_line_number`
> >> just uses `w->base_line_number` whenever it's not 0, so apparently it's
> >> set to 0 elsewhere.
> > It's set to zero in several places in xdisp.c.
> 
> I can't seem to find even one of them related to the fact that the
> buffer was modified.

This:

	  if (!just_this_one_p
	      || current_buffer->clip_changed
	      || BEG_UNCHANGED < CHARPOS (startp))
	    /* Forget any recorded base line for line number display.  */
	    w->base_line_number = 0;

And this:

  /* Forget any previously recorded base line for line number display.  */
  if (!buffer_unchanged_p)
    w->base_line_number = 0;

> When I test the code, I can see that it works correctly, but I can't see
> in the code how the cache gets flushed/ignored/refreshed when the
> buffer's contents is modified (e.g. by inserting a newline at BOB).

Of course, this works: it's about the oldest code in the display
engine.

> > But again, if you don't want to trust the cached values, just use
> > display_count_lines starting from BOB.
> 
> That's already what nlinum does (via `line-number-at-pos`).

Then maybe all this discussion is just a waste of breath.