/* Write cell data. */ void screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) { struct screen *s = ctx->s; 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_cell tmp_gc, now_gc; struct grid_cell_entry *gce; int insert, skip, selected, wrapped = 0; ctx->cells++; /* Ignore padding. */ if (gc->flags & GRID_FLAG_PADDING) return; width = gc->data.width; /* * 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 (screen_write_combine(ctx, &gc->data) == 0) { screen_write_initctx(ctx, &ttyctx); tty_write(tty_cmd_utf8character, &ttyctx); } return; } /* Initialise the redraw context. */ screen_write_initctx(ctx, &ttyctx); /* If in insert mode, make space for the cells. */ if (s->mode & MODE_INSERT) { if (s->cx <= sx - width) { screen_write_flush(ctx); 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. */ if ((s->mode & MODE_WRAP) && s->cx > sx - width) { screen_write_flush(ctx); screen_write_save_last(ctx, &ttyctx); screen_write_linefeed(ctx, 1); s->cx = 0; /* carriage return */ skip = 0; wrapped = 1; } /* Sanity check cursor position. */ if (s->cx > sx - width || s->cy > sy - 1) return; /* Handle overwriting of UTF-8 characters. */ gl = &s->grid->linedata[s->grid->hsize + s->cy]; if (gl->flags & GRID_LINE_EXTENDED) { grid_view_get_cell(gd, s->cx, s->cy, &now_gc); if (screen_write_overwrite(ctx, &now_gc, width)) skip = 0; } /* * If the new character is UTF-8 wide, fill in padding cells. Have * already ensured there is enough room. */ for (xx = s->cx + 1; xx < s->cx + width; xx++) { grid_view_set_cell(gd, xx, s->cy, &screen_write_pad_cell); skip = 0; } /* If no change, do not draw. */ if (skip) { if (s->cx >= gl->cellsize) skip = grid_cells_equal(gc, &grid_default_cell); else { gce = &gl->celldata[s->cx]; if (gce->flags & GRID_FLAG_EXTENDED) skip = 0; else if (gc->flags != gce->flags) skip = 0; else if (gc->attr != gce->data.attr) skip = 0; else if (gc->fg != gce->data.fg) skip = 0; else if (gc->bg != gce->data.bg) skip = 0; else if (gc->data.width != 1) skip = 0; else if (gce->data.data != gc->data.data[0]) skip = 0; } } /* Update the selection the flag and set the cell. */ selected = screen_check_selection(s, s->cx, s->cy); if (selected && ~gc->flags & GRID_FLAG_SELECTED) { skip = 0; memcpy(&tmp_gc, gc, sizeof tmp_gc); tmp_gc.flags |= GRID_FLAG_SELECTED; grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc); } else if (!selected && gc->flags & GRID_FLAG_SELECTED) { skip = 0; memcpy(&tmp_gc, gc, sizeof tmp_gc); tmp_gc.flags &= ~GRID_FLAG_SELECTED; grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc); } else if (!skip) grid_view_set_cell(gd, s->cx, s->cy, gc); /* * Move the cursor. If not wrapping, stick at the last character and * replace it. */ last = !(s->mode & MODE_WRAP); if (s->cx <= sx - last - width) s->cx += width; else s->cx = sx - last; /* Create space for character in insert mode. */ if (insert) { ttyctx.num = width; tty_write(tty_cmd_insertcharacter, &ttyctx); } /* Write to the screen. */ if (selected) { screen_write_flush(ctx); screen_select_cell(s, &tmp_gc, gc); ttyctx.cell = &tmp_gc; tty_write(tty_cmd_cell, &ttyctx); ctx->written++; } else if (!skip) { if (wrapped) { ttyctx.cell = gc; tty_write(tty_cmd_cell, &ttyctx); ctx->written++; } else { /* * 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 ctx->skipped++; }
/* Write cell data. */ void screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) { struct screen *s = ctx->s; struct grid *gd = s->grid; struct tty_ctx ttyctx; u_int width, xx, last; struct grid_cell tmp_gc, now_gc; int insert, skip, selected; /* Ignore padding. */ if (gc->flags & GRID_FLAG_PADDING) return; width = gc->data.width; /* * 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 > screen_size_x(s) || (s->cx != screen_size_x(s) && s->cx > screen_size_x(s) - width)))) return; /* * If the width is zero, combine onto the previous character, if * there is space. */ if (width == 0) { if (screen_write_combine(ctx, &gc->data) == 0) { screen_write_initctx(ctx, &ttyctx); tty_write(tty_cmd_utf8character, &ttyctx); } return; } /* Initialise the redraw context. */ screen_write_initctx(ctx, &ttyctx); /* If in insert mode, make space for the cells. */ if ((s->mode & MODE_INSERT) && s->cx <= screen_size_x(s) - width) { xx = screen_size_x(s) - s->cx - width; grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx); insert = 1; } else insert = 0; skip = !insert; /* Check this will fit on the current line and wrap if not. */ if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) { screen_write_linefeed(ctx, 1); s->cx = 0; /* carriage return */ skip = 0; } /* Sanity check cursor position. */ if (s->cx > screen_size_x(s) - width || s->cy > screen_size_y(s) - 1) return; /* Handle overwriting of UTF-8 characters. */ grid_view_get_cell(gd, s->cx, s->cy, &now_gc); if (screen_write_overwrite(ctx, &now_gc, width)) skip = 0; /* * If the new character is UTF-8 wide, fill in padding cells. Have * already ensured there is enough room. */ for (xx = s->cx + 1; xx < s->cx + width; xx++) { grid_view_set_cell(gd, xx, s->cy, &screen_write_pad_cell); skip = 0; } /* If no change, do not draw. */ if (skip) skip = (memcmp(&now_gc, gc, sizeof now_gc) == 0); /* Update the selection the flag and set the cell. */ selected = screen_check_selection(s, s->cx, s->cy); if (selected && ~gc->flags & GRID_FLAG_SELECTED) { skip = 0; memcpy(&tmp_gc, gc, sizeof tmp_gc); tmp_gc.flags |= GRID_FLAG_SELECTED; grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc); } else if (!selected && gc->flags & GRID_FLAG_SELECTED) { skip = 0; memcpy(&tmp_gc, gc, sizeof tmp_gc); tmp_gc.flags &= ~GRID_FLAG_SELECTED; grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc); } else if (!skip) grid_view_set_cell(gd, s->cx, s->cy, gc); /* * Move the cursor. If not wrapping, stick at the last character and * replace it. */ last = !(s->mode & MODE_WRAP); if (s->cx <= screen_size_x(s) - last - width) s->cx += width; else s->cx = screen_size_x(s) - last; /* Create space for character in insert mode. */ if (insert) { ttyctx.num = width; tty_write(tty_cmd_insertcharacter, &ttyctx); } /* Save last cell if it will be needed. */ if (!skip && ctx->wp != NULL && ttyctx.ocx > ctx->wp->sx - width) screen_write_save_last(ctx, &ttyctx); /* Write to the screen. */ if (selected) { memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc); utf8_copy(&tmp_gc.data, &gc->data); tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET; tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET; tmp_gc.flags = gc->flags; tmp_gc.flags &= ~(GRID_FLAG_FGRGB|GRID_FLAG_BGRGB); tmp_gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256); tmp_gc.flags |= s->sel.cell.flags & (GRID_FLAG_FG256|GRID_FLAG_BG256); ttyctx.cell = &tmp_gc; tty_write(tty_cmd_cell, &ttyctx); } else if (!skip) { ttyctx.cell = gc; tty_write(tty_cmd_cell, &ttyctx); } }
/* Write cell data. */ void screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc, const struct utf8_data *utf8data) { struct screen *s = ctx->s; struct grid *gd = s->grid; struct tty_ctx ttyctx; struct grid_utf8 gu; u_int width, xx; struct grid_cell tmp_gc, *tmp_gcp; int insert = 0; /* Ignore padding. */ if (gc->flags & GRID_FLAG_PADDING) return; /* Find character width. */ if (gc->flags & GRID_FLAG_UTF8) width = utf8data->width; else width = 1; /* * 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 > screen_size_x(s) || (s->cx != screen_size_x(s) && s->cx > screen_size_x(s) - width)))) return; /* * If the width is zero, combine onto the previous character, if * there is space. */ if (width == 0) { if (screen_write_combine(ctx, utf8data) == 0) { screen_write_initctx(ctx, &ttyctx, 0); tty_write(tty_cmd_utf8character, &ttyctx); } return; } /* Initialise the redraw context, saving the last cell. */ screen_write_initctx(ctx, &ttyctx, 1); /* If in insert mode, make space for the cells. */ if ((s->mode & MODE_INSERT) && s->cx <= screen_size_x(s) - width) { xx = screen_size_x(s) - s->cx - width; grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx); insert = 1; } /* Check this will fit on the current line and wrap if not. */ if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) { screen_write_linefeed(ctx, 1); s->cx = 0; /* carriage return */ } /* Sanity checks. */ if (((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) || s->cy > screen_size_y(s) - 1) return; /* Handle overwriting of UTF-8 characters. */ screen_write_overwrite(ctx, width); /* * If the new character is UTF-8 wide, fill in padding cells. Have * already ensured there is enough room. */ for (xx = s->cx + 1; xx < s->cx + width; xx++) { tmp_gcp = grid_view_get_cell(gd, xx, s->cy); if (tmp_gcp != NULL) tmp_gcp->flags |= GRID_FLAG_PADDING; } /* Set the cell. */ grid_view_set_cell(gd, s->cx, s->cy, gc); if (gc->flags & GRID_FLAG_UTF8) { /* Construct UTF-8 and write it. */ grid_utf8_set(&gu, utf8data); grid_view_set_utf8(gd, s->cx, s->cy, &gu); } /* Move the cursor. */ s->cx += width; /* Draw to the screen if necessary. */ if (insert) { ttyctx.num = width; tty_write(tty_cmd_insertcharacter, &ttyctx); } ttyctx.utf8 = &gu; if (screen_check_selection(s, s->cx - width, s->cy)) { memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc); tmp_gc.data = gc->data; tmp_gc.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256); tmp_gc.flags |= s->sel.cell.flags & (GRID_FLAG_FG256|GRID_FLAG_BG256); ttyctx.cell = &tmp_gc; tty_write(tty_cmd_cell, &ttyctx); } else { ttyctx.cell = gc; tty_write(tty_cmd_cell, &ttyctx); } }
/* Write cell data. */ void screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) { struct screen *s = ctx->s; struct grid *gd = s->grid; struct tty_ctx ttyctx; u_int width, xx, last; struct grid_cell tmp_gc; int insert; /* Ignore padding. */ if (gc->flags & GRID_FLAG_PADDING) return; width = gc->data.width; /* * 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 > screen_size_x(s) || (s->cx != screen_size_x(s) && s->cx > screen_size_x(s) - width)))) return; /* * If the width is zero, combine onto the previous character, if * there is space. */ if (width == 0) { if (screen_write_combine(ctx, &gc->data) == 0) { screen_write_initctx(ctx, &ttyctx, 0); tty_write(tty_cmd_utf8character, &ttyctx); } return; } /* Initialise the redraw context, saving the last cell. */ screen_write_initctx(ctx, &ttyctx, 1); /* If in insert mode, make space for the cells. */ if ((s->mode & MODE_INSERT) && s->cx <= screen_size_x(s) - width) { xx = screen_size_x(s) - s->cx - width; grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx); insert = 1; } else insert = 0; /* Check this will fit on the current line and wrap if not. */ if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) { screen_write_linefeed(ctx, 1); s->cx = 0; /* carriage return */ } /* Sanity check cursor position. */ if (s->cx > screen_size_x(s) - width || s->cy > screen_size_y(s) - 1) return; /* Handle overwriting of UTF-8 characters. */ screen_write_overwrite(ctx, width); /* * If the new character is UTF-8 wide, fill in padding cells. Have * already ensured there is enough room. */ memcpy(&tmp_gc, &grid_default_cell, sizeof tmp_gc); tmp_gc.flags |= GRID_FLAG_PADDING; tmp_gc.data.width = 0; for (xx = s->cx + 1; xx < s->cx + width; xx++) grid_view_set_cell(gd, xx, s->cy, &tmp_gc); /* Set the cell. */ grid_view_set_cell(gd, s->cx, s->cy, gc); /* * Move the cursor. If not wrapping, stick at the last character and * replace it. */ last = !(s->mode & MODE_WRAP); if (s->cx <= screen_size_x(s) - last - width) s->cx += width; else s->cx = screen_size_x(s) - last; /* Draw to the screen if necessary. */ if (insert) { ttyctx.num = width; tty_write(tty_cmd_insertcharacter, &ttyctx); } if (screen_check_selection(s, s->cx - width, s->cy)) { memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc); utf8_copy(&tmp_gc.data, &gc->data); tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET; tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET; tmp_gc.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256); tmp_gc.flags |= s->sel.cell.flags & (GRID_FLAG_FG256|GRID_FLAG_BG256); ttyctx.cell = &tmp_gc; tty_write(tty_cmd_cell, &ttyctx); } else { ttyctx.cell = gc; tty_write(tty_cmd_cell, &ttyctx); } }