#include "lib9.h"#include "draw.h"#include "tk.h" /* * XXX TODO * - grid rowcget|columncget * - grid columnconfigure/rowconfigure accepts a list of indexes? */ #define O(t, e) ((long)(&((t*)0)->e)) typedef struct TkGridparam TkGridparam;typedef struct TkBeamparam TkBeamparam; struct TkGridparam{ Point span; Tk* in; Point pad; Point ipad; char *row; char *col; int sticky;}; struct TkBeamparam{ int minsize; int maxsize; int weight; int pad; char *name; int equalise;}; staticTkOption opts[] ={ "padx", OPTnndist, O(TkGridparam, pad.x), nil, "pady", OPTnndist, O(TkGridparam, pad.y), nil, "ipadx", OPTnndist, O(TkGridparam, ipad.x), nil, "ipady", OPTnndist, O(TkGridparam, ipad.y), nil, "in", OPTwinp, O(TkGridparam, in), nil, "row", OPTtext, O(TkGridparam, row), nil, "column", OPTtext, O(TkGridparam, col), nil, "rowspan", OPTnndist, O(TkGridparam, span.y), nil, "columnspan", OPTnndist, O(TkGridparam, span.x), nil, "sticky", OPTsticky, O(TkGridparam, sticky), nil, nil}; staticTkOption beamopts[] ={ "minsize", OPTnndist, O(TkBeamparam, minsize), nil, "maxsize", OPTnndist, O(TkBeamparam, maxsize), nil, "weight", OPTnndist, O(TkBeamparam, weight), nil, "pad", OPTnndist, O(TkBeamparam, pad), nil, "name", OPTtext, O(TkBeamparam, name), nil, "equalise", OPTstab, O(TkBeamparam, equalise), tkbool, nil}; voidprintgrid(TkGrid *grid){ int x, y; Point dim; dim = grid->dim; print("grid %P\n", grid->dim); print(" row heights: "); for(y = 0; y < dim.y; y++) print("%d[%d,%d,w%d,p%d]%s ", grid->rows[y].act, grid->rows[y].minsize, grid->rows[y].maxsize < 0x7fffffff ? grid->rows[y].maxsize : -1, grid->rows[y].weight, grid->rows[y].pad, grid->rows[y].name ? grid->rows[y].name : ""); print("\n"); print(" col widths: "); for(x = 0; x < dim.x; x++) print("%d[%d,%d,w%d,p%d]%s ", grid->cols[x].act, grid->cols[x].minsize, grid->cols[x].maxsize < 0x7fffffff ? grid->cols[x].maxsize : -1, grid->cols[x].weight, grid->cols[x].pad, grid->cols[x].name ? grid->cols[x].name : ""); print("\n"); for(y = 0; y < dim.y; y++){ print(" row %d: ", y); for(x = 0; x < dim.x; x++){ print("%p;", grid->cells[y][x].tk); print("%s%P\t", grid->cells[y][x].tk?grid->cells[y][x].tk->name->name:"(nil)", grid->cells[y][x].span); } print("\n"); }} static voidtkgridsetopt(TkGridparam *p, Tk *tk){ if(p->pad.x != -1) tk->pad.x = p->pad.x*2; if(p->pad.y != -1) tk->pad.y = p->pad.y*2; if(p->ipad.x != -1) tk->ipad.x = p->ipad.x*2; if(p->ipad.y != -1) tk->ipad.y = p->ipad.y*2; if(p->sticky != -1) tk->flag = (tk->flag & ~(Tkanchor|Tkfill)) | (p->sticky & (Tkanchor|Tkfill));} static voidinitbeam(TkGridbeam *beam, int n){ int i; memset(beam, 0, n * sizeof(TkGridbeam)); for(i = 0; i < n; i++) beam[i].maxsize = 0x7fffffff;} static char*ensuregridsize(TkGrid *grid, Point dim){ TkGridcell **cells, *cellrow; TkGridbeam *cols, *rows; Point olddim; int i; olddim = grid->dim; if(dim.x < olddim.x) dim.x = olddim.x; if(dim.y < olddim.y) dim.y = olddim.y; if(dim.y > olddim.y){ cells = realloc(grid->cells, sizeof(TkGridcell*)*dim.y); if(cells == nil) return TkNomem; grid->cells = cells; for(i = olddim.y; i < dim.y; i++){ cells[i] = malloc(sizeof(TkGridcell)*dim.x); if(cells[i] == nil){ while(--i >= olddim.y) free(cells[i]); return TkNomem; } } rows = realloc(grid->rows, sizeof(TkGridbeam)*dim.y); if(rows == nil) return TkNomem; grid->rows = rows; initbeam(rows + olddim.y, dim.y - olddim.y); grid->dim.y = dim.y; } if(dim.x > olddim.x){ /* * any newly allocated rows will have the correct number of * columns, so we don't need to reallocate them */ cells = grid->cells; for(i = 0; i < olddim.y; i++){ cellrow = realloc(cells[i], sizeof(TkGridcell) * dim.x); if(cellrow == nil) return TkNomem; /* leak some earlier rows, but not permanently */ memset(cellrow + olddim.x, 0, (dim.x-olddim.x)*sizeof(TkGridcell)); cells[i] = cellrow; } cols = realloc(grid->cols, sizeof(TkGridbeam)*dim.x); if(cols == nil) return TkNomem; initbeam(cols + olddim.x, dim.x - olddim.x); grid->cols = cols; grid->dim.x = dim.x; } return nil;} static TkGridbeam*delbeams(TkGridbeam *beam, int nb, int x0, int x1){ int i; TkGridbeam *b; for(i = x0; i < x1; i++) free(beam[i].name); memmove(&beam[x0], &beam[x1], sizeof(TkGridbeam) * (nb-x1)); b = realloc(beam, sizeof(TkGridbeam) * (nb-(x1-x0))); return b ? b : beam;} static voiddelrows(TkGrid *grid, int y0, int y1){ TkGridcell **cells; memmove(grid->cells+y0, grid->cells+y1, sizeof(TkGridcell*) * (grid->dim.y-y1)); grid->dim.y -= (y1 - y0); cells = realloc(grid->cells, sizeof(TkGridcell*) * grid->dim.y); if(cells != nil || grid->dim.y == 0) grid->cells = cells; /* can realloc to a smaller size ever fail? */} static voiddelcols(TkGrid *grid, int x0, int x1){ TkGridcell **cells, *row; int y, ndx; Point dim; dim = grid->dim; ndx = dim.x - (x1 - x0); cells = grid->cells; for(y = 0; y < dim.y; y++){ row = cells[y]; memmove(row+x0, row+x1, sizeof(TkGridcell) * (dim.x - x1)); row = realloc(row, sizeof(TkGridcell) * ndx); if(row != nil || ndx == 0) cells[y] = row; } grid->dim.x = ndx;} /* * insert items into rows/cols; the beam has already been expanded appropriately. */voidinsbeams(TkGridbeam *beam, int nb, int x, int n){ memmove(&beam[x+n], &beam[x], sizeof(TkGridbeam)*(nb-x-n)); initbeam(beam+x, n);} static char*insrows(TkGrid *grid, int y0, int n){ Point olddim; char *e; TkGridcell **cells, *tmp; int y; olddim = grid->dim; if(y0 > olddim.y){ n = y0 + n - olddim.y; y0 = olddim.y; } e = ensuregridsize(grid, Pt(olddim.x, olddim.y + n)); if(e != nil) return e; /* * we know the extra rows will have been filled * with blank, properly allocated rows, so just swap 'em with the * ones that need moving. */ cells = grid->cells; for(y = olddim.y - 1; y >= y0; y--){ tmp = cells[y + n]; cells[y + n] = cells[y]; cells[y] = tmp; } insbeams(grid->rows, grid->dim.y, y0, n); return nil;} static char*inscols(TkGrid *grid, int x0, int n){ TkGridcell **cells; Point olddim; int y; char *e; olddim = grid->dim; if(x0 > olddim.x){ n = x0 + n - olddim.x; x0 = olddim.x; } e = ensuregridsize(grid, Pt(olddim.x + n, olddim.y)); if(e != nil) return e; cells = grid->cells; for(y = 0; y < olddim.y; y++){ memmove(cells[y] + x0 + n, cells[y] + x0, sizeof(TkGridcell) * (olddim.x - x0)); memset(cells[y] + x0, 0, sizeof(TkGridcell) * n); } insbeams(grid->cols, grid->dim.x, x0, n); return nil;} static intmaximum(int a, int b){ if(a > b) return a; return b;} /* * return the width of cols/rows between x0 and x1 in the beam, * excluding the padding at either end, but including padding in the middle. */static intbeamsize(TkGridbeam *cols, int x0, int x1){ int tot, fpad, x; if(x0 >= x1) return 0; tot = cols[x0].act; fpad = cols[x0].pad; for(x = x0 + 1; x < x1; x++){ tot += cols[x].act + maximum(cols[x].pad, fpad); fpad = cols[x].pad; } return tot;} /* * return starting position of cell index on beam, relative * to top-left of grid */static intbeamcellpos(TkGridbeam *beam, int blen, int index){ int x; if(blen == 0 || index >= blen || index < 0) return 0; x = beam[0].pad + beamsize(beam, 0, index); if(index > 0) x += maximum(beam[index-1].pad, beam[index].pad); return x;} static Rectanglecellbbox(TkGrid *grid, Point pos){ Point dim; Rectangle r; dim = grid->dim; if(pos.x > dim.x) pos.x = dim.x; if(pos.y > dim.y) pos.y = dim.y; r.min.x = beamcellpos(grid->cols, dim.x, pos.x); r.min.y = beamcellpos(grid->rows, dim.y, pos.y); if(pos.x == dim.x) r.max.x = r.min.x; else r.max.x = r.min.x + grid->cols[pos.x].act; if(pos.y == dim.y) r.max.y = r.min.y; else r.max.y = r.min.y + grid->rows[pos.y].act; return rectaddpt(r, grid->origin);} /* * return true ifthere are any spanning cells covering row _index_ */static intgridrowhasspan(TkGrid *grid, int index){ int i, d; Point dim; TkGridcell *cell; dim = grid->dim; if(index > 0 && index < dim.y){ for(i = 0; i < dim.x; i++){ cell = &grid->cells[index][i]; if(cell->tk != nil){ d = cell->span.x; if(d == 0) return 1; i += d - 1; } } } return 0;} /* * return true ifthere are any spanning cells covering column _index_ */static intgridcolhasspan(TkGrid *grid, int index){ int i, d; Point dim; TkGridcell *cell; dim = grid->dim; if(index > 0 && index < dim.x){ for(i = 0; i < dim.y; i++){ cell = &grid->cells[i][index]; if(cell->tk != nil){ d = cell->span.y; if(d == 0) return 1; i += d - 1; } } } return 0;} /* * find cell that's spanning the grid position p */static intfindspan(TkGrid *grid, Point p, Point *cp){ Point dim; TkGridcell **cells; Tk *tk; dim = grid->dim; cells = grid->cells; if(p.x < 0 || p.y < 0 || p.x >= dim.x || p.y >= dim.y) return 0; if(cells[p.y][p.x].tk == nil) return 0; if(cells[p.y][p.x].span.x == 0){ tk = cells[p.y][p.x].tk; for(; p.y >= 0; p.y--) if(cells[p.y][p.x].tk != tk) break; p.y++; for(; p.x >= 0; p.x--) if(cells[p.y][p.x].tk != tk) break; p.x++; } *cp = p; return 1;} static intparsegridindex(TkGridbeam *beam, int blen, char *s){ int n, i; char *e; if(s[0] == '\0') return -1; n = strtol(s, &e, 10); if(*e == '\0') return n; if(strcmp(s, "end") == 0) return blen; for(i = 0; i < blen; i++) if(beam[i].name != nil && strcmp(beam[i].name, s) == 0) return i; return -1;} static char*tkgridconfigure(TkTop *t, TkGridparam *p, TkName *names){ TkGrid *grid; TkGridcell **cells; TkName *n; Tk *tkf, *tkp; Point dim, pos, q, span, startpos; int maxcol, c, i, j, x; char *e; if(names == nil) return nil; if(p->span.x < 1 || p->span.y < 1) return TkBadvl; tkf = nil; maxcol = 0; for(n = names; n; n = n->link){ c = n->name[0]; if((c=='-' || c=='^' || c=='x') && n->name[1] == '\0'){ maxcol++; continue; } tkp = tklook(t, n->name, 0); if(tkp == nil){ tkerr(t, n->name); return TkBadwp; } if(tkp->flag & Tkwindow)Lines 1–500 of 1526. Load more
#include "lib9.h" #include "draw.h" #include "tk.h" /* * XXX TODO * - grid rowcget|columncget * - grid columnconfigure/rowconfigure accepts a list of indexes? */ #define O(t, e) ((long)(&((t*)0)->e)) typedef struct TkGridparam TkGridparam; typedef struct TkBeamparam TkBeamparam; struct TkGridparam{ Point span; Tk* in; Point pad; Point ipad; char *row; char *col; int sticky; }; struct TkBeamparam{ int minsize; int maxsize; int weight; int pad; char *name; int equalise; }; static TkOption opts[] = { "padx", OPTnndist, O(TkGridparam, pad.x), nil, "pady", OPTnndist, O(TkGridparam, pad.y), nil, "ipadx", OPTnndist, O(TkGridparam, ipad.x), nil, "ipady", OPTnndist, O(TkGridparam, ipad.y), nil, "in", OPTwinp, O(TkGridparam, in), nil, "row", OPTtext, O(TkGridparam, row), nil, "column", OPTtext, O(TkGridparam, col), nil, "rowspan", OPTnndist, O(TkGridparam, span.y), nil, "columnspan", OPTnndist, O(TkGridparam, span.x), nil, "sticky", OPTsticky, O(TkGridparam, sticky), nil, nil }; static TkOption beamopts[] = { "minsize", OPTnndist, O(TkBeamparam, minsize), nil, "maxsize", OPTnndist, O(TkBeamparam, maxsize), nil, "weight", OPTnndist, O(TkBeamparam, weight), nil, "pad", OPTnndist, O(TkBeamparam, pad), nil, "name", OPTtext, O(TkBeamparam, name), nil, "equalise", OPTstab, O(TkBeamparam, equalise), tkbool, nil }; void printgrid(TkGrid *grid) { int x, y; Point dim; dim = grid->dim; print("grid %P\n", grid->dim); print(" row heights: "); for(y = 0; y < dim.y; y++) print("%d[%d,%d,w%d,p%d]%s ", grid->rows[y].act, grid->rows[y].minsize, grid->rows[y].maxsize < 0x7fffffff ? grid->rows[y].maxsize : -1, grid->rows[y].weight, grid->rows[y].pad, grid->rows[y].name ? grid->rows[y].name : ""); print("\n"); print(" col widths: "); for(x = 0; x < dim.x; x++) print("%d[%d,%d,w%d,p%d]%s ", grid->cols[x].act, grid->cols[x].minsize, grid->cols[x].maxsize < 0x7fffffff ? grid->cols[x].maxsize : -1, grid->cols[x].weight, grid->cols[x].pad, grid->cols[x].name ? grid->cols[x].name : ""); print("\n"); for(y = 0; y < dim.y; y++){ print(" row %d: ", y); for(x = 0; x < dim.x; x++){ print("%p;", grid->cells[y][x].tk); print("%s%P\t", grid->cells[y][x].tk?grid->cells[y][x].tk->name->name:"(nil)", grid->cells[y][x].span); } print("\n"); } } static void tkgridsetopt(TkGridparam *p, Tk *tk) { if(p->pad.x != -1) tk->pad.x = p->pad.x*2; if(p->pad.y != -1) tk->pad.y = p->pad.y*2; if(p->ipad.x != -1) tk->ipad.x = p->ipad.x*2; if(p->ipad.y != -1) tk->ipad.y = p->ipad.y*2; if(p->sticky != -1) tk->flag = (tk->flag & ~(Tkanchor|Tkfill)) | (p->sticky & (Tkanchor|Tkfill)); } static void initbeam(TkGridbeam *beam, int n) { int i; memset(beam, 0, n * sizeof(TkGridbeam)); for(i = 0; i < n; i++) beam[i].maxsize = 0x7fffffff; } static char* ensuregridsize(TkGrid *grid, Point dim) { TkGridcell **cells, *cellrow; TkGridbeam *cols, *rows; Point olddim; int i; olddim = grid->dim; if(dim.x < olddim.x) dim.x = olddim.x; if(dim.y < olddim.y) dim.y = olddim.y; if(dim.y > olddim.y){ cells = realloc(grid->cells, sizeof(TkGridcell*)*dim.y); if(cells == nil) return TkNomem; grid->cells = cells; for(i = olddim.y; i < dim.y; i++){ cells[i] = malloc(sizeof(TkGridcell)*dim.x); if(cells[i] == nil){ while(--i >= olddim.y) free(cells[i]); return TkNomem; } } rows = realloc(grid->rows, sizeof(TkGridbeam)*dim.y); if(rows == nil) return TkNomem; grid->rows = rows; initbeam(rows + olddim.y, dim.y - olddim.y); grid->dim.y = dim.y; } if(dim.x > olddim.x){ /* * any newly allocated rows will have the correct number of * columns, so we don't need to reallocate them */ cells = grid->cells; for(i = 0; i < olddim.y; i++){ cellrow = realloc(cells[i], sizeof(TkGridcell) * dim.x); if(cellrow == nil) return TkNomem; /* leak some earlier rows, but not permanently */ memset(cellrow + olddim.x, 0, (dim.x-olddim.x)*sizeof(TkGridcell)); cells[i] = cellrow; } cols = realloc(grid->cols, sizeof(TkGridbeam)*dim.x); if(cols == nil) return TkNomem; initbeam(cols + olddim.x, dim.x - olddim.x); grid->cols = cols; grid->dim.x = dim.x; } return nil; } static TkGridbeam* delbeams(TkGridbeam *beam, int nb, int x0, int x1) { int i; TkGridbeam *b; for(i = x0; i < x1; i++) free(beam[i].name); memmove(&beam[x0], &beam[x1], sizeof(TkGridbeam) * (nb-x1)); b = realloc(beam, sizeof(TkGridbeam) * (nb-(x1-x0))); return b ? b : beam; } static void delrows(TkGrid *grid, int y0, int y1) { TkGridcell **cells; memmove(grid->cells+y0, grid->cells+y1, sizeof(TkGridcell*) * (grid->dim.y-y1)); grid->dim.y -= (y1 - y0); cells = realloc(grid->cells, sizeof(TkGridcell*) * grid->dim.y); if(cells != nil || grid->dim.y == 0) grid->cells = cells; /* can realloc to a smaller size ever fail? */ } static void delcols(TkGrid *grid, int x0, int x1) { TkGridcell **cells, *row; int y, ndx; Point dim; dim = grid->dim; ndx = dim.x - (x1 - x0); cells = grid->cells; for(y = 0; y < dim.y; y++){ row = cells[y]; memmove(row+x0, row+x1, sizeof(TkGridcell) * (dim.x - x1)); row = realloc(row, sizeof(TkGridcell) * ndx); if(row != nil || ndx == 0) cells[y] = row; } grid->dim.x = ndx; } /* * insert items into rows/cols; the beam has already been expanded appropriately. */ void insbeams(TkGridbeam *beam, int nb, int x, int n) { memmove(&beam[x+n], &beam[x], sizeof(TkGridbeam)*(nb-x-n)); initbeam(beam+x, n); } static char* insrows(TkGrid *grid, int y0, int n) { Point olddim; char *e; TkGridcell **cells, *tmp; int y; olddim = grid->dim; if(y0 > olddim.y){ n = y0 + n - olddim.y; y0 = olddim.y; } e = ensuregridsize(grid, Pt(olddim.x, olddim.y + n)); if(e != nil) return e; /* * we know the extra rows will have been filled * with blank, properly allocated rows, so just swap 'em with the * ones that need moving. */ cells = grid->cells; for(y = olddim.y - 1; y >= y0; y--){ tmp = cells[y + n]; cells[y + n] = cells[y]; cells[y] = tmp; } insbeams(grid->rows, grid->dim.y, y0, n); return nil; } static char* inscols(TkGrid *grid, int x0, int n) { TkGridcell **cells; Point olddim; int y; char *e; olddim = grid->dim; if(x0 > olddim.x){ n = x0 + n - olddim.x; x0 = olddim.x; } e = ensuregridsize(grid, Pt(olddim.x + n, olddim.y)); if(e != nil) return e; cells = grid->cells; for(y = 0; y < olddim.y; y++){ memmove(cells[y] + x0 + n, cells[y] + x0, sizeof(TkGridcell) * (olddim.x - x0)); memset(cells[y] + x0, 0, sizeof(TkGridcell) * n); } insbeams(grid->cols, grid->dim.x, x0, n); return nil; } static int maximum(int a, int b) { if(a > b) return a; return b; } /* * return the width of cols/rows between x0 and x1 in the beam, * excluding the padding at either end, but including padding in the middle. */ static int beamsize(TkGridbeam *cols, int x0, int x1) { int tot, fpad, x; if(x0 >= x1) return 0; tot = cols[x0].act; fpad = cols[x0].pad; for(x = x0 + 1; x < x1; x++){ tot += cols[x].act + maximum(cols[x].pad, fpad); fpad = cols[x].pad; } return tot; } /* * return starting position of cell index on beam, relative * to top-left of grid */ static int beamcellpos(TkGridbeam *beam, int blen, int index) { int x; if(blen == 0 || index >= blen || index < 0) return 0; x = beam[0].pad + beamsize(beam, 0, index); if(index > 0) x += maximum(beam[index-1].pad, beam[index].pad); return x; } static Rectangle cellbbox(TkGrid *grid, Point pos) { Point dim; Rectangle r; dim = grid->dim; if(pos.x > dim.x) pos.x = dim.x; if(pos.y > dim.y) pos.y = dim.y; r.min.x = beamcellpos(grid->cols, dim.x, pos.x); r.min.y = beamcellpos(grid->rows, dim.y, pos.y); if(pos.x == dim.x) r.max.x = r.min.x; else r.max.x = r.min.x + grid->cols[pos.x].act; if(pos.y == dim.y) r.max.y = r.min.y; else r.max.y = r.min.y + grid->rows[pos.y].act; return rectaddpt(r, grid->origin); } /* * return true ifthere are any spanning cells covering row _index_ */ static int gridrowhasspan(TkGrid *grid, int index) { int i, d; Point dim; TkGridcell *cell; dim = grid->dim; if(index > 0 && index < dim.y){ for(i = 0; i < dim.x; i++){ cell = &grid->cells[index][i]; if(cell->tk != nil){ d = cell->span.x; if(d == 0) return 1; i += d - 1; } } } return 0; } /* * return true ifthere are any spanning cells covering column _index_ */ static int gridcolhasspan(TkGrid *grid, int index) { int i, d; Point dim; TkGridcell *cell; dim = grid->dim; if(index > 0 && index < dim.x){ for(i = 0; i < dim.y; i++){ cell = &grid->cells[i][index]; if(cell->tk != nil){ d = cell->span.y; if(d == 0) return 1; i += d - 1; } } } return 0; } /* * find cell that's spanning the grid position p */ static int findspan(TkGrid *grid, Point p, Point *cp) { Point dim; TkGridcell **cells; Tk *tk; dim = grid->dim; cells = grid->cells; if(p.x < 0 || p.y < 0 || p.x >= dim.x || p.y >= dim.y) return 0; if(cells[p.y][p.x].tk == nil) return 0; if(cells[p.y][p.x].span.x == 0){ tk = cells[p.y][p.x].tk; for(; p.y >= 0; p.y--) if(cells[p.y][p.x].tk != tk) break; p.y++; for(; p.x >= 0; p.x--) if(cells[p.y][p.x].tk != tk) break; p.x++; } *cp = p; return 1; } static int parsegridindex(TkGridbeam *beam, int blen, char *s) { int n, i; char *e; if(s[0] == '\0') return -1; n = strtol(s, &e, 10); if(*e == '\0') return n; if(strcmp(s, "end") == 0) return blen; for(i = 0; i < blen; i++) if(beam[i].name != nil && strcmp(beam[i].name, s) == 0) return i; return -1; } static char* tkgridconfigure(TkTop *t, TkGridparam *p, TkName *names) { TkGrid *grid; TkGridcell **cells; TkName *n; Tk *tkf, *tkp; Point dim, pos, q, span, startpos; int maxcol, c, i, j, x; char *e; if(names == nil) return nil; if(p->span.x < 1 || p->span.y < 1) return TkBadvl; tkf = nil; maxcol = 0; for(n = names; n; n = n->link){ c = n->name[0]; if((c=='-' || c=='^' || c=='x') && n->name[1] == '\0'){ maxcol++; continue; } tkp = tklook(t, n->name, 0); if(tkp == nil){ tkerr(t, n->name); return TkBadwp; } if(tkp->flag & Tkwindow)