I worried that my code did a lot of reallocations, but it ran fine even on
my older machines, so I let it be. This was also less of a concern when it
was an optional feature, but now it matters greatly.

Nicholas, your latest patch passes my smoke test. I will continue to use it
and let you know if it causes any trouble.


On Sun, Feb 10, 2013 at 11:38 AM, Nicholas Marriott <
nicholas.marri...@gmail.com> wrote:

> And another version. previous_wrap had to be 1 at the start to eat the
> blank line inserted because py started at 0 and was incremented before
> use. So switch things around so the line is incremented after it is
> used.
>
>
>
>
> diff --git a/grid.c b/grid.c
> index aabf66c..3bf02ae 100644
> --- a/grid.c
> +++ b/grid.c
> @@ -70,6 +70,11 @@ grid_check_y(struct grid *gd, u_int py)
>  }
>  #endif
>
> +void   grid_reflow_join(struct grid *, u_int *, struct grid_line *,
> u_int);
> +void   grid_reflow_split(struct grid *, u_int *, struct grid_line *,
> u_int,
> +           u_int);
> +void   grid_reflow_move(struct grid *, u_int *, struct grid_line *);
> +
>  /* Create a new grid. */
>  struct grid *
>  grid_create(u_int sx, u_int sy, u_int hlimit)
> @@ -461,43 +466,134 @@ grid_duplicate_lines(
>         }
>  }
>
> +/* Join line data. */
> +void
> +grid_reflow_join(struct grid *dst, u_int *py, struct grid_line *src_gl,
> +    u_int new_x)
> +{
> +       struct grid_line        *dst_gl = &dst->linedata[(*py) - 1];
> +       u_int                    left, to_copy, ox, nx;
> +
> +       /* How much is left on the old line? */
> +       left = new_x - dst_gl->cellsize;
> +
> +       /* Work out how much to append. */
> +       to_copy = src_gl->cellsize;
> +       if (to_copy > left)
> +               to_copy = left;
> +       ox = dst_gl->cellsize;
> +       nx = ox + to_copy;
> +
> +       /* Resize the destination line. */
> +       dst_gl->celldata = xrealloc(dst_gl->celldata, nx,
> +           sizeof *dst_gl->celldata);
> +       dst_gl->cellsize = nx;
> +
> +       /* Append as much as possible. */
> +       memcpy(&dst_gl->celldata[ox], &src_gl->celldata[0],
> +           to_copy * sizeof src_gl->celldata[0]);
> +
> +       /* If there is any left in the source, split it. */
> +       if (src_gl->cellsize > to_copy) {
> +               dst_gl->flags |= GRID_LINE_WRAPPED;
> +
> +               src_gl->cellsize -= to_copy;
> +               grid_reflow_split(dst, py, src_gl, new_x, to_copy);
> +       }
> +}
> +
> +/* Split line data. */
> +void
> +grid_reflow_split(struct grid *dst, u_int *py, struct grid_line *src_gl,
> +    u_int new_x, u_int offset)
> +{
> +       struct grid_line        *dst_gl;
> +       u_int                    to_copy;
> +
> +       /* Loop and copy sections of the source line. */
> +       while (src_gl->cellsize > 0) {
> +               /* Create new line. */
> +               if (*py >= dst->hsize + dst->sy)
> +                       grid_scroll_history(dst);
> +               dst_gl = &dst->linedata[*py];
> +               (*py)++;
> +
> +               /* How much should we copy? */
> +               to_copy = new_x;
> +               if (to_copy > src_gl->cellsize)
> +                       to_copy = src_gl->cellsize;
> +
> +               /* Expand destination line. */
> +               dst_gl->celldata = xmalloc(to_copy * sizeof
> *dst_gl->celldata);
> +               dst_gl->cellsize = to_copy;
> +               dst_gl->flags |= GRID_LINE_WRAPPED;
> +
> +               /* Copy the data. */
> +               memcpy (&dst_gl->celldata[0], &src_gl->celldata[offset],
> +                   to_copy * sizeof dst_gl->celldata[0]);
> +
> +               /* Move offset and reduce old line size. */
> +               offset += to_copy;
> +               src_gl->cellsize -= to_copy;
> +       }
> +
> +       /* Last line is not wrapped. */
> +       dst_gl->flags &= ~GRID_LINE_WRAPPED;
> +}
> +
> +/* Move line data. */
> +void
> +grid_reflow_move(struct grid *dst, u_int *py, struct grid_line *src_gl)
> +{
> +       struct grid_line        *dst_gl;
> +
> +       /* Create new line. */
> +       if (*py >= dst->hsize + dst->sy)
> +               grid_scroll_history(dst);
> +       dst_gl = &dst->linedata[*py];
> +       (*py)++;
> +
> +       /* Copy the old line. */
> +       memcpy(dst_gl, src_gl, sizeof *dst_gl);
> +       dst_gl->flags &= ~GRID_LINE_WRAPPED;
> +
> +       /* Clear old line. */
> +       src_gl->celldata = NULL;
> +}
> +
>  /*
> - * Reflow lines from src grid into dst grid based on width sx. Returns
> number
> - * of lines fewer in the visible area, or zero.
> + * Reflow lines from src grid into dst grid of width new_x. Returns
> number of
> + * lines fewer in the visible area. The source grid is destroyed.
>   */
>  u_int
> -grid_reflow(struct grid *dst, const struct grid *src, u_int sx)
> +grid_reflow(struct grid *dst, struct grid *src, u_int new_x)
>  {
> -       u_int                    px, py, line, cell;
> +       u_int                    py, sy, line;
>         int                      previous_wrapped;
> -       struct grid_line        *gl;
> +       struct grid_line        *src_gl;
> +
> +       py = 0;
> +       sy = src->sy;
>
> -       px = py = 0;
> -       previous_wrapped = 1;
> -       for (line = 0; line < src->sy + src->hsize; line++) {
> -               gl = src->linedata + line;
> +       previous_wrapped = 0;
> +       for (line = 0; line < sy + src->hsize; line++) {
> +               src_gl = src->linedata + line;
>                 if (!previous_wrapped) {
> -                       px = 0;
> -                       py++;
> -                       if (py >= dst->hsize + dst->sy)
> -                               grid_scroll_history(dst);
> +                       /* Wasn't wrapped. If smaller, move to
> destination. */
> +                       if (src_gl->cellsize <= new_x)
> +                               grid_reflow_move(dst, &py, src_gl);
> +                       else
> +                               grid_reflow_split(dst, &py, src_gl, new_x,
> 0);
> +               } else {
> +                       /* Previous was wrapped. Try to join. */
> +                       grid_reflow_join(dst, &py, src_gl, new_x);
>                 }
> -               for (cell = 0; cell < gl->cellsize; cell++) {
> -                       if (px == sx) {
> -                               dst->linedata[py].flags |=
> GRID_LINE_WRAPPED;
> -                               px = 0;
> -                               py++;
> -                               if (py >= dst->hsize + dst->sy)
> -                                       grid_scroll_history(dst);
> -                       }
> -                       grid_set_cell(dst, px, py, gl->celldata + cell);
> -                       px++;
> -               }
> -               previous_wrapped = gl->flags & GRID_LINE_WRAPPED;
> +               previous_wrapped = src_gl->flags & GRID_LINE_WRAPPED;
>         }
> -       py++; /* account for final line, which never wraps */
>
> -       if (py > src->sy)
> +       grid_destroy(src);
> +
> +       if (py > sy)
>                 return (0);
> -       return (src->sy - py);
> +       return (sy - py);
>  }
> diff --git a/screen.c b/screen.c
> index fe0b738..e92c6aa 100644
> --- a/screen.c
> +++ b/screen.c
> @@ -363,15 +363,10 @@ screen_check_selection(struct screen *s, u_int px,
> u_int py)
>
>  /* Reflow wrapped lines. */
>  void
> -screen_reflow(struct screen *s, u_int sx)
> +screen_reflow(struct screen *s, u_int new_x)
>  {
> -       struct grid     *old, *new;
> +       struct grid     *old = s->grid;
>
> -       old = s->grid;
> -       new = grid_create(old->sx, old->sy, old->hlimit);
> -
> -       s->cy -= grid_reflow(new, old, sx);
> -       s->grid = new;
> -
> -       grid_destroy(old);
> +       s->grid = grid_create(old->sx, old->sy, old->hlimit);
> +       s->cy -= grid_reflow(s->grid, old, new_x);
>  }
> diff --git a/tmux.h b/tmux.h
> index 1dd11ad..fd67724 100644
> --- a/tmux.h
> +++ b/tmux.h
> @@ -1960,7 +1960,7 @@ void       grid_move_cells(struct grid *, u_int,
> u_int, u_int, u_int);
>  char   *grid_string_cells(struct grid *, u_int, u_int, u_int);
>  void    grid_duplicate_lines(
>              struct grid *, u_int, struct grid *, u_int, u_int);
> -u_int   grid_reflow(struct grid *, const struct grid *, u_int);
> +u_int   grid_reflow(struct grid *, struct grid *, u_int);
>
>  /* grid-cell.c */
>  u_int   grid_cell_width(const struct grid_cell *);
>
>
> ------------------------------------------------------------------------------
> Free Next-Gen Firewall Hardware Offer
> Buy your Sophos next-gen firewall before the end March 2013
> and get the hardware for free! Learn more.
> http://p.sf.net/sfu/sophos-d2d-feb
> _______________________________________________
> tmux-users mailing list
> tmux-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/tmux-users
>
------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to