This is a slightly modified version of Pasi Kallinen menu color patch. The differences are: - Re-worked for use with patchable Nethack. Bones/save compatibility: This patch doesn't affect saved games or bones files. This patch is available at http://www.argon.org/~roderick/nethack/. Roderick Schertler diff -r -X /home/roderick/.diff-exclude -uN base.patchable/README.menucolor work.menu-color/README.menucolor --- base.patchable/README.menucolor 1969-12-31 19:00:00.000000000 -0500 +++ work.menu-color/README.menucolor 2003-03-20 17:29:16.000000000 -0500 @@ -0,0 +1,92 @@ + + This is version 1.1 of the menucolors patch. + + This patch allows the user to define in what color menus are shown. + For example, putting + + OPTIONS=menucolors + MENUCOLOR=" blessed "=green + MENUCOLOR=" holy "=green + MENUCOLOR=" cursed "=red + MENUCOLOR=" unholy "=red + MENUCOLOR=" cursed .* (being worn)"=orange&underline + + in the configuration file makes all known blessed items + show up in green, all cursed items show up in red and + all cursed worn items show up in orange and underlined + when viewing inventory. + + If you do not have GNU regex.h, comment + #define MENU_COLOR_REGEX out from include/config.h + and replace the MENUCOLOR lines in your config file with these: + + MENUCOLOR="* blessed *"=green + MENUCOLOR="* holy *"=green + MENUCOLOR="* cursed *"=red + MENUCOLOR="* unholy *"=red + MENUCOLOR="* cursed * (being worn)"=orange&underline + + + Colors: black, red, green, brown, blue, magenta, cyan, gray, orange, + lightgreen, yellow, lightblue, lightmagenta, lightcyan, white. + Attributes: none, bold, dim, underline, blink, inverse. + + Note that the terminal is free to interpret the attributes however + it wants. + + + TODO/BUGS: + + o Only works with TTY + o You can't use '=' or '&' in the match-string. + o Maybe add color-field to tty_menu_item in include/wintty.h + (so there's no need to find the color for the line again) + o Guidebook is not up to date + o Better place to put the functions, colornames[] and attrnames[]? + o Some menus do not need coloring; maybe add new parameter + to process_menu_window()? + + + FIXES: + + v1.1-patchable: + o Tweak for use with the patchable Nethack patch. + + v1.1: + o Updated to use 3.4.1 codebase. + o replaced USE_REGEX_MATCH with MENU_COLOR_REGEX + + v1.04: + o Oops! 1.03 worked only on *nixes... (GNU regex.h) + o Compile-time option USE_REGEX_MATCH: if it's defined, use regex, + otherwise use globbing. ('?' and '*' wildcards) + + v1.03: + + o Now using Nethack 3.4.0 codebase + o Compile-time option MENU_COLOR + o Strings match using regular expressions instead of globbing + o You can use attribute with color (attr must come after '&') + o Use ``MENUCOLOR="foo"=color'' instead of ``OPTIONS=menucolor=...'' + (Both work, but OPTIONS complains if you define menucolor + more than once) + + v1.02: + + o Should now work with OS/2, thanks to Jukka Lahtinen + o Strings match now using simple globbing. ('?' and '*' wildcards) + + v1.01: + + o Moved 'menucolors' boolean option, so now the options-menu + is in alphabetical order. + o Fixed 'menucolor' description in dat/opthelp. + o menu_colorings is now initialized to null in src/decl.c. + + v1.0: + + o Initial release + +-- + Pasi Kallinen + pkalli@cs.joensuu.fi diff -r -X /home/roderick/.diff-exclude -uN base.patchable/dat/opthelp work.menu-color/dat/opthelp --- base.patchable/dat/opthelp 2003-02-23 09:43:16.000000000 -0500 +++ work.menu-color/dat/opthelp 2003-03-20 17:26:10.000000000 -0500 @@ -71,6 +71,9 @@ color use different colors for objects on screen [TRUE for micros] hilite_pet display pets in a highlighted manner [FALSE] +Boolean option if TEXTCOLOR and MENU_COLOR were set at compile time: +menucolors use different colors for menus [TRUE for micros] + Boolean option if TIMED_DELAY was set at compile time (tty interface only): timed_delay on unix and VMS, use a timer instead of sending extra screen output when attempting to pause for @@ -169,6 +172,21 @@ still denote your gender using the "male" and "female" options, the "gender" option will take precedence. [RANDOM] horsename the name of your first horse [NONE] +menucolor Set colors for menus. (menucolor:"regex_string"=color) + If boolean option ``menucolors'' is true, menus will be shown + with different colors. + For example, setting ``menucolor:" blessed "=green'' shows + all lines in a menu with the text " blessed " in green. + The string is matched using regular expressions. + Valid values for the color are black, red, green, brown, blue, + magenta, cyan, gray, orange, lightgreen, yellow, lightblue, + lightmagenta, lightcyan and white. + You can define menucolor as many times as you wish; those + defined later will take precedence. + Instead of using this with OPTIONS, consider using + MENUCOLOR="regex_string"=color in the configuration file. + Setting menucolor has effect only if TEXTCOLOR and MENU_COLOR + were set at compile time. [NONE] menu_* create single character accelerators for menu commands. Below is a list of all commands. Each is followed by a list of window- ports that implement them: 'x' is X11, 't' is tty, 'g' is Gem, diff -r -X /home/roderick/.diff-exclude -uN base.patchable/include/color.h work.menu-color/include/color.h --- base.patchable/include/color.h 2003-02-23 09:43:19.000000000 -0500 +++ work.menu-color/include/color.h 2003-03-20 17:26:10.000000000 -0500 @@ -5,6 +5,12 @@ #ifndef COLOR_H #define COLOR_H +#ifdef MENU_COLOR +# ifdef MENU_COLOR_REGEX +# include +# endif +#endif + /* * The color scheme used is tailored for an IBM PC. It consists of the * standard 8 colors, folowed by their bright counterparts. There are @@ -49,4 +55,16 @@ #define DRAGON_SILVER CLR_BRIGHT_CYAN #define HI_ZAP CLR_BRIGHT_BLUE +#ifdef MENU_COLOR +struct menucoloring { +# ifdef MENU_COLOR_REGEX + struct re_pattern_buffer match; +# else + char *match; +# endif + int color, attr; + struct menucoloring *next; +}; +#endif + #endif /* COLOR_H */ diff -r -X /home/roderick/.diff-exclude -uN base.patchable/include/config.h work.menu-color/include/config.h --- base.patchable/include/config.h 2003-03-20 16:41:57.000000000 -0500 +++ work.menu-color/include/config.h 2003-03-20 17:27:51.000000000 -0500 @@ -364,6 +364,19 @@ /* * options patch point; see $top/README.patchable */ + +#ifdef TTY_GRAPHICS +# define MENU_COLOR +# define MENU_COLOR_REGEX +/* if MENU_COLOR_REGEX is defined, use regular expressions (GNU regex.h) + * otherwise use pmatch() to match menu color lines. + * pmatch() provides basic globbing: '*' and '?' wildcards. + */ +#endif + +/* + * options patch point; see $top/README.patchable + */ /* * options patch point; see $top/README.patchable */ diff -r -X /home/roderick/.diff-exclude -uN base.patchable/include/extern.h work.menu-color/include/extern.h --- base.patchable/include/extern.h 2003-02-23 09:43:20.000000000 -0500 +++ work.menu-color/include/extern.h 2003-03-20 17:26:10.000000000 -0500 @@ -1380,6 +1380,9 @@ E void FDECL(set_duplicate_opt_detection, (int)); E void FDECL(set_wc_option_mod_status, (unsigned long, int)); E void FDECL(set_option_mod_status, (const char *,int)); +#ifdef MENU_COLOR +E boolean FDECL(add_menu_coloring, (char *)); +#endif /* ### pager.c ### */ diff -r -X /home/roderick/.diff-exclude -uN base.patchable/include/flag.h work.menu-color/include/flag.h --- base.patchable/include/flag.h 2003-03-20 16:41:57.000000000 -0500 +++ work.menu-color/include/flag.h 2003-03-20 17:30:58.000000000 -0500 @@ -267,6 +267,12 @@ /* * real instance_flags patch point; see $top/README.patchable */ +#ifdef MENU_COLOR + boolean use_menu_color; /* use color in menus; only if wc_color */ +#endif + /* + * real instance_flags patch point; see $top/README.patchable + */ /* * real instance_flags patch point; see $top/README.patchable */ diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/decl.c work.menu-color/src/decl.c --- base.patchable/src/decl.c 2003-02-23 09:43:25.000000000 -0500 +++ work.menu-color/src/decl.c 2003-03-20 17:26:10.000000000 -0500 @@ -235,6 +235,10 @@ "white", /* CLR_WHITE */ }; +#ifdef MENU_COLOR +struct menucoloring *menu_colorings = 0; +#endif + struct c_common_strings c_common_strings = { "Nothing happens.", "That's enough tries!", "That is a silly thing to %s.", "shudder for a moment.", diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/files.c work.menu-color/src/files.c --- base.patchable/src/files.c 2003-02-23 09:43:26.000000000 -0500 +++ work.menu-color/src/files.c 2003-03-20 17:26:10.000000000 -0500 @@ -1746,6 +1746,10 @@ } else if (match_varname(buf, "BOULDER", 3)) { (void) get_uchars(fp, buf, bufp, &iflags.bouldersym, TRUE, 1, "BOULDER"); + } else if (match_varname(buf, "MENUCOLOR", 9)) { +#ifdef MENU_COLOR + add_menu_coloring(bufp); +#endif } else if (match_varname(buf, "GRAPHICS", 4)) { len = get_uchars(fp, buf, bufp, translate, FALSE, MAXPCHARS, "GRAPHICS"); diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/options.c work.menu-color/src/options.c --- base.patchable/src/options.c 2003-03-18 20:58:07.000000000 -0500 +++ work.menu-color/src/options.c 2003-03-20 17:26:10.000000000 -0500 @@ -128,6 +128,15 @@ #else {"mail", (boolean *)0, TRUE, SET_IN_FILE}, #endif +#ifdef MENU_COLOR +# ifdef MICRO + {"menucolors", &iflags.use_menu_color, TRUE, SET_IN_GAME}, +# else + {"menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME}, +# endif +#else + {"menucolors", (boolean *)0, FALSE, SET_IN_GAME}, +#endif #ifdef WIZARD /* for menu debugging only*/ {"menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME}, @@ -243,6 +252,7 @@ { "horsename", "the name of your (first) horse (e.g., horsename:Silver)", PL_PSIZ, DISP_IN_GAME }, { "map_mode", "map display mode under Windows", 20, DISP_IN_GAME }, /*WC*/ + { "menucolor", "set menu colors", PL_PSIZ, SET_IN_FILE }, { "menustyle", "user interface for object selection", MENUTYPELEN, SET_IN_GAME }, { "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE }, @@ -946,6 +956,120 @@ } } +#ifdef MENU_COLOR +extern struct menucoloring *menu_colorings; + +static const struct { + const char *name; + const int color; +} colornames[] = { + {"black", CLR_BLACK}, + {"red", CLR_RED}, + {"green", CLR_GREEN}, + {"brown", CLR_BROWN}, + {"blue", CLR_BLUE}, + {"magenta", CLR_MAGENTA}, + {"cyan", CLR_CYAN}, + {"gray", CLR_GRAY}, + {"orange", CLR_ORANGE}, + {"lightgreen", CLR_BRIGHT_GREEN}, + {"yellow", CLR_YELLOW}, + {"lightblue", CLR_BRIGHT_BLUE}, + {"lightmagenta", CLR_BRIGHT_MAGENTA}, + {"lightcyan", CLR_BRIGHT_CYAN}, + {"white", CLR_WHITE} +}; + +static const struct { + const char *name; + const int attr; +} attrnames[] = { + {"none", ATR_NONE}, + {"bold", ATR_BOLD}, + {"dim", ATR_DIM}, + {"underline", ATR_ULINE}, + {"blink", ATR_BLINK}, + {"inverse", ATR_INVERSE} + +}; + +/* parse '"regex_string"=color&attr' and add it to menucoloring */ +boolean +add_menu_coloring(str) +char *str; +{ + int i, c = NO_COLOR, a = ATR_NONE; + struct menucoloring *tmp; + char *tmps, *cs = strchr(str, '='); + const char *err = (char *)0; + + if (!cs || !str) return FALSE; + + tmps = cs; + tmps++; + while (*tmps && isspace(*tmps)) tmps++; + + for (i = 0; i < SIZE(colornames); i++) + if (strstri(tmps, colornames[i].name) == tmps) { + c = colornames[i].color; + break; + } + if ((i == SIZE(colornames)) && (*tmps >= '0' && *tmps <='9')) + c = atoi(tmps); + + if (c > 15) return FALSE; + + tmps = strchr(str, '&'); + if (tmps) { + tmps++; + while (*tmps && isspace(*tmps)) tmps++; + for (i = 0; i < SIZE(attrnames); i++) + if (strstri(tmps, attrnames[i].name) == tmps) { + a = attrnames[i].attr; + break; + } + if ((i == SIZE(attrnames)) && (*tmps >= '0' && *tmps <='9')) + a = atoi(tmps); + } + + *cs = '\0'; + tmps = str; + if ((*tmps == '"') || (*tmps == '\'')) { + cs--; + while (isspace(*cs)) cs--; + if (*cs == *tmps) { + *cs = '\0'; + tmps++; + } + } + + tmp = (struct menucoloring *)alloc(sizeof(struct menucoloring)); +#ifdef MENU_COLOR_REGEX + tmp->match.translate = 0; + tmp->match.fastmap = 0; + tmp->match.buffer = 0; + tmp->match.allocated = 0; + tmp->match.regs_allocated = REGS_FIXED; + err = re_compile_pattern(tmps, strlen(tmps), &tmp->match); +#else + tmp->match = (char *)alloc(strlen(tmps)+1); + (void) memcpy((genericptr_t)tmp->match, (genericptr_t)tmps, strlen(tmps)+1); +#endif + if (err) { + raw_printf("\nMenucolor regex error: %s\n", err); + wait_synch(); + free(tmp); + return FALSE; + } else { + tmp->next = menu_colorings; + tmp->color = c; + tmp->attr = a; + menu_colorings = tmp; + return TRUE; + } +} +#endif /* MENU_COLOR */ + void parseoptions(opts, tinitial, tfrom_file) register char *opts; @@ -1085,6 +1209,18 @@ return; } + /* menucolor:"regex_string"=color */ + fullname = "menucolor"; + if (match_optname(opts, fullname, 9, TRUE)) { +#ifdef MENU_COLOR + if (negated) bad_negation(fullname, FALSE); + else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) + if (!add_menu_coloring(op)) + badoption(opts); +#endif + return; + } + fullname = "msghistory"; if (match_optname(opts, fullname, 3, TRUE)) { op = string_for_env_opt(fullname, opts, negated); diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/save.c work.menu-color/src/save.c --- base.patchable/src/save.c 2003-02-23 09:43:30.000000000 -0500 +++ work.menu-color/src/save.c 2003-03-20 17:26:10.000000000 -0500 @@ -48,6 +48,10 @@ #define HUP #endif +#ifdef MENU_COLOR +extern struct menucoloring *menu_colorings; +#endif + /* need to preserve these during save to avoid accessing freed memory */ static unsigned ustuck_id = 0, usteed_id = 0; @@ -953,12 +957,35 @@ return; } +#ifdef MENU_COLOR +void +free_menu_coloring() +{ + struct menucoloring *tmp = menu_colorings; + + while (tmp) { + struct menucoloring *tmp2 = tmp->next; +# ifdef MENU_COLOR_REGEX + (void) regfree(&tmp->match); +# else + free(tmp->match); +# endif + free(tmp); + tmp = tmp2; + } + return; +} +#endif + void freedynamicdata() { unload_qtlist(); free_invbuf(); /* let_to_name (invent.c) */ free_youbuf(); /* You_buf,&c (pline.c) */ +#ifdef MENU_COLOR + free_menu_coloring(); +#endif tmp_at(DISP_FREEMEM, 0); /* temporary display effects */ #ifdef FREE_ALL_MEMORY # define freeobjchn(X) (saveobjchn(0, X, FREE_SAVE), X = 0) diff -r -X /home/roderick/.diff-exclude -uN base.patchable/util/makedefs.c work.menu-color/util/makedefs.c --- base.patchable/util/makedefs.c 2003-03-20 16:41:56.000000000 -0500 +++ work.menu-color/util/makedefs.c 2003-03-20 17:29:44.000000000 -0500 @@ -752,6 +752,12 @@ /* * patch list patch point; see $top/README.patchable */ +#ifdef MENU_COLOR + "patch: menu color v1.1-patchable", +#endif + /* + * patch list patch point; see $top/README.patchable + */ /* * patch list patch point; see $top/README.patchable */ diff -r -X /home/roderick/.diff-exclude -uN base.patchable/win/tty/wintty.c work.menu-color/win/tty/wintty.c --- base.patchable/win/tty/wintty.c 2003-02-23 09:43:46.000000000 -0500 +++ work.menu-color/win/tty/wintty.c 2003-03-20 17:26:10.000000000 -0500 @@ -124,6 +124,10 @@ static char winpanicstr[] = "Bad window id %d"; char defmorestr[] = "--More--"; +#ifdef MENU_COLOR +extern struct menucoloring *menu_colorings; +#endif + #ifdef CLIPPING # if defined(USE_TILES) && defined(MSDOS) boolean clipping = FALSE; /* clipping on? */ @@ -1121,6 +1125,28 @@ } } +#ifdef MENU_COLOR +STATIC_OVL boolean +get_menu_coloring(str, color, attr) +char *str; +int *color, *attr; +{ + struct menucoloring *tmpmc; + if (iflags.use_menu_color) + for (tmpmc = menu_colorings; tmpmc; tmpmc = tmpmc->next) +# ifdef MENU_COLOR_REGEX + if (re_search(&tmpmc->match, str, strlen(str), 0, 9999, 0) >= 0) { +# else + if (pmatch(tmpmc->match, str)) { +# endif + *color = tmpmc->color; + *attr = tmpmc->attr; + return TRUE; + } + return FALSE; +} +#endif /* MENU_COLOR */ + STATIC_OVL void process_menu_window(window, cw) winid window; @@ -1197,6 +1223,10 @@ for (page_lines = 0, curr = page_start; curr != page_end; page_lines++, curr = curr->next) { +#ifdef MENU_COLOR + int color = NO_COLOR, attr = ATR_NONE; + boolean menucolr = FALSE; +#endif if (curr->selector) *rp++ = curr->selector; @@ -1212,6 +1242,13 @@ * actually output the character. We're faster doing * this. */ +#ifdef MENU_COLOR + if (iflags.use_menu_color && + (menucolr = get_menu_coloring(curr->str, &color,&attr))) { + term_start_attr(attr); + if (color != NO_COLOR) term_start_color(color); + } else +#endif term_start_attr(curr->attr); for (n = 0, cp = curr->str; *cp && (int) ++ttyDisplay->curx < (int) ttyDisplay->cols; @@ -1224,6 +1261,12 @@ (void) putchar('#'); /* count selected */ } else (void) putchar(*cp); +#ifdef MENU_COLOR + if (iflags.use_menu_color && menucolr) { + if (color != NO_COLOR) term_end_color(); + term_end_attr(attr); + } else +#endif term_end_attr(curr->attr); } } else {