Change menu_headings to accept color and attribute

Instead of just accepting an attribute, it's now possible to
use a color, or both color and attribute, for example:

OPTIONS=menu_headings:inverse
OPTIONS=menu_headings:red
OPTIONS=menu_headings:red&underline

Default is still just inverse.
This lets the player change the menu heading color without
needing to use menu colors for them.

Also makes it so the core uses NO_COLOR instead of 0, for all
the menu lines which don't have any prefedefined color.

Tested for tty, curses, x11, qt, and win32
This commit is contained in:
Pasi Kallinen
2023-11-13 07:33:48 +02:00
parent dd6c249a8c
commit dd5ca5b058
47 changed files with 251 additions and 150 deletions

View File

@@ -471,11 +471,11 @@ void NetHackQtBind::qt_start_menu(winid wid, unsigned long mbehavior UNUSED)
}
void NetHackQtBind::qt_add_menu(winid wid, const glyph_info *glyphinfo,
const ANY_P * identifier, char ch, char gch, int attr, int clr UNUSED,
const ANY_P * identifier, char ch, char gch, int attr, int clr,
const char *str, unsigned itemflags)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->AddMenu(glyphinfo->glyph, identifier, ch, gch, attr,
window->AddMenu(glyphinfo->glyph, identifier, ch, gch, attr, clr,
QString::fromLatin1(str),
itemflags);
}

View File

@@ -258,7 +258,7 @@ NetHackQtMenuWindow::MenuItem::~MenuItem()
}
void NetHackQtMenuWindow::AddMenu(int glyph, const ANY_P *identifier,
char ch, char gch, int attr,
char ch, char gch, int attr, int clr,
const QString& str, unsigned itemflags)
{
bool presel = (itemflags & MENU_ITEMFLAGS_SELECTED) != 0;
@@ -279,11 +279,11 @@ void NetHackQtMenuWindow::AddMenu(int glyph, const ANY_P *identifier,
itemlist[itemcount].ch = ch;
itemlist[itemcount].gch = gch;
itemlist[itemcount].attr = attr;
itemlist[itemcount].color = clr;
itemlist[itemcount].str = str;
itemlist[itemcount].selected = itemlist[itemcount].preselected = presel;
itemlist[itemcount].itemflags = itemflags;
itemlist[itemcount].count = -1L;
itemlist[itemcount].color = -1;
// Display the boulder symbol correctly
if (str.left(8) == "boulder\t") {
int bracket = str.indexOf('[');
@@ -294,7 +294,7 @@ void NetHackQtMenuWindow::AddMenu(int glyph, const ANY_P *identifier,
}
}
int mcolor, mattr;
if (attr == 0 && ::iflags.use_menu_color
if (::iflags.use_menu_color
&& get_menu_coloring(str.toLatin1().constData(), &mcolor, &mattr)) {
itemlist[itemcount].attr = mattr;
itemlist[itemcount].color = mcolor;
@@ -618,7 +618,7 @@ void NetHackQtMenuWindow::AddRow(int row, const MenuItem& mi)
table->item(row, 4)->setFlags(Qt::ItemIsEnabled);
WidenColumn(4, fm.QFM_WIDTH(text));
if ((int) mi.color != -1) {
if ((int) mi.color != NO_COLOR) {
twi->setForeground(colors[mi.color].q);
}
@@ -1344,13 +1344,13 @@ void NetHackQtMenuOrTextWindow::StartMenu(bool using_WIN_INVEN)
}
void NetHackQtMenuOrTextWindow::AddMenu(
int glyph, const ANY_P* identifier,
char ch, char gch, int attr,
char ch, char gch, int attr, int clr,
const QString& str, unsigned itemflags)
{
if (!actual)
MenuOrText_too_soon_warning("AddMenu");
else
actual->AddMenu(glyph, identifier, ch, gch, attr, str, itemflags);
actual->AddMenu(glyph, identifier, ch, gch, attr, clr, str, itemflags);
}
void NetHackQtMenuOrTextWindow::EndMenu(const QString& prompt)
{

View File

@@ -58,7 +58,7 @@ public:
virtual void StartMenu(bool using_WIN_INVEN = false);
virtual void AddMenu(int glyph, const ANY_P *identifier,
char ch, char gch, int attr,
char ch, char gch, int attr, int clr,
const QString& str, unsigned itemflags);
virtual void EndMenu(const QString& prompt);
virtual int SelectMenu(int how, MENU_ITEM_P **menu_list);
@@ -195,7 +195,7 @@ public:
// Menu
virtual void StartMenu(bool using_WIN_INVENT = false);
virtual void AddMenu(int glyph, const ANY_P *identifier,
char ch, char gch, int attr,
char ch, char gch, int attr, int clr,
const QString& str, unsigned itemflags);
virtual void EndMenu(const QString& prompt);
virtual int SelectMenu(int how, MENU_ITEM_P **menu_list);

View File

@@ -103,7 +103,7 @@ void NetHackQtWindow::PutStr(int attr UNUSED, const QString& text UNUSED) { puts
void NetHackQtWindow::StartMenu(bool using_WIN_INVEN UNUSED)
{ puts("unexpected StartMenu"); }
void NetHackQtWindow::AddMenu(int glyph UNUSED, const ANY_P* identifier UNUSED,
char ch UNUSED, char gch UNUSED, int attr UNUSED,
char ch UNUSED, char gch UNUSED, int attr UNUSED, int clr UNUSED,
const QString& str UNUSED, unsigned itemflags UNUSED)
{ puts("unexpected AddMenu"); }
void NetHackQtWindow::EndMenu(const QString& prompt UNUSED) { puts("unexpected EndMenu"); }

View File

@@ -37,7 +37,7 @@ public:
}
virtual void StartMenu(bool using_WIN_INVEN = false);
virtual void AddMenu(int glyph, const ANY_P* identifier,
char ch, char gch, int attr,
char ch, char gch, int attr, int clr,
const QString& str, unsigned itemflags);
virtual void EndMenu(const QString& prompt);
virtual int SelectMenu(int how, MENU_ITEM_P **menu_list);

View File

@@ -794,7 +794,7 @@ X11_add_menu(winid window,
char ch, /* selector letter; 0 if not selectable */
char gch, /* group accelerator (0 = no group) */
int attr,
int clr UNUSED,
int clr,
const char *str,
unsigned itemflags)
{
@@ -813,6 +813,7 @@ X11_add_menu(winid window,
item->next = (x11_menu_item *) 0;
item->identifier = *identifier;
item->attr = attr;
item->color = clr;
item->itemflags = itemflags;
item->selected = item->preselected = preselected;
item->pick_count = -1L;
@@ -1314,8 +1315,10 @@ menu_create_entries(struct xwindow *wp, struct menu *curr_menu)
XtSetArg(args[num_args], nhStr(XtNvertDistance), 0); num_args++;
if (!iflags.use_menu_color || wp->menu_information->disable_mcolors
|| !get_menu_coloring(curr->str, &color, &attr))
|| !get_menu_coloring(curr->str, &color, &attr)) {
attr = curr->attr;
color = curr->color;
}
if (color != NO_COLOR) {
if (attr != ATR_INVERSE)

View File

@@ -34,6 +34,7 @@ typedef struct nhmi {
char accelerator; /* Character used to select item from menu */
char group_accel; /* Group accelerator for menu item, if any */
int attr; /* Text attributes for item */
int color; /* Color for item */
const char *str; /* Text of menu item */
boolean presel; /* Whether menu item should be preselected */
boolean selected; /* Whether item is currently selected */
@@ -585,7 +586,8 @@ curs_new_menu_item(winid wid, const char *str)
new_item->identifier = cg.zeroany;
new_item->accelerator = '\0';
new_item->group_accel = '\0';
new_item->attr = 0;
new_item->attr = ATR_NONE;
new_item->color = NO_COLOR;
new_item->str = new_str;
new_item->presel = FALSE;
new_item->selected = FALSE;
@@ -607,6 +609,7 @@ curses_add_nhmenu_item(
char accelerator,
char group_accel,
int attr,
int clr,
const char *str,
unsigned itemflags)
{
@@ -630,6 +633,7 @@ curses_add_nhmenu_item(
new_item->accelerator = accelerator;
new_item->group_accel = group_accel;
new_item->attr = attr;
new_item->color = clr;
new_item->presel = presel;
new_item->itemflags = itemflags;
current_items = current_menu->entries;
@@ -1204,7 +1208,9 @@ menu_display_page(
for (count = 0; count < num_lines; count++) {
tmpstr = curses_break_str(menu->prompt, menu->width, count + 1);
curses_toggle_color_attr(win, NO_COLOR, A_NORMAL, ON);
mvwprintw(win, count + 1, 1, "%s", tmpstr);
curses_toggle_color_attr(win, NO_COLOR, A_NORMAL, OFF);
free(tmpstr);
}
}
@@ -1284,6 +1290,7 @@ menu_display_page(
curses_menu_color_attr(win, color, attr, ON);
} else {
attr = menu_item_ptr->attr;
color = menu_item_ptr->color;
if (color != NONE || attr != A_NORMAL)
curses_toggle_color_attr(win, color, attr, ON);
}

View File

@@ -15,7 +15,7 @@ int curses_ext_cmd(void);
void curses_create_nhmenu(winid wid, unsigned long);
void curses_add_nhmenu_item(winid wid, const glyph_info *glyphinfo,
const ANY_P *identifier, char accelerator,
char group_accel, int attr,
char group_accel, int attr, int clr,
const char *str, unsigned itemflags);
void curs_menu_set_bottom_heavy(winid);
void curses_finalize_nhmenu(winid wid, const char *prompt);

View File

@@ -689,7 +689,7 @@ curses_character_dialog(const char **choices, const char *prompt)
anything identifier;
menu_item *selected = NULL;
winid wid = curses_get_wid(NHW_MENU);
int clr = 0;
int clr = NO_COLOR;
identifier.a_void = 0;
curses_start_menu(wid, MENU_BEHAVE_STANDARD);

View File

@@ -22,6 +22,7 @@ static void curs_show_invt(WINDOW *);
struct pi_line {
char *invtxt; /* class header or inventory item without letter prefix */
attr_t c_attr; /* attribute for class headers */
int color;
char letter; /* inventory letter; accelerator if this was really a menu;
* used to distinguish item lines from header lines and for
* display (no selection possible) */
@@ -290,6 +291,7 @@ curs_add_invt(
int linenum, /* line index; 1..n rather than 0..n-1 */
char accelerator, /* selector letter for items, 0 for class headers */
attr_t attr, /* curses attribute for headers, 0 for items */
int clr, /* NetHack color for headers, NO_COLOR for items */
const char *str) /* formatted inventory item, without invlet prefix,
* or class header text */
{
@@ -309,6 +311,7 @@ curs_add_invt(
newelement.invtxt = dupstr(str);
newelement.c_attr = attr; /* note: caller has already converted 'attr'
* from tty-style attribute to curses one */
newelement.color = clr;
newelement.letter = accelerator;
aptr[pi.inuseindx++] = newelement;
@@ -373,7 +376,7 @@ curs_show_invt(WINDOW *win)
str = pi.array[lineno].invtxt;
accelerator = pi.array[lineno].letter;
attr = pi.array[lineno].c_attr;
color = NO_COLOR;
color = pi.array[lineno].color;
if (accelerator)
++item_count;
@@ -413,7 +416,6 @@ curs_show_invt(WINDOW *win)
/* only perform menu coloring on item entries, not subtitles */
if (iflags.use_menu_color) {
attr = 0;
get_menu_coloring(str, &color, (int *) &attr);
attr = curses_convert_attr(attr);
}

View File

@@ -682,7 +682,7 @@ void
curses_add_menu(winid wid, const glyph_info *glyphinfo,
const ANY_P *identifier,
char accelerator, char group_accel, int attr,
int clr UNUSED, const char *str, unsigned itemflags)
int clr, const char *str, unsigned itemflags)
{
int curses_attr;
@@ -694,14 +694,14 @@ curses_add_menu(winid wid, const glyph_info *glyphinfo,
/* persistent inventory window; nothing is selectable;
omit glyphinfo because perm_invent is to the side of
the map so usually cramped for horizontal space */
curs_add_invt(inv_update, accelerator, curses_attr, str);
curs_add_invt(inv_update, accelerator, curses_attr, clr, str);
inv_update++;
return;
}
curses_add_nhmenu_item(wid, glyphinfo, identifier,
accelerator, group_accel,
curses_attr, str, itemflags);
curses_attr, clr, str, itemflags);
}
/*

View File

@@ -488,7 +488,7 @@ curses_prev_mesg(void)
boolean do_lifo = (iflags.prevmsg_window != 'f');
#ifdef DEBUG
static int showturn = 0; /* 1: show hero_seq value in separators */
int clr = 0;
int clr = NO_COLOR;
/*
* Set DEBUGFILES=MesgTurn in environment or sysconf to decorate

View File

@@ -78,6 +78,10 @@ curses_read_char(void)
void
curses_toggle_color_attr(WINDOW *win, int color, int attr, int onoff)
{
if (color == NO_COLOR)
color = NONE;
if (attr == ATR_NONE)
attr = NONE;
#ifdef TEXTCOLOR
int curses_color;
@@ -661,7 +665,7 @@ curses_view_file(const char *filename, boolean must_exist)
char buf[BUFSZ];
menu_item *selected = NULL;
dlb *fp = dlb_fopen(filename, "r");
int clr = 0;
int clr = NO_COLOR;
if (fp == NULL) {
if (must_exist)

View File

@@ -534,7 +534,7 @@ curses_puts(winid wid, int attr, const char *text)
}
Id = cg.zeroany;
curses_add_nhmenu_item(wid, &nul_glyphinfo, &Id, 0, 0,
attr, text, MENU_ITEMFLAGS_NONE);
attr, NO_COLOR, text, MENU_ITEMFLAGS_NONE);
} else {
waddstr(win, text);
wnoutrefresh(win);

View File

@@ -1170,8 +1170,12 @@ set_item_state(
HUPSKIP();
tty_curs(window, 4, lineno);
term_start_attr(item->attr);
if (item->color != NO_COLOR)
term_start_color(item->color);
(void) putchar(ch);
ttyDisplay->curx++;
if (item->color != NO_COLOR)
term_end_color();
term_end_attr(item->attr);
}
@@ -1412,8 +1416,10 @@ process_menu_window(winid window, struct WinDesc *cw)
++ttyDisplay->curx;
if (!iflags.use_menu_color
|| !get_menu_coloring(curr->str, &color, &attr))
|| !get_menu_coloring(curr->str, &color, &attr)) {
attr = curr->attr;
color = curr->color;
}
/* which character to start attribute highlighting;
whole line for headers and such, after the selector
@@ -2514,7 +2520,7 @@ tty_add_menu(
char ch, /* selector letter (0 = pick our own) */
char gch, /* group accelerator (0 = no group) */
int attr, /* attribute for string (like tty_putstr()) */
int clr UNUSED, /* color for string */
int clr, /* color for string */
const char *str, /* menu string */
unsigned int itemflags) /* itemflags such as MENU_ITEMFLAGS_SELECTED */
{
@@ -2564,6 +2570,7 @@ tty_add_menu(
item->selector = ch;
item->gselector = gch;
item->attr = attr;
item->color = clr;
item->str = dupstr(newstr);
item->next = cw->mlist;
@@ -2601,7 +2608,7 @@ tty_end_menu(
short len;
int lmax, n;
char menu_ch;
int clr = 0;
int clr = NO_COLOR;
if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0
|| cw->type != NHW_MENU) {

View File

@@ -32,6 +32,7 @@ typedef struct mswin_menu_item {
char accelerator;
char group_accel;
int attr;
int color;
char str[NHMENU_STR_SIZE];
boolean presel;
unsigned int itemflags;
@@ -623,6 +624,7 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
data->menui.menu.items[new_item].accelerator = msg_data->accelerator;
data->menui.menu.items[new_item].group_accel = msg_data->group_accel;
data->menui.menu.items[new_item].attr = msg_data->attr;
data->menui.menu.items[new_item].color = msg_data->color;
strncpy(data->menui.menu.items[new_item].str, msg_data->str,
NHMENU_STR_SIZE);
/* prevent & being interpreted as a mnemonic start */
@@ -1072,6 +1074,12 @@ onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
}
x += tm.tmAveCharWidth + tm.tmOverhang + spacing;
} else {
/* heading */
if (iflags.use_menu_color) {
color = item->color;
if (color != NO_COLOR)
(void) SetTextColor(lpdis->hDC, nhcolor_to_RGB(color));
}
x += tileXScaled + tm.tmAveCharWidth + tm.tmOverhang + 2 * spacing;
}

View File

@@ -54,7 +54,7 @@ typedef struct mswin_nhmsg_add_menu {
char accelerator;
char group_accel;
int attr;
int clr;
int color;
const char *str;
boolean presel;
unsigned int itemflags;

View File

@@ -337,7 +337,7 @@ prompt_for_player_selection(void)
anything any;
menu_item *selected = 0;
DWORD box_result;
int clr = 0;
int clr = NO_COLOR;
logDebug("prompt_for_player_selection()\n");
@@ -1156,6 +1156,7 @@ mswin_add_menu(winid wid, const glyph_info *glyphinfo,
data.accelerator = accelerator;
data.group_accel = group_accel;
data.attr = attr;
data.color = clr;
data.str = str;
data.presel = presel;
data.itemflags = itemflags;