diff --git a/src/common/default.h b/src/common/default.h index cd5725a..67ef7e1 100644 --- a/src/common/default.h +++ b/src/common/default.h @@ -3,8 +3,17 @@ #include -/* default width of a column */ +/* default width of a column (in "characters") */ #define DEF_COLUMNWIDTH 12 +/* The number of vertical slices to divide a row into. + Note that only integer multiples of this have any effect + in console mode, but fteapot can save and respect non- + integer multiples of this value */ +#define ROWHEIGHT_DENOMINATOR 12 +/* default height of a row, in units of ROWHEIGHT_DENOMINATOR, + i.e. these should be equal to make the default height be one. + */ +#define DEF_ROWHEIGHT 12 /* default precision of a printed value */ /* Since the default format now counts significant figures diff --git a/src/common/main.c b/src/common/main.c index 546067f..dd4aef0 100644 --- a/src/common/main.c +++ b/src/common/main.c @@ -39,6 +39,7 @@ unsigned int batchln=0; PrecisionLevel def_precision = DEF_PRECISION; StringFormat quote = DIRECT_STRING; bool header = true; +int fontsize = 14; bool always_redraw = false; int debug_level = 0; static bool usexdr = false; @@ -67,13 +68,13 @@ void moveto(Sheet *sheet, CoordT x, CoordT y, CoordT z) need_redraw = true; sheet->offy = (sheet->cur[Y] > 0) ? sheet->cur[Y]-1 : 0; } - if (sheet->cur[X] >= sheet->offx + sheet->maxx) { + if (sheet->cur[X] >= sheet->offx + (CoordT)sheet->maxx) { need_redraw = true; - sheet->offx = sheet->cur[X] - sheet->maxx + 2; + sheet->offx = sheet->cur[X] - (CoordT)sheet->maxx + 2; } - if (sheet->cur[Y] >= sheet->offy + sheet->maxy) { + if (sheet->cur[Y] >= sheet->offy + (CoordT)sheet->maxy) { need_redraw = true; - sheet->offy = sheet->cur[Y] - sheet->maxy + 2; + sheet->offy = sheet->cur[Y] - (CoordT)sheet->maxy + 2; } if (need_redraw) redraw_sheet(sheet); else if (need_cell) redraw_cell(sheet, sheet->cur); @@ -312,6 +313,23 @@ static int do_columnwidth(Sheet *cursheet) } /*}}}*/ +/* do_rowheight -- set the row height */ /*{{{*/ +static int do_rowheight(Sheet *cursheet) +{ + do_mark(cursheet, GET_MARK_CUR); + int n = (int)rowheight(cursheet, cursheet->mark1[Y], cursheet->mark1[Z]); + do { + int c = line_numedit(&n, _("Row height:")); + if (c < 0) return c; + } while (n <= 0); + RowHgtT rh = (RowHgtT)n; + for (int y = cursheet->mark1[Y]; y <= cursheet->mark2[Y]; ++y) + for (int z = cursheet->mark1[Z]; z <= cursheet->mark2[Z]; ++z) + setheight(cursheet, y, z, rh); + return -1; +} +/*}}}*/ + /* do_attribute -- set cell attributes */ /*{{{*/ static void do_attribute(Sheet *cursheet, Key action) { @@ -1329,6 +1347,7 @@ int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly) { case K_GOTO: do_goto(cursheet, (const char *)0); break; case K_COLWIDTH: do_columnwidth(cursheet); break; + case K_ROWHEIGHT: do_rowheight(cursheet); break; case BLOCK_CLEAR: do_clear(cursheet); update(cursheet); break; case BLOCK_INSERT: do_insert(cursheet); update(cursheet); break; case BLOCK_DELETE: do_delete(cursheet); update(cursheet); break; @@ -1577,19 +1596,20 @@ int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly) /* NPAGE -- page down */ /*{{{*/ case K_NPAGE: { - cursheet->offy += (cursheet->maxy-3); - relmoveto(cursheet, 0, cursheet->maxy-3, 0); + cursheet->offy += ((CoordT)(cursheet->maxy)-3); + relmoveto(cursheet, 0, (CoordT)(cursheet->maxy)-3, 0); break; } /*}}}*/ /* PPAGE -- page up */ /*{{{*/ case K_PPAGE: { - cursheet->offy = cursheet->offy >= cursheet->maxy - 3 - ? cursheet->offy - cursheet->maxy + 3 : 0; + cursheet->offy = + cursheet->offy >= (CoordT)(cursheet->maxy) - 3 + ? cursheet->offy - (CoordT)(cursheet->maxy) + 3 : 0; relmoveto(cursheet, 0, - cursheet->cur[Y] >= (cursheet->maxy - 3) - ? -(cursheet->maxy - 3) : -cursheet->cur[Y], + cursheet->cur[Y] >= ((CoordT)(cursheet->maxy) - 3) + ? -((CoordT)(cursheet->maxy) - 3) : -cursheet->cur[Y], 0); break; } @@ -1645,7 +1665,7 @@ int main(int argc, char *argv[]) find_helpfile(helpfile, sizeof(helpfile), argv[0]); /* parse options */ /*{{{*/ - while ((o=getopt(argc,argv,"bdhnrqHp:?"))!=EOF) switch (o) + while ((o=getopt(argc,argv,"bdhnrqHp:F:?"))!=EOF) switch (o) { /* b -- run batch */ /*{{{*/ case 'b': batch = true; break; @@ -1687,19 +1707,35 @@ int main(int argc, char *argv[]) break; } /*}}}*/ + /* F -- font size */ /*{{{*/ + case 'F': + { + long f; + char *end; + + f = strtol(optarg, &end, 0); + if (*end || f < 1) { + fprintf(stderr, _("teapot: font size must be positive.\n")); + exit(1); + } + fontsize = (int)f; + break; + } + /*}}}*/ /* default -- includes ? and h */ /*{{{*/ default: { fprintf(stderr,_( - "Usage: %s [-a] [-b] [-d]* [-h] [-n|-q] [-H] [-r] [-p digits] [file]\n" + "Usage: %s [-abFhHr] [-d]* [-n|-q] [-p digits] [file]\n" " -a: use ASCII file format as default\n" " -b: batch mode\n" " -d: increase debug level, once for each occurrence\n" + " -F nn: set font size to nn\n" " -h: print this message and exit\n" - " -n|-q: DO NOT or DO display strings in quotes, respectively\n" " -H: hide row/column headers\n" + " -n|-q: DO NOT or DO display strings in quotes, respectively\n" + " -p nn: set decimal precision to nn\n" " -r: redraw more often\n" - " -p: set decimal precision\n" ), argv[0]); exit(1); } diff --git a/src/common/main.h b/src/common/main.h index 96b5728..4ebf165 100644 --- a/src/common/main.h +++ b/src/common/main.h @@ -17,6 +17,7 @@ extern bool batch; extern PrecisionLevel def_precision; extern StringFormat quote; extern bool header; +extern int fontsize; extern int debug_level; extern bool always_redraw; extern unsigned int batchln; @@ -94,7 +95,8 @@ typedef enum ADJUST_BACKGROUND = -63, K_EDIT_STYLE_EXPR = -64, ADJUST_DIM = -65, - ADJUST_ITALIC = -66 + ADJUST_ITALIC = -66, + K_ROWHEIGHT = -67 } Key; extern int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly); diff --git a/src/common/sheet.c b/src/common/sheet.c index 8880146..6b5b91d 100644 --- a/src/common/sheet.c +++ b/src/common/sheet.c @@ -226,6 +226,7 @@ void initialize_sheet(Sheet *sheet) { sheet->dim[X] = sheet->dim[Y] = sheet->dim[Z] = 0; sheet->sheet = (Cell**)0; sheet->column = (ColWidT*)0; + sheet->rowhts = (RowHgtT*)0; sheet->orix = sheet->oriy = 0; sheet->maxx = sheet->maxy = 0; sheet->name = (char*)0; @@ -272,7 +273,7 @@ void resize(Sheet *sheet, CoordT x, CoordT y, CoordT z, bool *qextended) if (sheet->sheet!=(Cell**)0) free(sheet->sheet); sheet->sheet = dummy.sheet; /*}}}*/ - /* allocate new columns */ /*{{{*/ + /* allocate new column widths and row heights */ /*{{{*/ if ((size_t)x > sheet->dim[X] || (size_t)z >= sheet->dim[Z]) { dummy.column = malloc(dummy.dim[X] * dummy.dim[Z] * sizeof(ColWidT)); @@ -281,7 +282,7 @@ void resize(Sheet *sheet, CoordT x, CoordT y, CoordT z, bool *qextended) { if ((size_t)x < sheet->dim[X] && (size_t)z < sheet->dim[Z]) *(dummy.column + ((size_t)x)*dummy.dim[Z] + (size_t)z) - = *(sheet->column + ((size_t)x)*sheet->dim[Z] + z); + = *(sheet->column + ((size_t)x)*sheet->dim[Z] + (size_t)z); else *(dummy.column + ((size_t)x)*dummy.dim[Z] + (size_t)z) = DEF_COLUMNWIDTH; @@ -289,6 +290,21 @@ void resize(Sheet *sheet, CoordT x, CoordT y, CoordT z, bool *qextended) if (sheet->column != (ColWidT*)0) free(sheet->column); sheet->column = dummy.column; } + if ((size_t)(y) > sheet->dim[Y] || (size_t)z > sheet->dim[Z]) + { + dummy.rowhts = malloc(dummy.dim[Y] * dummy.dim[Z] * sizeof(RowHgtT)); + for (y=0; (size_t)y < dummy.dim[Y]; ++y) + for (z=0; (size_t)z < dummy.dim[Z]; ++z) + { + RowHgtT *dumht = dummy.rowhts + ((size_t)y)*dummy.dim[Z] + (size_t)z; + if ((size_t)y < sheet->dim[Y] && (size_t)z < sheet->dim[Z]) + *dumht = *(sheet->rowhts + ((size_t)y)*sheet->dim[Z] + (size_t)z); + else + *dumht = DEF_ROWHEIGHT; + } + if (sheet->rowhts != (RowHgtT*)0) free(sheet->rowhts); + sheet->rowhts = dummy.rowhts; + } /*}}}*/ for (Dimensions dd = X; dd < HYPER; ++dd) sheet->dim[dd] = dummy.dim[dd]; } @@ -408,12 +424,16 @@ void freesheet(Sheet *sheet, int all) } /*}}}*/ if (sheet->sheet) free(sheet->sheet); if (sheet->column) free(sheet->column); + if (sheet->rowhts) free(sheet->rowhts); if (sheet->name) free(sheet->name); if (!batch) display_end(sheet); } else { for (size_t x = 0; x < sheet->dim[X]; ++x) for (size_t z = 0; z < sheet->dim[Z]; ++z) *(sheet->column + x*sheet->dim[Z] + z) = DEF_COLUMNWIDTH; + for (size_t y = 0; y < sheet->dim[y]; ++y) + for (size_t z = 0; z < sheet->dim[Z]; ++z) + *(sheet->rowhts + y*sheet->dim[Z] + z) = DEF_ROWHEIGHT; cachelabels(sheet); forceupdate(sheet); } @@ -460,6 +480,17 @@ ColWidT columnwidth(Sheet *sheet, CoordT x, CoordT z) } /*}}}*/ +/* rowheight -- get height of row */ /*{{{*/ +ColWidT rowheight(Sheet *sheet, CoordT y, CoordT z) +{ + assert(sheet!=(Sheet*)0); + if ((size_t)y < sheet->dim[Y] && (size_t)z < sheet->dim[Z]) + return (*(sheet->rowhts + ((size_t)y)*sheet->dim[Z] + (size_t)z)); + else return DEF_ROWHEIGHT; +} +/*}}}*/ + + /* setwidth -- set width of column */ /*{{{*/ bool setwidth(Sheet *sheet, CoordT x, CoordT z, ColWidT width) { @@ -477,6 +508,24 @@ bool setwidth(Sheet *sheet, CoordT x, CoordT z, ColWidT width) } /*}}}*/ + +/* setheight -- set height of row */ /*{{{*/ +bool setheight(Sheet *sheet, CoordT y, CoordT z, RowHgtT height) +{ + assert(sheet != (Sheet*)0); + bool isbigger = false; + resize(sheet, 1, y, z, &isbigger); + if (isbigger) sheet->changed = true; + RowHgtT *storage = sheet->rowhts + (size_t)y*sheet->dim[Z] + (size_t)z; + if (*storage != height) { + *storage = height; + sheet->changed = true; + return true; + } + return isbigger; +} +/*}}}*/ + /* cellwidth -- get width of a cell */ /*{{{*/ ColWidT cellwidth(Sheet *sheet, const Location at) { @@ -489,6 +538,18 @@ ColWidT cellwidth(Sheet *sheet, const Location at) } /*}}}*/ + +/* cellheight -- get height of a cell */ /*{{{*/ +RowHgtT cellheight(Sheet *sheet, const Location at) +{ + /* At the moment this is trivial because there is no vertical + "shadowing". Probably rather than implementing that more + general cell merging would be a preferable way to go + */ + return rowheight(sheet, at[Y], at[Z]); +} +/*}}}*/ + /* putcont -- assign new contents */ /*{{{*/ void puttok(Sheet *sheet, const Location at, Token t, TokVariety v) { @@ -1232,6 +1293,8 @@ const char *saveport(Sheet *sheet, const char *name, unsigned int *count) { if (y == 0 && columnwidth(sheet,x,z) != DEF_COLUMNWIDTH) fprintf(fp,"W%d %d %zu\n", x, z, columnwidth(sheet,x,z)); + if (x == 0 && rowheight(sheet, y, z) != DEF_ROWHEIGHT) + fprintf(fp, "Y%d %d %zu\n", y, z, rowheight(sheet, y, z)); Cell *cell = CELL_ATC(sheet,x,y,z); if (cell != NULLCELL) { @@ -1283,6 +1346,7 @@ const char *loadport(Sheet *sheet, const char *name) size_t width = strlen(buf); if (width > 0 && buf[width-1] == '\n') buf[--width] = '\0'; /*}}}*/ + bool is_height = false; switch (buf[0]) { /* C -- parse cell */ /*{{{*/ @@ -1548,16 +1612,21 @@ const char *loadport(Sheet *sheet, const char *name) break; } /*}}}*/ + /* Y -- row height */ + case 'Y': + is_height = true; + /* FALL THROUGH */ /* W -- column width */ /*{{{*/ case 'W': { - /* parse x and z */ /*{{{*/ + /* parse x/y and z */ /*{{{*/ const char *os = buf+1; char *ns = buf+1; - CoordT cx = (CoordT)strtol(os, &ns, 0); + CoordT cxy = (CoordT)strtol(os, &ns, 0); if (os == ns) { - sprintf(errbuf, _("Parse error for x position in line %d"), line); + sprintf(errbuf, _("Parse error for %c position in line %d"), + is_height ? 'y' : 'x', line); err = errbuf; goto eek; } @@ -1571,10 +1640,10 @@ const char *loadport(Sheet *sheet, const char *name) goto eek; } /*}}}*/ - /* parse width */ /*{{{*/ + /* parse width/height */ /*{{{*/ while (*ns == ' ') ++ns; os = ns; - ColWidT cwidth = (ColWidT)strtol(os, &ns, 0); + long extent = strtol(os, &ns, 0); if (os == ns) { sprintf(errbuf, _("Parse error for width in line %d"), line); @@ -1582,7 +1651,8 @@ const char *loadport(Sheet *sheet, const char *name) goto eek; } /*}}}*/ - setwidth(sheet, cx, cz, cwidth); + if (is_height) setheight(sheet, cxy, cz, (RowHgtT)extent); + else setwidth(sheet, cxy, cz, (ColWidT)extent); break; } /*}}}*/ diff --git a/src/common/sheet.h b/src/common/sheet.h index 1542625..bcf9994 100644 --- a/src/common/sheet.h +++ b/src/common/sheet.h @@ -13,6 +13,7 @@ extern "C" { #define ASCENDING 001 typedef size_t ColWidT; +typedef size_t RowHgtT; /* Note measured in units of ROWHEIGHT_DENOMINATOR */ typedef struct { @@ -38,9 +39,10 @@ typedef struct CoordT offx, offy; Cell **sheet; ColWidT *column; + RowHgtT *rowhts; size_t dim[HYPER]; size_t orix, oriy; - CoordT maxx, maxy; + size_t maxx, maxy; size_t width; char *name; void *display; @@ -86,6 +88,9 @@ void freecellofsheet(Sheet *sheet, const Location at); ColWidT columnwidth(Sheet *sheet, CoordT x, CoordT z); bool setwidth(Sheet *sheet, CoordT x, CoordT z, ColWidT width); ColWidT cellwidth(Sheet *sheet, const Location at); +RowHgtT rowheight(Sheet *sheet, CoordT y, CoordT z); +bool setheight(Sheet *sheet, CoordT y, CoordT x, RowHgtT height); +RowHgtT cellheight(Sheet *sheet, const Location at); void puttok(Sheet *sheet, const Location at, Token t, TokVariety v); Token recompvalue(Sheet *sheet, const Location at); Token evaluate_at(Token t, Sheet *sheet, const Location at); diff --git a/src/display.c b/src/display.c index fc5f054..d6e08b4 100644 --- a/src/display.c +++ b/src/display.c @@ -272,15 +272,16 @@ static int do_block(Sheet *cursheet) } -int show_menu(Sheet *cursheet) +Key show_menu(Sheet *cursheet) { int c = K_INVALID; do { const char* menu[] = - { _("aA)ttributes"), _("wW)idth"), _("bB)lock"), _("fF)ile"), - _("gG)oto"), _("sS)hell"), _("vV)ersion"), _("qQ)uit"), NULL + { _("aA)ttributes"), _("wW)idth"), _("hH)eight"), _("bB)lock"), + _("fF)ile"), _("gG)oto"), _("sS)hell"), _("vV)ersion"), + _("qQ)uit"), NULL }; switch (c=line_menu(_("Main menu:"),menu,0)) { @@ -288,12 +289,13 @@ int show_menu(Sheet *cursheet) case -1: c = KEY_CANCEL; break; case 0: c = do_attribute(cursheet); break; case 1: c = K_COLWIDTH; break; - case 2: c = do_block(cursheet); break; - case 3: c = do_file(cursheet); break; - case 4: c = K_GOTO; break; - case 5: do_shell(); c = KEY_CANCEL; break; - case 6: c = K_ABOUT; break; - case 7: c = K_QUIT; break; + case 2: c = K_ROWHEIGHT; break; + case 3: c = do_block(cursheet); break; + case 4: c = do_file(cursheet); break; + case 5: c = K_GOTO; break; + case 6: do_shell(); c = KEY_CANCEL; break; + case 7: c = K_ABOUT; break; + case 8: c = K_QUIT; break; default: assert(0); } } while (c == K_INVALID); @@ -327,8 +329,8 @@ static void do_bg(void) void display_main(Sheet *cursheet) { - cursheet->maxx = COLS; - cursheet->maxy = LINES-1; + cursheet->maxx = (size_t)COLS; + cursheet->maxy = (size_t)(LINES-1); Key k; do @@ -396,10 +398,15 @@ void redraw_cell(Sheet *sheet, const Location at ) update(sheet); } +static RowHgtT eff_height(Sheet *sheet, CoordT y) { + RowHgtT eff = rowheight(sheet, y, sheet->cur[Z]) / ROWHEIGHT_DENOMINATOR; + if (eff == 0) return 1; + return eff; +} + /* redraw_sheet -- draw a sheet with cell cursor */ void redraw_sheet(Sheet *sheet) { - int x,y; char pbuf[80]; char *buf=malloc(128); size_t bufsz=128; @@ -421,18 +428,31 @@ void redraw_sheet(Sheet *sheet) --(sheet->cur[X]); assert(sheet->cur[X] >= 0); } - if (sheet->cur[Y] - sheet->offy > sheet->maxy - 2 - (header ? 1 : 0)) - sheet->offy = sheet->cur[Y] - sheet->maxy + 2 + (header ? 1 : 0); + /* Calculate the nearest Y offset that will show the current row */ if (sheet->cur[Y] < sheet->offy) sheet->offy = sheet->cur[Y]; + else { + size_t available = sheet->maxy - 2 - (header ? 1 : 0); + CoordT newoffy = sheet->cur[Y]; + size_t needed = eff_height(sheet, newoffy); + while (needed < available && newoffy > 0) { + RowHgtT prevhgt = eff_height(sheet, newoffy - 1); + if (needed + prevhgt > available) break; + needed += prevhgt; + --newoffy; + } + if (newoffy > sheet->offy) sheet->offy = newoffy; + } + /* Calculate the nearest X offset that will show the current column */ if (sheet->cur[X] < sheet->offx) sheet->offx = sheet->cur[X]; - size_t width = header ? 4 : 0; - bool again; - size_t col; - do - { + else { + size_t width = header ? 4 : 0; + bool again; + size_t col; + do + { again = false; col = 0; - for (x = sheet->offx; + for (CoordT x = sheet->offx; width <= (size_t)(sheet->maxx); width += columnwidth(sheet, x, sheet->cur[Z]), ++x, ++col); --col; @@ -444,7 +464,8 @@ void redraw_sheet(Sheet *sheet) sheet->offx++; again = true; } } - } while (again); + } while (again); + } short curcp = 1; init_pair(curcp, DefaultCN[FOREGROUND], COLOR_YELLOW); @@ -452,15 +473,15 @@ void redraw_sheet(Sheet *sheet) if (header) { (void)wattron(stdscr,DEF_NUMBER); /* draw x numbers */ - for (width=4; width < (size_t)(sheet->maxx); ++width) + for (size_t width=4; width < (size_t)(sheet->maxx); ++width) mvwaddch(stdscr, (int)(sheet->oriy), (int)(sheet->orix + width), (chtype)(unsigned char)' '); - for (width = 4, x = sheet->offx; width < (size_t)(sheet->maxx); - width += col, ++x) + ColWidT width = 4; + for (CoordT x = sheet->offx; width < sheet->maxx; ++x) { short usecp = 0; if (x == sheet->cur[X]) usecp = curcp; - col = columnwidth(sheet, x, sheet->cur[Z]); + ColWidT col = columnwidth(sheet, x, sheet->cur[Z]); if (bufsz<(size_t)(col*UTF8SZ+1)) buf=realloc(buf,bufsz=(size_t)(col*UTF8SZ+1)); snprintf(buf,bufsz,"%d",x); if (mbslen(buf)>col) { @@ -473,18 +494,27 @@ void redraw_sheet(Sheet *sheet) buf[(size_t)(sheet->maxx)-width] = '\0'; wcolor_set(stdscr, usecp, NULL); mvwaddstr(stdscr, (int)(sheet->oriy), (int)(sheet->orix+width), buf); + ColWidT used = strlen(buf); + while (used++ < col) waddch(stdscr, (chtype)(unsigned char)' '); wcolor_set(stdscr, 0, NULL); + width += col; } /* draw y numbers */ - for (y=1; y < sheet->maxy - 1; ++y) { + RowHgtT height = 1; + for (CoordT y = sheet->offy; height + 1 < sheet->maxy; ++y) { short usecp = 0; - CoordT realy = y - 1 + sheet->offy; - if (realy == sheet->cur[Y]) usecp = curcp; + if (y == sheet->cur[Y]) usecp = curcp; wcolor_set(stdscr, usecp, NULL); - (void)mvwprintw(stdscr, y + (CoordT)(sheet->oriy), (CoordT)(sheet->orix), - "%-4d", y-1 + (int)(sheet->offy)); + (void)mvwprintw(stdscr, (int)(height+sheet->oriy), (int)sheet->orix, + "%-4d", y); + RowHgtT rows = eff_height(sheet, y); + for (RowHgtT extra = 1; extra < rows; ++extra) { + mvwaddstr(stdscr, (int)(height+extra+sheet->oriy), (int)sheet->orix, + " "); + } wcolor_set(stdscr, 0, NULL); + height += eff_height(sheet, y); } (void)wattroff(stdscr,DEF_NUMBER); @@ -494,11 +524,14 @@ void redraw_sheet(Sheet *sheet) } ++curcp; /* draw elements */ - for (y = header ? 1 : 0; y < sheet->maxy - 1; ++y) - for (width = header ? 4 : 0, x = sheet->offx; - width < (size_t)sheet->maxx; + RowHgtT height = header ? 1 : 0; + for (CoordT y = sheet->offy; height + 1 < sheet->maxy; ++y) { + RowHgtT rows = eff_height(sheet, y); + ColWidT width = header ? 4 : 0; + for (CoordT x = sheet->offx; + width < sheet->maxx; width += columnwidth(sheet, x, sheet->cur[Z]), ++x) - { + { size_t size,realsize,fill, cutoff = 0; int realx = x; if (x == sheet->offx) { @@ -511,7 +544,7 @@ void redraw_sheet(Sheet *sheet) cutoff += columnwidth(sheet, realx, sheet->cur[Z]); } } - tmp[X] = realx; tmp[Y] = y - (header ? 1 : 0) + sheet->offy; + tmp[X] = realx; tmp[Y] = y; tmp[Z] = sheet->cur[Z]; cell = safe_cell_at(sheet, tmp); Style sc = getstyle(sheet, tmp); @@ -548,21 +581,30 @@ void redraw_sheet(Sheet *sheet) wcolor_set(stdscr, usecp, NULL); bool invert = (ms != UNMARKED) && loc_in_box(tmp, sheet->mark1, sheet->mark2); - if (x == sheet->cur[X] - && (y - (header ? 1 : 0) + sheet->offy == sheet->cur[Y])) + if (x == sheet->cur[X] && y == sheet->cur[Y]) invert = (ms == MARKING) ? true : !invert; if (invert) (void)wattron(stdscr,DEF_CELLCURSOR); if (sc.dim) wattron(stdscr, A_DIM); if (sc.bold) wattron(stdscr, A_BOLD); if (sc.underline) wattron(stdscr, A_UNDERLINE); - (void)mvwaddstr(stdscr, y+(int)(sheet->oriy), - (int)(sheet->orix + width), + (void)mvwaddstr(stdscr, (int)(height + sheet->oriy), + (int)(width + sheet->orix), buf+cutoff); for (fill=mbslen(buf+cutoff); filloriy), + (int)(width + sheet->orix), + " "); + for (fill = 1; fill < realsize; ++fill) + (void)waddch(stdscr, (chtype)(unsigned char)' '); + } wcolor_set(stdscr, 0, NULL); wstandend(stdscr); } + } + height += rows; } /* draw contents of current element */ @@ -596,11 +638,11 @@ void redraw_sheet(Sheet *sheet) FLT_COMPACT, -1, TRUNCATED_ERROR, &ic); } } - *mbspos(buf, sheet->maxx) = 0; + *mbspos(buf, (int)sheet->maxx) = 0; - (void)mvwaddstr(stdscr, (int)(sheet->oriy) + sheet->maxy - 1, + (void)mvwaddstr(stdscr, (int)(sheet->oriy + sheet->maxy) - 1, (int)(sheet->orix), buf); - for (col = mbslen(buf); col < (size_t)sheet->maxx; ++col) + for (size_t col = mbslen(buf); col < sheet->maxx; ++col) (void)waddch(stdscr, ' '); } diff --git a/src/fteapot.fl b/src/fteapot.fl index 78f2a8b..f6d255f 100644 --- a/src/fteapot.fl +++ b/src/fteapot.fl @@ -41,6 +41,7 @@ class TeapotTable {open : {public Fl_Table}} { decl {Sheet *cursheet;} {protected local} decl {bool cut, updating;} {protected local} + decl {int unit_width, unit_height;} {protected local} decl {static const TableContext ACTION = (TableContext)(1<<8);} {public local} decl {static const TableContext REFRESH = (TableContext)(1<<9);} @@ -48,14 +49,25 @@ class TeapotTable {open : {public Fl_Table}} Function {TeapotTable(int x, int y, int w, int h, const char *l=0) : - Fl_Table(x, y, w, h, l), cut(false), updating(false)} {open} {code + Fl_Table(x, y, w, h, l), cut(false), updating(false), + unit_width(10), unit_height(0)} {open} {code { end(); - col_resize_min(10); + col_resize_min(unit_width); col_resize(true); col_header(header); - row_resize(false); + unit_height = fl_height(FL_HELVETICA, fontsize); + col_header_height(unit_height); + fl_font(FL_HELVETICA, fontsize); + int ww = 0, hh = 0; + fl_measure("8888", ww, hh, 0); + int min_row_height = (unit_height + ROWHEIGHT_DENOMINATOR/2 - 1) + / ROWHEIGHT_DENOMINATOR; + if (min_row_height < 1) min_row_height = 1; + row_resize_min(min_row_height); + row_resize(true); row_header(header); + row_header_width(ww + unit_width); set_visible_focus(); table_box(FL_THIN_UP_FRAME); } {} } @@ -92,7 +104,7 @@ class TeapotTable {open : {public Fl_Table}} case CONTEXT_ENDPAGE: W = xx-x()-2; H = yy-y()-2; xx = x()+2; yy = y()+2; - fl_font(FL_HELVETICA | FL_BOLD, 14); + fl_font(FL_HELVETICA | FL_BOLD, fontsize); fl_push_clip(xx, yy, W, H); fl_draw_box(FL_DIAMOND_UP_BOX, xx, yy, W, H, col_header_color()); fl_color(FL_INACTIVE_COLOR); @@ -107,7 +119,7 @@ class TeapotTable {open : {public Fl_Table}} break; case CONTEXT_COL_HEADER: { - fl_font(FL_HELVETICA | FL_BOLD, 14); + fl_font(FL_HELVETICA | FL_BOLD, fontsize); fl_push_clip(xx, yy, W, H); Fl_Color hd_clr = col_header_color(); if (C == cursheet->cur[X]) hd_clr = tpt_selection_version(hd_clr); @@ -120,7 +132,7 @@ class TeapotTable {open : {public Fl_Table}} } case CONTEXT_ROW_HEADER: { - fl_font(FL_HELVETICA | FL_BOLD, 14); + fl_font(FL_HELVETICA | FL_BOLD, fontsize); fl_push_clip(xx, yy, W, H); Fl_Color hd_clr = row_header_color(); if (R == cursheet->cur[Y]) hd_clr = tpt_selection_version(hd_clr); @@ -171,7 +183,7 @@ class TeapotTable {open : {public Fl_Table}} Fl_Font cellfont = FL_HELVETICA; if (sc.bold) cellfont |= FL_BOLD; if (sc.italic) cellfont |= FL_ITALIC; - fl_font(cellfont, 14); + fl_font(cellfont, fontsize); size_t ulen = printvalue(s, sizeof(s), 0, quote, sc.fform, sc.precision, cursheet, test); @@ -216,21 +228,29 @@ class TeapotTable {open : {public Fl_Table}} { if (updating) return; updating = true; - if (debug_level > 2) - printf("update_table: %zux%zu@%i,%i; %i[%i], %i[%i]\\n", + if (debug_level > 1) + printf("update_table: %zux%zu@%i,%i; %i[%lu], %i[%lu]\\n", cursheet->dim[X], cursheet->dim[Y], cursheet->cur[X], cursheet->cur[Y], cursheet->offx, cursheet->maxx, cursheet->offy, cursheet->maxy); + bool no_table = (cols() == 0) || (rows() == 0); if (cursheet->dim[X] > (size_t)cols()) cols(cursheet->dim[X]); + if (no_table) col_width_all(DEF_COLUMNWIDTH*unit_width); if (cursheet->dim[Y] > (size_t)rows()) rows(cursheet->dim[Y]); + if (no_table) row_height_all(unit_height); adjust_outside(); for (int x = 0; (size_t)x < cursheet->dim[X]; x++) { - int w = columnwidth(cursheet, x, cursheet->cur[Z])*10; + int w = columnwidth(cursheet, x, cursheet->cur[Z])*unit_width; if (col_width(x) != w) col_width(x, w); } + for (int y = 0; (size_t)y < cursheet->dim[Y]; ++y) { + int h = rowheight(cursheet, y, cursheet->cur[Z])*unit_height + / ROWHEIGHT_DENOMINATOR; + if (row_height(y) != h) row_height(y, h); + } col_position(cursheet->offx); row_position(cursheet->offy); set_selection(cursheet->cur[Y], cursheet->cur[X], @@ -257,25 +277,34 @@ class TeapotTable {open : {public Fl_Table}} cursheet->marking = MARKED; } moveto(cursheet, current_col, current_row, -1); - visible_cells(cursheet->offy, cursheet->maxy, - cursheet->offx, cursheet->maxx); - cursheet->maxx -= cursheet->offx; - cursheet->maxy -= cursheet->offy; + int lastx, lasty; + visible_cells(cursheet->offy, lasty, + cursheet->offx, lastx); + cursheet->maxx = (size_t)(lastx - cursheet->offx); + cursheet->maxy = (size_t)(lasty - cursheet->offy); if (is_interactive_resize()) { for (size_t C = 0; C < cursheet->dim[X]; ++C) { - size_t w = (col_width(C) + 5)/10; + size_t w = (col_width(C) + unit_width/2)/unit_width; if (w != columnwidth(cursheet, C, cursheet->cur[Z])) setwidth(cursheet, C, cursheet->cur[Z], w); } + for (size_t R = 0; R < cursheet->dim[Y]; ++R) { + size_t h = + (row_height(R)*ROWHEIGHT_DENOMINATOR + unit_height/2) + / unit_height; + if (h != rowheight(cursheet, R, cursheet->cur[Z])) + setheight(cursheet, R, cursheet->cur[Z], h); + } } updating = false; - if (debug_level > 2) - printf("upd_sheet: %ix%i@%i,%i; %i[%i], %i[%i] (%i,%i)-(%i,%i)\\n", - cols(), rows(), cursheet->cur[X], cursheet->cur[Y], - cursheet->offx, cursheet->maxx, - cursheet->offy, cursheet->maxy, x1, y1, x2, y2); + if (debug_level > 1) + printf( + "upd_sheet: %ix%i@%i,%i; %i[%lu], %i[%lu] (%i,%i)-(%i,%i)\\n", + cols(), rows(), cursheet->cur[X], cursheet->cur[Y], + cursheet->offx, cursheet->maxx, + cursheet->offy, cursheet->maxy, x1, y1, x2, y2); } {} } Function @@ -399,7 +428,7 @@ class TeapotTable {open : {public Fl_Table}} if (!cols() || !rows()) { cols(1); rows(1); } visible_cells(y1, y2, x1, x2); - if (debug_level > 2) + if (debug_level > 1) printf("adj: (%i,%i)-(%i,%i) %ix%i\\n", x1, y1, x2, y2, cols(), rows()); if (x2+2 < cols() && (size_t)cols() > cursheet->dim[X])