Allow changing menucolors in-game via Options

This commit is contained in:
Pasi Kallinen
2015-04-27 17:45:40 +03:00
parent 4fa3c39b55
commit eecd19caa9
2 changed files with 268 additions and 54 deletions

View File

@@ -53,6 +53,7 @@
struct menucoloring { struct menucoloring {
struct nhregex *match; struct nhregex *match;
char *origstr;
int color, attr; int color, attr;
struct menucoloring *next; struct menucoloring *next;
}; };

View File

@@ -498,6 +498,13 @@ STATIC_OVL boolean FDECL(is_wc2_option, (const char *));
STATIC_OVL boolean FDECL(wc2_supported, (const char *)); STATIC_OVL boolean FDECL(wc2_supported, (const char *));
STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *)); STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *));
STATIC_OVL int FDECL(count_ape_maps, (int *, int *)); STATIC_OVL int FDECL(count_ape_maps, (int *, int *));
STATIC_DCL const char *FDECL(clr2colorname, (int));
STATIC_DCL const char *FDECL(attr2attrname, (int));
STATIC_DCL int NDECL(query_color);
STATIC_DCL int NDECL(query_attr);
STATIC_DCL boolean FDECL(add_menu_coloring_parsed, (char *, int, int));
STATIC_DCL void FDECL(free_one_menu_coloring, (int));
STATIC_DCL int NDECL(count_menucolors);
void void
@@ -1163,6 +1170,108 @@ static const struct {
{"inverse", ATR_INVERSE} {"inverse", ATR_INVERSE}
}; };
const char *
clr2colorname(clr)
int clr;
{
int i;
for (i = 0; i < SIZE(colornames); i++)
if (colornames[i].color == clr)
return colornames[i].name;
return NULL;
}
const char *
attr2attrname(attr)
int attr;
{
int i;
for (i = 0; i < SIZE(attrnames); i++)
if (attrnames[i].attr == attr)
return attrnames[i].name;
return NULL;
}
int
query_color()
{
winid tmpwin;
anything any;
int i, pick_cnt;
menu_item *picks = (menu_item *)0;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
any = zeroany;
for (i = 0; i < SIZE(colornames); i++) {
any.a_int = i + 1;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, colornames[i].name, MENU_UNSELECTED);
}
end_menu(tmpwin, "Pick a color");
pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
destroy_nhwindow(tmpwin);
if (pick_cnt > 0) {
i = colornames[picks->item.a_int - 1].color;
free((genericptr_t)picks);
return i;
}
return -1;
}
int
query_attr()
{
winid tmpwin;
anything any;
int i, pick_cnt;
menu_item *picks = (menu_item *)0;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
any = zeroany;
for (i = 0; i < SIZE(attrnames); i++) {
any.a_int = i + 1;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr, attrnames[i].name, MENU_UNSELECTED);
}
end_menu(tmpwin, "Pick an attribute");
pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
destroy_nhwindow(tmpwin);
if (pick_cnt > 0) {
i = attrnames[picks->item.a_int - 1].attr;
free((genericptr_t)picks);
return i;
}
return -1;
}
boolean
add_menu_coloring_parsed(str, c, a)
char *str;
int c, a;
{
struct menucoloring *tmp;
if (!str) return FALSE;
tmp = (struct menucoloring *)alloc(sizeof(struct menucoloring));
tmp->match = regex_init();
if (!regex_compile(str, tmp->match)) {
static const char *re_error = "Menucolor regex error";
if (!iflags.window_inited)
raw_printf("\n%s: %s\n", re_error, regex_error_desc(tmp->match));
else
pline("%s: %s", re_error, regex_error_desc(tmp->match));
wait_synch();
free(tmp);
return FALSE;
} else {
tmp->next = menu_colorings;
tmp->origstr = dupstr(str);
tmp->color = c;
tmp->attr = a;
menu_colorings = tmp;
return TRUE;
}
}
/* parse '"regex_string"=color&attr' and add it to menucoloring */ /* parse '"regex_string"=color&attr' and add it to menucoloring */
boolean boolean
add_menu_coloring(str) add_menu_coloring(str)
@@ -1212,20 +1321,7 @@ char *str;
} }
} }
tmp = (struct menucoloring *)alloc(sizeof(struct menucoloring)); return add_menu_coloring_parsed(tmps, c, a);
tmp->match = regex_init();
if (!regex_compile(tmps, tmp->match)) {
raw_printf("\nMenucolor regex error: %s\n", regex_error_desc(tmp->match));
wait_synch();
free(tmp);
return FALSE;
} else {
tmp->next = menu_colorings;
tmp->color = c;
tmp->attr = a;
menu_colorings = tmp;
return TRUE;
}
} }
boolean boolean
@@ -1252,11 +1348,48 @@ free_menu_coloring()
while (tmp) { while (tmp) {
struct menucoloring *tmp2 = tmp->next; struct menucoloring *tmp2 = tmp->next;
regex_free(tmp->match); regex_free(tmp->match);
free(tmp->origstr);
free(tmp); free(tmp);
tmp = tmp2; tmp = tmp2;
} }
} }
void
free_one_menu_coloring(idx)
int idx; /* 0 .. */
{
struct menucoloring *tmp = menu_colorings;
struct menucoloring *prev = NULL;
while (tmp) {
if (idx == 0) {
struct menucoloring *next = tmp->next;
regex_free(tmp->match);
free(tmp->origstr);
free(tmp);
if (prev) prev->next = next;
else menu_colorings = next;
return;
}
idx--;
prev = tmp;
tmp = tmp->next;
}
}
int
count_menucolors()
{
int count = 0;
struct menucoloring *tmp = menu_colorings;
while (tmp) {
count++;
tmp = tmp->next;
}
return count;
}
void void
parseoptions(opts, tinitial, tfrom_file) parseoptions(opts, tinitial, tfrom_file)
@@ -3087,6 +3220,11 @@ doset()
doset_add_menu(tmpwin, compopt[i].name, doset_add_menu(tmpwin, compopt[i].name,
(pass == DISP_IN_GAME) ? 0 : indexoffset); (pass == DISP_IN_GAME) ? 0 : indexoffset);
} }
any.a_int = -3;
Sprintf(buf2, "(%d currently set)", count_menucolors());
Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ",
"menucolors", buf2);
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
#ifdef STATUS_VIA_WINDOWPORT #ifdef STATUS_VIA_WINDOWPORT
# ifdef STATUS_HILITES # ifdef STATUS_HILITES
any.a_int = -2; any.a_int = -2;
@@ -3138,6 +3276,10 @@ doset()
} else } else
# endif # endif
#endif #endif
if (opt_indx == -4) {
(void)special_handling("menucolors",
setinitial, fromfile);
} else
if (opt_indx < boolcount) { if (opt_indx < boolcount) {
/* boolean option */ /* boolean option */
Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "", Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
@@ -3177,6 +3319,57 @@ doset()
return 0; return 0;
} }
int
handle_add_list_remove(optname, numtotal)
char *optname;
int numtotal;
{
winid tmpwin;
anything any;
int i, pick_cnt, pick_idx, opt_idx;
menu_item *pick_list = (menu_item *)0;
static const struct action {
char letr;
const char *desc;
} action_titles[] = {
{ 'a', "add new %s" }, /* [0] */
{ 'l', "list %s" }, /* [1] */
{ 'r', "remove existing %s" }, /* [2] */
{ 'x', "exit this menu" }, /* [3] */
};
opt_idx = 0;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
any = zeroany;
for (i = 0; i < SIZE(action_titles); i++) {
char tmpbuf[BUFSZ];
any.a_int++;
/* omit list and remove if there aren't any yet */
if (!numtotal && (i == 1 || i == 2)) continue;
Sprintf(tmpbuf, action_titles[i].desc, (i == 1) ? makeplural(optname) : optname);
add_menu(tmpwin, NO_GLYPH, &any, action_titles[i].letr,
0, ATR_NONE, tmpbuf,
#if 0 /* this ought to work but doesn't... */
(action_titles[i].letr == 'x') ? MENU_SELECTED :
#endif
MENU_UNSELECTED);
}
end_menu(tmpwin, "Do what?");
if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
opt_idx = pick_list[pick_idx].item.a_int - 1;
}
free((genericptr_t)pick_list);
pick_list = (menu_item *)0;
}
destroy_nhwindow(tmpwin);
if (pick_cnt < 1) opt_idx = 3; /* none selected, exit menu */
return opt_idx;
}
struct symsetentry *symset_list = 0; /* files.c will populate this with struct symsetentry *symset_list = 0; /* files.c will populate this with
list of available sets */ list of available sets */
@@ -3483,50 +3676,68 @@ boolean setinitial,setfromfile;
free((genericptr_t)mode_pick); free((genericptr_t)mode_pick);
} }
destroy_nhwindow(tmpwin); destroy_nhwindow(tmpwin);
} else if (!strcmp("autopickup_exception", optname)) { } else if (!strcmp("menucolors", optname)) {
int pick_cnt, pick_idx, opt_idx, pass; int opt_idx, nmc, mcclr, mcattr;
int totalapes = 0, numapes[2] = {0,0}; char mcbuf[BUFSZ];
menu_item *pick_list = (menu_item *)0; menucolors_again:
char apebuf[1+BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */ nmc = count_menucolors();
struct autopickup_exception *ape; opt_idx = handle_add_list_remove("menucolor", nmc);
static const struct ape_action { if (opt_idx == 3) {
char letr; ; /* done--fall through to function exit */
const char *desc; } else if (opt_idx == 0) { /* add new */
} action_titles[] = { getlin("What new menucolor pattern?", mcbuf);
{ 'a', "add new autopickup exception" }, /* [0] */ if (*mcbuf == '\033' || !*mcbuf) goto menucolors_again;
{ 'l', "list autopickup exceptions" }, /* [1] */ mcclr = query_color();
{ 'r', "remove existing autopickup exception" }, /* [2] */ if (mcclr == -1) goto menucolors_again;
{ 'x', "exit this menu" }, /* [3] */ mcattr = query_attr();
}; if (mcattr == -1) goto menucolors_again;
if (!add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
ape_again: pline("Error adding the menu color.");
opt_idx = 0; wait_synch();
totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]); goto menucolors_again;
tmpwin = create_nhwindow(NHW_MENU); }
start_menu(tmpwin); } else { /* list or remove */
any = zeroany; int pick_idx, pick_cnt;
for (i = 0; i < SIZE(action_titles); i++) { int mc_idx;
any.a_int++; menu_item *pick_list = (menu_item *)0;
/* omit list and remove if there aren't any yet */ struct menucoloring *tmp = menu_colorings;
if (!totalapes && (i == 1 || i == 2)) continue; tmpwin = create_nhwindow(NHW_MENU);
add_menu(tmpwin, NO_GLYPH, &any, action_titles[i].letr, start_menu(tmpwin);
0, ATR_NONE, action_titles[i].desc, any = zeroany;
#if 0 /* this ought to work but doesn't... */ mc_idx = 0;
(action_titles[i].letr == 'x') ? MENU_SELECTED : while (tmp) {
#endif const char *sattr = attr2attrname(tmp->attr);
MENU_UNSELECTED); const char *sclr = clr2colorname(tmp->color);
} any.a_int = (++mc_idx);
end_menu(tmpwin, "Do what?"); Sprintf(mcbuf, "\"%s\"=%s%s%s", tmp->origstr, sclr,
if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) { (tmp->attr != ATR_NONE) ? " & " : "",
for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) { (tmp->attr != ATR_NONE) ? sattr : "");
opt_idx = pick_list[pick_idx].item.a_int - 1; add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mcbuf, MENU_UNSELECTED);
tmp = tmp->next;
}
Sprintf(mcbuf, "%s menu colors",
(opt_idx == 1) ? "List of" : "Remove which");
end_menu(tmpwin, mcbuf);
pick_cnt = select_menu(tmpwin,
(opt_idx == 1) ? PICK_NONE : PICK_ANY,
&pick_list);
if (pick_cnt > 0) {
for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
free_one_menu_coloring(pick_list[pick_idx].item.a_int - 1 - pick_idx);
} }
free((genericptr_t)pick_list); free((genericptr_t)pick_list);
pick_list = (menu_item *)0; pick_list = (menu_item *)0;
destroy_nhwindow(tmpwin);
if (pick_cnt >= 0) goto menucolors_again;
} }
destroy_nhwindow(tmpwin); } else if (!strcmp("autopickup_exception", optname)) {
int opt_idx, pass, totalapes = 0, numapes[2] = {0,0};
if (pick_cnt < 1 || opt_idx == 3) { char apebuf[1+BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */
struct autopickup_exception *ape;
ape_again:
totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
opt_idx = handle_add_list_remove("autopickup exception", totalapes);
if (opt_idx == 3) {
; /* done--fall through to function exit */ ; /* done--fall through to function exit */
} else if (opt_idx == 0) { /* add new */ } else if (opt_idx == 0) { /* add new */
getlin("What new autopickup exception pattern?", &apebuf[1]); getlin("What new autopickup exception pattern?", &apebuf[1]);
@@ -3546,6 +3757,8 @@ boolean setinitial,setfromfile;
goto ape_again; goto ape_again;
} }
} else { /* list or remove */ } else { /* list or remove */
int pick_idx, pick_cnt;
menu_item *pick_list = (menu_item *)0;
tmpwin = create_nhwindow(NHW_MENU); tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin); start_menu(tmpwin);
for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) { for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {