feat: Add hashing color for cells (#93)

Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Reviewed-on: #93
This commit is contained in:
Glen Whitney 2023-07-26 03:21:43 +00:00
parent 8db9c30825
commit 00859ecbd2
11 changed files with 122 additions and 27 deletions

2
NEWS
View File

@ -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 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 change; you may need to wrap comparisons in int() if you are using the result
in a numerical computation.) 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 Variable row height for cells.
o Addition of an if() conditional operator. o Addition of an if() conditional operator.
o Addition of a find() macro to search for a cell satisfying a condition. o Addition of a find() macro to search for a cell satisfying a condition.

View File

@ -167,8 +167,8 @@ Copyright, Contributors and License
teapot teapot
\noun default \noun default
(Table Editor And Planner, Or: Teapot), is copyrighted 19952006 by Michael (Table Editor And Planner, Or: Teapot), is copyrighted 19952006 by Michael
Haardt, and 20092010 by Jörg Walter, and 2019 by Glen Whitney, and is Haardt, and 20092010 by Jörg Walter, and 2019-2023 by Glen Whitney, and
licensed under the Gnu General Public License v3 or later. is licensed under the Gnu General Public License v3 or later.
\end_layout \end_layout
\begin_layout Standard \begin_layout Standard
@ -3994,9 +3994,13 @@ foreground
\family sans \family sans
background background
\family default \family default
() colors used to display a cell may be set. () colors used to display a cell may be set and the
(Currently this only affects screen display.) The value of these attributes \family sans
is a positive integer which acts as an index into the 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 \begin_inset Quotes eld
\end_inset \end_inset
@ -8272,6 +8276,37 @@ is
for example. for example.
\end_layout \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 \begin_layout Description
hexact used as a keyword to the string() function; listed here to record hexact used as a keyword to the string() function; listed here to record
that this identifier may not be used as a cell label. that this identifier may not be used as a cell label.

View File

@ -1089,6 +1089,7 @@ static Token aspect_func(FunctionIdentifier self, int argc, const Token argv[])
{ {
ColorAspect ca = FOREGROUND; ColorAspect ca = FOREGROUND;
if (self == FUNC_BACKGROUND) ca = BACKGROUND; if (self == FUNC_BACKGROUND) ca = BACKGROUND;
if (self == FUNC_HASHING) ca = HASHING;
Token result; Token result;
if (argc != 1 || argv[0].type != INT) { if (argc != 1 || argv[0].type != INT) {
const char *templ = _("Usage: %s(int)"); const char *templ = _("Usage: %s(int)");
@ -1839,6 +1840,7 @@ Tfunc tfunc[]=
[FUNC_PRECISION] = { "precision", precision_func, PREFIX_FUNC, FUNCT, 0 }, [FUNC_PRECISION] = { "precision", precision_func, PREFIX_FUNC, FUNCT, 0 },
[FUNC_FOREGROUND] = { "foreground", aspect_func, PREFIX_FUNC, FUNCT, 0 }, [FUNC_FOREGROUND] = { "foreground", aspect_func, PREFIX_FUNC, FUNCT, 0 },
[FUNC_BACKGROUND] = { "background", 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_JUSTIFY] = { "justify", justify_func, PREFIX_FUNC, FUNCT, 0 },
[FUNC_FLOATFMT] = { "floatfmt", floatfmt_func, PREFIX_FUNC, FUNCT, 0 }, [FUNC_FLOATFMT] = { "floatfmt", floatfmt_func, PREFIX_FUNC, FUNCT, 0 },
[FUNC_SHADOWED] = { "shadowed", shadowed_func, PREFIX_FUNC, FUNCT, 0 }, [FUNC_SHADOWED] = { "shadowed", shadowed_func, PREFIX_FUNC, FUNCT, 0 },

View File

@ -44,6 +44,7 @@ typedef enum
FUNC_FUNCALL, FUNC_LIDENT, FUNC_LOCATION, FUNC_NUMBER, FUNC_OPERATOR, FUNC_FUNCALL, FUNC_LIDENT, FUNC_LOCATION, FUNC_NUMBER, FUNC_OPERATOR,
FUNC_IS, FUNC_FIND, FUNC_PRECISION, FUNC_FOREGROUND, FUNC_BACKGROUND, FUNC_IS, FUNC_FIND, FUNC_PRECISION, FUNC_FOREGROUND, FUNC_BACKGROUND,
FUNC_HASHING,
FUNC_JUSTIFY, FUNC_FLOATFMT, FUNC_SHADOWED, FUNC_TRANSPARENT, FUNC_BOLD, FUNC_JUSTIFY, FUNC_FLOATFMT, FUNC_SHADOWED, FUNC_TRANSPARENT, FUNC_BOLD,
FUNC_UNDERLINE, FUNC_CENTER, FUNC_STYLE, FUNC_UNDERLINE, FUNC_CENTER, FUNC_STYLE,

View File

@ -390,9 +390,8 @@ static void do_attribute(Sheet *cursheet, Key action)
} }
/*}}}*/ /*}}}*/
/* Set a color */ /*{{{*/ /* Set a color */ /*{{{*/
case ADJUST_BACKGROUND: case ADJUST_HASHING: ++ca; /* FALL THROUGH */
ca = BACKGROUND; case ADJUST_BACKGROUND: ++ca; /* FALL THROUGH */
/* FALL THROUGH */
case ADJUST_FOREGROUND: { case ADJUST_FOREGROUND: {
int n = fs.aspect[ca]; int n = fs.aspect[ca];
const char* prompt = _("%s for block:"); const char* prompt = _("%s for block:");
@ -1372,6 +1371,7 @@ int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly)
case ADJUST_UNDERLINE: case ADJUST_UNDERLINE:
case ADJUST_FOREGROUND: case ADJUST_FOREGROUND:
case ADJUST_BACKGROUND: case ADJUST_BACKGROUND:
case ADJUST_HASHING:
case ADJUST_TRANSPARENT: case ADJUST_TRANSPARENT:
case ADJUST_LABEL: case ADJUST_LABEL:
case ADJUST_LOCK: case ADJUST_LOCK:

View File

@ -96,7 +96,8 @@ typedef enum
K_EDIT_STYLE_EXPR = -64, K_EDIT_STYLE_EXPR = -64,
ADJUST_DIM = -65, ADJUST_DIM = -65,
ADJUST_ITALIC = -66, ADJUST_ITALIC = -66,
K_ROWHEIGHT = -67 K_ROWHEIGHT = -67,
ADJUST_HASHING = -68
} Key; } Key;
extern int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly); extern int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly);

View File

@ -16,10 +16,13 @@ const char *FloatFormat_Name[] =
const char FloatFormat_Char[] = "Ndsch"; const char FloatFormat_Char[] = "Ndsch";
const char *ColorAspect_Name[] = const char *ColorAspect_Name[] =
{ [FOREGROUND] = "foreground", [BACKGROUND] = "background" { [FOREGROUND] = "foreground", [BACKGROUND] = "background",
[HASHING] = "hashing"
}; };
const ColorNum DefaultCN[] = 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 */ /* clearstyle -- zero out a style */
void clearstyle(Style* s) { void clearstyle(Style* s) {

View File

@ -32,7 +32,9 @@ typedef unsigned char ColorNum;
#define MAX_MAX_COLORS UCHAR_MAX #define MAX_MAX_COLORS UCHAR_MAX
#define COLOR_FORMAT "%hhu" #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 char *ColorAspect_Name[];
extern const ColorNum DefaultCN[]; extern const ColorNum DefaultCN[];

View File

@ -112,7 +112,9 @@ static int do_attribute(Sheet *cursheet)
{ {
const char *typemenu[] = const char *typemenu[] =
{ _("bB)old"), _("dD)im"), _("uU)nderline"), { _("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)) switch (c = line_menu(prompt, typemenu, 0))
{ {
case -2: case -1: c = K_INVALID; break; 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 2: c = ADJUST_UNDERLINE; break;
case 3: c = ADJUST_FOREGROUND; break; case 3: c = ADJUST_FOREGROUND; break;
case 4: c = ADJUST_BACKGROUND; break; case 4: c = ADJUST_BACKGROUND; break;
case 5: c = ADJUST_HASHING; break;
default: assert(0); default: assert(0);
} }
break; break;
@ -566,18 +569,33 @@ void redraw_sheet(Sheet *sheet)
} }
else realsize = size; else realsize = size;
ms = getmarkstate(sheet); ms = getmarkstate(sheet);
short usecp = 0; short usecp = -1;
short hashcp = -1;
ColorNum fg = sc.aspect[FOREGROUND]; ColorNum fg = sc.aspect[FOREGROUND];
if (fg == NO_COLOR_SET) fg = DefaultCN[FOREGROUND]; if (fg == NO_COLOR_SET) fg = DefaultCN[FOREGROUND];
ColorNum bg = sc.aspect[BACKGROUND]; ColorNum bg = sc.aspect[BACKGROUND];
if (bg == NO_COLOR_SET) bg = DefaultCN[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; short pfg, pbg;
pair_content(usecp, &pfg, &pbg); pair_content(trycp, &pfg, &pbg);
if (fg == pfg && bg == pbg) break; if (fg != pfg) continue;
++usecp; 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); wcolor_set(stdscr, usecp, NULL);
bool invert = bool invert =
(ms != UNMARKED) && loc_in_box(tmp, sheet->mark1, sheet->mark2); (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.dim) wattron(stdscr, A_DIM);
if (sc.bold) wattron(stdscr, A_BOLD); if (sc.bold) wattron(stdscr, A_BOLD);
if (sc.underline) wattron(stdscr, A_UNDERLINE); if (sc.underline) wattron(stdscr, A_UNDERLINE);
short nextcp = hashcp;
if (hashcp == usecp) {
(void)mvwaddstr(stdscr, (int)(height + sheet->oriy), (void)mvwaddstr(stdscr, (int)(height + sheet->oriy),
(int)(width + sheet->orix), (int)(width + sheet->orix),
buf+cutoff); buf+cutoff);
for (fill=mbslen(buf+cutoff); fill<realsize; ++fill) } 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); fill<realsize; ++fill) {
if (usecp != hashcp) {
wcolor_set(stdscr, nextcp, NULL);
if (nextcp == hashcp) nextcp = usecp;
else nextcp = hashcp;
}
(void)waddch(stdscr,(chtype)(unsigned char)' '); (void)waddch(stdscr,(chtype)(unsigned char)' ');
}
for (RowHgtT extra = 1; extra < rows; ++extra) { for (RowHgtT extra = 1; extra < rows; ++extra) {
mvwaddstr(stdscr, mvwaddstr(stdscr,
(int)(height + extra + sheet->oriy), (int)(height + extra + sheet->oriy),

View File

@ -171,6 +171,7 @@ class TeapotTable {open : {public Fl_Table}}
bool iscurrent = (C == cursheet->cur[X] && R == cursheet->cur[Y]); bool iscurrent = (C == cursheet->cur[X] && R == cursheet->cur[Y]);
Style sc = getstyle(cursheet, test); Style sc = getstyle(cursheet, test);
ColorNum bgcn = sc.aspect[BACKGROUND]; ColorNum bgcn = sc.aspect[BACKGROUND];
ColorNum hgcn = sc.aspect[HASHING];
if (bgcn == NO_COLOR_SET) bgcn = DefaultCN[BACKGROUND]; if (bgcn == NO_COLOR_SET) bgcn = DefaultCN[BACKGROUND];
Fl_Color cellbg = ((Fl_Color *)(cursheet->palette))[bgcn]; Fl_Color cellbg = ((Fl_Color *)(cursheet->palette))[bgcn];
if (selected) cellbg = tpt_selection_version(cellbg); if (selected) cellbg = tpt_selection_version(cellbg);
@ -178,6 +179,14 @@ class TeapotTable {open : {public Fl_Table}}
cellbg = fl_color_average(cellbg, FL_BLACK, 0.97f); 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); 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) if (Fl::focus() == this && iscurrent)
draw_focus(FL_BORDER_BOX, xx, yy, W, H); draw_focus(FL_BORDER_BOX, xx, yy, W, H);
fl_pop_clip(); fl_pop_clip();
@ -658,6 +667,11 @@ class MainWindow {open}
MenuItem {} { MenuItem {} {
label {&Background...} label {&Background...}
user_data ADJUST_BACKGROUND user_data ADJUST_BACKGROUND
xywh {0 0 36 21} labelsize 0
}
MenuItem {} {
label {&Hashing...}
user_data ADJUST_HASHING
xywh {0 0 36 21} labelsize 0 divider xywh {0 0 36 21} labelsize 0 divider
} }
menuitem dec { menuitem dec {

View File

@ -84,7 +84,7 @@ Copyright (C) 2009-2012
J\(:org Walter J\(:org Walter
.Me .Me
.Pp .Pp
Copyright (C) 2019 Copyright (C) 2019-2023
.Mt glen@studioinfinity.org .Mt glen@studioinfinity.org
Glen Whitney Glen Whitney
.Me .Me