diff --git a/src/deh_soc.c b/src/deh_soc.c index 3516b4edc..905c5f07c 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1863,6 +1863,38 @@ static struct { const char *name; consvar_t *var; } HIDDENVARS[] = { { NULL, NULL } }; +// parses an item style in the form of "-SMALL--HIGHLIGHT" +// each component is optional, and the style cannot be written in arbitrary order +// returns IT_HIDDEN if style is invalid +static menuitemflags_t parsestyle(const char *p) +{ + menuitemflags_t style = 0; + + // yeah yeah, macro hell, but it's more economical than 100 entries in a table +#define STYLE(string, flag) \ + (!strncmp(p, string, sizeof(string)-1)) { \ + style |= flag; \ + p += sizeof(string)-1; \ + if (*p == '\0') return style; \ + if (*p++ != '-') return IT_HIDDEN; \ + } + + if STYLE("THIN2", ITF_THIN2) + else if STYLE("THIN", ITF_THIN) + else if STYLE("HEADER", ITF_HEADER|IT_HIGHLIGHT) + else if STYLE("PATCH", IT_PATCH) + + if STYLE("SMALL", IT_SMALL) + + if STYLE("CENTER", IT_CENTER) + else if STYLE("RIGHT", IT_RIGHT) + + if STYLE("HIGHLIGHT", IT_HIGHLIGHT) + + return IT_HIDDEN; +#undef STYLE +} + #define WARN(str, ...) deh_warning("MenuItem %s: " str, strbuf_get(menunames, menuitem->info.nameofs), __VA_ARGS__) #define WARN0(str) deh_warning("MenuItem %s: " str, strbuf_get(menunames, menuitem->info.nameofs)) static void readmenuitem(MYFILE *f, menuitem_t *menuitem) @@ -1872,7 +1904,7 @@ static void readmenuitem(MYFILE *f, menuitem_t *menuitem) char *word2; char *tmp; - UINT16 status = 0; + menuitemflags_t status = 0; // taking quite possibly the only opportunity i'll ever get // to avoid three tabs of indentation... @@ -1948,46 +1980,21 @@ static void readmenuitem(MYFILE *f, menuitem_t *menuitem) } else if (fastcmp(word, "STYLE")) { + menuitemflags_t style = 0; if (status & IT_STYLE) { WARN0("style already set!"); continue; } - - if (fasticmp(word2, "HEADER")) - status |= IT_HEADER|IT_HIGHLIGHT; - else if (fasticmp(word2, "HIGHLIGHT")) - status |= IT_HIGHLIGHT; - else if (fasticmp(word2, "CENTER")) - status |= IT_CENTER; - else if (fasticmp(word2, "CENTER-HIGHLIGHT")) - status |= IT_CENTER|IT_HIGHLIGHT; - else if (fasticmp(word2, "THIN")) - status |= IT_THIN; - else if (fasticmp(word2, "THIN-HIGHLIGHT")) - status |= IT_THIN|IT_HIGHLIGHT; - else if (fasticmp(word2, "PATCH")) - status |= IT_PATCH; - else if (fasticmp(word2, "PATCH-CENTER")) - status |= IT_PATCH|IT_CENTER; - else if (fasticmp(word2, "PATCH-SMALL")) - status |= IT_PATCH|IT_SMALL; - else if (fasticmp(word2, "PATCH-HIGHLIGHT")) - status |= IT_PATCH|IT_HIGHLIGHT; - else + strupr(word2); + style = parsestyle(word2); + if (style == IT_HIDDEN) WARN("unknown style '%s'", word2); + else + status |= style; } - else if (fastncmp(word, "CVAR", 4)) + else if (fastcmp(word, "CVAR") || fastcmp(word, "SLIDER")) { - UINT16 flags = IT_INTERACT; - if (fastcmp(word+4, "SLIDER")) - flags |= IT_SLIDER; - else if (word[4]) - { - WARN("unknown word '%s'", word); - continue; - } - consvar_t *cvar = CV_FindVar(word2); if (!cvar) for (size_t i = 0; HIDDENVARS[i].name; i++) @@ -2001,7 +2008,9 @@ static void readmenuitem(MYFILE *f, menuitem_t *menuitem) WARN("unable to find cvar '%s'", word2); continue; } - status |= flags; + status |= IT_INTERACT; + if (word[0] == 'S') + status |= IT_SLIDER; menuitem->cvar = cvar; } else if (fastcmp(word, "SUBMENU")) @@ -2017,17 +2026,15 @@ static void readmenuitem(MYFILE *f, menuitem_t *menuitem) } else if (fastcmp(word, "CALL") || fastcmp(word, "ARROWS")) { - UINT16 flags = IT_INTERACT; - if (word[0] == 'A') - flags |= IT_ARROWS; - menufunc_f *routine = get_menuroutine(word2); if (!routine) { WARN("unknown call routine '%s'", word2); continue; } - status |= flags; + status |= IT_INTERACT; + if (word[0] == 'A') + status |= IT_ARROWS; menuitem->routine = routine; } else diff --git a/src/m_menu.c b/src/m_menu.c index 555c35180..2d1b9a50e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -268,7 +268,7 @@ static INT16 M_GetMenuIndex(menutype_t type, const char *name) #define M_SetItemY(t, n, v) (M_GetMenuItem(t, n)->y = v) #define M_GetItemY(t, n) (M_GetMenuItem(t, n)->y) -static void M_ChangeItemStatus(menutype_t type, const char *name, UINT16 flag, boolean cond) +static void M_ChangeItemStatus(menutype_t type, const char *name, menuitemflags_t flag, boolean cond) { if (cond) M_GetMenuItem(type, name)->status |= flag; @@ -2204,12 +2204,14 @@ static void M_DrawRightString(menuitem_t *item, INT16 x, INT16 y, INT32 vflags, } } -static INT16 M_DrawMenuItem(menuitem_t *item, INT16 x, INT16 y, INT32 vflags, boolean selected) +// draws a menu item, returns cursor offset +static INT32 M_DrawMenuItem(menuitem_t *item, INT16 x, INT16 y, INT32 vflags, boolean selected) { + INT32 width = 0; const char *string = item->text ? item->text : ""; fixed_t scale = item->status & IT_SMALL ? FRACUNIT/2 : FRACUNIT; - int font = HU_FONT; - INT32 (*widthfunc)(const char *string, INT32 option) = V_StringWidth; + int font; + INT32 (*widthfunc)(const char *string, INT32 option); if (item->status & IT_SECRET) { @@ -2229,32 +2231,45 @@ static INT16 M_DrawMenuItem(menuitem_t *item, INT16 x, INT16 y, INT32 vflags, bo UINT8 *cmap = NULL; if (item->status & IT_CENTER) - x -= SHORT(p->width)/2; + width = SHORT(p->width)/2; + else if (item->status & IT_RIGHT) + width = SHORT(p->width); + if (item->status & IT_HIGHLIGHT) cmap = V_GetStringColormap(highlightflags); - V_DrawFixedPatch(x<width); + V_DrawFixedPatch((x - width)<status & IT_THIN) + switch (item->status & ITF_MASK) { + case ITF_THIN2: + vflags |= V_6WIDTHSPACE; // FALLTHRU + case ITF_THIN: font = TINY_FONT; - vflags |= V_6WIDTHSPACE; // TODO: make this a style? widthfunc = V_ThinStringWidth; + break; + + case ITF_HEADER: + x -= 16; // FALLTHRU + default: + font = HU_FONT; + widthfunc = V_StringWidth; + break; } if (item->status & IT_CENTER) - x -= widthfunc(string, vflags)/2; - if (item->status & IT_HEADER) - x -= 16; + width = widthfunc(string, vflags)/2; + else if (item->status & IT_RIGHT) + width = widthfunc(string, vflags); - V_DrawStringScaled(x<status & IT_HIGHLIGHT ? highlightflags : 0)|vflags, font, string); + V_DrawStringScaled((x - width)<status & IT_HIGHLIGHT ? highlightflags : 0)|vflags, font, string); if (!(item->status & (IT_SECRET|IT_GRAYEDOUT))) M_DrawRightString(item, x, y, vflags, selected); - return widthfunc(string, vflags); + return width; } // gets the absolute Y coordinate where this menuitem should be drawn (in a broken way) @@ -2359,7 +2374,7 @@ void M_DrawGenericMenu(void) if (i == itemOn) { cursory = y; - cursorx = x - (item->status & IT_CENTER ? w/2 : 0) - 24 + currentMenu->cursoroffset; + cursorx = x - w - 24 + currentMenu->cursoroffset; } nodraw: diff --git a/src/m_menu.h b/src/m_menu.h index 7c6c9922c..567701f53 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -172,11 +172,17 @@ typedef enum IT_PATCH = 1<<10, // display a patch instead of text IT_CENTER = 1<<11, // center the text/patch - IT_SMALL = 1<<12, // draw at half scale - IT_THIN = 1<<13, // thin font + IT_RIGHT = 1<<12, // right-align the text/patch + IT_SMALL = 1<<13, // draw at half scale IT_HIGHLIGHT = 1<<14, // add highlightflags to text/patch - IT_HEADER = 1<<15, // draw with an offset to the left - IT_STYLE = IT_PATCH|IT_CENTER|IT_SMALL|IT_THIN|IT_HIGHLIGHT|IT_HEADER, + + ITF_STANDARD = 0<<15, // standard font + ITF_HEADER = 1<<15, // standard font, with an offset to the left + ITF_THIN = 2<<15, // thin font + ITF_THIN2 = 3<<15, // thin font with tighter spacing + + ITF_MASK = 3<<15, + IT_STYLE = IT_PATCH|IT_CENTER|IT_RIGHT|IT_SMALL|IT_HIGHLIGHT|ITF_MASK, } menuitemflags_t; #define MAXSTRINGLENGTH 32 @@ -191,19 +197,18 @@ struct menuitem_t { dehinfo_t info; - // show IT_xxx - UINT16 status; + char *text; // left-side string + char *patch; // name of patch lump to draw, OR right-side string + char *tooltip; // help text displayed at bottom - menutype_t submenu; // IT_SUBMENU - consvar_t *cvar; // IT_CVAR - menufunc_f *routine; // IT_CALL, IT_ARROWS + consvar_t *cvar; // console variable to modify + menufunc_f *routine; // menu routine to call + menutype_t submenu; // navigate to another menu - const char *patch; - const char *text; // used when FONTBxx lump is found - const char *tooltip; + menuitemflags_t status; // show IT_xxx - INT32 argument; - INT16 x, y; + INT32 argument; // passed to routine/submenu, OR step size for cvars + INT16 x, y; // coordinates, see menuitemflags }; struct menu_t