Add menucolors

-Add a boolean option menucolors to toggle menu color
-Add MENUCOLOR -config file option

TODO:
-Better support for win32
-Support more windowports
-Update Guidebook
-Allow changing menucolor lines in-game
This commit is contained in:
Pasi Kallinen
2015-03-17 22:50:11 +02:00
parent 9f66b234ed
commit c8e781c418
15 changed files with 253 additions and 1 deletions

View File

@@ -219,6 +219,8 @@ NEARDATA struct c_color_names c_color_names = {
"white"
};
struct menucoloring *menu_colorings = NULL;
const char *c_obj_colors[] = {
"black", /* CLR_BLACK */
"red", /* CLR_RED */

View File

@@ -2290,6 +2290,8 @@ int src;
} 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)) {
(void) add_menu_coloring(bufp);
} else if (match_varname(buf, "WARNINGS", 5)) {
(void) get_uchars(fp, buf, bufp, translate, FALSE,
WARNCOUNT, "WARNINGS");

View File

@@ -141,6 +141,7 @@ static struct Bool_Opt
{"mail", (boolean *)0, TRUE, SET_IN_FILE},
#endif
{"mention_walls", &iflags.mention_walls, FALSE, SET_IN_GAME},
{"menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME},
/* for menu debugging only*/
{"menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME},
{"menu_objsyms", &iflags.menu_head_objsym, FALSE, SET_IN_GAME},
@@ -1090,6 +1091,174 @@ STATIC_VAR const struct paranoia_opts {
{ ~0, "all", 3, 0, 0, 0 }, /* ditto */
};
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},
{"grey", 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, '=');
#ifdef MENU_COLOR_REGEX_POSIX
int errnum;
char errbuf[80];
#endif
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
#ifdef MENU_COLOR_REGEX_POSIX
errnum = regcomp(&tmp->match, tmps, REG_EXTENDED | REG_NOSUB);
if (errnum != 0)
{
regerror(errnum, &tmp->match, errbuf, sizeof(errbuf));
err = errbuf;
}
#else
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);
#endif
#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;
}
}
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
# ifdef MENU_COLOR_REGEX_POSIX
if (regexec(&tmpmc->match, str, 0, NULL, 0) == 0) {
# else
if (re_search(&tmpmc->match, str, strlen(str), 0, 9999, 0) >= 0) {
# endif
#else
if (pmatch(tmpmc->match, str)) {
#endif
*color = tmpmc->color;
*attr = tmpmc->attr;
return TRUE;
}
return FALSE;
}
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;
}
}
void
parseoptions(opts, tinitial, tfrom_file)
register char *opts;
@@ -1431,6 +1600,16 @@ boolean tinitial, tfrom_file;
return;
}
/* menucolor:"regex_string"=color */
fullname = "menucolor";
if (match_optname(opts, fullname, 9, TRUE)) {
if (negated) bad_negation(fullname, FALSE);
else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
if (!add_menu_coloring(op))
badoption(opts);
return;
}
fullname = "msghistory";
if (match_optname(opts, fullname, 3, TRUE)) {
if (duplicate) complain_about_duplicate(opts,1);

View File

@@ -1296,6 +1296,7 @@ void
freedynamicdata()
{
unload_qtlist();
free_menu_coloring();
free_invbuf(); /* let_to_name (invent.c) */
free_youbuf(); /* You_buf,&c (pline.c) */
tmp_at(DISP_FREEMEM, 0); /* temporary display effects */