/* Get cell for reading. */ const struct grid_cell * grid_peek_cell(struct grid *gd, u_int px, u_int py) { if (grid_check_y(gd, py) != 0) return (&grid_default_cell); if (px >= gd->linedata[py].cellsize) return (&grid_default_cell); return (&gd->linedata[py].celldata[px]); }
/* Get cell for reading. */ void grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc) { if (grid_check_y(gd, __func__, py) != 0 || px >= gd->linedata[py].cellsize) { memcpy(gc, &grid_default_cell, sizeof *gc); return; } return (grid_get_cell1(&gd->linedata[py], px, gc)); }
/* Set cell at relative position. */ void grid_set_cell( struct grid *gd, u_int px, u_int py, const struct grid_cell *gc) { if (grid_check_y(gd, py) != 0) return; grid_expand_line(gd, py, px + 1); grid_put_cell(gd, px, py, gc); }
/* Clear lines. This just frees and truncates the lines. */ void grid_clear_lines(struct grid *gd, u_int py, u_int ny) { struct grid_line *gl; u_int yy; if (ny == 0) return; if (grid_check_y(gd, py) != 0) return; if (grid_check_y(gd, py + ny - 1) != 0) return; for (yy = py; yy < py + ny; yy++) { gl = &gd->linedata[yy]; free(gl->celldata); memset(gl, 0, sizeof *gl); } }
/* Clear lines. This just frees and truncates the lines. */ void grid_clear_lines(struct grid *gd, u_int py, u_int ny, u_int bg) { struct grid_line *gl; u_int yy; if (ny == 0) return; if (grid_check_y(gd, py) != 0) return; if (grid_check_y(gd, py + ny - 1) != 0) return; for (yy = py; yy < py + ny; yy++) { gl = &gd->linedata[yy]; free(gl->celldata); free(gl->extddata); grid_empty_line(gd, yy, bg); } }
/* Set cell at relative position. */ void grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc) { struct grid_line *gl; struct grid_cell_entry *gce; struct grid_cell *gcp; int extended; if (grid_check_y(gd, py) != 0) return; grid_expand_line(gd, py, px + 1, 8); gl = &gd->linedata[py]; gce = &gl->celldata[px]; if (px + 1 > gl->cellused) gl->cellused = px + 1; extended = (gce->flags & GRID_FLAG_EXTENDED); if (!extended && (gc->data.size != 1 || gc->data.width != 1)) extended = 1; if (!extended && ((gc->fg & COLOUR_FLAG_RGB) || (gc->bg & COLOUR_FLAG_RGB))) extended = 1; if (extended) { gl->flags |= GRID_LINE_EXTENDED; if (~gce->flags & GRID_FLAG_EXTENDED) { gl->extddata = xreallocarray(gl->extddata, gl->extdsize + 1, sizeof *gl->extddata); gce->offset = gl->extdsize++; gce->flags = gc->flags | GRID_FLAG_EXTENDED; } if (gce->offset >= gl->extdsize) fatalx("offset too big"); gcp = &gl->extddata[gce->offset]; memcpy(gcp, gc, sizeof *gcp); return; } gce->flags = gc->flags; gce->data.attr = gc->attr; gce->data.fg = gc->fg & 0xff; if (gc->fg & COLOUR_FLAG_256) gce->flags |= GRID_FLAG_FG256; gce->data.bg = gc->bg & 0xff; if (gc->bg & COLOUR_FLAG_256) gce->flags |= GRID_FLAG_BG256; gce->data.data = gc->data.data[0]; }
/* Move a group of lines. */ void grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny) { u_int yy; GRID_DEBUG(gd, "dy=%u, py=%u, ny=%u", dy, py, ny); if (ny == 0 || py == dy) return; if (grid_check_y(gd, py) != 0) return; if (grid_check_y(gd, py + ny - 1) != 0) return; if (grid_check_y(gd, dy) != 0) return; if (grid_check_y(gd, dy + ny - 1) != 0) return; /* Free any lines which are being replaced. */ for (yy = dy; yy < dy + ny; yy++) { if (yy >= py && yy < py + ny) continue; grid_clear_lines(gd, yy, 1); } memmove( &gd->linedata[dy], &gd->linedata[py], ny * (sizeof *gd->linedata)); /* Wipe any lines that have been moved (without freeing them). */ for (yy = py; yy < py + ny; yy++) { if (yy >= dy && yy < dy + ny) continue; memset(&gd->linedata[yy], 0, sizeof gd->linedata[yy]); } }
/* Move a group of lines. */ void grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny, u_int bg) { u_int yy; if (ny == 0 || py == dy) return; if (grid_check_y(gd, __func__, py) != 0) return; if (grid_check_y(gd, __func__, py + ny - 1) != 0) return; if (grid_check_y(gd, __func__, dy) != 0) return; if (grid_check_y(gd, __func__, dy + ny - 1) != 0) return; /* Free any lines which are being replaced. */ for (yy = dy; yy < dy + ny; yy++) { if (yy >= py && yy < py + ny) continue; grid_free_line(gd, yy); } memmove(&gd->linedata[dy], &gd->linedata[py], ny * (sizeof *gd->linedata)); /* * Wipe any lines that have been moved (without freeing them - they are * still present). */ for (yy = py; yy < py + ny; yy++) { if (yy < dy || yy >= dy + ny) grid_empty_line(gd, yy, bg); } }
/* Set cell at relative position. */ void grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc) { struct grid_line *gl; struct grid_cell_entry *gce; if (grid_check_y(gd, __func__, py) != 0) return; grid_expand_line(gd, py, px + 1, 8); gl = &gd->linedata[py]; if (px + 1 > gl->cellused) gl->cellused = px + 1; gce = &gl->celldata[px]; if (grid_need_extended_cell(gce, gc)) grid_extended_cell(gl, gce, gc); else grid_store_cell(gce, gc, gc->data.data[0]); }