/* Copy from another screen. */ void screen_write_copy(struct screen_write_ctx *ctx, struct screen *src, u_int px, u_int py, u_int nx, u_int ny) { struct screen *s = ctx->s; struct grid *gd = src->grid; struct grid_line *gl; const struct grid_cell *gc; const struct grid_utf8 *gu; struct utf8_data utf8data; u_int xx, yy, cx, cy, ax, bx; cx = s->cx; cy = s->cy; for (yy = py; yy < py + ny; yy++) { gl = &gd->linedata[yy]; if (yy < gd->hsize + gd->sy) { /* * Find start and end position and copy between * them. Limit to the real end of the line then use a * clear EOL only if copying to the end, otherwise * could overwrite whatever is there already. */ if (px > gl->cellsize) ax = gl->cellsize; else ax = px; if (px + nx == gd->sx && px + nx > gl->cellsize) bx = gl->cellsize; else bx = px + nx; for (xx = ax; xx < bx; xx++) { if (xx >= gl->cellsize) gc = &grid_default_cell; else gc = &gl->celldata[xx]; if (!(gc->flags & GRID_FLAG_UTF8)) { screen_write_cell(ctx, gc, NULL); continue; } /* Reinject the UTF-8 sequence. */ gu = &gl->utf8data[xx]; utf8data.size = grid_utf8_copy( gu, utf8data.data, sizeof utf8data.data); utf8data.width = gu->width; screen_write_cell(ctx, gc, &utf8data); } if (px + nx == gd->sx && px + nx > gl->cellsize) screen_write_clearendofline(ctx); } else screen_write_clearline(ctx); cy++; screen_write_cursormove(ctx, cx, cy); } }
void window_copy_copy_line(struct window_pane *wp, char **buf, size_t *off, u_int sy, u_int sx, u_int ex) { struct window_copy_mode_data *data = wp->modedata; struct grid *gd = data->backing->grid; const struct grid_cell *gc; const struct grid_utf8 *gu; struct grid_line *gl; u_int i, xx, wrapped = 0; size_t size; if (sx > ex) return; /* * Work out if the line was wrapped at the screen edge and all of it is * on screen. */ gl = &gd->linedata[sy]; if (gl->flags & GRID_LINE_WRAPPED && gl->cellsize <= gd->sx) wrapped = 1; /* If the line was wrapped, don't strip spaces (use the full length). */ if (wrapped) xx = gl->cellsize; else xx = window_copy_find_length(wp, sy); if (ex > xx) ex = xx; if (sx > xx) sx = xx; if (sx < ex) { for (i = sx; i < ex; i++) { gc = grid_peek_cell(gd, i, sy); if (gc->flags & GRID_FLAG_PADDING) continue; if (!(gc->flags & GRID_FLAG_UTF8)) { *buf = xrealloc(*buf, 1, (*off) + 1); (*buf)[(*off)++] = gc->data; } else { gu = grid_peek_utf8(gd, i, sy); size = grid_utf8_size(gu); *buf = xrealloc(*buf, 1, (*off) + size); *off += grid_utf8_copy(gu, *buf + *off, size); } } } /* Only add a newline if the line wasn't wrapped. */ if (!wrapped || ex != xx) { *buf = xrealloc(*buf, 1, (*off) + 1); (*buf)[(*off)++] = '\n'; } }
/* Convert cells into a string. */ char * grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx) { const struct grid_cell *gc; const struct grid_utf8 *gu; char *buf; size_t len, off, size; u_int xx; GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx); len = 128; buf = xmalloc(len); off = 0; for (xx = px; xx < px + nx; xx++) { gc = grid_peek_cell(gd, xx, py); if (gc->flags & GRID_FLAG_PADDING) continue; if (gc->flags & GRID_FLAG_UTF8) { gu = grid_peek_utf8(gd, xx, py); size = grid_utf8_size(gu); while (len < off + size + 1) { buf = xrealloc(buf, 2, len); len *= 2; } off += grid_utf8_copy(gu, buf + off, len - off); } else { while (len < off + 2) { buf = xrealloc(buf, 2, len); len *= 2; } buf[off++] = gc->data; } } while (off > 0 && buf[off - 1] == ' ') off--; buf[off] = '\0'; return (buf); }