emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: The future of Follow Mode - a proposal.


From: Alan Mackenzie
Subject: Re: The future of Follow Mode - a proposal.
Date: Tue, 23 Feb 2016 23:11:56 +0000
User-agent: Mutt/1.5.24 (2015-08-30)

Hello, Eli.

On Sat, Feb 20, 2016 at 03:05:16PM +0200, Eli Zaretskii wrote:
> > Date: Sat, 20 Feb 2016 12:44:15 +0000
> > Cc: address@hidden
> > From: Alan Mackenzie <address@hidden>

> > > The functions we talk about currently don't know what they are invoked
> > > for.  Your envisioned changes imply that they should behave
> > > differently depending on whether the results will be used for layout
> > > of the current window or the next/previous window in a group.  That's
> > > part of the changes I had in mind.  They are not trivial.  But without
> > > them, what you want to do will not work reliably.

> > How about adding an extra boolean parameter to the move_it_* functions,
> > perhaps called `physical', which when set would mean the function would
> > have to adjust its iterator when crossing a window boundary, when not set
> > would work the same way as it currently does?  `vertical-motion' would
> > also need this extra &optional parameter, possibly a few other defuns,
> > too.

> I don't think it's a boolean.  It should be the buffer position where
> the window should be switched.  So probably 2 parameters, for the
> beginning and end of the window.  Maybe also the window to switch to.

> And then you need to implement the handling of these new arguments.

An alternative approach, which would be slightly less disruptive, would
be to add in new functions which would work on window groups.  I
anticipate needing group versions of `move_it_by_lines', `move_it_to',
`move_it_vertically', and possibly `move_it_vertically_backward'.  struct
window would be augmented with the following three fields:

    /* The next and previous windows in any window group.  */
    Lisp_Object group_next;
    Lisp_Object group_prev;
    /* The window group this window belongs to, or nil.  */
    Lisp_Object window_group;

. A first draft of `move_it_by_lines_in_group' follows.  It compiles, but
hasn't been tested in the slightest.  If it moves off the boundary of a
window, the `struct it' is reinitialised in the adjoining window.  If it
goes off the top of the first window or the bottom of the last, it
behaves as currently.  Comments on the general approach would be welcome.


/* Move IT by a specified number DVPOS of screen lines down.  DVPOS
   negative means move up.  DVPOS == 0 means move to the start of the
   screen line.

   If IT moves off of the window top or bottom boundary, reinitialize IT
   for the next window in the window group (if any) and carry on there,
   and so on, until we've moved DVPOS screen lines.  */

void
move_it_by_lines_in_group (struct it *it, ptrdiff_t dvpos)
{
  struct window *w = it->w;

  if (dvpos <= 0)
    {
      while (!NILP (w->group_prev)
             && -dvpos > it->vpos - it->first_vpos)
        {
          dvpos += it->vpos - it->first_vpos;
          move_it_by_lines (it, it->first_vpos - it->vpos);
          w = XWINDOW (w->group_prev);
          /* Set the iterator to just off the bottom of the new window. */
          init_iterator (it, w, IT_CHARPOS (*it), IT_BYTEPOS (*it),
                         w->desired_matrix->rows + w->total_lines
                         - WINDOW_WANTS_MODELINE_P (w),
                         it->base_face_id);
          it->first_vpos = WINDOW_WANTS_HEADER_LINE_P (w);
          it->vpos = w->total_lines - WINDOW_WANTS_MODELINE_P (w);
          it->current_y = w->pixel_height
            - WINDOW_WANTS_MODELINE_P (w) * w->mode_line_height;
          it->hpos = 0;
          it->current_x = 0;
        }
      if (dvpos)
        move_it_by_lines (it, dvpos);
    }
  else
    {
      while (!NILP (w->group_next)
             && dvpos >= w->total_lines - WINDOW_WANTS_MODELINE_P (w)
             - it->vpos)
        {
          dvpos -= w->total_lines - WINDOW_WANTS_MODELINE_P (w) - it->vpos;
          move_it_by_lines (it, w->total_lines - WINDOW_WANTS_MODELINE_P (w)
                            - it->vpos);
          w = XWINDOW (w->group_next);
          /* Set the iterator to the top of the new window. */
          init_iterator (it, w, IT_CHARPOS (*it), IT_BYTEPOS (*it),
                         w->desired_matrix->rows
                         + WINDOW_WANTS_HEADER_LINE_P (w),
                         it->base_face_id);
          it->first_vpos = it->vpos = WINDOW_WANTS_HEADER_LINE_P (w);
          it->current_y = WINDOW_WANTS_HEADER_LINE_P (w)
            * w->header_line_height;
          it->hpos = 0;
          it->current_x = 0;
        }
      if (dvpos)
        move_it_by_lines (it, dvpos);
    }
}




> > There are around 150 calls to move_it_*.  I'm guessing that most of these
> > would set `physical' to false, perhaps more of the ones in window.c would
> > use true.

40 move_it_by_lines + 46 move_it_to + 20 move_it_vertically\(_backward\)? = 106.

> Maybe, I don't know.  The problem is that these functions are called
> in several layers, and all of them will have to know about these new
> arguments.  Also, some utility functions, like pos_visible_p, are
> called in different situations, so the caller will have to supply
> those arguments as required in each case.

Yes.  There's goint to be some complication here.

> > > > As an example, `compute_window_start_on_continuation_line' would have to
> > > > use the dimensions of the previous window to determine the window-start.
> > > > Jiggling the various windows around after text changes or scrolling is
> > > > going to be the hard part of the coding.

> > > Yes, and the result will be non-trivial changes in the overall logic,
> > > because redisplaying a window will no longer be independent of other
> > > windows.

> > Yes.  This is what is currently implemented in Follow Mode.

> No, I mean that redisplay of all the windows in a group will have to
> be done in one go, not one window at a time.

Indeed.  But often (say, a single character insertion), only one window
of a group will need redisplay.

-- 
Alan Mackenzie (Nuremberg, Germany).



reply via email to

[Prev in Thread] Current Thread [Next in Thread]