From dd5ca5b058ad145cfbdd3477012b59c0b299c7f3 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Mon, 13 Nov 2023 07:33:48 +0200 Subject: [PATCH] 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 --- doc/Guidebook.mn | 4 +- doc/Guidebook.tex | 5 +- doc/fixes3-7-0.txt | 1 + doc/window.txt | 15 +---- include/extern.h | 1 + include/flag.h | 6 +- include/winX.h | 1 + include/wincurs.h | 4 +- include/wintty.h | 1 + src/apply.c | 2 +- src/artifact.c | 4 +- src/botl.c | 22 +++---- src/cmd.c | 23 ++++--- src/do_name.c | 4 +- src/dungeon.c | 2 +- src/end.c | 5 +- src/insight.c | 6 +- src/invent.c | 6 +- src/nhlua.c | 2 +- src/o_init.c | 6 +- src/options.c | 146 +++++++++++++++++++++++++++++++----------- src/pager.c | 4 +- src/pickup.c | 12 ++-- src/restore.c | 2 +- src/role.c | 12 ++-- src/spell.c | 7 +- src/symbols.c | 2 +- src/teleport.c | 2 +- src/weapon.c | 2 +- win/Qt/qt_bind.cpp | 4 +- win/Qt/qt_menu.cpp | 12 ++-- win/Qt/qt_menu.h | 4 +- win/Qt/qt_win.cpp | 2 +- win/Qt/qt_win.h | 2 +- win/X11/winmenu.c | 7 +- win/curses/cursdial.c | 9 ++- win/curses/cursdial.h | 2 +- win/curses/cursinit.c | 2 +- win/curses/cursinvt.c | 6 +- win/curses/cursmain.c | 6 +- win/curses/cursmesg.c | 2 +- win/curses/cursmisc.c | 6 +- win/curses/curswins.c | 2 +- win/tty/wintty.c | 13 +++- win/win32/mhmenu.c | 8 +++ win/win32/mhmsg.h | 2 +- win/win32/mswproc.c | 3 +- 47 files changed, 251 insertions(+), 150 deletions(-) diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 7386fcd63..2155034f3 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -4071,8 +4071,8 @@ Key to jump to the first page in a menu. Default \(oq\(ha\(cq. .lp menu_headings Controls how the headings in a menu are highlighted. -Values are \(lqnone\(rq, \(lqbold\(rq, \(lqdim\(rq, \(lqitalic\(rq, -\(lqunderline\(rq, \(lqblink\(rq, or \(lqinverse\(rq. +Takes a text attribute, or text color and attribute separated by ampersand. +For allowed attributes and colors, see \(lqConfiguring Menu Colors\(rq. Not all ports can actually display all types. .lp menu_invert_all Key to invert all items in a menu. diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index e8dcfbe78..30d81761e 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -4449,9 +4449,8 @@ Implemented by the Amiga, Gem and tty ports. Default `\verb+^+'. \item[\ib{menu\verb+_+headings}] Controls how the headings in a menu are highlighted. -Values are ``{\tt none}'', ``{\tt bold}'', ``{\tt dim}'', -``{\tt italic}'', ``{\tt underline}'',``{\tt blink}'', or -``{\tt inverse}''. +Takes a text attribute, or text color and attribute separated by ampersand. +For allowed attributes and colors, see ``{\it Configuring Menu Colors\/}``. Not all ports can actually display all types. \item[\ib{menu\verb+_+invert\verb+_+all}] Key to invert all items in a menu. diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index d21cc9652..c4fe8cd5a 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1282,6 +1282,7 @@ docall naming of the monster that currently has the hero swallowed by using their visible interior give missiles thrown or shot by monsters the same chance to get used up upon hitting as when thrown or shot by the hero +change menu_headings to also accept a color or color&attribute Fixes to 3.7.0-x General Problems Exposed Via git Repository diff --git a/doc/window.txt b/doc/window.txt index 271b88294..d6f8fddac 100644 --- a/doc/window.txt +++ b/doc/window.txt @@ -381,20 +381,7 @@ add_menu(windid window, glyphinfo, const anything identifier, char accelerator, If a window-port does not support all of these, it may map unsupported attributes to a supported one (e.g. map them all to ATR_INVERSE). - -- clr color will hold a color value including 24-bit - true color values. To do that, and make it - distinguishable on the windowport side of things, the - windowport needs to treat it as follows: - 0 = not used, just ignore the clr value. - 1-16 = indicates a normal NetHack color value from - 0 - 15, so subtract 1 to get the NetHack - color value. - 17... = indicates a 24-bit RGB color value, so - subtract 17 to get the actual 24-bit - color value. - When placing the values into this parameter, the core - will add 1 to a NetHack color value, and add 17 to a - 24-bit RGB color value. + -- clr is color and is one of the NetHack CLR_ defines. -- str is a pointer to the menu item text. -- itemflags on this item (such as MENU_ITEMFLAGS_SELECTED etc.). diff --git a/include/extern.h b/include/extern.h index 8cfe3ce65..5710f150c 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2090,6 +2090,7 @@ extern void set_playmode(void); extern int sym_val(const char *); extern int query_color(const char *); extern int query_attr(const char *); +extern boolean query_color_attr(color_attr *, const char *); extern const char *clr2colorname(int); extern int match_str2clr(char *); extern int match_str2attr(const char *, boolean); diff --git a/include/flag.h b/include/flag.h index 4b8557793..22cd2b7cc 100644 --- a/include/flag.h +++ b/include/flag.h @@ -186,6 +186,10 @@ struct debug_flags { #endif }; +typedef struct color_and_attr { + int color, attr; +} color_attr; + /* * Stuff that really isn't option or platform related and does not * get saved and restored. They are set and cleared during the game @@ -251,7 +255,7 @@ struct instance_flags { int getpos_coords; /* show coordinates when getting cursor position */ int menuinvertmode; /* 0 = invert toggles every item; 1 = invert skips 'all items' item */ - int menu_headings; /* ATR for menu headings */ + color_attr menu_headings; /* ATR for menu headings */ uint32_t colorcount; /* store how many colors terminal is capable of */ boolean use_truecolor; /* force use of truecolor */ #ifdef ALTMETA diff --git a/include/winX.h b/include/winX.h index 98bf68e9f..a5c845b55 100644 --- a/include/winX.h +++ b/include/winX.h @@ -157,6 +157,7 @@ typedef struct x11_mi { long pick_count; /* specific selection count; -1 if none */ char *str; /* The text of the item. */ int attr; /* Attribute for the line. */ + int color; /* Color for the line. */ boolean selected; /* Been selected? */ boolean preselected; /* in advance? */ unsigned itemflags; /* MENU_ITEMFLAGS_foo */ diff --git a/include/wincurs.h b/include/wincurs.h index ce29d51a6..0cb4fb99f 100644 --- a/include/wincurs.h +++ b/include/wincurs.h @@ -188,7 +188,7 @@ extern int curses_ext_cmd(void); extern void curses_create_nhmenu(winid wid, unsigned long); extern void curses_add_nhmenu_item(winid wid, const glyph_info *, const ANY_P *identifier, char accelerator, - char group_accel, int attr, + char group_accel, int attr, int clr, const char *str, unsigned itemflags); extern void curs_menu_set_bottom_heavy(winid); extern void curses_finalize_nhmenu(winid wid, const char *prompt); @@ -207,7 +207,7 @@ extern void curses_status_update(int, genericptr_t, int, int, int, extern void curs_purge_perminv_data(boolean); extern void curs_update_invt(int); -extern void curs_add_invt(int, char, attr_t, const char *); +extern void curs_add_invt(int, char, attr_t, int, const char *); /* cursinit.c */ diff --git a/include/wintty.h b/include/wintty.h index 87152ff54..96ca71eff 100644 --- a/include/wintty.h +++ b/include/wintty.h @@ -37,6 +37,7 @@ typedef struct tty_mi { long count; /* user count */ char *str; /* description string (including accelerator) */ int attr; /* string attribute */ + int color; /* string color */ boolean selected; /* TRUE if selected by user */ unsigned itemflags; /* item flags */ char selector; /* keyboard accelerator */ diff --git a/src/apply.c b/src/apply.c index 32e7a4faf..7c10e3936 100644 --- a/src/apply.c +++ b/src/apply.c @@ -3622,7 +3622,7 @@ use_grapple(struct obj *obj) anything any; char buf[BUFSZ]; menu_item *selected; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; /* set all bits to zero */ any.a_int = 1; /* use index+1 (cant use 0) as identifier */ diff --git a/src/artifact.c b/src/artifact.c index 7aae6ebd9..5a557541e 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -1072,7 +1072,7 @@ dump_artifact_info(winid tmpwin) char buf[BUFSZ], buf2[BUFSZ]; /* not a menu, but header uses same bold or whatever attribute as such */ - putstr(tmpwin, iflags.menu_headings, "Artifacts"); + putstr(tmpwin, iflags.menu_headings.attr, "Artifacts"); for (m = 1; m <= NROFARTIFACTS; ++m) { Snprintf(buf2, sizeof buf2, "[%s%s%s%s%s%s%s%s%s]", /* 9 bits overall */ @@ -1767,7 +1767,7 @@ arti_invoke(struct obj *obj) d_level newlev; winid tmpwin = create_nhwindow(NHW_MENU); anything any; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; /* set all bits to zero */ start_menu(tmpwin, MENU_BEHAVE_STANDARD); diff --git a/src/botl.c b/src/botl.c index 3517ad2cd..d148e660e 100644 --- a/src/botl.c +++ b/src/botl.c @@ -25,7 +25,7 @@ add_menu_heading(winid tmpwin, const char *buf) anything any = cg.zeroany; add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, - iflags.menu_headings, 0, + iflags.menu_headings.attr, iflags.menu_headings.color, buf, MENU_ITEMFLAGS_NONE); } @@ -35,7 +35,7 @@ add_menu_str(winid tmpwin, const char *buf) anything any = cg.zeroany; add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, - ATR_NONE, 0, + ATR_NONE, NO_COLOR, buf, MENU_ITEMFLAGS_NONE); } @@ -1124,7 +1124,7 @@ cond_menu(void) menu_item *picks = (menu_item *) 0; char mbuf[QBUFSZ]; boolean showmenu = TRUE; - int clr = 0; + int clr = NO_COLOR; boolean changed = FALSE; do { @@ -2465,7 +2465,7 @@ query_arrayvalue( anything any; menu_item *picks = (menu_item *) 0; int adj = (arrmin > 0) ? 1 : arrmax; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -2820,7 +2820,7 @@ query_conditions(void) winid tmpwin; anything any; menu_item *picks = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -3296,7 +3296,7 @@ static char * status_hilite2str(struct hilite_s *hl) { static char buf[BUFSZ]; - int clr = 0, attr = 0; + int clr = NO_COLOR, attr = ATR_NONE; char behavebuf[BUFSZ]; char clrbuf[BUFSZ]; char attrbuf[BUFSZ]; @@ -3381,7 +3381,7 @@ status_hilite_menu_choose_field(void) int i, res, fld = BL_FLUSH; anything any; menu_item *picks = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -3419,7 +3419,7 @@ status_hilite_menu_choose_behavior(int fld) char buf[BUFSZ]; int at; int onlybeh = BL_TH_NONE, nopts = 0; - int clr = 0; + int clr = NO_COLOR; if (fld < 0 || fld >= MAXBLSTATS) return BL_TH_NONE; @@ -3523,7 +3523,7 @@ status_hilite_menu_choose_updownboth( char buf[BUFSZ]; anything any; menu_item *picks = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -4060,7 +4060,7 @@ status_hilite_menu_fld(int fld) struct _status_hilite_line_str *hlstr; char buf[BUFSZ]; boolean acted; - int clr = 0; + int clr = NO_COLOR; if (!count) { if (status_hilite_menu_add(fld)) { @@ -4200,7 +4200,7 @@ status_hilite_menu(void) anything any; boolean redo; int countall; - int clr = 0; + int clr = NO_COLOR; shlmenu_redo: redo = FALSE; diff --git a/src/cmd.c b/src/cmd.c index 179e55480..370494cb1 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -587,7 +587,7 @@ doextlist(void) boolean redisplay = TRUE, search = FALSE; static const char *const headings[] = { "Extended commands", "Debugging Extended Commands" }; - int clr = 0; + int clr = NO_COLOR; searchbuf[0] = '\0'; menuwin = create_nhwindow(NHW_MENU); @@ -778,7 +778,7 @@ extcmd_via_menu(void) int accelerator, prevaccelerator; int matchlevel = 0; boolean wastoolong, one_per_line; - int clr = 0; + int clr = NO_COLOR; ret = 0; cbuf[0] = '\0'; @@ -2006,7 +2006,7 @@ wiz_intrinsic(void) long oldtimeout, newtimeout; const char *propname; menu_item *pick_list = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; win = create_nhwindow(NHW_MENU); @@ -2157,7 +2157,7 @@ doterrain(void) anything any; int n; int which; - int clr = 0; + int clr = NO_COLOR; /* * normal play: choose between known map without mons, obj, and traps @@ -3001,6 +3001,7 @@ handler_rebind_keys_add(boolean keyfirst) char buf[BUFSZ]; char buf2[QBUFSZ]; uchar key = '\0'; + int clr = NO_COLOR; if (keyfirst) { pline("Bind which key? "); @@ -3027,7 +3028,8 @@ handler_rebind_keys_add(boolean keyfirst) } any.a_int = -1; - add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, "nothing: unbind the key", + add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, clr, + "nothing: unbind the key", MENU_ITEMFLAGS_NONE); add_menu_str(win, ""); @@ -3040,7 +3042,7 @@ handler_rebind_keys_add(boolean keyfirst) any.a_int = (i + 1); Sprintf(buf, "%s: %s", ec->ef_txt, ec->ef_desc); - add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, buf, + add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, clr, buf, MENU_ITEMFLAGS_NONE); } if (key) @@ -3096,6 +3098,7 @@ handler_rebind_keys(void) anything any; int i, npick; menu_item *picks = (menu_item *) 0; + int clr = NO_COLOR; redo_rebind: @@ -3104,14 +3107,14 @@ redo_rebind: any = cg.zeroany; any.a_int = 1; - add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, "bind key to a command", + add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, clr, "bind key to a command", MENU_ITEMFLAGS_NONE); any.a_int = 2; - add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, "bind command to a key", + add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, clr, "bind command to a key", MENU_ITEMFLAGS_NONE); if (count_bind_keys()) { any.a_int = 3; - add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, "view changed key binds", + add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, clr, "view changed key binds", MENU_ITEMFLAGS_NONE); } end_menu(win, "Do what?"); @@ -5647,7 +5650,7 @@ static void mcmd_addmenu(winid win, int act, const char *txt) { anything any; - int clr = 0; + int clr = NO_COLOR; /* TODO: fixed letters for the menu entries? */ any = cg.zeroany; diff --git a/src/do_name.c b/src/do_name.c index 9cfff97e9..3d0ddbec2 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -643,7 +643,7 @@ getpos_menu(coord *ccp, int gloc) int i, pick_cnt; menu_item *picks = (menu_item *) 0; char tmpbuf[BUFSZ]; - int clr = 0; + int clr = NO_COLOR; gather_locs(&garr, &gcount, gloc); @@ -1635,7 +1635,7 @@ docallcmd(void) char ch = 0; /* if player wants a,b,c instead of i,o when looting, do that here too */ boolean abc = flags.lootabc; - int clr = 0; + int clr = NO_COLOR; if ((cmdq = cmdq_pop()) != 0) { cq = *cmdq; diff --git a/src/dungeon.c b/src/dungeon.c index d80d5a4d7..b990b362b 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -2281,7 +2281,7 @@ tport_menu( { char tmpbuf[BUFSZ]; anything any; - int clr = 0; + int clr = NO_COLOR; lchoices->lev[lchoices->idx] = lvl_p->dlevel; lchoices->dgn[lchoices->idx] = lvl_p->dnum; diff --git a/src/end.c b/src/end.c index 4f276594d..53e7fcb4a 100644 --- a/src/end.c +++ b/src/end.c @@ -1081,11 +1081,12 @@ disclose(int how, boolean taken) if (c == 'y') { /* save and restore menu_headings in case something like #saveoptions is ever allowed to be run at the very end */ - int save_menu_headings = iflags.menu_headings; + color_attr save_menu_headings = iflags.menu_headings; /* caller has already ID'd everything; we pass 'want_reply=True' to force display_pickinv() to avoid using WIN_INVENT */ - iflags.menu_headings = ATR_NONE; /* don't highlight class hdrs */ + iflags.menu_headings.attr = ATR_NONE; /* don't highlight class hdrs */ + iflags.menu_headings.color = NO_COLOR; (void) display_inventory((char *) 0, TRUE); iflags.menu_headings = save_menu_headings; container_contents(gi.invent, TRUE, TRUE, FALSE); diff --git a/src/insight.c b/src/insight.c index b007cba02..4c95410e3 100644 --- a/src/insight.c +++ b/src/insight.c @@ -2639,7 +2639,7 @@ set_vanq_order(boolean for_vanq) char buf[BUFSZ]; const char *desc; int i, n, choice, - clr = 0; + clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -2760,7 +2760,7 @@ list_vanquished(char defquery, boolean ask) Strcpy(buf, def_monsyms[(int) mlet].explain); /* 'ask' implies final disclosure, where highlighting of various header lines is suppressed */ - putstr(klwin, ask ? ATR_NONE : iflags.menu_headings, + putstr(klwin, ask ? ATR_NONE : iflags.menu_headings.attr, upstart(buf)); prev_mlet = mlet; } @@ -2971,7 +2971,7 @@ list_genocided(char defquery, boolean ask) Strcpy(buf, def_monsyms[(int) mlet].explain); /* 'ask' implies final disclosure, where highlighting of various header lines is suppressed */ - putstr(klwin, ask ? ATR_NONE : iflags.menu_headings, + putstr(klwin, ask ? ATR_NONE : iflags.menu_headings.attr, upstart(buf)); prev_mlet = mlet; } diff --git a/src/invent.c b/src/invent.c index 9d2431898..405601d52 100644 --- a/src/invent.c +++ b/src/invent.c @@ -2763,7 +2763,7 @@ static void ia_addmenu(winid win, int act, char let, const char *txt) { anything any; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; any.a_int = act; @@ -3295,7 +3295,7 @@ display_pickinv( unsigned sortflags; Loot *sortedinvent, *srtinv; boolean wizid = (wizard && iflags.override_ID), gotsomething = FALSE; - int clr = 0, menu_behavior = MENU_BEHAVE_STANDARD; + int clr = NO_COLOR, menu_behavior = MENU_BEHAVE_STANDARD; boolean show_gold = TRUE, inuse_only = FALSE, skipped_gold = FALSE, skipped_noninuse = FALSE, doing_perm_invent = FALSE, save_flags_sortpack = flags.sortpack; @@ -3623,7 +3623,7 @@ display_used_invlets(char avoidlet) winid win; anything any; menu_item *selected; - int clr = 0; + int clr = NO_COLOR; if (gi.invent) { win = create_nhwindow(NHW_MENU); diff --git a/src/nhlua.c b/src/nhlua.c index 78fec779a..79b7c45a1 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -703,7 +703,7 @@ nhl_menu(lua_State *L) winid tmpwin; anything any; menu_item *picks = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; if (argc < 2 || argc > 4) { nhl_error(L, "Wrong args"); diff --git a/src/o_init.c b/src/o_init.c index 61ec1f80d..43b03952a 100644 --- a/src/o_init.c +++ b/src/o_init.c @@ -574,7 +574,7 @@ choose_disco_sort( menu_item *selected; anything any; int i, n, choice; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -820,7 +820,7 @@ doclassdisco(void) *sorted_lines[NUM_OBJECTS]; /* overkill */ int i, ct, dis, xtras, sorted_ct; boolean traditional, alphabetized, lootsort; - int clr = 0; + int clr = NO_COLOR; if (!flags.discosort || !(p = strchr(disco_order_let, flags.discosort))) flags.discosort = 'o'; @@ -1025,7 +1025,7 @@ rename_disco(void) winid tmpwin; anything any; menu_item *selected = 0; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; tmpwin = create_nhwindow(NHW_MENU); diff --git a/src/options.c b/src/options.c index 223a578df..f5ac201fd 100644 --- a/src/options.c +++ b/src/options.c @@ -423,10 +423,10 @@ ask_do_tutorial(void) any = cg.zeroany; any.a_char = 'y'; add_menu(win, &nul_glyphinfo, &any, any.a_char, 0, - ATR_NONE, 0, "Yes, do a tutorial", MENU_ITEMFLAGS_NONE); + ATR_NONE, NO_COLOR, "Yes, do a tutorial", MENU_ITEMFLAGS_NONE); any.a_char = 'n'; add_menu(win, &nul_glyphinfo, &any, any.a_char, 0, - ATR_NONE, 0, "No, just start play", MENU_ITEMFLAGS_NONE); + ATR_NONE, NO_COLOR, "No, just start play", MENU_ITEMFLAGS_NONE); add_menu_str(win, ""); add_menu_str(win, buf); @@ -2090,30 +2090,83 @@ optfn_menu_shift_right(int optidx, int req, boolean negated, /* end of shared key assignments for menu commands */ +static char * +color_attr_to_str(color_attr *ca) +{ + static char buf[BUFSZ]; + + Sprintf(buf, "%s&%s", + clr2colorname(ca->color), + attr2attrname(ca->attr)); + return buf; +} + +/* parse string like "color&attr" into color_attr */ +static boolean +color_attr_parse_str(color_attr *ca, char *str) +{ + char buf[BUFSZ]; + char *amp = NULL; + int tmp, c = NO_COLOR, a = ATR_NONE; + + (void) strncpy(buf, str, sizeof buf - 1); + buf[sizeof buf - 1] = '\0'; + + if ((amp = strchr(buf, '&')) != 0) + *amp = '\0'; + + if (amp) { + amp++; + c = match_str2clr(buf); + a = match_str2attr(amp, TRUE); + /* FIXME: match_str2clr & match_str2attr give config_error_add(), so this is useless */ + if (c >= CLR_MAX && a == -1) { + /* try other way around */ + c = match_str2clr(amp); + a = match_str2attr(buf, TRUE); + } + if (c >= CLR_MAX || a == -1) + return FALSE; + } else { + /* one param only */ + tmp = match_str2attr(buf, FALSE); + if (tmp == -1) { + tmp = match_str2clr(buf); + if (tmp >= CLR_MAX) + return FALSE; + c = tmp; + } else { + a = tmp; + } + } + ca->attr = a; + ca->color = c; + return TRUE; +} + static int optfn_menu_headings(int optidx, int req, boolean negated UNUSED, char *opts, char *op UNUSED) { - int tmpattr; - if (req == do_init) { return optn_ok; } if (req == do_set) { + color_attr ca; + if ((opts = string_for_env_opt(allopt[optidx].name, opts, FALSE)) == empty_optstr) { return optn_err; } - tmpattr = match_str2attr(opts, TRUE); - if (tmpattr == -1) + if (!color_attr_parse_str(&ca, opts)) return optn_err; - iflags.menu_headings = tmpattr; + iflags.menu_headings = ca; return optn_ok; } if (req == get_val || req == get_cnf_val) { if (!opts) return optn_err; - Sprintf(opts, "%s", attr2attrname(iflags.menu_headings)); + Sprintf(opts, "%s", color_attr_to_str(&iflags.menu_headings)); return optn_ok; } if (req == do_handler) { @@ -5316,7 +5369,7 @@ handler_menustyle(void) int i, n, old_menu_style = flags.menu_style; char buf[BUFSZ], sep = iflags.menu_tab_sep ? '\t' : ' '; menu_item *style_pick = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -5356,7 +5409,7 @@ handler_align_misc(int optidx) anything any; menu_item *window_pick = (menu_item *) 0; char abuf[BUFSZ]; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -5398,7 +5451,7 @@ handler_autounlock(int optidx) char buf[BUFSZ], sep = iflags.menu_tab_sep ? '\t' : ' '; menu_item *window_pick = (menu_item *) 0; int i, n, presel, res = optn_ok; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -5455,7 +5508,7 @@ handler_disclose(void) int pick_cnt, pick_idx, opt_idx; char c; menu_item *disclosure_pick = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -5546,10 +5599,10 @@ handler_disclose(void) static int handler_menu_headings(void) { - int mhattr = query_attr("How to highlight menu headings:"); + boolean gotca = query_color_attr(&iflags.menu_headings, + "How to highlight menu headings:"); - if (mhattr != -1) { - iflags.menu_headings = mhattr; + if (gotca) { /* header highlighting affects persistent inventory display */ if (iflags.perm_invent) update_inventory(); @@ -5564,7 +5617,7 @@ handler_msg_window(void) winid tmpwin; anything any; boolean is_tty = WINDOWPORT(tty), is_curses = WINDOWPORT(curses); - int clr = 0; + int clr = NO_COLOR; if (is_tty || is_curses) { /* by Christian W. Cooper */ @@ -5629,7 +5682,7 @@ handler_number_pad(void) "-1 (off, 'z' to move upper-left, 'y' to zap wands)" }; menu_item *mode_pick = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -5685,7 +5738,7 @@ handler_paranoid_confirmation(void) char mkey, mbuf[QBUFSZ], ebuf[BUFSZ], cbuf[QBUFSZ]; const char *explain, *cmdnm; menu_item *paranoia_picks = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -5816,7 +5869,7 @@ handler_pickup_burden(void) int i; const char *burden_name, *burden_letters = "ubsntl"; menu_item *burden_pick = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -5854,7 +5907,7 @@ handler_runmode(void) int i; const char *mode_name; menu_item *mode_pick = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -5882,7 +5935,7 @@ handler_sortloot(void) int i, n; const char *sortl_name; menu_item *sortl_pick = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -5922,7 +5975,7 @@ handler_whatis_coord(void) menu_item *window_pick = (menu_item *) 0; int pick_cnt; char gpc = iflags.getpos_coords; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -5994,7 +6047,7 @@ handler_whatis_filter(void) menu_item *window_pick = (menu_item *) 0; int pick_cnt; char gfilt = iflags.getloc_filter; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -6047,7 +6100,7 @@ handler_autopickup_exception(void) int opt_idx, numapes = 0; char apebuf[2 + BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */ struct autopickup_exception *ape; - int clr = 0; + int clr = NO_COLOR; ape_again: numapes = count_apes(); @@ -6122,7 +6175,7 @@ handler_menu_colors(void) char buf[BUFSZ]; int opt_idx, nmc, mcclr, mcattr; char mcbuf[BUFSZ]; - int clr = 0; + int clr = NO_COLOR; menucolors_again: nmc = count_menucolors(); @@ -6242,7 +6295,7 @@ handler_msgtype(void) const char *mtype; menu_item *pick_list = (menu_item *) 0; struct plinemsg_type *tmp = gp.plinemsg_types; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -6289,7 +6342,7 @@ handler_windowborders(void) int i; const char *mode_name; menu_item *mode_pick = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; static const char *const windowborders_text[] = { "Off, never show borders", "On, always show borders", @@ -6846,7 +6899,8 @@ initoptions_init(void) #endif #endif - iflags.menu_headings = ATR_INVERSE; + iflags.menu_headings.attr = ATR_INVERSE; + iflags.menu_headings.color = NO_COLOR; iflags.getpos_coords = GPCOORDS_NONE; /* hero's role, race, &c haven't been chosen yet */ @@ -7517,7 +7571,7 @@ query_color(const char *prompt) anything any; int i, pick_cnt; menu_item *picks = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; /* replace user patterns with color name ones and force 'menucolors' On */ basic_menu_colors(TRUE); @@ -7570,10 +7624,10 @@ query_attr(const char *prompt) menu_item *picks = (menu_item *) 0; boolean allow_many = (prompt && !strncmpi(prompt, "Choose", 6)); int default_attr = ATR_NONE; - int clr = 0; + int clr = NO_COLOR; if (prompt && strstri(prompt, "menu headings")) - default_attr = iflags.menu_headings; + default_attr = iflags.menu_headings.attr; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); any = cg.zeroany; @@ -7640,6 +7694,22 @@ query_attr(const char *prompt) return -1; } +boolean +query_color_attr(color_attr *ca, const char *prompt) +{ + int c, a; + + c = query_color(prompt); + if (c == -1) + return FALSE; + a = query_attr(prompt); + if (a == -1) + return FALSE; + ca->color = c; + ca->attr = a; + return TRUE; +} + static const struct { const char *name; xint8 msgtyp; @@ -7671,7 +7741,7 @@ query_msgtype(void) anything any; int i, pick_cnt; menu_item *picks = (menu_item *) 0; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -8675,7 +8745,7 @@ doset_simple_menu(void) } any = cg.zeroany; any.a_int = -2 + 1; - add_menu(tmpwin, &nul_glyphinfo, &any, '?', 0, ATR_NONE, 0, + add_menu(tmpwin, &nul_glyphinfo, &any, '?', 0, ATR_NONE, NO_COLOR, gs.simple_options_help ? "hide help" : "show help", MENU_ITEMFLAGS_NONE); @@ -8730,7 +8800,7 @@ doset_simple_menu(void) || allopt[i].idx == opt_pickup_thrown) Strcat(buf, " (for autopickup)"); add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, - ATR_NONE, 0, buf, MENU_ITEMFLAGS_NONE); + ATR_NONE, NO_COLOR, buf, MENU_ITEMFLAGS_NONE); if (gs.simple_options_help && allopt[i].descr) { Sprintf(buf, " %s", allopt[i].descr); add_menu_str(tmpwin, buf); @@ -8870,7 +8940,7 @@ doset(void) /* changing options via menu by Per Liboriussen */ int indexoffset, startpass, endpass; boolean setinitial = FALSE, fromfile = FALSE, gavehelp = FALSE, skiphelp = !iflags.cmdassist; - int clr = 0; + int clr = NO_COLOR; if (iflags.menu_requested) { /* doset_simple() checks for 'm' and calls doset(); clear the @@ -9103,7 +9173,7 @@ doset_add_menu( #ifdef PREFIXES_IN_USE int j; #endif - int clr = 0; + int clr = NO_COLOR; buf2[0] = '\0'; /* per opt functs may not guarantee this, so do it */ any = cg.zeroany; @@ -9292,7 +9362,7 @@ handle_add_list_remove(const char *optname, int numtotal) { 'r', "remove existing %s" }, /* [2] */ { 'x', "exit this menu" }, /* [3] */ }; - int clr = 0; + int clr = NO_COLOR; opt_idx = 0; tmpwin = create_nhwindow(NHW_MENU); @@ -9846,7 +9916,7 @@ choose_classes_menu(const char *prompt, int i, n; int ret; int next_accelerator, accelerator; - int clr = 0; + int clr = NO_COLOR; if (class_list == (char *) 0 || class_select == (char *) 0) return 0; diff --git a/src/pager.c b/src/pager.c index 82cdd1c13..c79c8a88b 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1543,7 +1543,7 @@ do_look(int mode, coord *click_cc) coord cc; /* screen pos of unknown glyph */ boolean save_verbose; /* saved value of flags.verbose */ boolean from_screen; /* question from the screen */ - int clr = 0; + int clr = NO_COLOR; cc.x = 0; cc.y = 0; @@ -2601,7 +2601,7 @@ dohelp(void) menu_item *selected; anything any; int sel; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; /* zero all bits */ start_menu(tmpwin, MENU_BEHAVE_STANDARD); diff --git a/src/pickup.c b/src/pickup.c index e2c3c7064..30fe251e4 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -989,7 +989,7 @@ query_objlist(const char *qstr, /* query string */ unsigned sortflags; glyph_info tmpglyphinfo = nul_glyphinfo; Loot *sortedolist, *srtoli; - int clr = 0; + int clr = NO_COLOR; *pick_list = (menu_item *) 0; if (!olist && !engulfer) @@ -1188,7 +1188,7 @@ query_category( boolean (*ofilter)(OBJ_P) = (boolean (*)(OBJ_P)) 0; boolean do_unpaid = FALSE, do_blessed = FALSE, do_cursed = FALSE, do_uncursed = FALSE, do_buc_unknown = FALSE, verify_All = FALSE; - int num_buc_types = 0, num_justpicked = 0, clr = 0; + int num_buc_types = 0, num_justpicked = 0, clr = NO_COLOR; *pick_list = (menu_item *) 0; if (!olist) @@ -2055,7 +2055,7 @@ doloot_core(void) int prev_inquiry = 0; boolean prev_loot = FALSE; int num_conts = 0; - int clr = 0; + int clr = NO_COLOR; ga.abort_looting = FALSE; @@ -3251,7 +3251,7 @@ in_or_out_menu( char buf[BUFSZ]; int n; const char *menuselector = flags.lootabc ? abc_chars : lootchars; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; win = create_nhwindow(NHW_MENU); @@ -3378,7 +3378,7 @@ dotip(void) anything any; menu_item *pick_list = (menu_item *) 0; struct obj dummyobj, *otmp; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; win = create_nhwindow(NHW_MENU); @@ -3701,7 +3701,7 @@ tipcontainer_gettarget( menu_item *pick_list = (menu_item *) 0; struct obj dummyobj, *otmp; boolean hands_available = TRUE, exclude_it; - int clr = 0; + int clr = NO_COLOR; #if 0 /* [skip potential early return so that menu response is needed * regardless of whether other containers are being carried] */ diff --git a/src/restore.c b/src/restore.c index 6570ddbfc..fe9034be6 100644 --- a/src/restore.c +++ b/src/restore.c @@ -1403,7 +1403,7 @@ restore_menu( char **saved; menu_item *chosen_game = (menu_item *) 0; int k, clet, ch = 0; /* ch: 0 => new game */ - int clr = 0; + int clr = NO_COLOR; *gp.plname = '\0'; saved = get_saved_games(); /* array of character names */ diff --git a/src/role.c b/src/role.c index 690fcd5bb..cbd6ca7c8 100644 --- a/src/role.c +++ b/src/role.c @@ -1811,7 +1811,7 @@ role_menu_extra(int which, winid where, boolean preselect) char buf[BUFSZ]; const char *what = 0, *constrainer = 0, *forcedvalue = 0; int f = 0, r, c, gend, a, i, allowmask; - int clr = 0; + int clr = NO_COLOR; r = flags.initrole; c = flags.initrace; @@ -2192,7 +2192,7 @@ genl_player_setup(int screenheight) boolean getconfirmation, picksomething; winid win = WIN_ERR; menu_item *selected = 0; - int clr = 0; + int clr = NO_COLOR; char pick4u = 'n'; int result = 0; /* assume failure (player chooses to 'quit') */ @@ -2837,7 +2837,7 @@ setup_rolemenu( int i; boolean role_ok; char thisch, lastch = '\0', rolenamebuf[50]; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; /* zero out all bits */ for (i = 0; roles[i].name.m; i++) { @@ -2887,7 +2887,7 @@ setup_racemenu( boolean race_ok; int i; char this_ch; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; for (i = 0; races[i].noun; i++) { @@ -2925,7 +2925,7 @@ setup_gendmenu( boolean gend_ok; int i; char this_ch; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; for (i = 0; i < ROLE_GENDERS; i++) { @@ -2961,7 +2961,7 @@ setup_algnmenu( boolean algn_ok; int i; char this_ch; - int clr = 0; + int clr = NO_COLOR; any = cg.zeroany; for (i = 0; i < ROLE_ALIGNS; i++) { diff --git a/src/spell.c b/src/spell.c index a1ee37071..c8458dc2a 100644 --- a/src/spell.c +++ b/src/spell.c @@ -773,7 +773,8 @@ dowizcast(void) if (n >= SPE_BLANK_PAPER) break; any.a_int = n; - add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, 0, OBJ_NAME(objects[n]), MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, NO_COLOR, + OBJ_NAME(objects[n]), MENU_ITEMFLAGS_NONE); } end_menu(win, "Cast which spell?"); n = select_menu(win, PICK_ONE, &selected); @@ -1664,7 +1665,7 @@ spellsortmenu(void) anything any; char let; int i, n, choice; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); @@ -1753,7 +1754,7 @@ dospellmenu( const char *fmt; menu_item *selected; anything any; - int clr = 0; + int clr = NO_COLOR; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); diff --git a/src/symbols.c b/src/symbols.c index c277c76ab..8e3456c87 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -893,7 +893,7 @@ do_symset(boolean rogueflag) char *symset_name, fmtstr[20]; struct symsetentry *sl; int res, which_set, setcount = 0, chosen = -2, defindx = 0; - int clr = 0; + int clr = NO_COLOR; which_set = rogueflag ? ROGUESET : PRIMARYSET; gs.symset_list = (struct symsetentry *) 0; diff --git a/src/teleport.c b/src/teleport.c index 9400cbc82..5183db45b 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -911,7 +911,7 @@ dotelecmd(void) menu_item *picks = (menu_item *) 0; anything any; winid win; - int i, tmode, clr = 0; + int i, tmode, clr = NO_COLOR; win = create_nhwindow(NHW_MENU); start_menu(win, MENU_BEHAVE_STANDARD); diff --git a/src/weapon.c b/src/weapon.c index 0dc32d81f..3f294aca6 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -1165,7 +1165,7 @@ enhance_weapon_skill(void) anything any; winid win; boolean speedy = FALSE; - int clr = 0; + int clr = NO_COLOR; /* player knows about #enhance, don't show tip anymore */ gc.context.tips[TIP_ENHANCE] = TRUE; diff --git a/win/Qt/qt_bind.cpp b/win/Qt/qt_bind.cpp index a287c19dc..96a727a35 100644 --- a/win/Qt/qt_bind.cpp +++ b/win/Qt/qt_bind.cpp @@ -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); } diff --git a/win/Qt/qt_menu.cpp b/win/Qt/qt_menu.cpp index b98c68b9c..834d91d00 100644 --- a/win/Qt/qt_menu.cpp +++ b/win/Qt/qt_menu.cpp @@ -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) { diff --git a/win/Qt/qt_menu.h b/win/Qt/qt_menu.h index bdb3f83c5..b6134c974 100644 --- a/win/Qt/qt_menu.h +++ b/win/Qt/qt_menu.h @@ -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); diff --git a/win/Qt/qt_win.cpp b/win/Qt/qt_win.cpp index 907d260d0..1e37337ad 100644 --- a/win/Qt/qt_win.cpp +++ b/win/Qt/qt_win.cpp @@ -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"); } diff --git a/win/Qt/qt_win.h b/win/Qt/qt_win.h index ffc10efea..9dce3baec 100644 --- a/win/Qt/qt_win.h +++ b/win/Qt/qt_win.h @@ -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); diff --git a/win/X11/winmenu.c b/win/X11/winmenu.c index 067de1a42..c6eff3af8 100644 --- a/win/X11/winmenu.c +++ b/win/X11/winmenu.c @@ -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) diff --git a/win/curses/cursdial.c b/win/curses/cursdial.c index 78368656d..bf62dcc1b 100644 --- a/win/curses/cursdial.c +++ b/win/curses/cursdial.c @@ -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); } diff --git a/win/curses/cursdial.h b/win/curses/cursdial.h index bda9508d9..977ffa966 100644 --- a/win/curses/cursdial.h +++ b/win/curses/cursdial.h @@ -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); diff --git a/win/curses/cursinit.c b/win/curses/cursinit.c index 26f0b9ecf..65e23c224 100644 --- a/win/curses/cursinit.c +++ b/win/curses/cursinit.c @@ -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); diff --git a/win/curses/cursinvt.c b/win/curses/cursinvt.c index bce148cb0..416b4d77d 100644 --- a/win/curses/cursinvt.c +++ b/win/curses/cursinvt.c @@ -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); } diff --git a/win/curses/cursmain.c b/win/curses/cursmain.c index 0f8db9239..9f46d68eb 100644 --- a/win/curses/cursmain.c +++ b/win/curses/cursmain.c @@ -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); } /* diff --git a/win/curses/cursmesg.c b/win/curses/cursmesg.c index ef207fa62..259187a57 100644 --- a/win/curses/cursmesg.c +++ b/win/curses/cursmesg.c @@ -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 diff --git a/win/curses/cursmisc.c b/win/curses/cursmisc.c index b348194e3..1f70385ab 100644 --- a/win/curses/cursmisc.c +++ b/win/curses/cursmisc.c @@ -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) diff --git a/win/curses/curswins.c b/win/curses/curswins.c index dba94069e..fb76dae93 100644 --- a/win/curses/curswins.c +++ b/win/curses/curswins.c @@ -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); diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 76dd46824..951f0b273 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -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) { diff --git a/win/win32/mhmenu.c b/win/win32/mhmenu.c index 1cabfe025..123b19bf8 100644 --- a/win/win32/mhmenu.c +++ b/win/win32/mhmenu.c @@ -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; } diff --git a/win/win32/mhmsg.h b/win/win32/mhmsg.h index 90413e0cc..54a2e4c3d 100644 --- a/win/win32/mhmsg.h +++ b/win/win32/mhmsg.h @@ -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; diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index aed320e82..02d48b775 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -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;