version 1.57, 2016/10/11 13:21:59 |
version 1.58, 2016/10/13 20:27:27 |
|
|
0, { .data = { 0, 8, 8, ' ' } } |
0, { .data = { 0, 8, 8, ' ' } } |
}; |
}; |
|
|
static void grid_expand_line(struct grid *, u_int, u_int); |
static void grid_expand_line(struct grid *, u_int, u_int, u_int); |
|
static void grid_empty_line(struct grid *, u_int, u_int); |
|
|
static void grid_reflow_copy(struct grid_line *, u_int, struct grid_line *, |
static void grid_reflow_copy(struct grid_line *, u_int, struct grid_line *, |
u_int, u_int); |
u_int, u_int); |
|
|
|
|
/* Copy default into a cell. */ |
/* Copy default into a cell. */ |
static void |
static void |
grid_clear_cell(struct grid *gd, u_int px, u_int py) |
grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg) |
{ |
{ |
gd->linedata[py].celldata[px] = grid_default_entry; |
gd->linedata[py].celldata[px] = grid_default_entry; |
|
gd->linedata[py].celldata[px].data.bg = bg; |
} |
} |
|
|
/* Check grid y position. */ |
/* Check grid y position. */ |
|
|
* and shift up. |
* and shift up. |
*/ |
*/ |
void |
void |
grid_collect_history(struct grid *gd) |
grid_collect_history(struct grid *gd, u_int bg) |
{ |
{ |
u_int yy; |
u_int yy; |
|
|
|
|
if (yy < 1) |
if (yy < 1) |
yy = 1; |
yy = 1; |
|
|
grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy); |
grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy, bg); |
gd->hsize -= yy; |
gd->hsize -= yy; |
if (gd->hscrolled > gd->hsize) |
if (gd->hscrolled > gd->hsize) |
gd->hscrolled = gd->hsize; |
gd->hscrolled = gd->hsize; |
|
|
* allocate a new line at the bottom and move the history size indicator. |
* allocate a new line at the bottom and move the history size indicator. |
*/ |
*/ |
void |
void |
grid_scroll_history(struct grid *gd) |
grid_scroll_history(struct grid *gd, u_int bg) |
{ |
{ |
u_int yy; |
u_int yy; |
|
|
yy = gd->hsize + gd->sy; |
yy = gd->hsize + gd->sy; |
gd->linedata = xreallocarray(gd->linedata, yy + 1, |
gd->linedata = xreallocarray(gd->linedata, yy + 1, |
sizeof *gd->linedata); |
sizeof *gd->linedata); |
memset(&gd->linedata[yy], 0, sizeof gd->linedata[yy]); |
grid_empty_line(gd, yy, bg); |
|
|
gd->hscrolled++; |
gd->hscrolled++; |
gd->hsize++; |
gd->hsize++; |
|
|
void |
void |
grid_clear_history(struct grid *gd) |
grid_clear_history(struct grid *gd) |
{ |
{ |
grid_clear_lines(gd, 0, gd->hsize); |
grid_clear_lines(gd, 0, gd->hsize, 8); |
grid_move_lines(gd, 0, gd->hsize, gd->sy); |
grid_move_lines(gd, 0, gd->hsize, gd->sy, 8); |
|
|
gd->hscrolled = 0; |
gd->hscrolled = 0; |
gd->hsize = 0; |
gd->hsize = 0; |
|
|
|
|
/* Expand line to fit to cell. */ |
/* Expand line to fit to cell. */ |
static void |
static void |
grid_expand_line(struct grid *gd, u_int py, u_int sx) |
grid_expand_line(struct grid *gd, u_int py, u_int sx, u_int bg) |
{ |
{ |
struct grid_line *gl; |
struct grid_line *gl; |
u_int xx; |
u_int xx; |
|
|
|
|
gl->celldata = xreallocarray(gl->celldata, sx, sizeof *gl->celldata); |
gl->celldata = xreallocarray(gl->celldata, sx, sizeof *gl->celldata); |
for (xx = gl->cellsize; xx < sx; xx++) |
for (xx = gl->cellsize; xx < sx; xx++) |
grid_clear_cell(gd, xx, py); |
grid_clear_cell(gd, xx, py, bg); |
gl->cellsize = sx; |
gl->cellsize = sx; |
} |
} |
|
|
|
/* Empty a line and set background colour if needed. */ |
|
static void |
|
grid_empty_line(struct grid *gd, u_int py, u_int bg) |
|
{ |
|
memset(&gd->linedata[py], 0, sizeof gd->linedata[py]); |
|
if (bg != 8) |
|
grid_expand_line(gd, py, gd->sx, bg); |
|
} |
|
|
/* Peek at grid line. */ |
/* Peek at grid line. */ |
const struct grid_line * |
const struct grid_line * |
grid_peek_line(struct grid *gd, u_int py) |
grid_peek_line(struct grid *gd, u_int py) |
|
|
if (grid_check_y(gd, py) != 0) |
if (grid_check_y(gd, py) != 0) |
return; |
return; |
|
|
grid_expand_line(gd, py, px + 1); |
grid_expand_line(gd, py, px + 1, 8); |
|
|
gl = &gd->linedata[py]; |
gl = &gd->linedata[py]; |
gce = &gl->celldata[px]; |
gce = &gl->celldata[px]; |
|
|
|
if (px + 1 > gl->cellused) |
|
gl->cellused = px + 1; |
|
|
extended = (gce->flags & GRID_FLAG_EXTENDED); |
extended = (gce->flags & GRID_FLAG_EXTENDED); |
if (!extended && (gc->data.size != 1 || gc->data.width != 1)) |
if (!extended && (gc->data.size != 1 || gc->data.width != 1)) |
extended = 1; |
extended = 1; |
|
|
|
|
/* Clear area. */ |
/* Clear area. */ |
void |
void |
grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny) |
grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny, u_int bg) |
{ |
{ |
u_int xx, yy; |
u_int xx, yy; |
|
|
|
|
return; |
return; |
|
|
if (px == 0 && nx == gd->sx) { |
if (px == 0 && nx == gd->sx) { |
grid_clear_lines(gd, py, ny); |
grid_clear_lines(gd, py, ny, bg); |
return; |
return; |
} |
} |
|
|
|
|
return; |
return; |
|
|
for (yy = py; yy < py + ny; yy++) { |
for (yy = py; yy < py + ny; yy++) { |
if (px >= gd->linedata[yy].cellsize) |
if (px + nx >= gd->sx && px < gd->linedata[yy].cellused) |
|
gd->linedata[yy].cellused = px; |
|
if (px > gd->linedata[yy].cellsize && bg == 8) |
continue; |
continue; |
if (px + nx >= gd->linedata[yy].cellsize) { |
if (px + nx >= gd->linedata[yy].cellsize && bg == 8) { |
gd->linedata[yy].cellsize = px; |
gd->linedata[yy].cellsize = px; |
continue; |
continue; |
} |
} |
for (xx = px; xx < px + nx; xx++) { |
grid_expand_line(gd, yy, px + nx, bg); |
if (xx >= gd->linedata[yy].cellsize) |
for (xx = px; xx < px + nx; xx++) |
break; |
grid_clear_cell(gd, xx, yy, bg); |
grid_clear_cell(gd, xx, yy); |
|
} |
|
} |
} |
} |
} |
|
|
/* Clear lines. This just frees and truncates the lines. */ |
/* Clear lines. This just frees and truncates the lines. */ |
void |
void |
grid_clear_lines(struct grid *gd, u_int py, u_int ny) |
grid_clear_lines(struct grid *gd, u_int py, u_int ny, u_int bg) |
{ |
{ |
struct grid_line *gl; |
struct grid_line *gl; |
u_int yy; |
u_int yy; |
|
|
gl = &gd->linedata[yy]; |
gl = &gd->linedata[yy]; |
free(gl->celldata); |
free(gl->celldata); |
free(gl->extddata); |
free(gl->extddata); |
memset(gl, 0, sizeof *gl); |
grid_empty_line(gd, yy, bg); |
} |
} |
} |
} |
|
|
/* Move a group of lines. */ |
/* Move a group of lines. */ |
void |
void |
grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny) |
grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny, u_int bg) |
{ |
{ |
u_int yy; |
u_int yy; |
|
|
|
|
for (yy = dy; yy < dy + ny; yy++) { |
for (yy = dy; yy < dy + ny; yy++) { |
if (yy >= py && yy < py + ny) |
if (yy >= py && yy < py + ny) |
continue; |
continue; |
grid_clear_lines(gd, yy, 1); |
grid_clear_lines(gd, yy, 1, bg); |
} |
} |
|
|
memmove(&gd->linedata[dy], &gd->linedata[py], |
memmove(&gd->linedata[dy], &gd->linedata[py], |
|
|
|
|
/* Wipe any lines that have been moved (without freeing them). */ |
/* Wipe any lines that have been moved (without freeing them). */ |
for (yy = py; yy < py + ny; yy++) { |
for (yy = py; yy < py + ny; yy++) { |
if (yy >= dy && yy < dy + ny) |
if (yy < dy || yy >= dy + ny) |
continue; |
grid_empty_line(gd, yy, bg); |
memset(&gd->linedata[yy], 0, sizeof gd->linedata[yy]); |
|
} |
} |
} |
} |
|
|
/* Move a group of cells. */ |
/* Move a group of cells. */ |
void |
void |
grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx) |
grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx, |
|
u_int bg) |
{ |
{ |
struct grid_line *gl; |
struct grid_line *gl; |
u_int xx; |
u_int xx; |
|
|
return; |
return; |
gl = &gd->linedata[py]; |
gl = &gd->linedata[py]; |
|
|
grid_expand_line(gd, py, px + nx); |
grid_expand_line(gd, py, px + nx, 8); |
grid_expand_line(gd, py, dx + nx); |
grid_expand_line(gd, py, dx + nx, 8); |
memmove(&gl->celldata[dx], &gl->celldata[px], |
memmove(&gl->celldata[dx], &gl->celldata[px], |
nx * sizeof *gl->celldata); |
nx * sizeof *gl->celldata); |
|
|
|
|
for (xx = px; xx < px + nx; xx++) { |
for (xx = px; xx < px + nx; xx++) { |
if (xx >= dx && xx < dx + nx) |
if (xx >= dx && xx < dx + nx) |
continue; |
continue; |
grid_clear_cell(gd, xx, py); |
grid_clear_cell(gd, xx, py, bg); |
} |
} |
} |
} |
|
|
|
|
ny = dst->hsize + dst->sy - dy; |
ny = dst->hsize + dst->sy - dy; |
if (sy + ny > src->hsize + src->sy) |
if (sy + ny > src->hsize + src->sy) |
ny = src->hsize + src->sy - sy; |
ny = src->hsize + src->sy - sy; |
grid_clear_lines(dst, dy, ny); |
grid_clear_lines(dst, dy, ny, 8); |
|
|
for (yy = 0; yy < ny; yy++) { |
for (yy = 0; yy < ny; yy++) { |
srcl = &src->linedata[sy]; |
srcl = &src->linedata[sy]; |
|
|
u_int left, to_copy, ox, nx; |
u_int left, to_copy, ox, nx; |
|
|
/* How much is left on the old line? */ |
/* How much is left on the old line? */ |
left = new_x - dst_gl->cellsize; |
left = new_x - dst_gl->cellused; |
|
|
/* Work out how much to append. */ |
/* Work out how much to append. */ |
to_copy = src_gl->cellsize; |
to_copy = src_gl->cellused; |
if (to_copy > left) |
if (to_copy > left) |
to_copy = left; |
to_copy = left; |
ox = dst_gl->cellsize; |
ox = dst_gl->cellused; |
nx = ox + to_copy; |
nx = ox + to_copy; |
|
|
/* Resize the destination line. */ |
/* Resize the destination line. */ |
dst_gl->celldata = xreallocarray(dst_gl->celldata, nx, |
dst_gl->celldata = xreallocarray(dst_gl->celldata, nx, |
sizeof *dst_gl->celldata); |
sizeof *dst_gl->celldata); |
dst_gl->cellsize = nx; |
dst_gl->cellsize = dst_gl->cellused = nx; |
|
|
/* Append as much as possible. */ |
/* Append as much as possible. */ |
grid_reflow_copy(dst_gl, ox, src_gl, 0, to_copy); |
grid_reflow_copy(dst_gl, ox, src_gl, 0, to_copy); |
|
|
/* If there is any left in the source, split it. */ |
/* If there is any left in the source, split it. */ |
if (src_gl->cellsize > to_copy) { |
if (src_gl->cellused > to_copy) { |
dst_gl->flags |= GRID_LINE_WRAPPED; |
dst_gl->flags |= GRID_LINE_WRAPPED; |
|
|
src_gl->cellsize -= to_copy; |
src_gl->cellused -= to_copy; |
grid_reflow_split(dst, py, src_gl, new_x, to_copy); |
grid_reflow_split(dst, py, src_gl, new_x, to_copy); |
} |
} |
} |
} |
|
|
u_int to_copy; |
u_int to_copy; |
|
|
/* Loop and copy sections of the source line. */ |
/* Loop and copy sections of the source line. */ |
while (src_gl->cellsize > 0) { |
while (src_gl->cellused > 0) { |
/* Create new line. */ |
/* Create new line. */ |
if (*py >= dst->hsize + dst->sy) |
if (*py >= dst->hsize + dst->sy) |
grid_scroll_history(dst); |
grid_scroll_history(dst, 8); |
dst_gl = &dst->linedata[*py]; |
dst_gl = &dst->linedata[*py]; |
(*py)++; |
(*py)++; |
|
|
/* How much should we copy? */ |
/* How much should we copy? */ |
to_copy = new_x; |
to_copy = new_x; |
if (to_copy > src_gl->cellsize) |
if (to_copy > src_gl->cellused) |
to_copy = src_gl->cellsize; |
to_copy = src_gl->cellused; |
|
|
/* Expand destination line. */ |
/* Expand destination line. */ |
dst_gl->celldata = xreallocarray(NULL, to_copy, |
dst_gl->celldata = xreallocarray(NULL, to_copy, |
sizeof *dst_gl->celldata); |
sizeof *dst_gl->celldata); |
dst_gl->cellsize = to_copy; |
dst_gl->cellsize = dst_gl->cellused = to_copy; |
dst_gl->flags |= GRID_LINE_WRAPPED; |
dst_gl->flags |= GRID_LINE_WRAPPED; |
|
|
/* Copy the data. */ |
/* Copy the data. */ |
|
|
|
|
/* Move offset and reduce old line size. */ |
/* Move offset and reduce old line size. */ |
offset += to_copy; |
offset += to_copy; |
src_gl->cellsize -= to_copy; |
src_gl->cellused -= to_copy; |
} |
} |
|
|
/* Last line is not wrapped. */ |
/* Last line is not wrapped. */ |
|
|
|
|
/* Create new line. */ |
/* Create new line. */ |
if (*py >= dst->hsize + dst->sy) |
if (*py >= dst->hsize + dst->sy) |
grid_scroll_history(dst); |
grid_scroll_history(dst, 8); |
dst_gl = &dst->linedata[*py]; |
dst_gl = &dst->linedata[*py]; |
(*py)++; |
(*py)++; |
|
|
|
|
src_gl = src->linedata + line; |
src_gl = src->linedata + line; |
if (!previous_wrapped) { |
if (!previous_wrapped) { |
/* Wasn't wrapped. If smaller, move to destination. */ |
/* Wasn't wrapped. If smaller, move to destination. */ |
if (src_gl->cellsize <= new_x) |
if (src_gl->cellused <= new_x) |
grid_reflow_move(dst, &py, src_gl); |
grid_reflow_move(dst, &py, src_gl); |
else |
else |
grid_reflow_split(dst, &py, src_gl, new_x, 0); |
grid_reflow_split(dst, &py, src_gl, new_x, 0); |