Refactored setup menu to use generic widgets

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1863 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
mcmartin
2005-08-28 11:11:49 +00:00
parent 592eb6cb82
commit 15e6a2f23f
4 changed files with 488 additions and 186 deletions
+1
View File
@@ -1,4 +1,5 @@
Changes towards version 0.5:
- Refactored setupmenu code to use generic widgets - Michael
- Support UTF-8 chars in mineral names (bug #770) - SvdB
- Modified scalers to use surface pitch instead of width - reported to
fix bug #740 - Michael
+342
View File
@@ -1,5 +1,9 @@
#include "graphics/gfx_common.h"
#include "graphics/widgets.h"
#include "setup.h"
#include "units.h"
WIDGET *widget_focus = NULL;
void
DrawShadowedBox(PRECT r, COLOR bg, COLOR dark, COLOR medium)
@@ -39,3 +43,341 @@ DrawShadowedBox(PRECT r, COLOR bg, COLOR dark, COLOR medium)
SetContextForeGroundColor (oldcolor);
UnbatchGraphics ();
}
static void
Widget_DrawToolTips (int numlines, const char **tips)
{
RECT r;
FONT oldfont = SetContextFont (StarConFont);
FONTEFFECT oldFontEffect = SetContextFontEffect (0, 0, 0);
COLOR oldtext = SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F));
TEXT t;
int i;
r.corner.x = 2;
r.corner.y = 2;
r.extent.width = SCREEN_WIDTH - 4;
r.extent.height = SCREEN_HEIGHT - 4;
t.align = ALIGN_CENTER;
t.valign = VALIGN_BOTTOM;
t.baseline.x = r.corner.x + (r.extent.width >> 1);
t.baseline.y = r.corner.y + (r.extent.height - 8 - 8 * numlines);
for (i = 0; i < numlines; i++)
{
t.pStr = tips[i];
font_DrawText(&t);
t.baseline.y += 8;
}
SetContextFontEffect (oldFontEffect.type, oldFontEffect.from, oldFontEffect.to);
SetContextFont (oldfont);
SetContextForeGroundColor (oldtext);
}
void
Widget_DrawMenuScreen (WIDGET *_self, int x, int y)
{
RECT r;
COLOR title, oldtext;
COLOR inactive, default_color, selected;
FONT oldfont = SetContextFont (StarConFont);
FONTEFFECT oldFontEffect = SetContextFontEffect (0, 0, 0);
TEXT t;
int widget_index, height, widget_y;
WIDGET_MENU_SCREEN *self = (WIDGET_MENU_SCREEN *)_self;
r.corner.x = 2;
r.corner.y = 2;
r.extent.width = SCREEN_WIDTH - 4;
r.extent.height = SCREEN_HEIGHT - 4;
title = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F);
selected = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x0E);
inactive = BUILD_COLOR (MAKE_RGB15 (0x18, 0x18, 0x1F), 0x07);
default_color = title;
DrawStamp (&self->bgStamp);
oldtext = SetContextForeGroundColor (title);
t.baseline.x = r.corner.x + (r.extent.width >> 1);
t.baseline.y = r.corner.y + 8;
t.pStr = self->title;
t.align = ALIGN_CENTER;
t.valign = VALIGN_BOTTOM;
t.CharCount = ~0;
font_DrawText (&t);
t.baseline.y += 8;
t.pStr = self->subtitle;
font_DrawText (&t);
height = 0;
for (widget_index = 0; widget_index < self->num_children; widget_index++)
{
WIDGET *child = self->child[widget_index];
height += (*child->height)(child);
height += 8; /* spacing */
}
height -= 8;
widget_y = (SCREEN_HEIGHT - height) >> 1;
for (widget_index = 0; widget_index < self->num_children; widget_index++)
{
WIDGET *c = self->child[widget_index];
(*c->draw)(c, 0, widget_y);
widget_y += (*c->height)(c) + 8;
}
SetContextFontEffect (oldFontEffect.type, oldFontEffect.from, oldFontEffect.to);
SetContextFont (oldfont);
SetContextForeGroundColor (oldtext);
}
void
Widget_DrawChoice (WIDGET *_self, int x, int y)
{
WIDGET_CHOICE *self = (WIDGET_CHOICE *)_self;
COLOR oldtext;
COLOR inactive, default_color, selected;
FONT oldfont = SetContextFont (StarConFont);
FONTEFFECT oldFontEffect = SetContextFontEffect (0, 0, 0);
TEXT t;
int i, home_x, home_y;
default_color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F);
selected = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x0E);
inactive = BUILD_COLOR (MAKE_RGB15 (0x18, 0x18, 0x1F), 0x07);
t.baseline.x = x;
t.baseline.y = y;
t.align = ALIGN_LEFT;
t.valign = VALIGN_BOTTOM;
t.pStr = self->category;
if (widget_focus == _self)
{
oldtext = SetContextForeGroundColor (selected);
}
else
{
oldtext = SetContextForeGroundColor (default_color);
}
font_DrawText (&t);
home_x = t.baseline.x + 3 * (SCREEN_WIDTH / 8);
home_y = t.baseline.y;
t.align = ALIGN_CENTER;
for (i = 0; i < self->numopts; i++)
{
t.baseline.x = home_x + ((i % 3) * (SCREEN_WIDTH / 4));
t.baseline.y = home_y + (8 * (i / 3));
t.pStr = self->options[i].optname;
if ((widget_focus == _self) &&
(self->highlighted == i))
{
SetContextForeGroundColor (selected);
Widget_DrawToolTips (3, self->options[i].tooltip);
}
else if (i == self->selected)
{
SetContextForeGroundColor (default_color);
}
else
{
SetContextForeGroundColor (inactive);
}
font_DrawText (&t);
}
SetContextFontEffect (oldFontEffect.type, oldFontEffect.from, oldFontEffect.to);
SetContextFont (oldfont);
SetContextForeGroundColor (oldtext);
}
void
Widget_DrawButton (WIDGET *_self, int x, int y)
{
WIDGET_BUTTON *self = (WIDGET_BUTTON *)_self;
COLOR oldtext;
COLOR inactive, selected;
FONT oldfont = SetContextFont (StarConFont);
FONTEFFECT oldFontEffect = SetContextFontEffect (0, 0, 0);
TEXT t;
int i, home_x, home_y;
selected = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x0E);
inactive = BUILD_COLOR (MAKE_RGB15 (0x18, 0x18, 0x1F), 0x07);
t.baseline.x = 160;
t.baseline.y = y;
t.align = ALIGN_CENTER;
t.valign = VALIGN_BOTTOM;
t.pStr = self->name;
if (widget_focus == _self)
{
oldtext = SetContextForeGroundColor (selected);
Widget_DrawToolTips (3, self->tooltip);
}
else
{
oldtext = SetContextForeGroundColor (inactive);
}
font_DrawText (&t);
SetContextFontEffect (oldFontEffect.type, oldFontEffect.from, oldFontEffect.to);
SetContextFont (oldfont);
SetContextForeGroundColor (oldtext);
}
int
Widget_HeightChoice (WIDGET *_self)
{
return ((((WIDGET_CHOICE *)_self)->numopts + 2) / 3) * 8;
}
int
Widget_HeightFullScreen (WIDGET *_self)
{
return SCREEN_HEIGHT;
}
int
Widget_HeightOneLine (WIDGET *_self)
{
return 8;
}
int Widget_WidthFullScreen (WIDGET *_self)
{
return SCREEN_WIDTH;
}
int
Widget_ReceiveFocusButton (WIDGET *_self, int event)
{
widget_focus = _self;
return TRUE;
}
int
Widget_ReceiveFocusChoice (WIDGET *_self, int event)
{
WIDGET_CHOICE *self = (WIDGET_CHOICE *)_self;
widget_focus = _self;
self->highlighted = self->selected;
return TRUE;
}
int
Widget_ReceiveFocusMenuScreen (WIDGET *_self, int event)
{
WIDGET_MENU_SCREEN *self = (WIDGET_MENU_SCREEN *)_self;
int x, last_x, dx;
for (x = 0; x < self->num_children; x++)
{
self->child[x]->parent = _self;
}
if (event == WIDGET_EVENT_UP)
{
x = self->num_children - 1;
dx = -1;
last_x = -1;
}
else
{
x = 0;
dx = 1;
last_x = self->num_children;
}
for ( ; x != last_x; x += dx)
{
WIDGET *child = self->child[x];
if ((*child->receiveFocus)(child, event))
{
self->highlighted = x;
return TRUE;
}
}
return FALSE;
}
int
Widget_HandleEventIgnoreAll (WIDGET *self, int event)
{
return FALSE;
}
int
Widget_HandleEventChoice (WIDGET *_self, int event)
{
WIDGET_CHOICE *self = (WIDGET_CHOICE *)_self;
switch (event)
{
case WIDGET_EVENT_LEFT:
self->highlighted -= 1;
if (self->highlighted < 0)
self->highlighted = self->numopts - 1;
return TRUE;
case WIDGET_EVENT_RIGHT:
self->highlighted += 1;
if (self->highlighted >= self->numopts)
self->highlighted = 0;
return TRUE;
case WIDGET_EVENT_SELECT:
self->selected = self->highlighted;
return TRUE;
default:
return FALSE;
}
}
int
Widget_HandleEventMenuScreen (WIDGET *_self, int event)
{
WIDGET_MENU_SCREEN *self = (WIDGET_MENU_SCREEN *)_self;
int x, last_x, dx;
switch (event)
{
case WIDGET_EVENT_UP:
dx = -1;
break;
case WIDGET_EVENT_DOWN:
dx = 1;
break;
default:
return FALSE;
}
last_x = self->highlighted;
x = self->highlighted + dx;
while (x != last_x)
{
WIDGET *child;
if (x == -1)
x = self->num_children - 1;
if (x == self->num_children)
x = 0;
child = self->child[x];
if ((*child->receiveFocus)(child, event))
{
self->highlighted = x;
return TRUE;
}
x += dx;
}
return FALSE;
}
int
Widget_Event (int event)
{
WIDGET *widget = widget_focus;
while (widget != NULL)
{
if ((*widget->handleEvent)(widget, event))
return TRUE;
widget = widget->parent;
}
return FALSE;
}
+87
View File
@@ -19,6 +19,93 @@
#ifndef _WIDGETS_H
#define _WIDGETS_H
#include "libs/gfxlib.h"
enum {
WIDGET_EVENT_UP,
WIDGET_EVENT_DOWN,
WIDGET_EVENT_LEFT,
WIDGET_EVENT_RIGHT,
WIDGET_EVENT_SELECT,
WIDGET_EVENT_CANCEL,
NUM_WIDGET_EVENTS
};
typedef struct _widget {
struct _widget *parent;
int (*handleEvent)(struct _widget *self, int event);
int (*receiveFocus)(struct _widget *self, int event);
void (*draw)(struct _widget *self, int x, int y);
int (*height)(struct _widget *self);
int (*width)(struct _widget *self);
} WIDGET;
typedef struct _widget_menu_screen {
struct _widget *parent;
int (*handleEvent)(struct _widget *self, int event);
int (*receiveFocus)(struct _widget *self, int event);
void (*draw)(struct _widget *self, int x, int y);
int (*height)(struct _widget *self);
int (*width)(struct _widget *self);
const char *title;
const char *subtitle;
STAMP bgStamp;
int num_children;
struct _widget **child;
int highlighted;
} WIDGET_MENU_SCREEN;
typedef struct {
const char *optname;
const char *tooltip[3];
} CHOICE_OPTION;
typedef struct _widget_choice {
struct _widget *parent;
int (*handleEvent)(struct _widget *self, int event);
int (*receiveFocus)(struct _widget *self, int event);
void (*draw)(struct _widget *self, int x, int y);
int (*height)(struct _widget *self);
int (*width)(struct _widget *self);
const char *category;
int numopts;
CHOICE_OPTION *options;
int selected, highlighted;
} WIDGET_CHOICE;
typedef struct _widget_button {
struct _widget *parent;
int (*handleEvent)(struct _widget *self, int event);
int (*receiveFocus)(struct _widget *self, int event);
void (*draw)(struct _widget *self, int x, int y);
int (*height)(struct _widget *self);
int (*width)(struct _widget *self);
const char *name;
const char *tooltip[3];
} WIDGET_BUTTON;
void DrawShadowedBox (PRECT r, COLOR bg, COLOR dark, COLOR medium);
int Widget_Event (int event);
/* Methods for filling in widgets with */
int Widget_ReceiveFocusMenuScreen (WIDGET *_self, int event);
int Widget_ReceiveFocusChoice (WIDGET *_self, int event);
int Widget_ReceiveFocusButton (WIDGET *_self, int event);
int Widget_HandleEventMenuScreen (WIDGET *_self, int event);
int Widget_HandleEventChoice (WIDGET *_self, int event);
int Widget_HandleEventIgnoreAll (WIDGET *_self, int event);
int Widget_HeightChoice (WIDGET *_self);
int Widget_HeightFullScreen (WIDGET *_self);
int Widget_HeightOneLine (WIDGET *_self);
int Widget_WidthFullScreen (WIDGET *_self);
void Widget_DrawMenuScreen (WIDGET *_self, int x, int y);
void Widget_DrawChoice (WIDGET *_self, int x, int y);
void Widget_DrawButton (WIDGET *_self, int x, int y);
#endif /* _WIDGETS_H */
+57 -185
View File
@@ -35,28 +35,13 @@ typedef struct setup_menu_state {
BOOLEAN initialized;
int anim_frame_count;
DWORD NextTime;
int category;
int option;
} SETUP_MENU_STATE;
typedef SETUP_MENU_STATE *PSETUP_MENU_STATE;
typedef struct {
const char *optname;
const char *tooltip[3];
} OPTION;
typedef struct {
const char *category;
int numopts;
OPTION *options;
int selected;
} MENU_CATEGORY;
static BOOLEAN DoSetupMenu (PSETUP_MENU_STATE pInputState);
static STAMP bkgStamp = { {0, 0}, NULL };
static OPTION scaler_opts[] = {
static CHOICE_OPTION scaler_opts[] = {
{ "None",
{ "No scaling.",
"Simulates the original 320x240 display.",
@@ -83,7 +68,7 @@ static OPTION scaler_opts[] = {
"Based on the Scale2x algorithm.",
} } };
static OPTION scanlines_opts[] = {
static CHOICE_OPTION scanlines_opts[] = {
{ "Disabled",
{ "Do not attempt to simulate an interlaced display.",
"",
@@ -95,7 +80,7 @@ static OPTION scanlines_opts[] = {
""
} } };
static OPTION music_opts[] = {
static CHOICE_OPTION music_opts[] = {
{ "PC",
{ "Uses the music from the Original PC version.",
"Prefers .MOD files to .OGG files.",
@@ -107,7 +92,7 @@ static OPTION music_opts[] = {
"Prefers .OGG files over .MOD."
} } };
static OPTION menu_opts[] = {
static CHOICE_OPTION menu_opts[] = {
{ "Text",
{ "In-game menus resemble the Original PC version.",
"",
@@ -119,7 +104,7 @@ static OPTION menu_opts[] = {
""
} } };
static OPTION font_opts[] = {
static CHOICE_OPTION font_opts[] = {
{ "Gradients",
{ "Certain menu texts and dialogs use gradients,",
"as per the original PC version.",
@@ -131,7 +116,7 @@ static OPTION font_opts[] = {
"Easier to read."
} } };
static OPTION scan_opts[] = {
static CHOICE_OPTION scan_opts[] = {
{ "Text",
{ "Displays planet scan information as text,",
"as per the original PC version.",
@@ -143,7 +128,7 @@ static OPTION scan_opts[] = {
""
} } };
static OPTION scroll_opts[] = {
static CHOICE_OPTION scroll_opts[] = {
{ "Per-Page",
{ "When fast-forwarding or rewinding conversations",
"in-game, advance one screen of subtitles at a time.",
@@ -155,7 +140,7 @@ static OPTION scroll_opts[] = {
"This mimics the 3do version."
} } };
static OPTION subtitles_opts[] = {
static CHOICE_OPTION subtitles_opts[] = {
{ "Disabled",
{ "Do not subtitle alien speech.",
"",
@@ -167,7 +152,7 @@ static OPTION subtitles_opts[] = {
""
} } };
static OPTION resdriver_opts[] = {
static CHOICE_OPTION resdriver_opts[] = {
{ "320x240",
{ "320x240 resolution.",
"Uses the SDL frame buffer directly.",
@@ -207,7 +192,7 @@ static OPTION resdriver_opts[] = {
#endif
};
static OPTION bpp_opts[] = {
static CHOICE_OPTION bpp_opts[] = {
{ "16",
{ "16-bit color depth.",
"",
@@ -224,12 +209,6 @@ static OPTION bpp_opts[] = {
""
} } };
//static char *title_str = "Ur-Quan Masters Setup";
//static char *subtitle_str = "Graphics Options";
static const char *title_str = "Use arrows and fire to select options";
static const char *subtitle_str = "Press cancel when done";
static const char **tooltip;
#ifdef HAVE_OPENGL
#define RES_OPTS 6
#else
@@ -238,17 +217,40 @@ static const char **tooltip;
#define NUM_OPTS 9
static MENU_CATEGORY cmdline_opts[] = {
{ "Resolution", RES_OPTS, resdriver_opts, 0 },
{ "Color depth", 3, bpp_opts, 0 },
{ "Scaler", 5, scaler_opts, 0 },
{ "Scanlines", 2, scanlines_opts, 0 },
{ "Menu Style", 2, menu_opts, 0 },
{ "Font Style", 2, font_opts, 0 },
{ "Scan Style", 2, scan_opts, 0 },
{ "Scroll Style", 2, scroll_opts, 0 },
{ "Subtitles", 2, subtitles_opts, 0 },
{ NULL, 0, NULL, 0 } };
#define CHOICE_PREFACE NULL, Widget_HandleEventChoice, Widget_ReceiveFocusChoice, Widget_DrawChoice, Widget_HeightChoice, Widget_WidthFullScreen
static WIDGET_CHOICE cmdline_opts[] = {
{ CHOICE_PREFACE, "Resolution", RES_OPTS, resdriver_opts, 0, 0},
{ CHOICE_PREFACE, "Color depth", 3, bpp_opts, 0, 0 },
{ CHOICE_PREFACE, "Scaler", 5, scaler_opts, 0, 0 },
{ CHOICE_PREFACE, "Scanlines", 2, scanlines_opts, 0, 0 },
{ CHOICE_PREFACE, "Menu Style", 2, menu_opts, 0, 0 },
{ CHOICE_PREFACE, "Font Style", 2, font_opts, 0, 0 },
{ CHOICE_PREFACE, "Scan Style", 2, scan_opts, 0, 0 },
{ CHOICE_PREFACE, "Scroll Style", 2, scroll_opts, 0, 0 },
{ CHOICE_PREFACE, "Subtitles", 2, subtitles_opts, 0, 0 } };
static WIDGET *opt_widgets[] = {
(WIDGET *)(&cmdline_opts[0]),
(WIDGET *)(&cmdline_opts[1]),
(WIDGET *)(&cmdline_opts[2]),
(WIDGET *)(&cmdline_opts[3]),
(WIDGET *)(&cmdline_opts[4]),
(WIDGET *)(&cmdline_opts[5]),
(WIDGET *)(&cmdline_opts[6]),
(WIDGET *)(&cmdline_opts[7]),
(WIDGET *)(&cmdline_opts[8]) } ;
static WIDGET_MENU_SCREEN menu = {
NULL, Widget_HandleEventMenuScreen, Widget_ReceiveFocusMenuScreen,
Widget_DrawMenuScreen, Widget_HeightFullScreen, Widget_WidthFullScreen,
// "Ur-Quan Masters Setup",
// "Graphics Options",
"Use arrows and fire to select options",
"Press cancel when done",
{ {0, 0}, NULL },
9, opt_widgets,
0 };
#define NUM_STEPS 20
#define X_STEP (SCREEN_WIDTH / NUM_STEPS)
@@ -297,176 +299,46 @@ PropagateResults (void)
SetGlobalOptions (&opts);
}
static void
DrawMenu (PSETUP_MENU_STATE pInputState)
{
RECT r;
COLOR title, oldtext;
COLOR inactive, default_color, selected;
FONT oldfont = SetContextFont (StarConFont);
FONTEFFECT oldFontEffect = SetContextFontEffect (0, 0, 0);
TEXT t;
MENU_CATEGORY *menu;
int cat_index;
r.corner.x = 2;
r.corner.y = 2;
r.extent.width = SCREEN_WIDTH - 4;
r.extent.height = SCREEN_HEIGHT - 4;
title = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F);
selected = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x0E);
inactive = BUILD_COLOR (MAKE_RGB15 (0x18, 0x18, 0x1F), 0x07);
default_color = title;
if (!bkgStamp.frame)
{
bkgStamp.origin.x = 0;
bkgStamp.origin.y = 0;
bkgStamp.frame = CaptureDrawable (LoadCelFile (MENU_BKG));
}
DrawStamp (&bkgStamp);
oldtext = SetContextForeGroundColor (title);
t.baseline.x = r.corner.x + (r.extent.width >> 1);
t.baseline.y = r.corner.y + 8;
t.pStr = title_str;
t.align = ALIGN_CENTER;
t.valign = VALIGN_BOTTOM;
t.CharCount = ~0;
font_DrawText (&t);
t.baseline.y += 8;
t.pStr = subtitle_str;
font_DrawText (&t);
t.baseline.y += 8;
menu = cmdline_opts;
cat_index = 0;
while (menu->category)
{
int i, home_x, home_y;
t.baseline.x = r.corner.x; // + (r.extent.width / 8);
t.baseline.y += 16;
t.align = ALIGN_LEFT;
t.pStr = menu->category;
if (pInputState->category == cat_index)
{
SetContextForeGroundColor (selected);
}
else
{
SetContextForeGroundColor (title);
}
font_DrawText (&t);
home_x = t.baseline.x + 3 * (r.extent.width / 8);
home_y = t.baseline.y;
t.align = ALIGN_CENTER;
for (i = 0; i < menu->numopts; i++)
{
t.baseline.x = home_x + ((i % 3) * (r.extent.width / 4));
t.baseline.y = home_y + (8 * (i / 3));
t.pStr = menu->options[i].optname;
if ((pInputState->category == cat_index) &&
(pInputState->option == i))
{
SetContextForeGroundColor (selected);
tooltip = menu->options[i].tooltip;
}
else if (i == menu->selected)
{
SetContextForeGroundColor (default_color);
}
else
{
SetContextForeGroundColor (inactive);
}
font_DrawText (&t);
}
menu++;
cat_index++;
}
t.baseline.x = r.corner.x + (r.extent.width >> 1);
t.baseline.y = r.corner.y + (r.extent.height - 32);
t.pStr = tooltip[0];
SetContextForeGroundColor (title);
font_DrawText(&t);
t.baseline.y += 8;
t.pStr = tooltip[1];
font_DrawText(&t);
t.baseline.y += 8;
t.pStr = tooltip[2];
font_DrawText(&t);
SetContextFontEffect (oldFontEffect.type, oldFontEffect.from, oldFontEffect.to);
SetContextFont (oldfont);
SetContextForeGroundColor (oldtext);
}
static BOOLEAN
DoSetupMenu (PSETUP_MENU_STATE pInputState)
{
int opt, cat;
MENU_CATEGORY *menu = cmdline_opts;
if (!pInputState->initialized)
{
SetDefaultMenuRepeatDelay ();
SetTransitionSource (NULL);
pInputState->NextTime = GetTimeCounter ();
pInputState->category = 0;
SetDefaults ();
pInputState->option = menu[0].selected;
(*menu.receiveFocus) ((WIDGET *)(&menu), WIDGET_EVENT_DOWN);
}
if (!menu.bgStamp.frame)
{
menu.bgStamp.origin.x = 0;
menu.bgStamp.origin.y = 0;
menu.bgStamp.frame = CaptureDrawable (LoadCelFile (MENU_BKG));
}
BatchGraphics ();
DrawMenu (pInputState);
cat = pInputState->category;
opt = pInputState->option;
(*menu.draw)((WIDGET *)(&menu), 0, 0);
if (PulsedInputState.key[KEY_MENU_UP])
{
cat--;
if (cat < 0)
{
cat = NUM_OPTS-1;
}
/* Preserve column if possible */
opt = menu[cat].selected;
Widget_Event (WIDGET_EVENT_UP);
}
else if (PulsedInputState.key[KEY_MENU_DOWN])
{
cat++;
if (cat >= NUM_OPTS)
{
cat = 0;
}
opt = menu[cat].selected;
Widget_Event (WIDGET_EVENT_DOWN);
}
else if (PulsedInputState.key[KEY_MENU_LEFT])
{
opt--;
if (opt < 0)
{
opt = menu[cat].numopts - 1;
}
Widget_Event (WIDGET_EVENT_LEFT);
}
else if (PulsedInputState.key[KEY_MENU_RIGHT])
{
opt++;
if (opt >= menu[cat].numopts)
{
opt = 0;
Widget_Event (WIDGET_EVENT_RIGHT);
}
}
pInputState->category = cat;
pInputState->option = opt;
if (PulsedInputState.key[KEY_MENU_SELECT])
{
cmdline_opts[cat].selected = opt;
Widget_Event (WIDGET_EVENT_SELECT);
}
if (!pInputState->initialized)