[BACK]Return to screen-write.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Diff for /src/usr.bin/tmux/screen-write.c between version 1.108 and 1.109

version 1.108, 2017/02/08 15:49:29 version 1.109, 2017/02/08 16:45:18
Line 25 
Line 25 
   
 static void     screen_write_initctx(struct screen_write_ctx *,  static void     screen_write_initctx(struct screen_write_ctx *,
                     struct tty_ctx *);                      struct tty_ctx *);
 static void     screen_write_flush(struct screen_write_ctx *);  static void     screen_write_collect_clear(struct screen_write_ctx *, u_int,
                       u_int);
   static void     screen_write_collect_scroll(struct screen_write_ctx *);
   static void     screen_write_collect_flush(struct screen_write_ctx *);
   
 static int      screen_write_overwrite(struct screen_write_ctx *,  static int      screen_write_overwrite(struct screen_write_ctx *,
                     struct grid_cell *, u_int);                      struct grid_cell *, u_int);
Line 36 
Line 39 
         GRID_FLAG_PADDING, 0, 8, 8, { { 0 }, 0, 0, 0 }          GRID_FLAG_PADDING, 0, 8, 8, { { 0 }, 0, 0, 0 }
 };  };
   
 #define screen_dirty_bit(s, x, y) (((y) * screen_size_x(s)) + (x))  struct screen_write_collect_item {
 #define screen_dirty_clear(s, sx, sy, ex, ey)                   \          u_int                    x;
         do {                                                    \  
                 if (s->dirty != NULL) {                         \  
                         bit_nclear(s->dirty,                    \  
                             screen_dirty_bit(s, sx, sy),        \  
                             screen_dirty_bit(s, ex, ey));       \  
                 }                                               \  
         } while (0)  
   
           u_int                    used;
           char                     data[256];
   
           struct grid_cell         gc;
   
           TAILQ_ENTRY (screen_write_collect_item) entry;
   };
   struct screen_write_collect_line {
           TAILQ_HEAD(, screen_write_collect_item) items;
   };
   
 /* Initialize writing with a window. */  /* Initialize writing with a window. */
 void  void
 screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,  screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
     struct screen *s)      struct screen *s)
 {  {
         u_int   size;  
         char    tmp[16];          char    tmp[16];
           u_int   y;
   
           memset(ctx, 0, sizeof *ctx);
   
         ctx->wp = wp;          ctx->wp = wp;
         if (wp != NULL && s == NULL)          if (wp != NULL && s == NULL)
                 ctx->s = wp->screen;                  ctx->s = wp->screen;
         else          else
                 ctx->s = s;                  ctx->s = s;
   
         size = screen_size_x(ctx->s) * screen_size_y(ctx->s);          ctx->list = xcalloc(screen_size_y(ctx->s), sizeof *ctx->list);
         if (ctx->s->dirtysize != size) {          for (y = 0; y < screen_size_y(ctx->s); y++)
                 free(ctx->s->dirty);                  TAILQ_INIT(&ctx->list[y].items);
                 ctx->s->dirty = NULL;          ctx->item = xcalloc(1, sizeof *ctx->item);
                 ctx->s->dirtysize = size;  
         }  
         ctx->dirty = 0;  
   
         ctx->cells = ctx->written = ctx->skipped = 0;  
   
         if (wp != NULL)          if (wp != NULL)
                 snprintf(tmp, sizeof tmp, "pane %%%u", wp->id);                  snprintf(tmp, sizeof tmp, "pane %%%u", wp->id);
         log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s),          log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s),
Line 80 
Line 84 
 void  void
 screen_write_stop(struct screen_write_ctx *ctx)  screen_write_stop(struct screen_write_ctx *ctx)
 {  {
         screen_write_flush(ctx);          screen_write_collect_end(ctx);
           screen_write_collect_flush(ctx);
   
         log_debug("%s: %u of %u written (dirty %u, skipped %u)", __func__,          log_debug("%s: %u cells (%u written, %u skipped)", __func__,
             ctx->written, ctx->cells, ctx->cells - ctx->written, ctx->skipped);              ctx->cells, ctx->written, ctx->skipped);
 }  
   
 /* Flush outstanding cell writes. */          free(ctx->item);
 static void          free(ctx->list); /* flush will have emptied */
 screen_write_flush(struct screen_write_ctx *ctx)  
 {  
         struct screen   *s = ctx->s;  
         struct tty_ctx   ttyctx;  
         u_int            x, y, offset, cx, cy, dirty;  
         struct grid_cell gc;  
   
         if (ctx->dirty == 0)  
                 return;  
         dirty = 0;  
         log_debug("%s: dirty %u", __func__, ctx->dirty);  
   
         cx = s->cx;  
         cy = s->cy;  
   
         offset = 0;  
         for (y = 0; y < screen_size_y(s); y++) {  
                 for (x = 0; x < screen_size_x(s); x++) {  
                         offset++;  
                         if (!bit_test(s->dirty, offset - 1))  
                                 continue;  
                         bit_clear(s->dirty, offset - 1);  
   
                         screen_write_cursormove(ctx, x, y);  
                         grid_view_get_cell(s->grid, x, y, &gc);  
   
                         screen_write_initctx(ctx, &ttyctx);  
                         ttyctx.cell = &gc;  
                         tty_write(tty_cmd_cell, &ttyctx);  
                         ctx->written++;  
   
                         if (++dirty == ctx->dirty)  
                                 break;  
                 }  
                 if (dirty == ctx->dirty)  
                         break;  
         }  
         ctx->dirty = 0;  
   
         s->cx = cx;  
         s->cy = cy;  
 }  }
   
 /* Reset screen state. */  /* Reset screen state. */
Line 563 
Line 526 
         struct tty_ctx           ttyctx;          struct tty_ctx           ttyctx;
         struct grid_cell         gc;          struct grid_cell         gc;
         u_int                    xx, yy;          u_int                    xx, yy;
         u_int                    sx = screen_size_x(s), sy = screen_size_y(s);  
   
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
   
         screen_dirty_clear(s, 0, 0, sx - 1, sy  - 1);  
   
         memcpy(&gc, &grid_default_cell, sizeof gc);          memcpy(&gc, &grid_default_cell, sizeof gc);
         utf8_set(&gc.data, 'E');          utf8_set(&gc.data, 'E');
   
Line 583 
Line 543 
         s->rupper = 0;          s->rupper = 0;
         s->rlower = screen_size_y(s) - 1;          s->rlower = screen_size_y(s) - 1;
   
           screen_write_collect_clear(ctx, 0, screen_size_y(s) - 1);
         tty_write(tty_cmd_alignmenttest, &ttyctx);          tty_write(tty_cmd_alignmenttest, &ttyctx);
 }  }
   
Line 604 
Line 565 
         if (s->cx > screen_size_x(s) - 1)          if (s->cx > screen_size_x(s) - 1)
                 return;                  return;
   
         screen_write_flush(ctx);  
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
         ttyctx.bg = bg;          ttyctx.bg = bg;
   
         grid_view_insert_cells(s->grid, s->cx, s->cy, nx, bg);          grid_view_insert_cells(s->grid, s->cx, s->cy, nx, bg);
   
           screen_write_collect_flush(ctx);
         ttyctx.num = nx;          ttyctx.num = nx;
         tty_write(tty_cmd_insertcharacter, &ttyctx);          tty_write(tty_cmd_insertcharacter, &ttyctx);
 }  }
Line 632 
Line 593 
         if (s->cx > screen_size_x(s) - 1)          if (s->cx > screen_size_x(s) - 1)
                 return;                  return;
   
         screen_write_flush(ctx);  
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
         ttyctx.bg = bg;          ttyctx.bg = bg;
   
         grid_view_delete_cells(s->grid, s->cx, s->cy, nx, bg);          grid_view_delete_cells(s->grid, s->cx, s->cy, nx, bg);
   
           screen_write_collect_flush(ctx);
         ttyctx.num = nx;          ttyctx.num = nx;
         tty_write(tty_cmd_deletecharacter, &ttyctx);          tty_write(tty_cmd_deletecharacter, &ttyctx);
 }  }
Line 662 
Line 623 
   
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
   
         screen_dirty_clear(s, s->cx, s->cy, s->cx + nx - 1, s->cy);  
         grid_view_clear(s->grid, s->cx, s->cy, nx, 1, 8);          grid_view_clear(s->grid, s->cx, s->cy, nx, 1, 8);
   
           screen_write_collect_flush(ctx);
         ttyctx.num = nx;          ttyctx.num = nx;
         tty_write(tty_cmd_clearcharacter, &ttyctx);          tty_write(tty_cmd_clearcharacter, &ttyctx);
 }  }
Line 686 
Line 647 
                 if (ny == 0)                  if (ny == 0)
                         return;                          return;
   
                 screen_write_flush(ctx);  
                 screen_write_initctx(ctx, &ttyctx);                  screen_write_initctx(ctx, &ttyctx);
                 ttyctx.bg = bg;                  ttyctx.bg = bg;
   
                 grid_view_insert_lines(gd, s->cy, ny, bg);                  grid_view_insert_lines(gd, s->cy, ny, bg);
   
                   screen_write_collect_flush(ctx);
                 ttyctx.num = ny;                  ttyctx.num = ny;
                 tty_write(tty_cmd_insertline, &ttyctx);                  tty_write(tty_cmd_insertline, &ttyctx);
                 return;                  return;
Line 702 
Line 663 
         if (ny == 0)          if (ny == 0)
                 return;                  return;
   
         screen_write_flush(ctx);  
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
         ttyctx.bg = bg;          ttyctx.bg = bg;
   
Line 711 
Line 671 
         else          else
                 grid_view_insert_lines_region(gd, s->rlower, s->cy, ny, bg);                  grid_view_insert_lines_region(gd, s->rlower, s->cy, ny, bg);
   
           screen_write_collect_flush(ctx);
         ttyctx.num = ny;          ttyctx.num = ny;
         tty_write(tty_cmd_insertline, &ttyctx);          tty_write(tty_cmd_insertline, &ttyctx);
 }  }
Line 732 
Line 693 
                 if (ny == 0)                  if (ny == 0)
                         return;                          return;
   
                 screen_write_flush(ctx);  
                 screen_write_initctx(ctx, &ttyctx);                  screen_write_initctx(ctx, &ttyctx);
                 ttyctx.bg = bg;                  ttyctx.bg = bg;
   
                 grid_view_delete_lines(gd, s->cy, ny, bg);                  grid_view_delete_lines(gd, s->cy, ny, bg);
   
                   screen_write_collect_flush(ctx);
                 ttyctx.num = ny;                  ttyctx.num = ny;
                 tty_write(tty_cmd_deleteline, &ttyctx);                  tty_write(tty_cmd_deleteline, &ttyctx);
                 return;                  return;
Line 748 
Line 709 
         if (ny == 0)          if (ny == 0)
                 return;                  return;
   
         screen_write_flush(ctx);  
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
         ttyctx.bg = bg;          ttyctx.bg = bg;
   
Line 757 
Line 717 
         else          else
                 grid_view_delete_lines_region(gd, s->rlower, s->cy, ny, bg);                  grid_view_delete_lines_region(gd, s->rlower, s->cy, ny, bg);
   
           screen_write_collect_flush(ctx);
         ttyctx.num = ny;          ttyctx.num = ny;
         tty_write(tty_cmd_deleteline, &ttyctx);          tty_write(tty_cmd_deleteline, &ttyctx);
 }  }
Line 777 
Line 738 
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
         ttyctx.bg = bg;          ttyctx.bg = bg;
   
         screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);  
         grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);          grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
   
           screen_write_collect_clear(ctx, s->cy, 1);
         tty_write(tty_cmd_clearline, &ttyctx);          tty_write(tty_cmd_clearline, &ttyctx);
 }  }
   
Line 799 
Line 760 
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
         ttyctx.bg = bg;          ttyctx.bg = bg;
   
         screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);  
         grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg);          grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg);
   
           if (s->cx == 0)
                   screen_write_collect_clear(ctx, s->cy, 1);
           else
                   screen_write_collect_flush(ctx);
         tty_write(tty_cmd_clearendofline, &ttyctx);          tty_write(tty_cmd_clearendofline, &ttyctx);
 }  }
   
Line 816 
Line 780 
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
         ttyctx.bg = bg;          ttyctx.bg = bg;
   
         if (s->cx > sx - 1) {          if (s->cx > sx - 1)
                 screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);  
                 grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);                  grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
         } else {          else
                 screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);  
                 grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);                  grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
         }  
   
           if (s->cx > sx - 1)
                   screen_write_collect_clear(ctx, s->cy, 1);
           else
                   screen_write_collect_flush(ctx);
         tty_write(tty_cmd_clearstartofline, &ttyctx);          tty_write(tty_cmd_clearstartofline, &ttyctx);
 }  }
   
Line 851 
Line 816 
   
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
   
         if (s->cy == s->rupper) {          if (s->cy == s->rupper)
                 screen_write_flush(ctx);  
                 grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);                  grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
         } else if (s->cy > 0)          else if (s->cy > 0)
                 s->cy--;                  s->cy--;
   
           screen_write_collect_flush(ctx);
         tty_write(tty_cmd_reverseindex, &ttyctx);          tty_write(tty_cmd_reverseindex, &ttyctx);
 }  }
   
Line 887 
Line 852 
 screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)  screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
 {  {
         struct screen           *s = ctx->s;          struct screen           *s = ctx->s;
           struct grid             *gd = s->grid;
         struct grid_line        *gl;          struct grid_line        *gl;
         struct tty_ctx           ttyctx;          struct tty_ctx           ttyctx;
         u_int                    sx = screen_size_x(s), sy = screen_size_y(s);  
   
         screen_write_initctx(ctx, &ttyctx);          gl = &gd->linedata[gd->hsize + s->cy];
   
         gl = &s->grid->linedata[s->grid->hsize + s->cy];  
         if (wrapped)          if (wrapped)
                 gl->flags |= GRID_LINE_WRAPPED;                  gl->flags |= GRID_LINE_WRAPPED;
         else          else
                 gl->flags &= ~GRID_LINE_WRAPPED;                  gl->flags &= ~GRID_LINE_WRAPPED;
   
         if (s->cy == s->rlower) {          if (s->cy == s->rlower) {
                 screen_dirty_clear(s, 0, s->rupper, sx - 1, s->rupper);                  grid_view_scroll_region_up(gd, s->rupper, s->rlower);
                 screen_write_flush(ctx);  
                 grid_view_scroll_region_up(s->grid, s->rupper, s->rlower);  
         } else if (s->cy < sy - 1)  
                 s->cy++;  
   
         ttyctx.num = wrapped;                  screen_write_collect_scroll(ctx);
         tty_write(tty_cmd_linefeed, &ttyctx);                  screen_write_initctx(ctx, &ttyctx);
                   tty_write(tty_cmd_linefeed, &ttyctx);
           } else if (s->cy < screen_size_y(s) - 1)
                   s->cy++;
 }  }
   
 /* Carriage return (cursor to start of line). */  /* Carriage return (cursor to start of line). */
Line 932 
Line 894 
         ttyctx.bg = bg;          ttyctx.bg = bg;
   
         /* Scroll into history if it is enabled and clearing entire screen. */          /* Scroll into history if it is enabled and clearing entire screen. */
         if (s->cx == 0 && s->cy == 0 && gd->flags & GRID_HISTORY) {          if (s->cx == 0 && s->cy == 0 && (gd->flags & GRID_HISTORY))
                 screen_dirty_clear(s, 0, 0, sx - 1, sy  - 1);  
                 grid_view_clear_history(gd, bg);                  grid_view_clear_history(gd, bg);
         } else {          else {
                 if (s->cx <= sx - 1) {                  if (s->cx <= sx - 1)
                         screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);  
                         grid_view_clear(gd, s->cx, s->cy, sx - s->cx, 1, bg);                          grid_view_clear(gd, s->cx, s->cy, sx - s->cx, 1, bg);
                 }  
                 screen_dirty_clear(s, 0, s->cy + 1, sx - 1, sy - 1);  
                 grid_view_clear(gd, 0, s->cy + 1, sx, sy - (s->cy + 1), bg);                  grid_view_clear(gd, 0, s->cy + 1, sx, sy - (s->cy + 1), bg);
         }          }
   
           screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1));
           screen_write_collect_flush(ctx);
         tty_write(tty_cmd_clearendofscreen, &ttyctx);          tty_write(tty_cmd_clearendofscreen, &ttyctx);
 }  }
   
Line 958 
Line 918 
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
         ttyctx.bg = bg;          ttyctx.bg = bg;
   
         if (s->cy > 0) {          if (s->cy > 0)
                 screen_dirty_clear(s, 0, 0, sx - 1, s->cy);  
                 grid_view_clear(s->grid, 0, 0, sx, s->cy, bg);                  grid_view_clear(s->grid, 0, 0, sx, s->cy, bg);
         }          if (s->cx > sx - 1)
         if (s->cx > sx - 1) {                  grid_view_clear(s->grid, 0, s->cy, sx, 1, 8);
                 screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);          else
                 grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);                  grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, 8);
         } else {  
                 screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);  
                 grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);  
         }  
   
           screen_write_collect_clear(ctx, 0, s->cy);
           screen_write_collect_flush(ctx);
         tty_write(tty_cmd_clearstartofscreen, &ttyctx);          tty_write(tty_cmd_clearstartofscreen, &ttyctx);
 }  }
   
Line 984 
Line 941 
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
         ttyctx.bg = bg;          ttyctx.bg = bg;
   
         screen_dirty_clear(s, 0, 0, sx - 1, sy  - 1);  
   
         /* Scroll into history if it is enabled. */          /* Scroll into history if it is enabled. */
         if (s->grid->flags & GRID_HISTORY)          if (s->grid->flags & GRID_HISTORY)
                 grid_view_clear_history(s->grid, bg);                  grid_view_clear_history(s->grid, bg);
         else          else
                 grid_view_clear(s->grid, 0, 0, sx, sy, bg);                  grid_view_clear(s->grid, 0, 0, sx, sy, bg);
   
           screen_write_collect_clear(ctx, 0, sy);
         tty_write(tty_cmd_clearscreen, &ttyctx);          tty_write(tty_cmd_clearscreen, &ttyctx);
 }  }
   
Line 1006 
Line 962 
         gd->hscrolled = gd->hsize = 0;          gd->hscrolled = gd->hsize = 0;
 }  }
   
   /* Clear a collected line. */
   static void
   screen_write_collect_clear(struct screen_write_ctx *ctx, u_int y, u_int n)
   {
           struct screen_write_collect_item        *ci, *tmp;
           u_int                                    i;
           size_t                                   size;
   
           for (i = y ; i < y + n; i++) {
                   if (TAILQ_EMPTY(&ctx->list[i].items))
                           continue;
                   size = 0;
                   TAILQ_FOREACH_SAFE(ci, &ctx->list[i].items, entry, tmp) {
                           size += ci->used;
                           TAILQ_REMOVE(&ctx->list[i].items, ci, entry);
                           free(ci);
                   }
                   ctx->skipped += size;
                   log_debug("discarding %zu bytes on line %u", size, i);
           }
   }
   
   /* Scroll collected lines up. */
   static void
   screen_write_collect_scroll(struct screen_write_ctx *ctx)
   {
           struct screen                           *s = ctx->s;
           struct screen_write_collect_line        *cl;
           u_int                                    y;
   
           screen_write_collect_clear(ctx, s->rupper, 1);
           for (y = s->rupper; y < s->rlower; y++) {
                   cl = &ctx->list[y + 1];
                   TAILQ_CONCAT(&ctx->list[y].items, &cl->items, entry);
                   TAILQ_INIT(&cl->items);
           }
   }
   
   /* Flush collected lines. */
   static void
   screen_write_collect_flush(struct screen_write_ctx *ctx)
   {
           struct screen                           *s = ctx->s;
           struct screen_write_collect_item        *ci, *tmp;
           u_int                                    y, cx, cy;
           struct tty_ctx                           ttyctx;
   
           cx = s->cx; cy = s->cy;
           for (y = 0; y < screen_size_y(s); y++) {
                   TAILQ_FOREACH_SAFE(ci, &ctx->list[y].items, entry, tmp) {
                           screen_write_cursormove(ctx, ci->x, y);
                           screen_write_initctx(ctx, &ttyctx);
                           ttyctx.cell = &ci->gc;
                           ttyctx.ptr = ci->data;
                           ttyctx.num = ci->used;
                           tty_write(tty_cmd_cells, &ttyctx);
                           ctx->written += ci->used;
   
                           TAILQ_REMOVE(&ctx->list[y].items, ci, entry);
                           free(ci);
                   }
           }
           s->cx = cx; s->cy = cy;
   }
   
   /* Finish and store collected cells. */
   void
   screen_write_collect_end(struct screen_write_ctx *ctx)
   {
           struct screen                           *s = ctx->s;
           struct screen_write_collect_item        *ci = ctx->item;
           struct grid_cell                         gc;
   
           if (ci->used == 0)
                   return;
           ci->data[ci->used] = '\0';
   
           ci->x = s->cx;
           TAILQ_INSERT_TAIL(&ctx->list[s->cy].items, ci, entry);
           ctx->item = xcalloc(1, sizeof *ctx->item);
   
           log_debug("%s: %u %s (at %u,%u)", __func__, ci->used, ci->data, s->cx,
               s->cy);
   
           memcpy(&gc, &ci->gc, sizeof gc);
           grid_view_set_cells(s->grid, s->cx, s->cy, &gc, ci->data, ci->used);
           s->cx += ci->used;
   }
   
   /* Write cell data, collecting if necessary. */
   void
   screen_write_collect_add(struct screen_write_ctx *ctx,
       const struct grid_cell *gc)
   {
           struct screen                           *s = ctx->s;
           struct screen_write_collect_item        *ci;
           u_int                                    sx = screen_size_x(s);
           int                                      collect;
   
           /*
            * Don't need to check that the attributes and whatnot are still the
            * same - input_parse will do a flush when anything that isn't a plain
            * character is encountered. Also nothing should make it here that
            * isn't a single ASCII character.
            */
   
           collect = 1;
           if (gc->data.width != 1)
                   collect = 0;
           else if (gc->attr & GRID_ATTR_CHARSET)
                   collect = 0;
           else if (~s->mode & MODE_WRAP)
                   collect = 0;
           else if (s->mode & MODE_INSERT)
                   collect = 0;
           else if (s->sel.flag)
                   collect = 0;
           if (!collect) {
                   screen_write_collect_end(ctx);
                   screen_write_cell(ctx, gc);
                   return;
           }
           ctx->cells++;
   
           if (s->cx > sx - 1 || ctx->item->used > sx - 1 - s->cx)
                   screen_write_collect_end(ctx);
           if (s->cx > sx - 1) {
                   screen_write_linefeed(ctx, 1);
                   s->cx = 0;
           }
   
           ci = ctx->item; /* may have changed */
           if (ci->used == 0)
                   memcpy(&ci->gc, gc, sizeof ci->gc);
           ci->data[ci->used++] = gc->data.data[0];
           if (ci->used == (sizeof ci->data) - 1)
                   screen_write_collect_end(ctx);
   }
   
 /* Write cell data. */  /* Write cell data. */
 void  void
 screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)  screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
 {  {
         struct screen           *s = ctx->s;          struct screen           *s = ctx->s;
         struct grid             *gd = s->grid;          struct grid             *gd = s->grid;
         struct tty_ctx           ttyctx;  
         u_int                    width, xx, last;  
         u_int                    sx = screen_size_x(s), sy = screen_size_y(s);  
         struct grid_line        *gl;          struct grid_line        *gl;
         struct grid_cell         tmp_gc, now_gc;  
         struct grid_cell_entry  *gce;          struct grid_cell_entry  *gce;
         int                      insert, skip, selected;          struct grid_cell         tmp_gc, now_gc;
           struct tty_ctx           ttyctx;
           u_int                    sx = screen_size_x(s), sy = screen_size_y(s);
           u_int                    width = gc->data.width, xx, last;
           int                      selected, skip = 1;
   
         ctx->cells++;          /* Ignore padding cells. */
   
         /* Ignore padding. */  
         if (gc->flags & GRID_FLAG_PADDING)          if (gc->flags & GRID_FLAG_PADDING)
                 return;                  return;
         width = gc->data.width;          ctx->cells++;
   
         /*          /* If the width is zero, combine onto the previous character. */
          * If this is a wide character and there is no room on the screen for  
          * the entire character, don't print it.  
          */  
         if (!(s->mode & MODE_WRAP) && (width > 1 &&  
             (width > sx || (s->cx != sx && s->cx > sx - width))))  
                 return;  
   
         /*  
          * If the width is zero, combine onto the previous character, if  
          * there is space.  
          */  
         if (width == 0) {          if (width == 0) {
                 if ((gc = screen_write_combine(ctx, &gc->data, &xx)) != 0) {                  if ((gc = screen_write_combine(ctx, &gc->data, &xx)) != 0) {
                         screen_write_cursormove(ctx, xx, s->cy);                          screen_write_cursormove(ctx, xx, s->cy);
Line 1049 
Line 1131 
                 return;                  return;
         }          }
   
           /* If this character doesn't fit, ignore it. */
           if ((~s->mode & MODE_WRAP) &&
               width > 1 &&
               (width > sx || (s->cx != sx && s->cx > sx - width)))
                   return;
   
         /* If in insert mode, make space for the cells. */          /* If in insert mode, make space for the cells. */
         if (s->mode & MODE_INSERT) {          if (s->mode & MODE_INSERT) {
                 if (s->cx <= sx - width) {                  grid_view_insert_cells(s->grid, s->cx, s->cy, width, 8);
                         screen_write_flush(ctx);                  skip = 0;
                         xx = sx - s->cx - width;          }
                         grid_view_insert_cells(s->grid, s->cx, s->cy, xx, 8);  
                 }  
                 insert = 1;  
         } else  
                 insert = 0;  
         skip = !insert;  
   
         /* Check this will fit on the current line and wrap if not. */          /* Check this will fit on the current line and wrap if not. */
         if ((s->mode & MODE_WRAP) && s->cx > sx - width) {          if ((s->mode & MODE_WRAP) && s->cx > sx - width) {
                 screen_write_linefeed(ctx, 1);                  screen_write_linefeed(ctx, 1);
                 s->cx = 0;      /* carriage return */                  s->cx = 0;
         }          }
   
         /* Sanity check cursor position. */          /* Sanity check cursor position. */
         if (s->cx > sx - width || s->cy > sy - 1)          if (s->cx > sx - width || s->cy > sy - 1)
                 return;                  return;
   
         /* Initialise the redraw context. */  
         screen_write_initctx(ctx, &ttyctx);          screen_write_initctx(ctx, &ttyctx);
   
         /* Handle overwriting of UTF-8 characters. */          /* Handle overwriting of UTF-8 characters. */
Line 1109 
Line 1189 
                                 skip = 0;                                  skip = 0;
                         else if (gc->data.width != 1)                          else if (gc->data.width != 1)
                                 skip = 0;                                  skip = 0;
                           else if (gc->data.size != 1)
                                   skip = 0;
                         else if (gce->data.data != gc->data.data[0])                          else if (gce->data.data != gc->data.data[0])
                                 skip = 0;                                  skip = 0;
                 }                  }
Line 1116 
Line 1198 
   
         /* Update the selection the flag and set the cell. */          /* Update the selection the flag and set the cell. */
         selected = screen_check_selection(s, s->cx, s->cy);          selected = screen_check_selection(s, s->cx, s->cy);
         if (selected && ~gc->flags & GRID_FLAG_SELECTED) {          if (selected && (~gc->flags & GRID_FLAG_SELECTED)) {
                 skip = 0;  
                 memcpy(&tmp_gc, gc, sizeof tmp_gc);                  memcpy(&tmp_gc, gc, sizeof tmp_gc);
                 tmp_gc.flags |= GRID_FLAG_SELECTED;                  tmp_gc.flags |= GRID_FLAG_SELECTED;
                 grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);                  grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);
         } else if (!selected && gc->flags & GRID_FLAG_SELECTED) {          } else if (!selected && (gc->flags & GRID_FLAG_SELECTED)) {
                 skip = 0;  
                 memcpy(&tmp_gc, gc, sizeof tmp_gc);                  memcpy(&tmp_gc, gc, sizeof tmp_gc);
                 tmp_gc.flags &= ~GRID_FLAG_SELECTED;                  tmp_gc.flags &= ~GRID_FLAG_SELECTED;
                 grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);                  grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);
         } else if (!skip)          } else if (!skip)
                 grid_view_set_cell(gd, s->cx, s->cy, gc);                  grid_view_set_cell(gd, s->cx, s->cy, gc);
           if (selected)
                   skip = 0;
   
         /*          /*
          * Move the cursor. If not wrapping, stick at the last character and           * Move the cursor. If not wrapping, stick at the last character and
Line 1140 
Line 1222 
                 s->cx = sx - last;                  s->cx = sx - last;
   
         /* Create space for character in insert mode. */          /* Create space for character in insert mode. */
         if (insert) {          if (s->mode & MODE_INSERT) {
                   screen_write_collect_flush(ctx);
                 ttyctx.num = width;                  ttyctx.num = width;
                 tty_write(tty_cmd_insertcharacter, &ttyctx);                  tty_write(tty_cmd_insertcharacter, &ttyctx);
         }          }
   
         /* Write to the screen. */          /* Write to the screen. */
         if (selected) {          if (!skip) {
                 screen_write_flush(ctx);                  if (selected) {
                 screen_select_cell(s, &tmp_gc, gc);                          screen_select_cell(s, &tmp_gc, gc);
                 ttyctx.cell = &tmp_gc;                          ttyctx.cell = &tmp_gc;
                   } else
                           ttyctx.cell = gc;
                 tty_write(tty_cmd_cell, &ttyctx);                  tty_write(tty_cmd_cell, &ttyctx);
                 ctx->written++;                  ctx->written++;
         } else if (!skip) {  
                 /*  
                  * If wp is NULL, we are not updating the terminal and don't  
                  * care about actually writing the cells (tty_write will just  
                  * return). So don't even bother allocating the dirty array.  
                  */  
                 if (ctx->wp != NULL && s->dirty == NULL) {  
                         log_debug("%s: allocating %u bits", __func__,  
                             s->dirtysize);  
                         s->dirty = bit_alloc(s->dirtysize);  
                 }  
                 if (s->dirty != NULL) {  
                         bit_set(s->dirty, screen_dirty_bit(s,  
                             ttyctx.ocx, ttyctx.ocy));  
                         ctx->dirty++;  
                 }  
         } else          } else
                 ctx->skipped++;                  ctx->skipped++;
 }  }

Legend:
Removed from v.1.108  
changed lines
  Added in v.1.109