From 00859ecbd2e9951d90f07459e81c21ccf925405b Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Wed, 26 Jul 2023 03:21:43 +0000 Subject: [PATCH] feat: Add hashing color for cells (#93) Co-authored-by: Glen Whitney Reviewed-on: https://code.studioinfinity.org/glen/teapot-spreadsheet/pulls/93 --- NEWS | 2 +- doc/teapot.lyx | 45 +++++++++++++++++++++++++++++++---- src/common/func.c | 2 ++ src/common/func.h | 1 + src/common/main.c | 6 ++--- src/common/main.h | 3 ++- src/common/style.c | 7 ++++-- src/common/style.h | 4 +++- src/display.c | 59 +++++++++++++++++++++++++++++++++++++--------- src/fteapot.fl | 18 ++++++++++++-- teapot.1 | 2 +- 11 files changed, 122 insertions(+), 27 deletions(-) diff --git a/NEWS b/NEWS index eb1b2bc..f301eb2 100644 --- a/NEWS +++ b/NEWS @@ -17,7 +17,7 @@ o New token types: style and bool. o Comparison operators return bool rather than int (Note this can be a breaking change; you may need to wrap comparisons in int() if you are using the result in a numerical computation.) -o Foreground and background color style attributes for cells. +o Foreground, background, and hashing color style attributes for cells. o Variable row height for cells. o Addition of an if() conditional operator. o Addition of a find() macro to search for a cell satisfying a condition. diff --git a/doc/teapot.lyx b/doc/teapot.lyx index f9134e2..3d5f1bc 100644 --- a/doc/teapot.lyx +++ b/doc/teapot.lyx @@ -167,8 +167,8 @@ Copyright, Contributors and License teapot \noun default (Table Editor And Planner, Or: Teapot), is copyrighted 1995–2006 by Michael - Haardt, and 2009–2010 by Jörg Walter, and 2019 by Glen Whitney, and is - licensed under the Gnu General Public License v3 or later. + Haardt, and 2009–2010 by Jörg Walter, and 2019-2023 by Glen Whitney, and + is licensed under the Gnu General Public License v3 or later. \end_layout \begin_layout Standard @@ -3994,9 +3994,13 @@ foreground \family sans background \family default -() colors used to display a cell may be set. - (Currently this only affects screen display.) The value of these attributes - is a positive integer which acts as an index into the +() colors used to display a cell may be set and the +\family sans + hashing +\family default +() color may be set as well. + (Currently this only affects screen display.) The value of each of these + attributes is a positive integer which acts as an index into the \begin_inset Quotes eld \end_inset @@ -8272,6 +8276,37 @@ is for example. \end_layout +\begin_layout Description + +\series medium +style +\emph on + +\begin_inset space ~ +\end_inset + + +\series default +\emph default +hashing +\series medium +(int +\emph on + +\begin_inset space ~ +\end_inset + + +\emph default +c) +\series default + evaluates to a style token with the hashing color set to +\emph on +c +\emph default + (and no other fields set). +\end_layout + \begin_layout Description hexact used as a keyword to the string() function; listed here to record that this identifier may not be used as a cell label. diff --git a/src/common/func.c b/src/common/func.c index a9e4d9a..d3078db 100644 --- a/src/common/func.c +++ b/src/common/func.c @@ -1089,6 +1089,7 @@ static Token aspect_func(FunctionIdentifier self, int argc, const Token argv[]) { ColorAspect ca = FOREGROUND; if (self == FUNC_BACKGROUND) ca = BACKGROUND; + if (self == FUNC_HASHING) ca = HASHING; Token result; if (argc != 1 || argv[0].type != INT) { const char *templ = _("Usage: %s(int)"); @@ -1839,6 +1840,7 @@ Tfunc tfunc[]= [FUNC_PRECISION] = { "precision", precision_func, PREFIX_FUNC, FUNCT, 0 }, [FUNC_FOREGROUND] = { "foreground", aspect_func, PREFIX_FUNC, FUNCT, 0 }, [FUNC_BACKGROUND] = { "background", aspect_func, PREFIX_FUNC, FUNCT, 0 }, + [FUNC_HASHING] = { "hashing", aspect_func, PREFIX_FUNC, FUNCT, 0 }, [FUNC_JUSTIFY] = { "justify", justify_func, PREFIX_FUNC, FUNCT, 0 }, [FUNC_FLOATFMT] = { "floatfmt", floatfmt_func, PREFIX_FUNC, FUNCT, 0 }, [FUNC_SHADOWED] = { "shadowed", shadowed_func, PREFIX_FUNC, FUNCT, 0 }, diff --git a/src/common/func.h b/src/common/func.h index 97eb799..a9adc4f 100644 --- a/src/common/func.h +++ b/src/common/func.h @@ -44,6 +44,7 @@ typedef enum FUNC_FUNCALL, FUNC_LIDENT, FUNC_LOCATION, FUNC_NUMBER, FUNC_OPERATOR, FUNC_IS, FUNC_FIND, FUNC_PRECISION, FUNC_FOREGROUND, FUNC_BACKGROUND, + FUNC_HASHING, FUNC_JUSTIFY, FUNC_FLOATFMT, FUNC_SHADOWED, FUNC_TRANSPARENT, FUNC_BOLD, FUNC_UNDERLINE, FUNC_CENTER, FUNC_STYLE, diff --git a/src/common/main.c b/src/common/main.c index 0b49da1..7e7b2b9 100644 --- a/src/common/main.c +++ b/src/common/main.c @@ -390,9 +390,8 @@ static void do_attribute(Sheet *cursheet, Key action) } /*}}}*/ /* Set a color */ /*{{{*/ - case ADJUST_BACKGROUND: - ca = BACKGROUND; - /* FALL THROUGH */ + case ADJUST_HASHING: ++ca; /* FALL THROUGH */ + case ADJUST_BACKGROUND: ++ca; /* FALL THROUGH */ case ADJUST_FOREGROUND: { int n = fs.aspect[ca]; const char* prompt = _("%s for block:"); @@ -1372,6 +1371,7 @@ int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly) case ADJUST_UNDERLINE: case ADJUST_FOREGROUND: case ADJUST_BACKGROUND: + case ADJUST_HASHING: case ADJUST_TRANSPARENT: case ADJUST_LABEL: case ADJUST_LOCK: diff --git a/src/common/main.h b/src/common/main.h index 4ebf165..29c655c 100644 --- a/src/common/main.h +++ b/src/common/main.h @@ -96,7 +96,8 @@ typedef enum K_EDIT_STYLE_EXPR = -64, ADJUST_DIM = -65, ADJUST_ITALIC = -66, - K_ROWHEIGHT = -67 + K_ROWHEIGHT = -67, + ADJUST_HASHING = -68 } Key; extern int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly); diff --git a/src/common/style.c b/src/common/style.c index 74f3c17..c1504f5 100644 --- a/src/common/style.c +++ b/src/common/style.c @@ -16,10 +16,13 @@ const char *FloatFormat_Name[] = const char FloatFormat_Char[] = "Ndsch"; const char *ColorAspect_Name[] = - { [FOREGROUND] = "foreground", [BACKGROUND] = "background" + { [FOREGROUND] = "foreground", [BACKGROUND] = "background", + [HASHING] = "hashing" }; const ColorNum DefaultCN[] = - { [FOREGROUND] = 0, [BACKGROUND] = 16, [NUM_COLOR_ASPECTS] = 255 }; + { [FOREGROUND] = 0, [BACKGROUND] = 16, [HASHING] = 16, + [NUM_COLOR_ASPECTS] = 255 + }; /* clearstyle -- zero out a style */ void clearstyle(Style* s) { diff --git a/src/common/style.h b/src/common/style.h index 6dc5dc5..9ba8dd4 100644 --- a/src/common/style.h +++ b/src/common/style.h @@ -32,7 +32,9 @@ typedef unsigned char ColorNum; #define MAX_MAX_COLORS UCHAR_MAX #define COLOR_FORMAT "%hhu" -typedef enum { FOREGROUND = 0, BACKGROUND, NUM_COLOR_ASPECTS } ColorAspect; +typedef enum + { FOREGROUND = 0, BACKGROUND, HASHING, NUM_COLOR_ASPECTS } + ColorAspect; extern const char *ColorAspect_Name[]; extern const ColorNum DefaultCN[]; diff --git a/src/display.c b/src/display.c index d0c28f8..bbe27cf 100644 --- a/src/display.c +++ b/src/display.c @@ -112,7 +112,9 @@ static int do_attribute(Sheet *cursheet) { const char *typemenu[] = { _("bB)old"), _("dD)im"), _("uU)nderline"), - _("fF)oreground"), _("kBack)ground"), NULL }; + _("fF)oreground"), _("kBack)ground"), _("hH)ashing"), + NULL + }; switch (c = line_menu(prompt, typemenu, 0)) { case -2: case -1: c = K_INVALID; break; @@ -121,6 +123,7 @@ static int do_attribute(Sheet *cursheet) case 2: c = ADJUST_UNDERLINE; break; case 3: c = ADJUST_FOREGROUND; break; case 4: c = ADJUST_BACKGROUND; break; + case 5: c = ADJUST_HASHING; break; default: assert(0); } break; @@ -566,18 +569,33 @@ void redraw_sheet(Sheet *sheet) } else realsize = size; ms = getmarkstate(sheet); - short usecp = 0; + short usecp = -1; + short hashcp = -1; ColorNum fg = sc.aspect[FOREGROUND]; if (fg == NO_COLOR_SET) fg = DefaultCN[FOREGROUND]; ColorNum bg = sc.aspect[BACKGROUND]; if (bg == NO_COLOR_SET) bg = DefaultCN[BACKGROUND]; - while (usecp < curcp) { + ColorNum hg = sc.aspect[HASHING]; + if (hg == NO_COLOR_SET) hg = bg; + for (short trycp = 0; trycp < curcp; ++trycp) { short pfg, pbg; - pair_content(usecp, &pfg, &pbg); - if (fg == pfg && bg == pbg) break; - ++usecp; + pair_content(trycp, &pfg, &pbg); + if (fg != pfg) continue; + if (bg == pbg) usecp = trycp; + if (hg == pbg) hashcp = trycp; + if (usecp >= 0 && hashcp >= 0) break; + } + if (usecp < 0) { + usecp = curcp; + init_pair(curcp++, fg, bg); + } + if (hashcp < 0) { + if (bg == hg) hashcp = usecp; + else { + hashcp = curcp; + init_pair(curcp++, fg, hg); + } } - if (usecp == curcp) init_pair(curcp++, fg, bg); wcolor_set(stdscr, usecp, NULL); bool invert = (ms != UNMARKED) && loc_in_box(tmp, sheet->mark1, sheet->mark2); @@ -587,11 +605,30 @@ void redraw_sheet(Sheet *sheet) if (sc.dim) wattron(stdscr, A_DIM); if (sc.bold) wattron(stdscr, A_BOLD); if (sc.underline) wattron(stdscr, A_UNDERLINE); - (void)mvwaddstr(stdscr, (int)(height + sheet->oriy), - (int)(width + sheet->orix), - buf+cutoff); - for (fill=mbslen(buf+cutoff); filloriy), + (int)(width + sheet->orix), + buf+cutoff); + } else { // Alternate colors to simulate hash + (void)mvwaddch(stdscr, (int)(height + sheet->oriy), + (int)(width + sheet->orix), + (chtype)buf[cutoff]); + for (size_t ix = cutoff+1; buf[ix]; ++ix) { + wcolor_set(stdscr, nextcp, NULL); + if (nextcp == hashcp) nextcp = usecp; + else nextcp = hashcp; + (void)waddch(stdscr, (chtype)buf[ix]); + } + } + for (fill=mbslen(buf+cutoff); filloriy), diff --git a/src/fteapot.fl b/src/fteapot.fl index 7b40a1a..3813330 100644 --- a/src/fteapot.fl +++ b/src/fteapot.fl @@ -171,13 +171,22 @@ class TeapotTable {open : {public Fl_Table}} bool iscurrent = (C == cursheet->cur[X] && R == cursheet->cur[Y]); Style sc = getstyle(cursheet, test); ColorNum bgcn = sc.aspect[BACKGROUND]; + ColorNum hgcn = sc.aspect[HASHING]; if (bgcn == NO_COLOR_SET) bgcn = DefaultCN[BACKGROUND]; Fl_Color cellbg = ((Fl_Color *)(cursheet->palette))[bgcn]; if (selected) cellbg = tpt_selection_version(cellbg); if (!LOC_WITHIN(cursheet,test)) cellbg = fl_color_average(cellbg, FL_BLACK, 0.97f); - fl_draw_box(iscurrent ? FL_BORDER_BOX : FL_THIN_DOWN_BOX, + fl_draw_box(iscurrent ? FL_BORDER_BOX : FL_THIN_DOWN_BOX, xx, yy, W, H, cellbg); + if (hgcn != NO_COLOR_SET) { + // draw the hashes, even if they are background + // since the background might be modified + fl_color(((Fl_Color *)(cursheet->palette))[hgcn]); + for (int hashoff = -H; hashoff < W; hashoff += 8) { + fl_line(xx+hashoff, yy, xx+hashoff+H, yy+H); + } + } if (Fl::focus() == this && iscurrent) draw_focus(FL_BORDER_BOX, xx, yy, W, H); fl_pop_clip(); @@ -658,8 +667,13 @@ class MainWindow {open} MenuItem {} { label {&Background...} user_data ADJUST_BACKGROUND - xywh {0 0 36 21} labelsize 0 divider + xywh {0 0 36 21} labelsize 0 } + MenuItem {} { + label {&Hashing...} + user_data ADJUST_HASHING + xywh {0 0 36 21} labelsize 0 divider + } menuitem dec { label {&Decimal} user_data ADJUST_DECIMAL diff --git a/teapot.1 b/teapot.1 index f5b9fbe..69e9fb8 100644 --- a/teapot.1 +++ b/teapot.1 @@ -84,7 +84,7 @@ Copyright (C) 2009-2012 J\(:org Walter .Me .Pp -Copyright (C) 2019 +Copyright (C) 2019-2023 .Mt glen@studioinfinity.org Glen Whitney .Me