Major reworking of key configuration internals.
VControl no longer uses a custom configuration format; instead, control bindings are read in from the standard resource system. Menu controls are specified in menu.key in the content; flight controls are now copied from uqm.key to flight.cfg instead of from starcon.key to uqm.key. This change permits significant streamlining of the VControl code itself, and allows more fine-grained control over what the key configuration code iself does. This update thus closes both Bug #949 and Bug #961. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2705 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -44,150 +44,145 @@ static BOOLEAN InputInitialized = FALSE;
|
||||
|
||||
static BOOLEAN _in_character_mode = FALSE;
|
||||
|
||||
#define VCONTROL_VERSION 4
|
||||
static const char *menu_res_names[] = {
|
||||
"pause",
|
||||
"exit",
|
||||
"abort",
|
||||
"debug",
|
||||
"up",
|
||||
"down",
|
||||
"left",
|
||||
"right",
|
||||
"select",
|
||||
"cancel",
|
||||
"special",
|
||||
"pageup",
|
||||
"pagedown",
|
||||
"home",
|
||||
"end",
|
||||
"zoomin",
|
||||
"zoomout",
|
||||
"delete",
|
||||
"backspace",
|
||||
"editcancel",
|
||||
"search",
|
||||
"next",
|
||||
NULL
|
||||
};
|
||||
|
||||
static VControl_NameBinding control_names[] = {
|
||||
{ "Menu-Up", (int *)&ImmediateInputState.menu[KEY_MENU_UP] },
|
||||
{ "Menu-Down", (int *)&ImmediateInputState.menu[KEY_MENU_DOWN] },
|
||||
{ "Menu-Left", (int *)&ImmediateInputState.menu[KEY_MENU_LEFT] },
|
||||
{ "Menu-Right", (int *)&ImmediateInputState.menu[KEY_MENU_RIGHT] },
|
||||
{ "Menu-Select", (int *)&ImmediateInputState.menu[KEY_MENU_SELECT] },
|
||||
{ "Menu-Cancel", (int *)&ImmediateInputState.menu[KEY_MENU_CANCEL] },
|
||||
{ "Menu-Special", (int *)&ImmediateInputState.menu[KEY_MENU_SPECIAL] },
|
||||
{ "Menu-Page-Up", (int *)&ImmediateInputState.menu[KEY_MENU_PAGE_UP] },
|
||||
{ "Menu-Page-Down", (int *)&ImmediateInputState.menu[KEY_MENU_PAGE_DOWN] },
|
||||
{ "Menu-Home", (int *)&ImmediateInputState.menu[KEY_MENU_HOME] },
|
||||
{ "Menu-End", (int *)&ImmediateInputState.menu[KEY_MENU_END] },
|
||||
{ "Menu-Zoom-In", (int *)&ImmediateInputState.menu[KEY_MENU_ZOOM_IN] },
|
||||
{ "Menu-Zoom-Out", (int *)&ImmediateInputState.menu[KEY_MENU_ZOOM_OUT] },
|
||||
{ "Menu-Delete", (int *)&ImmediateInputState.menu[KEY_MENU_DELETE] },
|
||||
{ "Menu-Backspace", (int *)&ImmediateInputState.menu[KEY_MENU_BACKSPACE] },
|
||||
{ "Menu-Edit-Cancel", (int *)&ImmediateInputState.menu[KEY_MENU_EDIT_CANCEL] },
|
||||
{ "Menu-Search", (int *)&ImmediateInputState.menu[KEY_MENU_SEARCH] },
|
||||
{ "Menu-Next", (int *)&ImmediateInputState.menu[KEY_MENU_NEXT] },
|
||||
{ "Template-1-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_UP] },
|
||||
{ "Template-1-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_DOWN] },
|
||||
{ "Template-1-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_LEFT] },
|
||||
{ "Template-1-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_RIGHT] },
|
||||
{ "Template-1-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_WEAPON] },
|
||||
{ "Template-1-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_SPECIAL] },
|
||||
{ "Template-1-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_ESCAPE] },
|
||||
{ "Template-2-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_UP] },
|
||||
{ "Template-2-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_DOWN] },
|
||||
{ "Template-2-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_LEFT] },
|
||||
{ "Template-2-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_RIGHT] },
|
||||
{ "Template-2-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_WEAPON] },
|
||||
{ "Template-2-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_SPECIAL] },
|
||||
{ "Template-2-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_ESCAPE] },
|
||||
{ "Template-3-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_UP] },
|
||||
{ "Template-3-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_DOWN] },
|
||||
{ "Template-3-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_LEFT] },
|
||||
{ "Template-3-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_RIGHT] },
|
||||
{ "Template-3-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_WEAPON] },
|
||||
{ "Template-3-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_SPECIAL] },
|
||||
{ "Template-3-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_ESCAPE] },
|
||||
{ "Template-4-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_UP] },
|
||||
{ "Template-4-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_DOWN] },
|
||||
{ "Template-4-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_LEFT] },
|
||||
{ "Template-4-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_RIGHT] },
|
||||
{ "Template-4-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_WEAPON] },
|
||||
{ "Template-4-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_SPECIAL] },
|
||||
{ "Template-4-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_ESCAPE] },
|
||||
{ "Template-5-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_UP] },
|
||||
{ "Template-5-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_DOWN] },
|
||||
{ "Template-5-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_LEFT] },
|
||||
{ "Template-5-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_RIGHT] },
|
||||
{ "Template-5-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_WEAPON] },
|
||||
{ "Template-5-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_SPECIAL] },
|
||||
{ "Template-5-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_ESCAPE] },
|
||||
{ "Template-6-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_UP] },
|
||||
{ "Template-6-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_DOWN] },
|
||||
{ "Template-6-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_LEFT] },
|
||||
{ "Template-6-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_RIGHT] },
|
||||
{ "Template-6-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_WEAPON] },
|
||||
{ "Template-6-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_SPECIAL] },
|
||||
{ "Template-6-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_ESCAPE] },
|
||||
{ "Pause", (int *)&ImmediateInputState.menu[KEY_PAUSE] },
|
||||
{ "Exit", (int *)&ImmediateInputState.menu[KEY_EXIT] },
|
||||
{ "Abort", (int *)&ImmediateInputState.menu[KEY_ABORT] },
|
||||
{ "Debug", (int *)&ImmediateInputState.menu[KEY_DEBUG] },
|
||||
{ "Illegal", NULL}};
|
||||
static const char *flight_res_names[] = {
|
||||
"up",
|
||||
"down",
|
||||
"left",
|
||||
"right",
|
||||
"weapon",
|
||||
"special",
|
||||
"escape",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
register_menu_controls (int index)
|
||||
{
|
||||
int i;
|
||||
char buf[40];
|
||||
buf[39] = '\0';
|
||||
|
||||
i = 1;
|
||||
while (TRUE)
|
||||
{
|
||||
VCONTROL_GESTURE g;
|
||||
snprintf (buf, 39, "menu.%s.%d", menu_res_names[index], i);
|
||||
if (!res_HasKey (buf))
|
||||
break;
|
||||
VControl_ParseGesture (&g, res_GetString (buf));
|
||||
VControl_AddGestureBinding (&g, (int *)&ImmediateInputState.menu[index]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static VCONTROL_GESTURE controls[NUM_TEMPLATES][NUM_KEYS][2];
|
||||
|
||||
static void
|
||||
register_flight_controls (void)
|
||||
{
|
||||
int i, j, k;
|
||||
char buf[40];
|
||||
|
||||
buf[39] = '\0';
|
||||
|
||||
for (i = 0; i < NUM_TEMPLATES; i++)
|
||||
{
|
||||
/* Copy in name */
|
||||
snprintf (buf, 39, "keys.%d.name", i+1);
|
||||
if (res_HasKey (buf))
|
||||
{
|
||||
strncpy (input_templates[i].name, res_GetString (buf), 29);
|
||||
input_templates[i].name[29] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
input_templates[i].name[0] = '\0';
|
||||
}
|
||||
for (j = 0; j < NUM_KEYS; j++)
|
||||
{
|
||||
for (k = 0; k < 2; k++)
|
||||
{
|
||||
VCONTROL_GESTURE *g = &controls[i][j][k];
|
||||
snprintf (buf, 39, "keys.%d.%s.%d", i+1, flight_res_names[j], k+1);
|
||||
if (!res_HasKey (buf))
|
||||
{
|
||||
g->type = VCONTROL_NONE;
|
||||
continue;
|
||||
}
|
||||
VControl_ParseGesture (g, res_GetString (buf));
|
||||
VControl_AddGestureBinding (g, (int *)&ImmediateInputState.key[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
initKeyConfig (void)
|
||||
{
|
||||
uio_Stream *fp;
|
||||
int i, errors;
|
||||
|
||||
for (i = 0; i < 2; ++i)
|
||||
int i;
|
||||
|
||||
/* First, load in the menu keys */
|
||||
res_LoadFilename (contentDir, "menu.key");
|
||||
for (i = 0; i < NUM_MENU_KEYS; i++)
|
||||
{
|
||||
if ((fp = res_OpenResFile (configDir, "keys.cfg", "rt")) == NULL)
|
||||
if (!menu_res_names[i])
|
||||
break;
|
||||
register_menu_controls (i);
|
||||
}
|
||||
|
||||
fp = res_OpenResFile (configDir, "flight.cfg", "rt");
|
||||
if (!fp)
|
||||
{
|
||||
if (copyFile (contentDir, "uqm.key",
|
||||
configDir, "flight.cfg") == -1)
|
||||
{
|
||||
if (copyFile (contentDir, "starcon.key",
|
||||
configDir, "keys.cfg") == -1)
|
||||
{
|
||||
log_add (log_Fatal, "Error: Could not copy default key config "
|
||||
"to user config dir: %s.", strerror (errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
log_add (log_Info, "Copying default key config file to user "
|
||||
"config dir.");
|
||||
|
||||
if ((fp = res_OpenResFile (configDir, "keys.cfg", "rt")) == NULL)
|
||||
{
|
||||
log_add (log_Fatal, "Error: Could not open keys.cfg");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
errors = VControl_ReadConfiguration (fp);
|
||||
res_CloseResFile (fp);
|
||||
|
||||
if (errors || (VControl_GetConfigFileVersion () != VCONTROL_VERSION))
|
||||
{
|
||||
bool do_rename = false;
|
||||
if (errors)
|
||||
log_add (log_Warning, "%d errors encountered in key configuration file.", errors);
|
||||
|
||||
if (VControl_GetValidCount () == 0)
|
||||
{
|
||||
log_add (log_Error, "\nI didn't understand a single line in your configuration file.");
|
||||
log_add (log_Error, "This is likely because you're still using a 0.2 era or earlier keys.cfg.");
|
||||
do_rename = true;
|
||||
}
|
||||
if (VControl_GetConfigFileVersion () != VCONTROL_VERSION)
|
||||
{
|
||||
log_add (log_Error, "\nThe control scheme for UQM has changed since you last updated keys.cfg.");
|
||||
log_add (log_Error, "(I'm using control scheme version %d, while your config file appears to be\nfor version %d.)", VCONTROL_VERSION, VControl_GetConfigFileVersion ());
|
||||
do_rename = true;
|
||||
}
|
||||
|
||||
if (do_rename)
|
||||
{
|
||||
log_add (log_Error, "\nRenaming keys.cfg to keys.old and retrying.");
|
||||
|
||||
if (fileExists2 (configDir, "keys.old"))
|
||||
uio_unlink (configDir, "keys.old");
|
||||
if ((uio_rename (configDir, "keys.cfg", configDir, "keys.old")) == -1)
|
||||
{
|
||||
log_add (log_Fatal, "Error: Renaming failed!");
|
||||
log_add (log_Fatal, "You must delete keys.cfg manually before you can run the game.");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
log_add (log_Fatal, "\nRepair your keys.cfg file to continue.");
|
||||
log_add (log_Fatal, "Error: Could not copy default key config "
|
||||
"to user config dir: %s.", strerror (errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
log_add (log_Info, "Copying default key config file to user "
|
||||
"config dir.");
|
||||
|
||||
return;
|
||||
if ((fp = res_OpenResFile (configDir, "flight.cfg", "rt")) == NULL)
|
||||
{
|
||||
log_add (log_Fatal, "Error: Could not open flight.cfg");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
res_LoadFile (fp);
|
||||
res_CloseResFile (fp);
|
||||
|
||||
log_add (log_Fatal, "Error: Something went wrong and we were looping again and again so aborting.");
|
||||
log_add (log_Fatal, "Possible cause is your content dir not being up-to-date.");
|
||||
exit (EXIT_FAILURE);
|
||||
register_flight_controls ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -239,7 +234,6 @@ TFB_InitInput (int driver, int flags)
|
||||
|
||||
/* Prepare the Virtual Controller system. */
|
||||
VControl_Init ();
|
||||
VControl_RegisterNameTable (control_names);
|
||||
|
||||
initKeyConfig ();
|
||||
|
||||
@@ -387,62 +381,45 @@ FlushInput (void)
|
||||
void
|
||||
InterrogateInputState (int template, int control, int index, char *buffer, int maxlen)
|
||||
{
|
||||
int i;
|
||||
VCONTROL_GESTURE g;
|
||||
VCONTROL_GESTURE *g = &controls[template][control][index];
|
||||
|
||||
VControl_StartIter (&ImmediateInputState.key[template][control]);
|
||||
i = 0;
|
||||
while (VControl_NextBinding (&g))
|
||||
switch (g->type)
|
||||
{
|
||||
if (i++ < index)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (g.type)
|
||||
{
|
||||
case VCONTROL_KEY:
|
||||
snprintf (buffer, maxlen, "%s", VControl_code2name (g.gesture.key));
|
||||
buffer[maxlen-1] = 0;
|
||||
break;
|
||||
case VCONTROL_JOYBUTTON:
|
||||
snprintf (buffer, maxlen, "[J%d B%d]", g.gesture.button.port, g.gesture.button.index + 1);
|
||||
buffer[maxlen-1] = 0;
|
||||
break;
|
||||
case VCONTROL_JOYAXIS:
|
||||
snprintf (buffer, maxlen, "[J%d A%d %c]", g.gesture.axis.port, g.gesture.axis.index, g.gesture.axis.polarity > 0 ? '+' : '-');
|
||||
break;
|
||||
case VCONTROL_JOYHAT:
|
||||
snprintf (buffer, maxlen, "[J%d H%d %d]", g.gesture.hat.port, g.gesture.hat.index, g.gesture.hat.dir);
|
||||
break;
|
||||
default:
|
||||
/* Something we don't handle yet */
|
||||
buffer[0] = 0;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
case VCONTROL_KEY:
|
||||
snprintf (buffer, maxlen, "%s", VControl_code2name (g->gesture.key));
|
||||
buffer[maxlen-1] = 0;
|
||||
break;
|
||||
case VCONTROL_JOYBUTTON:
|
||||
snprintf (buffer, maxlen, "[J%d B%d]", g->gesture.button.port, g->gesture.button.index + 1);
|
||||
buffer[maxlen-1] = 0;
|
||||
break;
|
||||
case VCONTROL_JOYAXIS:
|
||||
snprintf (buffer, maxlen, "[J%d A%d %c]", g->gesture.axis.port, g->gesture.axis.index, g->gesture.axis.polarity > 0 ? '+' : '-');
|
||||
break;
|
||||
case VCONTROL_JOYHAT:
|
||||
snprintf (buffer, maxlen, "[J%d H%d %d]", g->gesture.hat.port, g->gesture.hat.index, g->gesture.hat.dir);
|
||||
break;
|
||||
default:
|
||||
/* Something we don't handle yet */
|
||||
buffer[0] = 0;
|
||||
break;
|
||||
}
|
||||
/* There aren't that many bindings, so return blank string */
|
||||
buffer[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
RemoveInputState (int template, int control, int index)
|
||||
{
|
||||
int i;
|
||||
VCONTROL_GESTURE g;
|
||||
VCONTROL_GESTURE *g = &controls[template][control][index];
|
||||
char keybuf[40];
|
||||
keybuf[39] = '\0';
|
||||
|
||||
VControl_RemoveGestureBinding (g, (int *)&ImmediateInputState.key[template][control]);
|
||||
g->type = VCONTROL_NONE;
|
||||
|
||||
snprintf (keybuf, 39, "keys.%d.%s.%d", template+1, flight_res_names[control], index+1);
|
||||
res_Remove (keybuf);
|
||||
|
||||
VControl_StartIter (&ImmediateInputState.key[template][control]);
|
||||
i = 0;
|
||||
while (VControl_NextBinding (&g))
|
||||
{
|
||||
if (i++ < index)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
VControl_RemoveGestureBinding (&g, &ImmediateInputState.key[template][control]);
|
||||
return;
|
||||
}
|
||||
/* No such gesture! */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -450,6 +427,8 @@ void
|
||||
RebindInputState (int template, int control, int index)
|
||||
{
|
||||
VCONTROL_GESTURE g;
|
||||
char keybuf[40], valbuf[40];
|
||||
keybuf[39] = valbuf[39] = '\0';
|
||||
|
||||
/* Remove the old binding on this spot */
|
||||
RemoveInputState (template, control, index);
|
||||
@@ -462,7 +441,11 @@ RebindInputState (int template, int control, int index)
|
||||
}
|
||||
|
||||
/* And now, add the new binding. */
|
||||
VControl_AddGestureBinding (&g, &ImmediateInputState.key[template][control]);
|
||||
VControl_AddGestureBinding (&g, (int *)&ImmediateInputState.key[template][control]);
|
||||
controls[template][control][index] = g;
|
||||
snprintf (keybuf, 39, "keys.%d.%s.%d", template+1, flight_res_names[control], index+1);
|
||||
VControl_DumpGesture (valbuf, 39, &g);
|
||||
res_PutString (keybuf, valbuf);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -473,9 +456,9 @@ SaveKeyConfiguration (uio_DirHandle *path, const char *fname)
|
||||
f = res_OpenResFile (path, fname, "wb");
|
||||
if (f)
|
||||
{
|
||||
VControl_Dump (f);
|
||||
res_SaveFile (f, "keys.");
|
||||
res_CloseResFile (f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -71,16 +71,6 @@ static int num_sdl_keys = 0;
|
||||
static keybinding **bindings = NULL;
|
||||
|
||||
static keypool *pool;
|
||||
static VControl_NameBinding *nametable;
|
||||
|
||||
/* Statistics variables - set by VControl_ReadConfiguration */
|
||||
|
||||
static int version, errors, validlines;
|
||||
|
||||
/* Iterator temp variables */
|
||||
|
||||
static int *iter_target;
|
||||
static int iter_device, iter_index;
|
||||
|
||||
/* Last interesting event */
|
||||
static int event_ready;
|
||||
@@ -243,30 +233,16 @@ key_uninit (void)
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
}
|
||||
|
||||
static void
|
||||
name_init (void)
|
||||
{
|
||||
nametable = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
name_uninit (void)
|
||||
{
|
||||
nametable = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
VControl_Init (void)
|
||||
{
|
||||
key_init ();
|
||||
name_init ();
|
||||
}
|
||||
|
||||
void
|
||||
VControl_Uninit (void)
|
||||
{
|
||||
key_uninit ();
|
||||
name_uninit ();
|
||||
}
|
||||
|
||||
int
|
||||
@@ -413,8 +389,6 @@ event2gesture (SDL_Event *e, VCONTROL_GESTURE *g)
|
||||
g->type = VCONTROL_KEY;
|
||||
g->gesture.key = e->key.keysym.sym;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_JOYSTICK
|
||||
case SDL_JOYAXISMOTION:
|
||||
g->type = VCONTROL_JOYAXIS;
|
||||
g->gesture.axis.port = e->jaxis.which;
|
||||
@@ -432,7 +406,6 @@ event2gesture (SDL_Event *e, VCONTROL_GESTURE *g)
|
||||
g->gesture.button.port = e->jbutton.which;
|
||||
g->gesture.button.index = e->jbutton.button;
|
||||
break;
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
|
||||
default:
|
||||
g->type = VCONTROL_NONE;
|
||||
@@ -450,17 +423,24 @@ VControl_AddGestureBinding (VCONTROL_GESTURE *g, int *target)
|
||||
result = VControl_AddKeyBinding (g->gesture.key, target);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_JOYSTICK
|
||||
case VCONTROL_JOYAXIS:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
result = VControl_AddJoyAxisBinding (g->gesture.axis.port, g->gesture.axis.index, (g->gesture.axis.polarity < 0) ? -1 : 1, target);
|
||||
break;
|
||||
#endif
|
||||
case VCONTROL_JOYHAT:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
result = VControl_AddJoyHatBinding (g->gesture.hat.port, g->gesture.hat.index, g->gesture.hat.dir, target);
|
||||
break;
|
||||
#endif
|
||||
case VCONTROL_JOYBUTTON:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
result = VControl_AddJoyButtonBinding (g->gesture.button.port, g->gesture.button.index, target);
|
||||
break;
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
case VCONTROL_NONE:
|
||||
/* Do nothing */
|
||||
break;
|
||||
|
||||
default:
|
||||
log_add (log_Warning, "VControl_AddGestureBinding didn't understand argument gesture");
|
||||
@@ -479,18 +459,23 @@ VControl_RemoveGestureBinding (VCONTROL_GESTURE *g, int *target)
|
||||
VControl_RemoveKeyBinding (g->gesture.key, target);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_JOYSTICK
|
||||
case VCONTROL_JOYAXIS:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
VControl_RemoveJoyAxisBinding (g->gesture.axis.port, g->gesture.axis.index, (g->gesture.axis.polarity < 0) ? -1 : 1, target);
|
||||
break;
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
case VCONTROL_JOYHAT:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
VControl_RemoveJoyHatBinding (g->gesture.hat.port, g->gesture.hat.index, g->gesture.hat.dir, target);
|
||||
break;
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
case VCONTROL_JOYBUTTON:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
VControl_RemoveJoyButtonBinding (g->gesture.button.port, g->gesture.button.index, target);
|
||||
break;
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
|
||||
case VCONTROL_NONE:
|
||||
break;
|
||||
default:
|
||||
log_add (log_Warning, "VControl_RemoveGestureBinding didn't understand argument gesture");
|
||||
break;
|
||||
@@ -948,299 +933,6 @@ VControl_HandleEvent (const SDL_Event *e)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VControl_RegisterNameTable (VControl_NameBinding *table)
|
||||
{
|
||||
nametable = table;
|
||||
}
|
||||
|
||||
static char *
|
||||
target2name (int *target)
|
||||
{
|
||||
VControl_NameBinding *b = nametable;
|
||||
while (b->target)
|
||||
{
|
||||
if (target == b->target)
|
||||
{
|
||||
return b->name;
|
||||
}
|
||||
++b;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int *
|
||||
name2target (char *name)
|
||||
{
|
||||
VControl_NameBinding *b = nametable;
|
||||
while (b->target)
|
||||
{
|
||||
if (!stricmp (name, b->name))
|
||||
{
|
||||
return b->target;
|
||||
}
|
||||
++b;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_keybindings (uio_Stream *out, keybinding *kb, char *name)
|
||||
{
|
||||
while (kb != NULL)
|
||||
{
|
||||
char *targetname = target2name (kb->target);
|
||||
WriteResFile (targetname, 1, strlen (targetname), out);
|
||||
PutResFileChar (':', out);
|
||||
PutResFileChar (' ', out);
|
||||
WriteResFile (name, 1, strlen (name), out);
|
||||
PutResFileNewline (out);
|
||||
|
||||
kb = kb->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VControl_Dump (uio_Stream *out)
|
||||
{
|
||||
int i;
|
||||
char namebuffer[64];
|
||||
|
||||
sprintf (namebuffer, "version %d", version);
|
||||
WriteResFile (namebuffer, 1, strlen (namebuffer), out);
|
||||
PutResFileNewline (out);
|
||||
|
||||
/* Print out keyboard bindings */
|
||||
for (i = 0; i < num_sdl_keys; i++)
|
||||
{
|
||||
keybinding *kb = bindings[i];
|
||||
if (kb != NULL)
|
||||
{
|
||||
sprintf (namebuffer, "key %s", VControl_code2name (i));
|
||||
dump_keybindings (out, kb, namebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_JOYSTICK
|
||||
/* Print out joystick bindings */
|
||||
for (i = 0; i < joycount; i++)
|
||||
{
|
||||
if (joysticks[i].stick)
|
||||
{
|
||||
int j;
|
||||
|
||||
sprintf (namebuffer, "joystick %d threshold %d", i, joysticks[i].threshold);
|
||||
WriteResFile (namebuffer, 1, strlen (namebuffer), out);
|
||||
PutResFileNewline (out);
|
||||
|
||||
for (j = 0; j < joysticks[i].numaxes; j++)
|
||||
{
|
||||
sprintf (namebuffer, "joystick %d axis %d negative", i, j);
|
||||
dump_keybindings (out, joysticks[i].axes[j].neg, namebuffer);
|
||||
sprintf (namebuffer, "joystick %d axis %d positive", i, j);
|
||||
dump_keybindings (out, joysticks[i].axes[j].pos, namebuffer);
|
||||
}
|
||||
for (j = 0; j < joysticks[i].numbuttons; j++)
|
||||
{
|
||||
keybinding *kb = joysticks[i].buttons[j];
|
||||
if (kb != NULL)
|
||||
{
|
||||
sprintf (namebuffer, "joystick %d button %d", i, j);
|
||||
dump_keybindings (out, kb, namebuffer);
|
||||
}
|
||||
}
|
||||
for (j = 0; j < joysticks[i].numhats; j++)
|
||||
{
|
||||
sprintf (namebuffer, "joystick %d hat %d left", i, j);
|
||||
dump_keybindings (out, joysticks[i].hats[j].left, namebuffer);
|
||||
sprintf (namebuffer, "joystick %d hat %d right", i, j);
|
||||
dump_keybindings (out, joysticks[i].hats[j].right, namebuffer);
|
||||
sprintf (namebuffer, "joystick %d hat %d up", i, j);
|
||||
dump_keybindings (out, joysticks[i].hats[j].up, namebuffer);
|
||||
sprintf (namebuffer, "joystick %d hat %d down", i, j);
|
||||
dump_keybindings (out, joysticks[i].hats[j].down, namebuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
|
||||
#ifdef VCONTROL_DEBUG
|
||||
/* Print out allocation data */
|
||||
{
|
||||
keypool bp = pool;
|
||||
i = 0;
|
||||
while (bp != NULL)
|
||||
{
|
||||
fprintf (out, "# Internal Debug: Chunk #%i: %d slots remaining.\n", i, bp->remaining);
|
||||
i++;
|
||||
bp = bp->next;
|
||||
}
|
||||
fprintf (out, "# Internal Debug: %d chunks allocated.\n", i);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Iterator routines. iter_target holds the target keybinding.
|
||||
iter_device is -1 for the keyboard, otherwise it is joystick
|
||||
#(iter_device/3). (iter_device%3) gives whether we're checking the
|
||||
joystick's axes (0), buttons (1), or hats (2). */
|
||||
|
||||
static int *iter_target;
|
||||
static int iter_device, iter_index;
|
||||
|
||||
void
|
||||
VControl_StartIter (int *target)
|
||||
{
|
||||
iter_target = target;
|
||||
iter_device = -1;
|
||||
iter_index = 0;
|
||||
}
|
||||
|
||||
void
|
||||
VControl_StartIterByName (char *targetname)
|
||||
{
|
||||
VControl_StartIter (name2target (targetname));
|
||||
}
|
||||
|
||||
int
|
||||
VControl_NextBinding (VCONTROL_GESTURE *gesture)
|
||||
{
|
||||
if ((gesture == NULL) || (iter_target == NULL)
|
||||
|| iter_device >= (joycount * 3))
|
||||
return 0;
|
||||
while (iter_device < (joycount * 3))
|
||||
{
|
||||
if (iter_device == -1) /* keyboard */
|
||||
{
|
||||
keybinding *kb = bindings[iter_index];
|
||||
int done = 0;
|
||||
while (kb != NULL)
|
||||
{
|
||||
if (kb->target == iter_target)
|
||||
{
|
||||
gesture->type = VCONTROL_KEY;
|
||||
gesture->gesture.key = iter_index;
|
||||
done = 1;
|
||||
}
|
||||
kb = kb->next;
|
||||
}
|
||||
if (++iter_index == num_sdl_keys)
|
||||
{
|
||||
iter_device = 0;
|
||||
iter_index = 0;
|
||||
}
|
||||
if (done) return 1;
|
||||
}
|
||||
#ifdef HAVE_JOYSTICK
|
||||
else
|
||||
{
|
||||
int i = iter_device / 3;
|
||||
int t = iter_device % 3;
|
||||
if (!joysticks[i].stick) /* Joystick wasn't opened; this binding is dead */
|
||||
{
|
||||
iter_device++;
|
||||
iter_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int done = 0;
|
||||
switch (t)
|
||||
{
|
||||
case 0: { /* Axes */
|
||||
int axis = iter_index / 2;
|
||||
int dir = iter_index % 2;
|
||||
if (axis >= joysticks[i].numaxes)
|
||||
{
|
||||
iter_device++;
|
||||
iter_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
keybinding *kb = (dir) ? joysticks[i].axes[axis].pos : joysticks[i].axes[axis].neg;
|
||||
while (kb != NULL)
|
||||
{
|
||||
if (kb->target == iter_target)
|
||||
{
|
||||
done = 1;
|
||||
gesture->type = VCONTROL_JOYAXIS;
|
||||
gesture->gesture.axis.port = i;
|
||||
gesture->gesture.axis.index = axis;
|
||||
gesture->gesture.axis.polarity = (dir) ? 1 : -1;
|
||||
}
|
||||
kb = kb->next;
|
||||
}
|
||||
iter_index++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: { /* Buttons */
|
||||
keybinding *kb = joysticks[i].buttons[iter_index];
|
||||
if (iter_index >= joysticks[i].numbuttons)
|
||||
{
|
||||
iter_device++;
|
||||
iter_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (kb != NULL)
|
||||
{
|
||||
if (kb->target == iter_target)
|
||||
{
|
||||
gesture->type = VCONTROL_JOYBUTTON;
|
||||
gesture->gesture.button.port = i;
|
||||
gesture->gesture.button.index = iter_index;
|
||||
done = 1;
|
||||
}
|
||||
kb = kb->next;
|
||||
}
|
||||
iter_index++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: { /* Hats */
|
||||
int hat = iter_index / 4;
|
||||
int hatd = iter_index % 4;
|
||||
if (hat >= joysticks[i].numhats)
|
||||
{
|
||||
iter_device++;
|
||||
iter_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
keybinding *kb;
|
||||
Uint8 targetdir;
|
||||
switch (hatd)
|
||||
{
|
||||
case 0: kb = joysticks[i].hats[hat].left; targetdir = SDL_HAT_LEFT; break;
|
||||
case 1: kb = joysticks[i].hats[hat].right; targetdir = SDL_HAT_RIGHT; break;
|
||||
case 2: kb = joysticks[i].hats[hat].up; targetdir = SDL_HAT_UP; break;
|
||||
default: kb = joysticks[i].hats[hat].down; targetdir = SDL_HAT_DOWN; break;
|
||||
}
|
||||
while (kb != NULL)
|
||||
{
|
||||
if (kb->target == iter_target)
|
||||
{
|
||||
done = 1;
|
||||
gesture->type = VCONTROL_JOYHAT;
|
||||
gesture->gesture.hat.port = i;
|
||||
gesture->gesture.hat.index = hat;
|
||||
gesture->gesture.hat.dir = targetdir;
|
||||
}
|
||||
kb = kb->next;
|
||||
}
|
||||
iter_index++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (done) return 1;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Tracking the last interesting event */
|
||||
|
||||
void
|
||||
@@ -1337,43 +1029,6 @@ next_token (parse_state *state)
|
||||
state->index = base+index;
|
||||
}
|
||||
|
||||
static void
|
||||
next_line (parse_state *state, uio_Stream *in)
|
||||
{
|
||||
int i, ch = 0;
|
||||
state->linenum++;
|
||||
for (i = 0; i < LINE_SIZE-1; i++)
|
||||
{
|
||||
if (uio_feof (in))
|
||||
{
|
||||
break;
|
||||
}
|
||||
ch = uio_fgetc (in);
|
||||
if (ch == '#' || ch == '\n' || ch == EOF)
|
||||
{
|
||||
/* If this line is blank or all commented, include some
|
||||
* whitespace. This lets us detect EOF as a completely
|
||||
* blank line. */
|
||||
if (i==0)
|
||||
{
|
||||
state->line[i] = '\n';
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
state->line[i] = ch;
|
||||
}
|
||||
state->line[i] = '\0';
|
||||
/* Skip to end of line */
|
||||
while (ch != '\n' && !uio_feof (in))
|
||||
{
|
||||
ch = uio_fgetc (in);
|
||||
}
|
||||
state->token[0] = 0;
|
||||
state->index = 0;
|
||||
state->error = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
expected_error (parse_state *state, char *expected)
|
||||
{
|
||||
@@ -1406,45 +1061,6 @@ consume_keyname (parse_state *state)
|
||||
return keysym;
|
||||
}
|
||||
|
||||
static int *
|
||||
consume_idname (parse_state *state)
|
||||
{
|
||||
int *result = NULL;
|
||||
int index = 0;
|
||||
while (state->token[index])
|
||||
{
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
log_add (log_Debug, "VControl: Can't happen: blank token to consume_idname (line %d)",
|
||||
state->linenum);
|
||||
state->error = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index--;
|
||||
if (state->token[index] != ':')
|
||||
{
|
||||
expected_error (state, ":");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->token[index] = 0; /* remove trailing colon */
|
||||
|
||||
result = name2target (state->token);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
log_add (log_Warning, "VControl: Illegal command type '%s' on config file line %d",
|
||||
state->token, state->linenum);
|
||||
state->error = 1;
|
||||
}
|
||||
next_token (state);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
consume_num (parse_state *state)
|
||||
{
|
||||
@@ -1484,7 +1100,6 @@ static Uint8
|
||||
consume_dir (parse_state *state)
|
||||
{
|
||||
Uint8 result = 0;
|
||||
#ifdef HAVE_JOYSTICK
|
||||
if (!stricmp (state->token, "left"))
|
||||
{
|
||||
result = SDL_HAT_LEFT;
|
||||
@@ -1505,7 +1120,6 @@ consume_dir (parse_state *state)
|
||||
{
|
||||
expected_error (state, "left', 'right', 'up' or 'down");
|
||||
}
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
next_token (state);
|
||||
return result;
|
||||
}
|
||||
@@ -1586,29 +1200,14 @@ parse_gesture (parse_state *state, VCONTROL_GESTURE *gesture)
|
||||
gesture->type = VCONTROL_KEY;
|
||||
gesture->gesture.key = keysym;
|
||||
}
|
||||
else if (!stricmp (state->token, "joystick"))
|
||||
{
|
||||
parse_joybinding (state, gesture);
|
||||
}
|
||||
else
|
||||
{
|
||||
expected_error (state, "key' or 'joystick");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_binding (parse_state *state)
|
||||
{
|
||||
int *target = consume_idname (state);
|
||||
if (!state->error)
|
||||
else if (!stricmp (state->token, "joystick"))
|
||||
{
|
||||
VCONTROL_GESTURE g;
|
||||
parse_gesture (state, &g);
|
||||
if (g.type != VCONTROL_NONE)
|
||||
{
|
||||
VControl_AddGestureBinding (&g, target);
|
||||
}
|
||||
parse_joybinding (state, gesture);
|
||||
}
|
||||
else
|
||||
{
|
||||
expected_error (state, "key' or 'joystick");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1624,6 +1223,8 @@ VControl_ParseGesture (VCONTROL_GESTURE *g, const char *spec)
|
||||
|
||||
next_token (&ps);
|
||||
parse_gesture (&ps, g);
|
||||
if (ps.error)
|
||||
printf ("Error parsing %s\n", spec);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -1648,133 +1249,3 @@ VControl_DumpGesture (char *buf, int n, VCONTROL_GESTURE *g)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_config_line (parse_state *state)
|
||||
{
|
||||
state->error = 0;
|
||||
next_token (state);
|
||||
if (!state->token[0])
|
||||
{
|
||||
/* Blank line, skip it */
|
||||
return;
|
||||
}
|
||||
if (!stricmp (state->token, "joystick"))
|
||||
{
|
||||
int sticknum, threshold = 0;
|
||||
consume (state, "joystick");
|
||||
sticknum = consume_num (state);
|
||||
if (!state->error) consume (state, "threshold");
|
||||
if (!state->error) threshold = consume_num (state);
|
||||
if (!state->error)
|
||||
{
|
||||
if (VControl_SetJoyThreshold (sticknum, threshold))
|
||||
{
|
||||
// Don't count this as an error
|
||||
// state->error = 1;
|
||||
}
|
||||
}
|
||||
if (!state->error)
|
||||
{
|
||||
validlines++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!stricmp (state->token, "version"))
|
||||
{
|
||||
consume (state, "version");
|
||||
version = consume_num (state);
|
||||
if (!state->error)
|
||||
{
|
||||
validlines++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Otherwise, it must be a binding */
|
||||
parse_binding (state);
|
||||
if (!state->error)
|
||||
{
|
||||
validlines++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
VControl_ReadConfiguration (uio_Stream *in)
|
||||
{
|
||||
parse_state ps;
|
||||
if (!in)
|
||||
{
|
||||
log_add (log_Warning, "VControl: Invalid configuration file stream");
|
||||
return 1;
|
||||
}
|
||||
ps.linenum = 0;
|
||||
errors = version = validlines = 0;
|
||||
while (1)
|
||||
{
|
||||
next_line (&ps, in);
|
||||
if (!ps.line[0])
|
||||
break;
|
||||
parse_config_line (&ps);
|
||||
if (ps.error)
|
||||
{
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
int
|
||||
VControl_GetErrorCount (void)
|
||||
{
|
||||
return errors;
|
||||
}
|
||||
|
||||
int
|
||||
VControl_GetValidCount (void)
|
||||
{
|
||||
return validlines;
|
||||
}
|
||||
|
||||
int
|
||||
VControl_GetConfigFileVersion (void)
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
void
|
||||
VControl_SetConfigFileVersion (int v)
|
||||
{
|
||||
version = v;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This was kinda handy for proving (lack of) buffer overrun
|
||||
* vulnerabilities, but there's no real need for it otherwise. */
|
||||
void
|
||||
VControl_TokenizeFile (FILE *in)
|
||||
{
|
||||
parse_state ps;
|
||||
if (!in)
|
||||
{
|
||||
log_add (log_Warning, "VControl: Invalid configuration file stream");
|
||||
return;
|
||||
}
|
||||
ps.linenum = 0;
|
||||
while (1)
|
||||
{
|
||||
_next_line (&ps, in);
|
||||
if (!ps.line[0])
|
||||
break;
|
||||
printf ("%3d:", ps.linenum);
|
||||
while (1)
|
||||
{
|
||||
_next_token (&ps);
|
||||
if (!ps.token[0])
|
||||
break;
|
||||
printf (" \"%s\"", ps.token);
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define _VCONTROL_H_
|
||||
|
||||
#include "port.h"
|
||||
#include "libs/uio.h"
|
||||
#include SDL_INCLUDE(SDL.h)
|
||||
|
||||
/* Initialization routines */
|
||||
@@ -80,45 +79,10 @@ void VControl_ProcessJoyHat (int port, int which, Uint8 value);
|
||||
/* Force the input into the blank state. For preventing "sticky" keys. */
|
||||
void VControl_ResetInput (void);
|
||||
|
||||
/* Name control. To provide a table of names and bindings, declare
|
||||
* a persistent, unchanging array of VControl_NameBinding and end it
|
||||
* with a {0, 0} entry. Pass this array to VControl_RegisterNameTable.
|
||||
* Only one name table may be registered at a time; subsequent calls
|
||||
* replace the previous values. */
|
||||
|
||||
typedef struct vcontrol_namebinding {
|
||||
char *name;
|
||||
int *target;
|
||||
} VControl_NameBinding;
|
||||
|
||||
void VControl_RegisterNameTable (VControl_NameBinding *table);
|
||||
|
||||
/* Version number control */
|
||||
int VControl_GetConfigFileVersion (void);
|
||||
void VControl_SetConfigFileVersion (int v);
|
||||
|
||||
/* Translate between gestures and string representations thereof. */
|
||||
void VControl_ParseGesture (VCONTROL_GESTURE *g, const char *spec);
|
||||
int VControl_DumpGesture (char *buf, int n, VCONTROL_GESTURE *g);
|
||||
|
||||
/* Dump a configuration file corresponding to the current bindings and names. */
|
||||
void VControl_Dump (uio_Stream *out);
|
||||
void VControl_SaveFilename (uio_DirHandle *path, const char *fname);
|
||||
|
||||
/* Read a configuration file. Returns number of errors encountered. */
|
||||
int VControl_ReadConfiguration (uio_Stream *in);
|
||||
int VControl_GetErrorCount (void);
|
||||
int VControl_GetValidCount (void);
|
||||
|
||||
|
||||
/* Iterator control. Start an iteration with StartIter or
|
||||
StartIterByName; then call NextBindingName until it returns 0.
|
||||
Produces gestures. */
|
||||
|
||||
void VControl_StartIter (int *target);
|
||||
void VControl_StartIterByName (char *targetname);
|
||||
int VControl_NextBinding (VCONTROL_GESTURE *gesture);
|
||||
|
||||
/* Tracking the "last interesting gesture." Used to poll to find new
|
||||
control keys. */
|
||||
|
||||
|
||||
@@ -1360,13 +1360,13 @@ SetGlobalOptions (GLOBALOPTS *opts)
|
||||
SetMusicVolume (musicVolume);
|
||||
SetSpeechVolume (speechVolumeScale);
|
||||
|
||||
res_PutString ("config.keys.1.name", input_templates[0].name);
|
||||
res_PutString ("config.keys.2.name", input_templates[1].name);
|
||||
res_PutString ("config.keys.3.name", input_templates[2].name);
|
||||
res_PutString ("config.keys.4.name", input_templates[3].name);
|
||||
res_PutString ("config.keys.5.name", input_templates[4].name);
|
||||
res_PutString ("config.keys.6.name", input_templates[5].name);
|
||||
res_PutString ("keys.1.name", input_templates[0].name);
|
||||
res_PutString ("keys.2.name", input_templates[1].name);
|
||||
res_PutString ("keys.3.name", input_templates[2].name);
|
||||
res_PutString ("keys.4.name", input_templates[3].name);
|
||||
res_PutString ("keys.5.name", input_templates[4].name);
|
||||
res_PutString ("keys.6.name", input_templates[5].name);
|
||||
|
||||
res_SaveFilename (configDir, "uqm.cfg", "config.");
|
||||
SaveKeyConfiguration (configDir, "keys.cfg");
|
||||
SaveKeyConfiguration (configDir, "flight.cfg");
|
||||
}
|
||||
|
||||
+2
-16
@@ -369,12 +369,7 @@ main (int argc, char *argv[])
|
||||
&options.speechVolumeScale, "speech volume");
|
||||
}
|
||||
|
||||
{ /* init control template names */
|
||||
static const char* defaultNames[] =
|
||||
{
|
||||
"Arrows", "WASD", "Arrows (2)",
|
||||
"ESDF", "Joystick 1", "Joystick 2"
|
||||
};
|
||||
{ /* remove old control template names */
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; ++i)
|
||||
@@ -384,16 +379,7 @@ main (int argc, char *argv[])
|
||||
snprintf(cfgkey, sizeof(cfgkey), "config.keys.%d.name", i + 1);
|
||||
cfgkey[sizeof(cfgkey) - 1] = '\0';
|
||||
|
||||
if (res_HasKey (cfgkey))
|
||||
{
|
||||
strncpy (input_templates[i].name, res_GetString (cfgkey), 30);
|
||||
input_templates[i].name[29] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (input_templates[i].name, defaultNames[i]);
|
||||
res_PutString (cfgkey, input_templates[i].name);
|
||||
}
|
||||
res_Remove (cfgkey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user