/* Scroll a region up, moving the top line into the history. */ void grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower, u_int bg) { struct grid_line *gl_history, *gl_upper; u_int yy; /* Create a space for a new line. */ yy = gd->hsize + gd->sy; gd->linedata = xreallocarray(gd->linedata, yy + 1, sizeof *gd->linedata); /* Move the entire screen down to free a space for this line. */ gl_history = &gd->linedata[gd->hsize]; memmove(gl_history + 1, gl_history, gd->sy * sizeof *gl_history); /* Adjust the region and find its start and end. */ upper++; gl_upper = &gd->linedata[upper]; lower++; /* Move the line into the history. */ memcpy(gl_history, gl_upper, sizeof *gl_history); /* Then move the region up and clear the bottom line. */ memmove(gl_upper, gl_upper + 1, (lower - upper) * sizeof *gl_upper); grid_empty_line(gd, lower, bg); /* Move the history offset down over the line. */ gd->hscrolled++; gd->hsize++; }
/* 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, 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, bg); } 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) grid_empty_line(gd, yy, bg); } }
/* * Scroll the entire visible screen, moving one line into the history. Just * allocate a new line at the bottom and move the history size indicator. */ void grid_scroll_history(struct grid *gd, u_int bg) { u_int yy; yy = gd->hsize + gd->sy; gd->linedata = xreallocarray(gd->linedata, yy + 1, sizeof *gd->linedata); grid_empty_line(gd, yy, bg); gd->hscrolled++; gd->hsize++; }
/* 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) { u_int yy; if (ny == 0) return; if (grid_check_y(gd, __func__, py) != 0) return; if (grid_check_y(gd, __func__, py + ny - 1) != 0) return; for (yy = py; yy < py + ny; yy++) { grid_free_line(gd, yy); grid_empty_line(gd, yy, bg); } }
/* 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); } }