- moved most of the console code to 'common'.
The main console.cpp file cannot be done yet, but the rest is ready to go.
This commit is contained in:
parent
a712866219
commit
c3a381ed92
19 changed files with 16 additions and 12 deletions
|
|
@ -1,840 +0,0 @@
|
|||
/*
|
||||
** c_bind.cpp
|
||||
** Functions for using and maintaining key bindings
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include "keydef.h"
|
||||
#include "c_commandline.h"
|
||||
#include "c_bind.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "configfile.h"
|
||||
#include "filesystem.h"
|
||||
#include "templates.h"
|
||||
#include "i_time.h"
|
||||
#include "printf.h"
|
||||
#include "sc_man.h"
|
||||
#include "c_cvars.h"
|
||||
|
||||
#include "d_event.h"
|
||||
|
||||
extern int chatmodeon;
|
||||
|
||||
const char *KeyNames[NUM_KEYS] =
|
||||
{
|
||||
// We use the DirectInput codes and assume a qwerty keyboard layout.
|
||||
// See <dinput.h> for the DIK_* codes
|
||||
|
||||
nullptr, "Escape", "1", "2", "3", "4", "5", "6", //00
|
||||
"7", "8", "9", "0", "-", "=", "Backspace","Tab", //08
|
||||
"Q", "W", "E", "R", "T", "Y", "U", "I", //10
|
||||
"O", "P", "[", "]", "Enter", "LCtrl", "A", "S", //18
|
||||
"D", "F", "G", "H", "J", "K", "L", ";", //20
|
||||
"'", "`", "LShift", "\\", "Z", "X", "C", "V", //28
|
||||
"B", "N", "M", ",", ".", "/", "RShift", "KP*", //30
|
||||
"LAlt", "Space", "CapsLock", "F1", "F2", "F3", "F4", "F5", //38
|
||||
"F6", "F7", "F8", "F9", "F10", "NumLock", "Scroll", "KP7", //40
|
||||
"KP8", "KP9", "KP-", "KP4", "KP5", "KP6", "KP+", "KP1", //48
|
||||
"KP2", "KP3", "KP0", "KP.", nullptr, nullptr, "OEM102", "F11", //50
|
||||
"F12", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //58
|
||||
nullptr, nullptr, nullptr, nullptr, "F13", "F14", "F15", "F16", //60
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //68
|
||||
"Kana", nullptr, nullptr, "Abnt_C1", nullptr, nullptr, nullptr, nullptr, //70
|
||||
nullptr, "Convert", nullptr, "NoConvert",nullptr, "Yen", "Abnt_C2", nullptr, //78
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //80
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, "KP=", nullptr, nullptr, //88
|
||||
"Circumflex","@", ":", "_", "Kanji", "Stop", "Ax", "Unlabeled",//90
|
||||
nullptr, "PrevTrack",nullptr, nullptr, "KP-Enter", "RCtrl", nullptr, nullptr, //98
|
||||
"Mute", "Calculator","Play", nullptr, "Stop", nullptr, nullptr, nullptr, //A0
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "VolDown", nullptr, //A8
|
||||
"VolUp", nullptr, "WebHome", "KP,", nullptr, "KP/", nullptr, "SysRq", //B0
|
||||
"RAlt", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //B8
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, "Pause", nullptr, "Home", //C0
|
||||
"UpArrow", "PgUp", nullptr, "LeftArrow",nullptr, "RightArrow",nullptr, "End", //C8
|
||||
"DownArrow","PgDn", "Ins", "Del", nullptr, nullptr, nullptr, nullptr, //D0
|
||||
#ifdef __APPLE__
|
||||
nullptr, nullptr, nullptr, "Command", nullptr, "Apps", "Power", "Sleep", //D8
|
||||
#else // !__APPLE__
|
||||
nullptr, nullptr, nullptr, "LWin", "RWin", "Apps", "Power", "Sleep", //D8
|
||||
#endif // __APPLE__
|
||||
nullptr, nullptr, nullptr, "Wake", nullptr, "Search", "Favorites","Refresh", //E0
|
||||
"WebStop", "WebForward","WebBack", "MyComputer","Mail", "MediaSelect",nullptr, nullptr, //E8
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //F0
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //F8
|
||||
|
||||
// non-keyboard buttons that can be bound
|
||||
"Mouse1", "Mouse2", "Mouse3", "Mouse4", // 8 mouse buttons
|
||||
"Mouse5", "Mouse6", "Mouse7", "Mouse8",
|
||||
|
||||
"Joy1", "Joy2", "Joy3", "Joy4", // 128 joystick buttons!
|
||||
"Joy5", "Joy6", "Joy7", "Joy8",
|
||||
"Joy9", "Joy10", "Joy11", "Joy12",
|
||||
"Joy13", "Joy14", "Joy15", "Joy16",
|
||||
"Joy17", "Joy18", "Joy19", "Joy20",
|
||||
"Joy21", "Joy22", "Joy23", "Joy24",
|
||||
"Joy25", "Joy26", "Joy27", "Joy28",
|
||||
"Joy29", "Joy30", "Joy31", "Joy32",
|
||||
"Joy33", "Joy34", "Joy35", "Joy36",
|
||||
"Joy37", "Joy38", "Joy39", "Joy40",
|
||||
"Joy41", "Joy42", "Joy43", "Joy44",
|
||||
"Joy45", "Joy46", "Joy47", "Joy48",
|
||||
"Joy49", "Joy50", "Joy51", "Joy52",
|
||||
"Joy53", "Joy54", "Joy55", "Joy56",
|
||||
"Joy57", "Joy58", "Joy59", "Joy60",
|
||||
"Joy61", "Joy62", "Joy63", "Joy64",
|
||||
"Joy65", "Joy66", "Joy67", "Joy68",
|
||||
"Joy69", "Joy70", "Joy71", "Joy72",
|
||||
"Joy73", "Joy74", "Joy75", "Joy76",
|
||||
"Joy77", "Joy78", "Joy79", "Joy80",
|
||||
"Joy81", "Joy82", "Joy83", "Joy84",
|
||||
"Joy85", "Joy86", "Joy87", "Joy88",
|
||||
"Joy89", "Joy90", "Joy91", "Joy92",
|
||||
"Joy93", "Joy94", "Joy95", "Joy96",
|
||||
"Joy97", "Joy98", "Joy99", "Joy100",
|
||||
"Joy101", "Joy102", "Joy103", "Joy104",
|
||||
"Joy105", "Joy106", "Joy107", "Joy108",
|
||||
"Joy109", "Joy110", "Joy111", "Joy112",
|
||||
"Joy113", "Joy114", "Joy115", "Joy116",
|
||||
"Joy117", "Joy118", "Joy119", "Joy120",
|
||||
"Joy121", "Joy122", "Joy123", "Joy124",
|
||||
"Joy125", "Joy126", "Joy127", "Joy128",
|
||||
|
||||
"POV1Up", "POV1Right","POV1Down", "POV1Left", // First POV hat
|
||||
"POV2Up", "POV2Right","POV2Down", "POV2Left", // Second POV hat
|
||||
"POV3Up", "POV3Right","POV3Down", "POV3Left", // Third POV hat
|
||||
"POV4Up", "POV4Right","POV4Down", "POV4Left", // Fourth POV hat
|
||||
|
||||
"MWheelUp", "MWheelDown", // the mouse wheel
|
||||
"MWheelRight", "MWheelLeft",
|
||||
|
||||
"Axis1Plus","Axis1Minus","Axis2Plus","Axis2Minus", // joystick axes as buttons
|
||||
"Axis3Plus","Axis3Minus","Axis4Plus","Axis4Minus",
|
||||
"Axis5Plus","Axis5Minus","Axis6Plus","Axis6Minus",
|
||||
"Axis7Plus","Axis7Minus","Axis8Plus","Axis8Minus",
|
||||
|
||||
"LStickRight","LStickLeft","LStickDown","LStickUp", // Gamepad axis-based buttons
|
||||
"RStickRight","RStickLeft","RStickDown","RStickUp",
|
||||
|
||||
"DPadUp","DPadDown","DPadLeft","DPadRight", // Gamepad buttons
|
||||
"Pad_Start","Pad_Back","LThumb","RThumb",
|
||||
"LShoulder","RShoulder","LTrigger","RTrigger",
|
||||
"Pad_A", "Pad_B", "Pad_X", "Pad_Y"
|
||||
};
|
||||
|
||||
FKeyBindings Bindings;
|
||||
FKeyBindings DoubleBindings;
|
||||
FKeyBindings AutomapBindings;
|
||||
|
||||
static unsigned int DClickTime[NUM_KEYS];
|
||||
static FixedBitArray<NUM_KEYS> DClicked;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
static int GetKeyFromName (const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Names of the form #xxx are translated to key xxx automatically
|
||||
if (name[0] == '#' && name[1] != 0)
|
||||
{
|
||||
return atoi (name + 1);
|
||||
}
|
||||
|
||||
// Otherwise, we scan the KeyNames[] array for a matching name
|
||||
for (i = 0; i < NUM_KEYS; i++)
|
||||
{
|
||||
if (KeyNames[i] && !stricmp (KeyNames[i], name))
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
static int GetConfigKeyFromName (const char *key)
|
||||
{
|
||||
int keynum = GetKeyFromName(key);
|
||||
if (keynum == 0)
|
||||
{
|
||||
if (stricmp (key, "LeftBracket") == 0)
|
||||
{
|
||||
keynum = GetKeyFromName ("[");
|
||||
}
|
||||
else if (stricmp (key, "RightBracket") == 0)
|
||||
{
|
||||
keynum = GetKeyFromName ("]");
|
||||
}
|
||||
else if (stricmp (key, "Equals") == 0)
|
||||
{
|
||||
keynum = GetKeyFromName ("=");
|
||||
}
|
||||
else if (stricmp (key, "KP-Equals") == 0)
|
||||
{
|
||||
keynum = GetKeyFromName ("kp=");
|
||||
}
|
||||
}
|
||||
return keynum;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
const char *KeyName (int key)
|
||||
{
|
||||
static char name[5];
|
||||
|
||||
if (KeyNames[key])
|
||||
return KeyNames[key];
|
||||
|
||||
mysnprintf (name, countof(name), "Key_%d", key);
|
||||
return name;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
static const char *ConfigKeyName(int keynum)
|
||||
{
|
||||
const char *name = KeyName(keynum);
|
||||
if (name[1] == 0) // Make sure given name is config-safe
|
||||
{
|
||||
if (name[0] == '[')
|
||||
return "LeftBracket";
|
||||
else if (name[0] == ']')
|
||||
return "RightBracket";
|
||||
else if (name[0] == '=')
|
||||
return "Equals";
|
||||
else if (strcmp (name, "kp=") == 0)
|
||||
return "KP-Equals";
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void C_NameKeys (char *str, int first, int second)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
*str = 0;
|
||||
if (second == first) second = 0;
|
||||
if (first)
|
||||
{
|
||||
c++;
|
||||
strcpy (str, KeyName (first));
|
||||
if (second)
|
||||
strcat (str, TEXTCOLOR_BLACK ", " TEXTCOLOR_NORMAL);
|
||||
}
|
||||
|
||||
if (second)
|
||||
{
|
||||
c++;
|
||||
strcat (str, KeyName (second));
|
||||
}
|
||||
|
||||
if (!c)
|
||||
*str = '\0';
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
FString C_NameKeys (int *keys, int count, bool colors)
|
||||
{
|
||||
FString result;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int key = keys[i];
|
||||
if (key == 0) continue;
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
if (key == keys[j])
|
||||
{
|
||||
key = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (key == 0) continue;
|
||||
if (result.IsNotEmpty()) result += colors? TEXTCOLOR_BLACK ", " TEXTCOLOR_NORMAL : ", ";
|
||||
result += KeyName(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FKeyBindings::DoBind (const char *key, const char *bind)
|
||||
{
|
||||
int keynum = GetConfigKeyFromName (key);
|
||||
if (keynum != 0)
|
||||
{
|
||||
Binds[keynum] = bind;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FKeyBindings::UnbindAll ()
|
||||
{
|
||||
for (int i = 0; i < NUM_KEYS; ++i)
|
||||
{
|
||||
Binds[i] = "";
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FKeyBindings::UnbindKey(const char *key)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( (i = GetKeyFromName (key)) )
|
||||
{
|
||||
Binds[i] = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("Unknown key \"%s\"\n", key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FKeyBindings::PerformBind(FCommandLine &argv, const char *msg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
i = GetKeyFromName (argv[1]);
|
||||
if (!i)
|
||||
{
|
||||
Printf ("Unknown key \"%s\"\n", argv[1]);
|
||||
return;
|
||||
}
|
||||
if (argv.argc() == 2)
|
||||
{
|
||||
Printf ("\"%s\" = \"%s\"\n", argv[1], Binds[i].GetChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
Binds[i] = argv[2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("%s:\n", msg);
|
||||
|
||||
for (i = 0; i < NUM_KEYS; i++)
|
||||
{
|
||||
if (!Binds[i].IsEmpty())
|
||||
Printf ("%s \"%s\"\n", KeyName (i), Binds[i].GetChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// This function is first called for functions in custom key sections.
|
||||
// In this case, matchcmd is non-null, and only keys bound to that command
|
||||
// are stored. If a match is found, its binding is set to "\1".
|
||||
// After all custom key sections are saved, it is called one more for the
|
||||
// normal Bindings and DoubleBindings sections for this game. In this case
|
||||
// matchcmd is null and all keys will be stored. The config section was not
|
||||
// previously cleared, so all old bindings are still in place. If the binding
|
||||
// for a key is empty, the corresponding key in the config is removed as well.
|
||||
// If a binding is "\1", then the binding itself is cleared, but nothing
|
||||
// happens to the entry in the config.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FKeyBindings::ArchiveBindings(FConfigFile *f, const char *matchcmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_KEYS; i++)
|
||||
{
|
||||
if (Binds[i].IsEmpty())
|
||||
{
|
||||
if (matchcmd == nullptr)
|
||||
{
|
||||
f->ClearKey(ConfigKeyName(i));
|
||||
}
|
||||
}
|
||||
else if (matchcmd == nullptr || stricmp(Binds[i], matchcmd) == 0)
|
||||
{
|
||||
if (Binds[i][0] == '\1')
|
||||
{
|
||||
Binds[i] = "";
|
||||
continue;
|
||||
}
|
||||
f->SetValueForKey(ConfigKeyName(i), Binds[i]);
|
||||
if (matchcmd != nullptr)
|
||||
{ // If saving a specific command, set a marker so that
|
||||
// it does not get saved in the general binding list.
|
||||
Binds[i] = "\1";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int FKeyBindings::GetKeysForCommand (const char *cmd, int *first, int *second)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
*first = *second = c = i = 0;
|
||||
|
||||
while (i < NUM_KEYS && c < 2)
|
||||
{
|
||||
if (stricmp (cmd, Binds[i]) == 0)
|
||||
{
|
||||
if (c++ == 0)
|
||||
*first = i;
|
||||
else
|
||||
*second = i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
TArray<int> FKeyBindings::GetKeysForCommand (const char *cmd)
|
||||
{
|
||||
int i = 0;
|
||||
TArray<int> result;
|
||||
|
||||
while (i < NUM_KEYS)
|
||||
{
|
||||
if (stricmp (cmd, Binds[i]) == 0)
|
||||
{
|
||||
result.Push(i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FKeyBindings::UnbindACommand (const char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_KEYS; i++)
|
||||
{
|
||||
if (!stricmp (str, Binds[i]))
|
||||
{
|
||||
Binds[i] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FKeyBindings::DefaultBind(const char *keyname, const char *cmd)
|
||||
{
|
||||
int key = GetKeyFromName (keyname);
|
||||
if (key == 0)
|
||||
{
|
||||
Printf ("Unknown key \"%s\"\n", keyname);
|
||||
return;
|
||||
}
|
||||
if (!Binds[key].IsEmpty())
|
||||
{ // This key is already bound.
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < NUM_KEYS; ++i)
|
||||
{
|
||||
if (!Binds[i].IsEmpty() && stricmp (Binds[i], cmd) == 0)
|
||||
{ // This command is already bound to a key.
|
||||
return;
|
||||
}
|
||||
}
|
||||
// It is safe to do the bind, so do it.
|
||||
Binds[key] = cmd;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void C_UnbindAll ()
|
||||
{
|
||||
Bindings.UnbindAll();
|
||||
DoubleBindings.UnbindAll();
|
||||
AutomapBindings.UnbindAll();
|
||||
}
|
||||
|
||||
UNSAFE_CCMD (unbindall)
|
||||
{
|
||||
C_UnbindAll ();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
CCMD (unbind)
|
||||
{
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
Bindings.UnbindKey(argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
CCMD (undoublebind)
|
||||
{
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
DoubleBindings.UnbindKey(argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
CCMD (unmapbind)
|
||||
{
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
AutomapBindings.UnbindKey(argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
CCMD (bind)
|
||||
{
|
||||
Bindings.PerformBind(argv, "Current key bindings");
|
||||
}
|
||||
|
||||
CCMD (doublebind)
|
||||
{
|
||||
DoubleBindings.PerformBind(argv, "Current key doublebindings");
|
||||
}
|
||||
|
||||
CCMD (mapbind)
|
||||
{
|
||||
AutomapBindings.PerformBind(argv, "Current automap key bindings");
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CCMD defaultbind
|
||||
//
|
||||
// Binds a command to a key if that key is not already bound and if
|
||||
// that command is not already bound to another key.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD (defaultbind)
|
||||
{
|
||||
if (argv.argc() < 3)
|
||||
{
|
||||
Printf ("Usage: defaultbind <key> <command>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Bindings.DefaultBind(argv[1], argv[2]);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
CCMD(rebind)
|
||||
{
|
||||
FKeyBindings* bindings;
|
||||
|
||||
if (key == 0)
|
||||
{
|
||||
Printf("Rebind cannot be used from the console\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (key & KEY_DBLCLICKED)
|
||||
{
|
||||
bindings = &DoubleBindings;
|
||||
key &= KEY_DBLCLICKED - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bindings = &Bindings;
|
||||
}
|
||||
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
bindings->SetBind(key, argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void ReadBindings(int lump, bool override)
|
||||
{
|
||||
FScanner sc(lump);
|
||||
|
||||
while (sc.GetString())
|
||||
{
|
||||
FKeyBindings* dest = &Bindings;
|
||||
int key;
|
||||
|
||||
// bind destination is optional and is the same as the console command
|
||||
if (sc.Compare("bind"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
}
|
||||
else if (sc.Compare("doublebind"))
|
||||
{
|
||||
dest = &DoubleBindings;
|
||||
sc.MustGetString();
|
||||
}
|
||||
else if (sc.Compare("mapbind"))
|
||||
{
|
||||
dest = &AutomapBindings;
|
||||
sc.MustGetString();
|
||||
}
|
||||
key = GetConfigKeyFromName(sc.String);
|
||||
sc.MustGetString();
|
||||
dest->SetBind(key, sc.String, override);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void C_SetDefaultKeys(const char* baseconfig)
|
||||
{
|
||||
auto lump = fileSystem.CheckNumForFullName("engine/commonbinds.txt");
|
||||
if (lump >= 0) ReadBindings(lump, true);
|
||||
int lastlump = 0;
|
||||
|
||||
while ((lump = fileSystem.FindLumpFullName(baseconfig, &lastlump)) != -1)
|
||||
{
|
||||
if (fileSystem.GetFileContainer(lump) > 0) break;
|
||||
ReadBindings(lump, true);
|
||||
}
|
||||
|
||||
while ((lump = fileSystem.FindLump("DEFBINDS", &lastlump)) != -1)
|
||||
{
|
||||
ReadBindings(lump, false);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
CVAR(Int, cl_defaultconfiguration, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
|
||||
void C_BindDefaults()
|
||||
{
|
||||
C_SetDefaultKeys(cl_defaultconfiguration == 1 ? "engine/origbinds.txt" : cl_defaultconfiguration == 2 ? "engine/leftbinds.txt" : "engine/defbinds.txt");
|
||||
}
|
||||
|
||||
CCMD(controlpreset)
|
||||
{
|
||||
if (argv.argc() < 2)
|
||||
{
|
||||
Printf("Usage: Controlpreset {0,1,2}\n");
|
||||
return;
|
||||
}
|
||||
int v = atoi(argv[1]);
|
||||
if (v < 0 || v > 2) return;
|
||||
cl_defaultconfiguration = v;
|
||||
C_BindDefaults();
|
||||
}
|
||||
|
||||
CCMD(binddefaults)
|
||||
{
|
||||
C_BindDefaults();
|
||||
}
|
||||
|
||||
void C_SetDefaultBindings()
|
||||
{
|
||||
C_UnbindAll();
|
||||
C_BindDefaults();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds)
|
||||
{
|
||||
FString binding;
|
||||
bool dclick;
|
||||
unsigned int nowtime;
|
||||
|
||||
if (ev->type != EV_KeyDown && ev->type != EV_KeyUp)
|
||||
return false;
|
||||
|
||||
if ((unsigned int)ev->data1 >= NUM_KEYS)
|
||||
return false;
|
||||
|
||||
dclick = false;
|
||||
|
||||
nowtime = (unsigned)I_msTime();
|
||||
if (doublebinds != nullptr && int(DClickTime[ev->data1] - nowtime) > 0 && ev->type == EV_KeyDown)
|
||||
{
|
||||
// Key pressed for a double click
|
||||
binding = doublebinds->GetBinding(ev->data1);
|
||||
DClicked.Set(ev->data1);
|
||||
dclick = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ev->type == EV_KeyDown)
|
||||
{ // Key pressed for a normal press
|
||||
binding = binds->GetBinding(ev->data1);
|
||||
DClickTime[ev->data1] = nowtime + 571;
|
||||
}
|
||||
else if (doublebinds != nullptr && DClicked[ev->data1])
|
||||
{ // Key released from a double click
|
||||
binding = doublebinds->GetBinding(ev->data1);
|
||||
DClicked.Clear(ev->data1);
|
||||
DClickTime[ev->data1] = 0;
|
||||
dclick = true;
|
||||
}
|
||||
else
|
||||
{ // Key released from a normal press
|
||||
binding = binds->GetBinding(ev->data1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (binding.IsEmpty())
|
||||
{
|
||||
binding = binds->GetBinding(ev->data1);
|
||||
dclick = false;
|
||||
}
|
||||
|
||||
if (ev->type == EV_KeyUp && binding[0] != '+')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!binding.IsEmpty() && (chatmodeon == 0 || ev->data1 < 256))
|
||||
{
|
||||
char *copy = binding.LockBuffer();
|
||||
|
||||
if (ev->type == EV_KeyUp)
|
||||
{
|
||||
copy[0] = '-';
|
||||
}
|
||||
|
||||
AddCommandString (copy, dclick ? ev->data1 | KEY_DBLCLICKED : ev->data1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
** c_bind.h
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __C_BINDINGS_H__
|
||||
#define __C_BINDINGS_H__
|
||||
|
||||
#include "keydef.h"
|
||||
#include "zstring.h"
|
||||
#include "tarray.h"
|
||||
|
||||
struct event_t;
|
||||
class FConfigFile;
|
||||
class FCommandLine;
|
||||
|
||||
void C_NameKeys (char *str, int first, int second);
|
||||
FString C_NameKeys (int *keys, int count, bool colors = false);
|
||||
|
||||
class FKeyBindings
|
||||
{
|
||||
FString Binds[NUM_KEYS];
|
||||
|
||||
public:
|
||||
void PerformBind(FCommandLine &argv, const char *msg);
|
||||
bool DoKey(event_t *ev);
|
||||
void ArchiveBindings(FConfigFile *F, const char *matchcmd = NULL);
|
||||
int GetKeysForCommand (const char *cmd, int *first, int *second);
|
||||
TArray<int> GetKeysForCommand (const char *cmd);
|
||||
void UnbindACommand (const char *str);
|
||||
void UnbindAll ();
|
||||
void UnbindKey(const char *key);
|
||||
void DoBind (const char *key, const char *bind);
|
||||
void DefaultBind(const char *keyname, const char *cmd);
|
||||
|
||||
void SetBind(unsigned int key, const char *bind, bool override = true)
|
||||
{
|
||||
if (!override && Binds[key].IsNotEmpty()) return;
|
||||
if (key < NUM_KEYS) Binds[key] = bind;
|
||||
}
|
||||
|
||||
const FString &GetBinding(unsigned int index) const
|
||||
{
|
||||
return Binds[index];
|
||||
}
|
||||
|
||||
const char *GetBind(unsigned int index) const
|
||||
{
|
||||
if (index < NUM_KEYS)
|
||||
{
|
||||
auto c = Binds[index].GetChars();
|
||||
if (*c) return c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern FKeyBindings Bindings;
|
||||
extern FKeyBindings DoubleBindings;
|
||||
extern FKeyBindings AutomapBindings;
|
||||
extern FKeyBindings MenuBindings;
|
||||
|
||||
|
||||
bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds);
|
||||
|
||||
// Stuff used by the customize controls menu
|
||||
void C_SetDefaultBindings ();
|
||||
void C_UnbindAll ();
|
||||
|
||||
extern const char *KeyNames[];
|
||||
|
||||
struct FKeyAction
|
||||
{
|
||||
FString mTitle;
|
||||
FString mAction;
|
||||
};
|
||||
|
||||
struct FKeySection
|
||||
{
|
||||
FString mTitle;
|
||||
FString mSection;
|
||||
TArray<FKeyAction> mActions;
|
||||
};
|
||||
extern TArray<FKeySection> KeySections;
|
||||
|
||||
#endif //__C_BINDINGS_H__
|
||||
|
||||
|
|
@ -1,261 +0,0 @@
|
|||
/*
|
||||
** c_dispatch.cpp
|
||||
** Functions for executing console commands and aliases
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2007 Randy Heit
|
||||
** Copyright 2019 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include "c_buttons.h"
|
||||
#include "templates.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "printf.h"
|
||||
#include "cmdlib.h"
|
||||
#include "c_console.h"
|
||||
|
||||
ButtonMap buttonMap;
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void ButtonMap::SetButtons(const char** names, int count)
|
||||
{
|
||||
Buttons.Resize(count);
|
||||
NumToName.Resize(count);
|
||||
NameToNum.Clear();
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
Buttons[i] = {};
|
||||
NameToNum.Insert(names[i], i);
|
||||
NumToName[i] = names[i];
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int ButtonMap::ListActionCommands (const char *pattern)
|
||||
{
|
||||
char matcher[32];
|
||||
int count = 0;
|
||||
|
||||
for (auto& btn : NumToName)
|
||||
{
|
||||
if (pattern == NULL || CheckWildcards (pattern,
|
||||
(mysnprintf (matcher, countof(matcher), "+%s", btn.GetChars()), matcher)))
|
||||
{
|
||||
Printf ("+%s\n", btn.GetChars());
|
||||
count++;
|
||||
}
|
||||
if (pattern == NULL || CheckWildcards (pattern,
|
||||
(mysnprintf (matcher, countof(matcher), "-%s", btn.GetChars()), matcher)))
|
||||
{
|
||||
Printf ("-%s\n", btn.GetChars());
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
int ButtonMap::FindButtonIndex (const char *key, int funclen) const
|
||||
{
|
||||
if (!key) return -1;
|
||||
|
||||
FName name = funclen == -1? FName(key, true) : FName(key, funclen, true);
|
||||
if (name == NAME_None) return -1;
|
||||
|
||||
auto res = NameToNum.CheckKey(name);
|
||||
if (!res) return -1;
|
||||
|
||||
return *res;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void ButtonMap::ResetButtonTriggers ()
|
||||
{
|
||||
for (auto &button : Buttons)
|
||||
{
|
||||
button.ResetTriggers ();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void ButtonMap::ResetButtonStates ()
|
||||
{
|
||||
for (auto &btn : Buttons)
|
||||
{
|
||||
if (!btn.bReleaseLock)
|
||||
{
|
||||
btn.ReleaseKey (0);
|
||||
}
|
||||
btn.ResetTriggers ();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool FButtonStatus::PressKey (int keynum)
|
||||
{
|
||||
int i, open;
|
||||
|
||||
keynum &= KEY_DBLCLICKED-1;
|
||||
|
||||
if (keynum == 0)
|
||||
{ // Issued from console instead of a key, so force on
|
||||
Keys[0] = 0xffff;
|
||||
for (i = MAX_KEYS-1; i > 0; --i)
|
||||
{
|
||||
Keys[i] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = MAX_KEYS-1, open = -1; i >= 0; --i)
|
||||
{
|
||||
if (Keys[i] == 0)
|
||||
{
|
||||
open = i;
|
||||
}
|
||||
else if (Keys[i] == keynum)
|
||||
{ // Key is already down; do nothing
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (open < 0)
|
||||
{ // No free key slots, so do nothing
|
||||
Printf ("More than %u keys pressed for a single action!\n", MAX_KEYS);
|
||||
return false;
|
||||
}
|
||||
Keys[open] = keynum;
|
||||
}
|
||||
uint8_t wasdown = bDown;
|
||||
bDown = bWentDown = true;
|
||||
// Returns true if this key caused the button to go down.
|
||||
return !wasdown;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool FButtonStatus::ReleaseKey (int keynum)
|
||||
{
|
||||
int i, numdown, match;
|
||||
uint8_t wasdown = bDown;
|
||||
|
||||
keynum &= KEY_DBLCLICKED-1;
|
||||
|
||||
if (keynum == 0)
|
||||
{ // Issued from console instead of a key, so force off
|
||||
for (i = MAX_KEYS-1; i >= 0; --i)
|
||||
{
|
||||
Keys[i] = 0;
|
||||
}
|
||||
bWentUp = true;
|
||||
bDown = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = MAX_KEYS-1, numdown = 0, match = -1; i >= 0; --i)
|
||||
{
|
||||
if (Keys[i] != 0)
|
||||
{
|
||||
++numdown;
|
||||
if (Keys[i] == keynum)
|
||||
{
|
||||
match = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match < 0)
|
||||
{ // Key was not down; do nothing
|
||||
return false;
|
||||
}
|
||||
Keys[match] = 0;
|
||||
bWentUp = true;
|
||||
if (--numdown == 0)
|
||||
{
|
||||
bDown = false;
|
||||
}
|
||||
}
|
||||
// Returns true if releasing this key caused the button to go up.
|
||||
return wasdown && !bDown;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void ButtonMap::AddButtonTabCommands()
|
||||
{
|
||||
// Add all the action commands for tab completion
|
||||
for (auto& btn : NumToName)
|
||||
{
|
||||
char tname[16];
|
||||
strcpy (&tname[1], btn.GetChars());
|
||||
tname[0] = '+';
|
||||
C_AddTabCommand (tname);
|
||||
tname[0] = '-';
|
||||
C_AddTabCommand (tname);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "tarray.h"
|
||||
#include "name.h"
|
||||
|
||||
// Actions
|
||||
struct FButtonStatus
|
||||
{
|
||||
enum { MAX_KEYS = 6 }; // Maximum number of keys that can press this button
|
||||
|
||||
uint16_t Keys[MAX_KEYS];
|
||||
bool bDown; // Button is down right now
|
||||
bool bWentDown; // Button went down this tic
|
||||
bool bWentUp; // Button went up this tic
|
||||
bool bReleaseLock; // Lock ReleaseKey call in ResetButtonStates
|
||||
void (*PressHandler)(); // for optional game-side customization
|
||||
void (*ReleaseHandler)();
|
||||
|
||||
bool PressKey (int keynum); // Returns true if this key caused the button to be pressed.
|
||||
bool ReleaseKey (int keynum); // Returns true if this key is no longer pressed.
|
||||
void ResetTriggers () { bWentDown = bWentUp = false; }
|
||||
void Reset () { bDown = bWentDown = bWentUp = false; }
|
||||
};
|
||||
|
||||
class ButtonMap
|
||||
{
|
||||
|
||||
TArray<FButtonStatus> Buttons;
|
||||
TArray<FString> NumToName; // The internal name of the button
|
||||
TMap<FName, int> NameToNum;
|
||||
|
||||
public:
|
||||
void SetButtons(const char** names, int count);
|
||||
|
||||
int NumButtons() const
|
||||
{
|
||||
return Buttons.Size();
|
||||
}
|
||||
|
||||
int FindButtonIndex(const char* func, int funclen = -1) const;
|
||||
|
||||
FButtonStatus* FindButton(const char* func, int funclen = -1)
|
||||
{
|
||||
int index = FindButtonIndex(func, funclen);
|
||||
return index > -1 ? &Buttons[index] : nullptr;
|
||||
}
|
||||
|
||||
FButtonStatus* GetButton(int index)
|
||||
{
|
||||
return &Buttons[index];
|
||||
}
|
||||
|
||||
void ResetButtonTriggers(); // Call ResetTriggers for all buttons
|
||||
void ResetButtonStates(); // Same as above, but also clear bDown
|
||||
int ListActionCommands(const char* pattern);
|
||||
void AddButtonTabCommands();
|
||||
|
||||
|
||||
bool ButtonDown(int x) const
|
||||
{
|
||||
return Buttons[x].bDown;
|
||||
}
|
||||
|
||||
bool ButtonPressed(int x) const
|
||||
{
|
||||
return Buttons[x].bWentDown;
|
||||
}
|
||||
|
||||
bool ButtonReleased(int x) const
|
||||
{
|
||||
return Buttons[x].bWentUp;
|
||||
}
|
||||
|
||||
void ClearButton(int x)
|
||||
{
|
||||
Buttons[x].Reset();
|
||||
}
|
||||
};
|
||||
|
||||
extern ButtonMap buttonMap;
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
** c_dispatch.cpp
|
||||
** Functions for executing console commands and aliases
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2007 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "c_commandline.h"
|
||||
#include "c_cvars.h"
|
||||
#include "v_text.h"
|
||||
|
||||
// ParseCommandLine
|
||||
//
|
||||
// Parse a command line (passed in args). If argc is non-NULL, it will
|
||||
// be set to the number of arguments. If argv is non-NULL, it will be
|
||||
// filled with pointers to each argument; argv[0] should be initialized
|
||||
// to point to a buffer large enough to hold all the arguments. The
|
||||
// return value is the necessary size of this buffer.
|
||||
//
|
||||
// Special processing:
|
||||
// Inside quoted strings, \" becomes just "
|
||||
// \\ becomes just a single backslash
|
||||
// \c becomes just TEXTCOLOR_ESCAPE
|
||||
// $<cvar> is replaced by the contents of <cvar>
|
||||
|
||||
static long ParseCommandLine(const char* args, int* argc, char** argv, bool no_escapes)
|
||||
{
|
||||
int count;
|
||||
char* buffplace;
|
||||
|
||||
count = 0;
|
||||
buffplace = NULL;
|
||||
if (argv != NULL)
|
||||
{
|
||||
buffplace = argv[0];
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (*args <= ' ' && *args)
|
||||
{ // skip white space
|
||||
args++;
|
||||
}
|
||||
if (*args == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (*args == '\"')
|
||||
{ // read quoted string
|
||||
char stuff;
|
||||
if (argv != NULL)
|
||||
{
|
||||
argv[count] = buffplace;
|
||||
}
|
||||
count++;
|
||||
args++;
|
||||
do
|
||||
{
|
||||
stuff = *args++;
|
||||
if (!no_escapes && stuff == '\\' && *args == '\"')
|
||||
{
|
||||
stuff = '\"', args++;
|
||||
}
|
||||
else if (!no_escapes && stuff == '\\' && *args == '\\')
|
||||
{
|
||||
args++;
|
||||
}
|
||||
else if (!no_escapes && stuff == '\\' && *args == 'c')
|
||||
{
|
||||
stuff = TEXTCOLOR_ESCAPE, args++;
|
||||
}
|
||||
else if (stuff == '\"')
|
||||
{
|
||||
stuff = 0;
|
||||
}
|
||||
else if (stuff == 0)
|
||||
{
|
||||
args--;
|
||||
}
|
||||
if (argv != NULL)
|
||||
{
|
||||
*buffplace = stuff;
|
||||
}
|
||||
buffplace++;
|
||||
} while (stuff);
|
||||
}
|
||||
else
|
||||
{ // read unquoted string
|
||||
const char* start = args++, * end;
|
||||
FBaseCVar* var;
|
||||
UCVarValue val;
|
||||
|
||||
while (*args && *args > ' ' && *args != '\"')
|
||||
args++;
|
||||
if (*start == '$' && (var = FindCVarSub(start + 1, int(args - start - 1))))
|
||||
{
|
||||
val = var->GetGenericRep(CVAR_String);
|
||||
start = val.String;
|
||||
end = start + strlen(start);
|
||||
}
|
||||
else
|
||||
{
|
||||
end = args;
|
||||
}
|
||||
if (argv != NULL)
|
||||
{
|
||||
argv[count] = buffplace;
|
||||
while (start < end)
|
||||
*buffplace++ = *start++;
|
||||
*buffplace++ = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffplace += end - start + 1;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (argc != NULL)
|
||||
{
|
||||
*argc = count;
|
||||
}
|
||||
return (long)(buffplace - (char*)0);
|
||||
}
|
||||
|
||||
FCommandLine::FCommandLine (const char *commandline, bool no_escapes)
|
||||
{
|
||||
cmd = commandline;
|
||||
_argc = -1;
|
||||
_argv = NULL;
|
||||
noescapes = no_escapes;
|
||||
}
|
||||
|
||||
FCommandLine::~FCommandLine ()
|
||||
{
|
||||
if (_argv != NULL)
|
||||
{
|
||||
delete[] _argv;
|
||||
}
|
||||
}
|
||||
|
||||
void FCommandLine::Shift()
|
||||
{
|
||||
// Only valid after _argv has been filled.
|
||||
for (int i = 1; i < _argc; ++i)
|
||||
{
|
||||
_argv[i - 1] = _argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
int FCommandLine::argc ()
|
||||
{
|
||||
if (_argc == -1)
|
||||
{
|
||||
argsize = ParseCommandLine (cmd, &_argc, NULL, noescapes);
|
||||
}
|
||||
return _argc;
|
||||
}
|
||||
|
||||
char *FCommandLine::operator[] (int i)
|
||||
{
|
||||
if (_argv == NULL)
|
||||
{
|
||||
int count = argc();
|
||||
_argv = new char *[count + (argsize+sizeof(char*)-1)/sizeof(char*)];
|
||||
_argv[0] = (char *)_argv + count*sizeof(char *);
|
||||
ParseCommandLine (cmd, NULL, _argv, noescapes);
|
||||
}
|
||||
return _argv[i];
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
#pragma once
|
||||
/*
|
||||
** c_dispatch.h
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
class FConfigFile;
|
||||
struct CCmdFuncParm;
|
||||
|
||||
|
||||
// Class that can parse command lines
|
||||
class FCommandLine
|
||||
{
|
||||
friend int C_RegisterFunction(const char* name, const char* help, int (*func)(CCmdFuncParm const* const));
|
||||
public:
|
||||
FCommandLine (const char *commandline, bool no_escapes = false);
|
||||
~FCommandLine ();
|
||||
int argc ();
|
||||
char *operator[] (int i);
|
||||
const char *args () { return cmd; }
|
||||
void Shift();
|
||||
|
||||
private:
|
||||
const char *cmd;
|
||||
int _argc;
|
||||
char **_argv;
|
||||
long argsize;
|
||||
bool noescapes;
|
||||
};
|
||||
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
** c_console.h
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __C_CONSOLE__
|
||||
#define __C_CONSOLE__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "basics.h"
|
||||
|
||||
struct event_t;
|
||||
|
||||
typedef enum cstate_t
|
||||
{
|
||||
c_up=0, c_down=1, c_falling=2, c_rising=3
|
||||
}
|
||||
constate_e;
|
||||
|
||||
enum
|
||||
{
|
||||
PRINTLEVELS = 5
|
||||
};
|
||||
extern int PrintColors[PRINTLEVELS + 2];
|
||||
|
||||
extern constate_e ConsoleState;
|
||||
|
||||
// Initialize the console
|
||||
void C_InitConsole (int width, int height, bool ingame);
|
||||
void C_DeinitConsole ();
|
||||
void C_InitConback();
|
||||
|
||||
// Adjust the console for a new screen mode
|
||||
void C_NewModeAdjust (void);
|
||||
|
||||
void C_Ticker (void);
|
||||
|
||||
void AddToConsole (int printlevel, const char *string);
|
||||
int PrintString (int printlevel, const char *string);
|
||||
int PrintStringHigh (const char *string);
|
||||
int VPrintf (int printlevel, const char *format, va_list parms) GCCFORMAT(2);
|
||||
|
||||
void C_DrawConsole ();
|
||||
void C_ToggleConsole (void);
|
||||
void C_FullConsole (void);
|
||||
void C_HideConsole (void);
|
||||
void C_AdjustBottom (void);
|
||||
void C_FlushDisplay (void);
|
||||
|
||||
class FFont;
|
||||
void C_MidPrint (FFont *font, const char *message, bool bold = false);
|
||||
|
||||
bool C_Responder (event_t *ev);
|
||||
|
||||
void C_AddTabCommand (const char *name);
|
||||
void C_RemoveTabCommand (const char *name);
|
||||
void C_ClearTabCommands(); // Removes all tab commands
|
||||
|
||||
extern const char *console_bar;
|
||||
|
||||
#endif
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
/*
|
||||
** consolebuffer.cpp
|
||||
**
|
||||
** manages the text for the console
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2014 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include "c_console.h"
|
||||
#include "c_consolebuffer.h"
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FConsoleBuffer::FConsoleBuffer()
|
||||
{
|
||||
mLogFile = NULL;
|
||||
mAddType = NEWLINE;
|
||||
mLastFont = NULL;
|
||||
mLastDisplayWidth = -1;
|
||||
mLastLineNeedsUpdate = false;
|
||||
mTextLines = 0;
|
||||
mBufferWasCleared = true;
|
||||
mBrokenStart.Push(0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Adds a new line of text to the console
|
||||
// This is kept as simple as possible. This function does not:
|
||||
// - remove old text if the buffer gets larger than the specified size
|
||||
// - format the text for the current screen layout
|
||||
//
|
||||
// These tasks will only be be performed once per frame because they are
|
||||
// relatively expensive. The old console did them each time text was added
|
||||
// resulting in extremely bad performance with a high output rate.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FConsoleBuffer::AddText(int printlevel, const char *text)
|
||||
{
|
||||
FString build = TEXTCOLOR_TAN;
|
||||
|
||||
if (mAddType == REPLACELINE)
|
||||
{
|
||||
// Just wondering: Do we actually need this case? If so, it may need some work.
|
||||
mConsoleText.Pop(); // remove the line to be replaced
|
||||
mLastLineNeedsUpdate = true;
|
||||
}
|
||||
else if (mAddType == APPENDLINE)
|
||||
{
|
||||
mConsoleText.Pop(build);
|
||||
printlevel = -1;
|
||||
mLastLineNeedsUpdate = true;
|
||||
}
|
||||
|
||||
if (printlevel >= 0 && printlevel != PRINT_HIGH)
|
||||
{
|
||||
if (printlevel == 200) build = TEXTCOLOR_GREEN;
|
||||
else if (printlevel < PRINTLEVELS) build.Format("%c%c", TEXTCOLOR_ESCAPE, PrintColors[printlevel]+'A');
|
||||
}
|
||||
|
||||
size_t textsize = strlen(text);
|
||||
|
||||
if (text[textsize-1] == '\r')
|
||||
{
|
||||
textsize--;
|
||||
mAddType = REPLACELINE;
|
||||
}
|
||||
else if (text[textsize-1] == '\n')
|
||||
{
|
||||
textsize--;
|
||||
mAddType = NEWLINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mAddType = APPENDLINE;
|
||||
}
|
||||
|
||||
// don't bother with linefeeds etc. inside the text, we'll let the formatter sort this out later.
|
||||
build.AppendCStrPart(text, textsize);
|
||||
mConsoleText.Push(build);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Format the text for output
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth)
|
||||
{
|
||||
if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared)
|
||||
{
|
||||
if (mBufferWasCleared)
|
||||
mLastLineNeedsUpdate = false;
|
||||
m_BrokenConsoleText.Clear();
|
||||
mBrokenStart.Clear();
|
||||
mBrokenStart.Push(0);
|
||||
mBrokenLines.Clear();
|
||||
mLastFont = formatfont;
|
||||
mLastDisplayWidth = displaywidth;
|
||||
mBufferWasCleared = false;
|
||||
}
|
||||
unsigned brokensize = m_BrokenConsoleText.Size();
|
||||
if (brokensize == mConsoleText.Size())
|
||||
{
|
||||
// The last line got text appended.
|
||||
if (mLastLineNeedsUpdate)
|
||||
{
|
||||
brokensize--;
|
||||
m_BrokenConsoleText.Resize(brokensize);
|
||||
}
|
||||
}
|
||||
mBrokenLines.Resize(mBrokenStart[brokensize]);
|
||||
mBrokenStart.Resize(brokensize);
|
||||
for (unsigned i = brokensize; i < mConsoleText.Size(); i++)
|
||||
{
|
||||
auto bl = V_BreakLines(formatfont, displaywidth, mConsoleText[i], true);
|
||||
m_BrokenConsoleText.Push(bl);
|
||||
mBrokenStart.Push(mBrokenLines.Size());
|
||||
for(auto &bline : bl)
|
||||
{
|
||||
mBrokenLines.Push(bline);
|
||||
}
|
||||
}
|
||||
mTextLines = mBrokenLines.Size();
|
||||
mBrokenStart.Push(mTextLines);
|
||||
mLastLineNeedsUpdate = false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Delete old content if number of lines gets too large
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FConsoleBuffer::ResizeBuffer(unsigned newsize)
|
||||
{
|
||||
if (mConsoleText.Size() > newsize)
|
||||
{
|
||||
unsigned todelete = mConsoleText.Size() - newsize;
|
||||
mConsoleText.Delete(0, todelete);
|
||||
mBufferWasCleared = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
** consolebuffer.h
|
||||
**
|
||||
** manages the text for the console
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2014 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include "zstring.h"
|
||||
#include "tarray.h"
|
||||
#include "v_text.h"
|
||||
|
||||
enum EAddType
|
||||
{
|
||||
NEWLINE,
|
||||
APPENDLINE,
|
||||
REPLACELINE
|
||||
};
|
||||
|
||||
class FConsoleBuffer
|
||||
{
|
||||
TArray<FString> mConsoleText;
|
||||
TArray<TArray<FBrokenLines>> m_BrokenConsoleText; // This holds the structures returned by V_BreakLines and is used for memory management.
|
||||
TArray<unsigned int> mBrokenStart;
|
||||
TArray<FBrokenLines> mBrokenLines; // This holds the single lines, indexed by mBrokenStart and is used for printing.
|
||||
FILE * mLogFile;
|
||||
EAddType mAddType;
|
||||
int mTextLines;
|
||||
bool mBufferWasCleared;
|
||||
|
||||
FFont *mLastFont;
|
||||
int mLastDisplayWidth;
|
||||
bool mLastLineNeedsUpdate;
|
||||
|
||||
|
||||
public:
|
||||
FConsoleBuffer();
|
||||
void AddText(int printlevel, const char *string);
|
||||
void FormatText(FFont *formatfont, int displaywidth);
|
||||
void ResizeBuffer(unsigned newsize);
|
||||
void Clear()
|
||||
{
|
||||
mBufferWasCleared = true;
|
||||
mConsoleText.Clear();
|
||||
}
|
||||
int GetFormattedLineCount() { return mTextLines; }
|
||||
FBrokenLines *GetLines() { return &mBrokenLines[0]; }
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,494 +0,0 @@
|
|||
/*
|
||||
** c_cvars.h
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __C_CVARS_H__
|
||||
#define __C_CVARS_H__
|
||||
#include "zstring.h"
|
||||
#include "tarray.h"
|
||||
|
||||
class FSerializer; // this needs to go away.
|
||||
/*
|
||||
==========================================================
|
||||
|
||||
CVARS (console variables)
|
||||
|
||||
==========================================================
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
CVAR_ARCHIVE = 1, // set to cause it to be saved to config.
|
||||
CVAR_USERINFO = 1 << 1, // added to userinfo when changed.
|
||||
CVAR_SERVERINFO = 1 << 2, // added to serverinfo when changed.
|
||||
CVAR_NOSET = 1 << 3, // don't allow change from console at all,
|
||||
// but can be set from the command line.
|
||||
CVAR_LATCH = 1 << 4, // save changes until server restart.
|
||||
CVAR_UNSETTABLE = 1 << 5, // can unset this var from console.
|
||||
CVAR_DEMOSAVE = 1 << 6, // save the value of this cvar in a demo.
|
||||
CVAR_ISDEFAULT = 1 << 7, // is cvar unchanged since creation?
|
||||
CVAR_AUTO = 1 << 8, // allocated; needs to be freed when destroyed.
|
||||
CVAR_NOINITCALL = 1 << 9, // don't call callback at game start.
|
||||
CVAR_GLOBALCONFIG = 1 << 10, // cvar is saved to global config section.
|
||||
CVAR_VIDEOCONFIG = 1 << 11, // cvar is saved to video config section (not implemented).
|
||||
CVAR_NOSAVE = 1 << 12, // when used with CVAR_SERVERINFO, do not save var to savegame
|
||||
// and config.
|
||||
CVAR_MOD = 1 << 13, // cvar was defined by a mod.
|
||||
CVAR_IGNORE = 1 << 14, // do not send cvar across the network/inaccesible from ACS
|
||||
// (dummy mod cvar).
|
||||
CVAR_CHEAT = 1 << 15, // can be set only when sv_cheats is enabled.
|
||||
CVAR_UNSAFECONTEXT = 1 << 16, // cvar value came from unsafe context.
|
||||
CVAR_VIRTUAL = 1 << 17, // do not invoke the callback recursively so it can be used to
|
||||
// mirror an external variable.
|
||||
CVAR_CONFIG_ONLY = 1 << 18, // do not save var to savegame and do not send it across network.
|
||||
};
|
||||
|
||||
union UCVarValue
|
||||
{
|
||||
bool Bool;
|
||||
int Int;
|
||||
float Float;
|
||||
const char* String;
|
||||
|
||||
UCVarValue() = default;
|
||||
UCVarValue(bool v) { Bool = v; }
|
||||
UCVarValue(int v) { Int = v; }
|
||||
UCVarValue(float v) { Float = v; }
|
||||
UCVarValue(const char * v) { String = v; }
|
||||
};
|
||||
|
||||
enum ECVarType
|
||||
{
|
||||
CVAR_Bool,
|
||||
CVAR_Int,
|
||||
CVAR_Float,
|
||||
CVAR_String,
|
||||
CVAR_Color, // stored as CVAR_Int
|
||||
CVAR_DummyBool, // just redirects to another cvar
|
||||
CVAR_DummyInt, // just redirects to another cvar
|
||||
CVAR_Dummy // Unknown
|
||||
};
|
||||
|
||||
class FConfigFile;
|
||||
|
||||
class FxCVar;
|
||||
|
||||
class FBaseCVar;
|
||||
|
||||
// These are calls into the game code. Having these hard coded in the CVAR implementation has always been the biggest blocker
|
||||
// for reusing the CVAR module outside of ZDoom. So now they get called through this struct for easier reusability.
|
||||
struct ConsoleCallbacks
|
||||
{
|
||||
void (*UserInfoChanged)(FBaseCVar*);
|
||||
void (*SendServerInfoChange)(FBaseCVar* cvar, UCVarValue value, ECVarType type);
|
||||
void (*SendServerFlagChange)(FBaseCVar* cvar, int bitnum, bool set, bool silent);
|
||||
FBaseCVar* (*GetUserCVar)(int playernum, const char* cvarname);
|
||||
bool (*MustLatch)();
|
||||
|
||||
};
|
||||
|
||||
class FBaseCVar
|
||||
{
|
||||
public:
|
||||
FBaseCVar (const char *name, uint32_t flags, void (*callback)(FBaseCVar &), const char *descr);
|
||||
virtual ~FBaseCVar ();
|
||||
|
||||
inline void Callback ()
|
||||
{
|
||||
if (m_Callback && !inCallback)
|
||||
{
|
||||
inCallback = !!(Flags & CVAR_VIRTUAL); // Virtual CVARs never invoke the callback recursively, giving it a chance to manipulate the value without side effects.
|
||||
m_Callback(*this);
|
||||
inCallback = false;
|
||||
}
|
||||
}
|
||||
|
||||
inline const char *GetName () const { return VarName.GetChars(); }
|
||||
inline uint32_t GetFlags () const { return Flags; }
|
||||
inline FBaseCVar *GetNext() const { return m_Next; }
|
||||
|
||||
void CmdSet (const char *newval);
|
||||
void ForceSet (UCVarValue value, ECVarType type, bool nouserinfosend=false);
|
||||
void SetGenericRep (UCVarValue value, ECVarType type);
|
||||
void ResetToDefault ();
|
||||
void SetArchiveBit () { Flags |= CVAR_ARCHIVE; }
|
||||
void MarkUnsafe();
|
||||
void MarkSafe() { Flags &= ~CVAR_UNSAFECONTEXT; }
|
||||
|
||||
int ToInt()
|
||||
{
|
||||
ECVarType vt;
|
||||
auto val = GetFavoriteRep(&vt);
|
||||
return ToInt(val, vt);
|
||||
}
|
||||
|
||||
virtual ECVarType GetRealType () const = 0;
|
||||
|
||||
virtual const char *GetHumanString(int precision=-1) const;
|
||||
virtual UCVarValue GetGenericRep (ECVarType type) const = 0;
|
||||
virtual UCVarValue GetFavoriteRep (ECVarType *type) const = 0;
|
||||
|
||||
virtual UCVarValue GetGenericRepDefault (ECVarType type) const = 0;
|
||||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const = 0;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type) = 0;
|
||||
|
||||
FBaseCVar &operator= (const FBaseCVar &var)
|
||||
{ UCVarValue val; ECVarType type; val = var.GetFavoriteRep (&type); SetGenericRep (val, type); return *this; }
|
||||
|
||||
static void EnableNoSet (); // enable the honoring of CVAR_NOSET
|
||||
static void EnableCallbacks ();
|
||||
static void DisableCallbacks ();
|
||||
static void ResetColors (); // recalc color cvars' indices after screen change
|
||||
|
||||
static void ListVars (const char *filter, bool plain);
|
||||
|
||||
const char *GetDescription() const { return Description; };
|
||||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type) = 0;
|
||||
|
||||
static bool ToBool (UCVarValue value, ECVarType type);
|
||||
static int ToInt (UCVarValue value, ECVarType type);
|
||||
static float ToFloat (UCVarValue value, ECVarType type);
|
||||
static const char *ToString (UCVarValue value, ECVarType type);
|
||||
static UCVarValue FromBool (bool value, ECVarType type);
|
||||
static UCVarValue FromInt (int value, ECVarType type);
|
||||
static UCVarValue FromFloat (float value, ECVarType type);
|
||||
static UCVarValue FromString (const char *value, ECVarType type);
|
||||
|
||||
FString VarName;
|
||||
FString SafeValue;
|
||||
FString Description;
|
||||
uint32_t Flags;
|
||||
bool inCallback = false;
|
||||
|
||||
private:
|
||||
FBaseCVar (const FBaseCVar &var) = delete;
|
||||
FBaseCVar (const char *name, uint32_t flags);
|
||||
|
||||
void (*m_Callback)(FBaseCVar &);
|
||||
FBaseCVar *m_Next;
|
||||
|
||||
static bool m_UseCallback;
|
||||
static bool m_DoNoSet;
|
||||
|
||||
// These need to go away!
|
||||
friend FString C_GetMassCVarString (uint32_t filter, bool compact);
|
||||
friend void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter);
|
||||
friend void C_ReadCVars (uint8_t **demo_p);
|
||||
friend void C_BackupCVars (void);
|
||||
friend FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev);
|
||||
friend FBaseCVar *FindCVarSub (const char *var_name, int namelen);
|
||||
friend void UnlatchCVars (void);
|
||||
friend void DestroyCVarsFlagged (uint32_t flags);
|
||||
friend void C_ArchiveCVars (FConfigFile *f, uint32_t filter);
|
||||
friend void C_SetCVarsToDefaults (void);
|
||||
friend void FilterCompactCVars (TArray<FBaseCVar *> &cvars, uint32_t filter);
|
||||
friend void C_DeinitConsole();
|
||||
};
|
||||
|
||||
// Returns a string with all cvars whose flags match filter. In compact mode,
|
||||
// the cvar names are omitted to save space.
|
||||
FString C_GetMassCVarString (uint32_t filter, bool compact=false);
|
||||
|
||||
// Writes all cvars that could effect demo sync to *demo_p. These are
|
||||
// cvars that have either CVAR_SERVERINFO or CVAR_DEMOSAVE set.
|
||||
void C_WriteCVars (uint8_t **demo_p, uint32_t filter, bool compact=false);
|
||||
|
||||
// Read all cvars from *demo_p and set them appropriately.
|
||||
void C_ReadCVars (uint8_t **demo_p);
|
||||
|
||||
void C_InstallHandlers(ConsoleCallbacks* cb);
|
||||
|
||||
// Backup demo cvars. Called before a demo starts playing to save all
|
||||
// cvars the demo might change.
|
||||
void C_BackupCVars (void);
|
||||
|
||||
// Finds a named cvar
|
||||
FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev);
|
||||
FBaseCVar *FindCVarSub (const char *var_name, int namelen);
|
||||
|
||||
// Used for ACS and DECORATE.
|
||||
FBaseCVar *GetCVar(int playernum, const char *cvarname);
|
||||
|
||||
// Create a new cvar with the specified name and type
|
||||
FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, uint32_t flags);
|
||||
|
||||
// Called from G_InitNew()
|
||||
void UnlatchCVars (void);
|
||||
|
||||
// Destroy CVars with the matching flags; called from CCMD(restart)
|
||||
void DestroyCVarsFlagged (uint32_t flags);
|
||||
|
||||
// archive cvars to FILE f
|
||||
void C_ArchiveCVars (FConfigFile *f, uint32_t filter);
|
||||
|
||||
// initialize cvars to default values after they are created
|
||||
void C_SetCVarsToDefaults (void);
|
||||
|
||||
void FilterCompactCVars (TArray<FBaseCVar *> &cvars, uint32_t filter);
|
||||
|
||||
void C_DeinitConsole();
|
||||
|
||||
class FBoolCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FBoolCVar (const char *name, bool def, uint32_t flags, void (*callback)(FBoolCVar &)=NULL, const char* descr = nullptr);
|
||||
|
||||
virtual ECVarType GetRealType () const;
|
||||
|
||||
virtual UCVarValue GetGenericRep (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRep (ECVarType *type) const;
|
||||
virtual UCVarValue GetGenericRepDefault (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type);
|
||||
|
||||
inline bool operator= (bool boolval)
|
||||
{ UCVarValue val; val.Bool = boolval; SetGenericRep (val, CVAR_Bool); return boolval; }
|
||||
inline operator bool () const { return Value; }
|
||||
inline bool operator *() const { return Value; }
|
||||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type);
|
||||
|
||||
bool Value;
|
||||
bool DefaultValue;
|
||||
};
|
||||
|
||||
class FIntCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FIntCVar (const char *name, int def, uint32_t flags, void (*callback)(FIntCVar &)=NULL, const char* descr = nullptr);
|
||||
|
||||
virtual ECVarType GetRealType () const;
|
||||
|
||||
virtual UCVarValue GetGenericRep (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRep (ECVarType *type) const;
|
||||
virtual UCVarValue GetGenericRepDefault (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type);
|
||||
|
||||
int operator= (int intval)
|
||||
{ UCVarValue val; val.Int = intval; SetGenericRep (val, CVAR_Int); return intval; }
|
||||
inline operator int () const { return Value; }
|
||||
inline int operator *() const { return Value; }
|
||||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type);
|
||||
|
||||
int Value;
|
||||
int DefaultValue;
|
||||
|
||||
friend class FFlagCVar;
|
||||
};
|
||||
|
||||
class FFloatCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FFloatCVar (const char *name, float def, uint32_t flags, void (*callback)(FFloatCVar &)=NULL, const char* descr = nullptr);
|
||||
|
||||
virtual ECVarType GetRealType () const override;
|
||||
|
||||
virtual UCVarValue GetGenericRep (ECVarType type) const override ;
|
||||
virtual UCVarValue GetFavoriteRep (ECVarType *type) const override;
|
||||
virtual UCVarValue GetGenericRepDefault (ECVarType type) const override;
|
||||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const override;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type) override;
|
||||
const char *GetHumanString(int precision) const override;
|
||||
|
||||
float operator= (float floatval)
|
||||
{ UCVarValue val; val.Float = floatval; SetGenericRep (val, CVAR_Float); return floatval; }
|
||||
inline operator float () const { return Value; }
|
||||
inline float operator *() const { return Value; }
|
||||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type) override;
|
||||
|
||||
float Value;
|
||||
float DefaultValue;
|
||||
};
|
||||
|
||||
class FStringCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FStringCVar (const char *name, const char *def, uint32_t flags, void (*callback)(FStringCVar &)=NULL, const char* descr = nullptr);
|
||||
~FStringCVar ();
|
||||
|
||||
virtual ECVarType GetRealType () const;
|
||||
|
||||
virtual UCVarValue GetGenericRep (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRep (ECVarType *type) const;
|
||||
virtual UCVarValue GetGenericRepDefault (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type);
|
||||
|
||||
const char *operator= (const char *stringrep)
|
||||
{ UCVarValue val; val.String = const_cast<char *>(stringrep); SetGenericRep (val, CVAR_String); return stringrep; }
|
||||
inline operator const char * () const { return mValue; }
|
||||
inline const char *operator *() const { return mValue; }
|
||||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type);
|
||||
|
||||
FString mValue;
|
||||
FString mDefaultValue;
|
||||
};
|
||||
|
||||
class FColorCVar : public FIntCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FColorCVar (const char *name, int def, uint32_t flags, void (*callback)(FColorCVar &)=NULL, const char* descr = nullptr);
|
||||
|
||||
virtual ECVarType GetRealType () const;
|
||||
|
||||
virtual UCVarValue GetGenericRep (ECVarType type) const;
|
||||
virtual UCVarValue GetGenericRepDefault (ECVarType type) const;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type);
|
||||
|
||||
inline operator uint32_t () const { return Value; }
|
||||
inline uint32_t operator *() const { return Value; }
|
||||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type);
|
||||
|
||||
static UCVarValue FromInt2 (int value, ECVarType type);
|
||||
static int ToInt2 (UCVarValue value, ECVarType type);
|
||||
};
|
||||
|
||||
class FFlagCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FFlagCVar (const char *name, FIntCVar &realvar, uint32_t bitval, const char* descr = nullptr);
|
||||
|
||||
virtual ECVarType GetRealType () const;
|
||||
|
||||
virtual UCVarValue GetGenericRep (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRep (ECVarType *type) const;
|
||||
virtual UCVarValue GetGenericRepDefault (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type);
|
||||
|
||||
bool operator= (bool boolval)
|
||||
{ UCVarValue val; val.Bool = boolval; SetGenericRep (val, CVAR_Bool); return boolval; }
|
||||
bool operator= (FFlagCVar &flag)
|
||||
{ UCVarValue val; val.Bool = !!flag; SetGenericRep (val, CVAR_Bool); return val.Bool; }
|
||||
inline operator int () const { return (ValueVar & BitVal); }
|
||||
inline int operator *() const { return (ValueVar & BitVal); }
|
||||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type);
|
||||
|
||||
FIntCVar &ValueVar;
|
||||
uint32_t BitVal;
|
||||
int BitNum;
|
||||
};
|
||||
|
||||
class FMaskCVar : public FBaseCVar
|
||||
{
|
||||
friend class FxCVar;
|
||||
public:
|
||||
FMaskCVar (const char *name, FIntCVar &realvar, uint32_t bitval, const char* descr = nullptr);
|
||||
|
||||
virtual ECVarType GetRealType () const;
|
||||
|
||||
virtual UCVarValue GetGenericRep (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRep (ECVarType *type) const;
|
||||
virtual UCVarValue GetGenericRepDefault (ECVarType type) const;
|
||||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type);
|
||||
|
||||
inline operator int () const { return (ValueVar & BitVal) >> BitNum; }
|
||||
inline int operator *() const { return (ValueVar & BitVal) >> BitNum; }
|
||||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type);
|
||||
|
||||
FIntCVar &ValueVar;
|
||||
uint32_t BitVal;
|
||||
int BitNum;
|
||||
};
|
||||
|
||||
extern int cvar_defflags;
|
||||
|
||||
FBaseCVar *cvar_set (const char *var_name, const char *value);
|
||||
FBaseCVar *cvar_forceset (const char *var_name, const char *value);
|
||||
|
||||
inline FBaseCVar *cvar_set (const char *var_name, const uint8_t *value) { return cvar_set (var_name, (const char *)value); }
|
||||
inline FBaseCVar *cvar_forceset (const char *var_name, const uint8_t *value) { return cvar_forceset (var_name, (const char *)value); }
|
||||
|
||||
|
||||
|
||||
// Restore demo cvars. Called after demo playback to restore all cvars
|
||||
// that might possibly have been changed during the course of demo playback.
|
||||
void C_RestoreCVars (void);
|
||||
|
||||
void C_ForgetCVars (void);
|
||||
|
||||
|
||||
#define CUSTOM_CVAR(type,name,def,flags) \
|
||||
static void cvarfunc_##name(F##type##CVar &); \
|
||||
F##type##CVar name (#name, def, flags, cvarfunc_##name); \
|
||||
static void cvarfunc_##name(F##type##CVar &self)
|
||||
|
||||
#define CUSTOM_CVAR_NAMED(type,name,cname,def,flags) \
|
||||
static void cvarfunc_##name(F##type##CVar &); \
|
||||
F##type##CVar name (#cname, def, flags, cvarfunc_##name); \
|
||||
static void cvarfunc_##name(F##type##CVar &self)
|
||||
|
||||
#define CVAR(type,name,def,flags) \
|
||||
F##type##CVar name (#name, def, flags);
|
||||
|
||||
#define EXTERN_CVAR(type,name) extern F##type##CVar name;
|
||||
|
||||
#define CUSTOM_CVARD(type,name,def,flags,descr) \
|
||||
static void cvarfunc_##name(F##type##CVar &); \
|
||||
F##type##CVar name (#name, def, flags, cvarfunc_##name, descr); \
|
||||
static void cvarfunc_##name(F##type##CVar &self)
|
||||
|
||||
#define CVARD(type,name,def,flags, descr) \
|
||||
F##type##CVar name (#name, def, flags, nullptr, descr);
|
||||
|
||||
#define CVARD_NAMED(type,name,varname,def,flags, descr) \
|
||||
F##type##CVar varname (#name, def, flags, nullptr, descr);
|
||||
|
||||
#define CVAR_UNAMED(type,varname) \
|
||||
F##type##CVar varname (nullptr, 0, 0, nullptr, nullptr);
|
||||
|
||||
extern FBaseCVar *CVars;
|
||||
|
||||
#endif //__C_CVARS_H__
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,214 +0,0 @@
|
|||
/*
|
||||
** c_dispatch.h
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __C_DISPATCH_H__
|
||||
#define __C_DISPATCH_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <functional>
|
||||
#include "c_console.h"
|
||||
#include "tarray.h"
|
||||
#include "c_commandline.h"
|
||||
#include "zstring.h"
|
||||
|
||||
class FConfigFile;
|
||||
|
||||
|
||||
// Contains the contents of an exec'ed file
|
||||
struct FExecList
|
||||
{
|
||||
TArray<FString> Commands;
|
||||
TArray<FString> Pullins;
|
||||
|
||||
void AddCommand(const char *cmd, const char *file = nullptr);
|
||||
void ExecCommands() const;
|
||||
void AddPullins(TArray<FString> &wads, FConfigFile *config) const;
|
||||
};
|
||||
|
||||
extern bool ParsingKeyConf, UnsafeExecutionContext;
|
||||
extern FString StoredWarp; // [RH] +warp at the command line
|
||||
|
||||
|
||||
extern bool CheckCheatmode (bool printmsg = true);
|
||||
|
||||
FExecList *C_ParseCmdLineParams(FExecList *exec);
|
||||
|
||||
// Add commands to the console as if they were typed in. Can handle wait
|
||||
// and semicolon-separated commands. This function may modify the source
|
||||
// string, but the string will be restored to its original state before
|
||||
// returning. Therefore, commands passed must not be in read-only memory.
|
||||
void AddCommandString (const char *text, int keynum=0);
|
||||
|
||||
void C_RunDelayedCommands();
|
||||
void C_ClearDelayedCommands();
|
||||
|
||||
// Process a single console command. Does not handle wait.
|
||||
void C_DoCommand (const char *cmd, int keynum=0);
|
||||
|
||||
FExecList *C_ParseExecFile(const char *file, FExecList *source);
|
||||
void C_SearchForPullins(FExecList *exec, const char *file, class FCommandLine &args);
|
||||
bool C_ExecFile(const char *file);
|
||||
void C_ClearDynCCmds();
|
||||
|
||||
// Write out alias commands to a file for all current aliases.
|
||||
void C_ArchiveAliases (FConfigFile *f);
|
||||
|
||||
void C_SetAlias (const char *name, const char *cmd);
|
||||
void C_ClearAliases ();
|
||||
|
||||
// build a single string out of multiple strings
|
||||
FString BuildString (int argc, FString *argv);
|
||||
|
||||
typedef std::function<void(FCommandLine & argv, int key)> CCmdRun;;
|
||||
|
||||
class FConsoleCommand
|
||||
{
|
||||
public:
|
||||
FConsoleCommand (const char *name, CCmdRun RunFunc);
|
||||
virtual ~FConsoleCommand ();
|
||||
virtual bool IsAlias ();
|
||||
void PrintCommand();
|
||||
|
||||
virtual void Run (FCommandLine &args, int key);
|
||||
static FConsoleCommand* FindByName (const char* name);
|
||||
|
||||
FConsoleCommand *m_Next, **m_Prev;
|
||||
FString m_Name;
|
||||
|
||||
enum { HASH_SIZE = 251 }; // Is this prime?
|
||||
|
||||
protected:
|
||||
FConsoleCommand ();
|
||||
bool AddToHash (FConsoleCommand **table);
|
||||
|
||||
CCmdRun m_RunFunc;
|
||||
|
||||
};
|
||||
|
||||
#define CCMD(n) \
|
||||
void Cmd_##n (FCommandLine &, int key); \
|
||||
FConsoleCommand Cmd_##n##_Ref (#n, Cmd_##n); \
|
||||
void Cmd_##n (FCommandLine &argv, int key)
|
||||
|
||||
class FUnsafeConsoleCommand : public FConsoleCommand
|
||||
{
|
||||
public:
|
||||
FUnsafeConsoleCommand (const char *name, CCmdRun RunFunc)
|
||||
: FConsoleCommand (name, RunFunc)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Run (FCommandLine &args, int key) override;
|
||||
};
|
||||
|
||||
#define UNSAFE_CCMD(n) \
|
||||
static void Cmd_##n (FCommandLine &, int key); \
|
||||
static FUnsafeConsoleCommand Cmd_##n##_Ref (#n, Cmd_##n); \
|
||||
void Cmd_##n (FCommandLine &argv, int key)
|
||||
|
||||
const int KEY_DBLCLICKED = 0x8000;
|
||||
|
||||
class FConsoleAlias : public FConsoleCommand
|
||||
{
|
||||
public:
|
||||
FConsoleAlias (const char *name, const char *command, bool noSave);
|
||||
~FConsoleAlias ();
|
||||
void Run (FCommandLine &args, int key);
|
||||
bool IsAlias ();
|
||||
void PrintAlias ();
|
||||
void Archive (FConfigFile *f);
|
||||
void Realias (const char *command, bool noSave);
|
||||
void SafeDelete ();
|
||||
protected:
|
||||
FString m_Command[2]; // Slot 0 is saved to the ini, slot 1 is not.
|
||||
bool bDoSubstitution;
|
||||
bool bRunning;
|
||||
bool bKill;
|
||||
};
|
||||
|
||||
class FUnsafeConsoleAlias : public FConsoleAlias
|
||||
{
|
||||
public:
|
||||
FUnsafeConsoleAlias (const char *name, const char *command)
|
||||
: FConsoleAlias (name, command, true)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Run (FCommandLine &args, int key) override;
|
||||
};
|
||||
|
||||
class UnsafeExecutionScope
|
||||
{
|
||||
const bool wasEnabled;
|
||||
|
||||
public:
|
||||
explicit UnsafeExecutionScope(const bool enable = true)
|
||||
: wasEnabled(UnsafeExecutionContext)
|
||||
{
|
||||
UnsafeExecutionContext = enable;
|
||||
}
|
||||
|
||||
~UnsafeExecutionScope()
|
||||
{
|
||||
UnsafeExecutionContext = wasEnabled;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
void execLogfile(const char *fn, bool append = false);
|
||||
|
||||
enum
|
||||
{
|
||||
CCMD_OK = 0,
|
||||
CCMD_SHOWHELP = 1
|
||||
};
|
||||
|
||||
struct CCmdFuncParm
|
||||
{
|
||||
int32_t numparms;
|
||||
const char* name;
|
||||
const char** parms;
|
||||
const char* raw;
|
||||
};
|
||||
|
||||
using CCmdFuncPtr = CCmdFuncParm const* const;
|
||||
|
||||
// registers a function
|
||||
// name = name of the function
|
||||
// help = a short help string
|
||||
// func = the entry point to the function
|
||||
int C_RegisterFunction(const char* name, const char* help, int (*func)(CCmdFuncPtr));
|
||||
|
||||
|
||||
#endif //__C_DISPATCH_H__
|
||||
|
|
@ -1,332 +0,0 @@
|
|||
/*
|
||||
** c_cmds.cpp
|
||||
** Miscellaneous game independent console commands.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "c_console.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "engineerrors.h"
|
||||
#include "printf.h"
|
||||
#include "files.h"
|
||||
#include "filesystem.h"
|
||||
#include "gstrings.h"
|
||||
#include "version.h"
|
||||
#include "findfile.h"
|
||||
#include "md5.h"
|
||||
|
||||
extern FILE* Logfile;
|
||||
|
||||
CCMD (quit)
|
||||
{
|
||||
throw CExitEvent(0);
|
||||
}
|
||||
|
||||
CCMD (exit)
|
||||
{
|
||||
throw CExitEvent(0);
|
||||
}
|
||||
|
||||
CCMD (gameversion)
|
||||
{
|
||||
Printf ("%s @ %s\nCommit %s\n", GetVersionString(), GetGitTime(), GetGitHash());
|
||||
}
|
||||
|
||||
CCMD (print)
|
||||
{
|
||||
if (argv.argc() != 2)
|
||||
{
|
||||
Printf ("print <name>: Print a string from the string table\n");
|
||||
return;
|
||||
}
|
||||
const char *str = GStrings[argv[1]];
|
||||
if (str == NULL)
|
||||
{
|
||||
Printf ("%s unknown\n", argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("%s\n", str);
|
||||
}
|
||||
}
|
||||
|
||||
UNSAFE_CCMD (exec)
|
||||
{
|
||||
if (argv.argc() < 2)
|
||||
return;
|
||||
|
||||
for (int i = 1; i < argv.argc(); ++i)
|
||||
{
|
||||
if (!C_ExecFile(argv[i]))
|
||||
{
|
||||
Printf ("Could not exec \"%s\"\n", argv[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void execLogfile(const char *fn, bool append)
|
||||
{
|
||||
if ((Logfile = fopen(fn, append? "a" : "w")))
|
||||
{
|
||||
const char *timestr = myasctime();
|
||||
Printf("Log started: %s\n", timestr);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("Could not start log\n");
|
||||
}
|
||||
}
|
||||
|
||||
UNSAFE_CCMD (logfile)
|
||||
{
|
||||
|
||||
if (Logfile)
|
||||
{
|
||||
const char *timestr = myasctime();
|
||||
Printf("Log stopped: %s\n", timestr);
|
||||
fclose (Logfile);
|
||||
Logfile = NULL;
|
||||
}
|
||||
|
||||
if (argv.argc() >= 2)
|
||||
{
|
||||
execLogfile(argv[1], argv.argc() >=3? !!argv[2]:false);
|
||||
}
|
||||
}
|
||||
|
||||
CCMD (error)
|
||||
{
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
I_Error ("%s", argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("Usage: error <error text>\n");
|
||||
}
|
||||
}
|
||||
|
||||
UNSAFE_CCMD (error_fatal)
|
||||
{
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
I_FatalError ("%s", argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("Usage: error_fatal <error text>\n");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CCMD crashout
|
||||
//
|
||||
// Debugging routine for testing the crash logger.
|
||||
// Useless in a win32 debug build, because that doesn't enable the crash logger.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
#if !defined(_WIN32) || !defined(_DEBUG)
|
||||
UNSAFE_CCMD (crashout)
|
||||
{
|
||||
*(volatile int *)0 = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
UNSAFE_CCMD (dir)
|
||||
{
|
||||
FString dir, path;
|
||||
char curdir[256];
|
||||
const char *match;
|
||||
findstate_t c_file;
|
||||
void *file;
|
||||
|
||||
if (!getcwd (curdir, countof(curdir)))
|
||||
{
|
||||
Printf ("Current path too long\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
path = NicePath(argv[1]);
|
||||
if (chdir(path))
|
||||
{
|
||||
match = path;
|
||||
dir = ExtractFilePath(path);
|
||||
if (dir[0] != '\0')
|
||||
{
|
||||
match += dir.Len();
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = "./";
|
||||
}
|
||||
if (match[0] == '\0')
|
||||
{
|
||||
match = "*";
|
||||
}
|
||||
if (chdir (dir))
|
||||
{
|
||||
Printf ("%s not found\n", dir.GetChars());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
match = "*";
|
||||
dir = path;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
match = "*";
|
||||
dir = curdir;
|
||||
}
|
||||
if (dir[dir.Len()-1] != '/')
|
||||
{
|
||||
dir += '/';
|
||||
}
|
||||
|
||||
if ( (file = I_FindFirst (match, &c_file)) == ((void *)(-1)))
|
||||
Printf ("Nothing matching %s%s\n", dir.GetChars(), match);
|
||||
else
|
||||
{
|
||||
Printf ("Listing of %s%s:\n", dir.GetChars(), match);
|
||||
do
|
||||
{
|
||||
if (I_FindAttr (&c_file) & FA_DIREC)
|
||||
Printf (PRINT_BOLD, "%s <dir>\n", I_FindName (&c_file));
|
||||
else
|
||||
Printf ("%s\n", I_FindName (&c_file));
|
||||
} while (I_FindNext (file, &c_file) == 0);
|
||||
I_FindClose (file);
|
||||
}
|
||||
|
||||
chdir (curdir);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CCMD wdir
|
||||
//
|
||||
// Lists the contents of a loaded wad file.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD (wdir)
|
||||
{
|
||||
int wadnum;
|
||||
if (argv.argc() != 2) wadnum = -1;
|
||||
else
|
||||
{
|
||||
wadnum = fileSystem.CheckIfResourceFileLoaded (argv[1]);
|
||||
if (wadnum < 0)
|
||||
{
|
||||
Printf ("%s must be loaded to view its directory.\n", argv[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < fileSystem.GetNumEntries(); ++i)
|
||||
{
|
||||
if (wadnum == -1 || fileSystem.GetFileContainer(i) == wadnum)
|
||||
{
|
||||
Printf ("%10d %s\n", fileSystem.FileLength(i), fileSystem.GetFileFullName(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CCMD md5sum
|
||||
//
|
||||
// Like the command-line tool, because I wanted to make sure I had it right.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD (md5sum)
|
||||
{
|
||||
if (argv.argc() < 2)
|
||||
{
|
||||
Printf("Usage: md5sum <file> ...\n");
|
||||
}
|
||||
for (int i = 1; i < argv.argc(); ++i)
|
||||
{
|
||||
FileReader fr;
|
||||
if (!fr.OpenFile(argv[i]))
|
||||
{
|
||||
Printf("%s: %s\n", argv[i], strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
MD5Context md5;
|
||||
uint8_t readbuf[8192];
|
||||
size_t len;
|
||||
|
||||
while ((len = fr.Read(readbuf, sizeof(readbuf))) > 0)
|
||||
{
|
||||
md5.Update(readbuf, (unsigned int)len);
|
||||
}
|
||||
md5.Final(readbuf);
|
||||
for(int j = 0; j < 16; ++j)
|
||||
{
|
||||
Printf("%02x", readbuf[j]);
|
||||
}
|
||||
Printf(" *%s\n", argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCMD(printlocalized)
|
||||
{
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
if (argv.argc() > 2)
|
||||
{
|
||||
FString lang = argv[2];
|
||||
lang.ToLower();
|
||||
if (lang.Len() >= 2)
|
||||
{
|
||||
Printf("%s\n", GStrings.GetLanguageString(argv[1], MAKE_ID(lang[0], lang[1], lang[2], 0)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
Printf("%s\n", GStrings(argv[1]));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,812 +0,0 @@
|
|||
/*
|
||||
** c_expr.cpp
|
||||
** Console commands dealing with mathematical expressions
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "c_dispatch.h"
|
||||
#include "c_cvars.h"
|
||||
#include "cmdlib.h"
|
||||
#include "printf.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
enum EProductionType
|
||||
{
|
||||
PROD_String, PROD_Double
|
||||
};
|
||||
|
||||
struct FProduction
|
||||
{
|
||||
EProductionType Type;
|
||||
};
|
||||
|
||||
struct FStringProd : public FProduction
|
||||
{
|
||||
char Value[1];
|
||||
};
|
||||
|
||||
struct FDoubleProd : public FProduction
|
||||
{
|
||||
double Value;
|
||||
};
|
||||
|
||||
struct FProducer
|
||||
{
|
||||
char Token[4];
|
||||
FProduction *(*DoubleProducer) (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *(*StringProducer) (FStringProd *prod1, FStringProd *prod2);
|
||||
};
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
bool IsFloat (const char *str);
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
static FProduction *ParseExpression (FCommandLine &argv, int &parsept);
|
||||
static const char *CIsNum (const char *str);
|
||||
static FStringProd *NewStringProd (const char *str);
|
||||
static FStringProd *NewStringProd (size_t len);
|
||||
static FDoubleProd *NewDoubleProd (double val);
|
||||
static FStringProd *DoubleToString (FProduction *prod);
|
||||
static FDoubleProd *StringToDouble (FProduction *prod);
|
||||
void MaybeStringCoerce (FProduction *&prod1, FProduction *&prod2);
|
||||
void MustStringCoerce (FProduction *&prod1, FProduction *&prod2);
|
||||
void DoubleCoerce (FProduction *&prod1, FProduction *&prod2);
|
||||
|
||||
FProduction *ProdAddDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdAddStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdSubDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdMulDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdDivDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdModDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdPowDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdLTDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdLTEDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdGTDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdGTEDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdEqDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdNeqDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdXorDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdAndDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdOrDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdLAndDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdLOrDbl (FDoubleProd *prod1, FDoubleProd *prod2);
|
||||
FProduction *ProdLTStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdLTEStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdGTStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdGTEStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdEqStr (FStringProd *prod1, FStringProd *prod2);
|
||||
FProduction *ProdNeqStr (FStringProd *prod1, FStringProd *prod2);
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static FProducer Producers[] =
|
||||
{
|
||||
{ "+", ProdAddDbl, ProdAddStr },
|
||||
{ "-", ProdSubDbl, NULL },
|
||||
{ "*", ProdMulDbl, NULL },
|
||||
{ "/", ProdDivDbl, NULL },
|
||||
{ "%", ProdModDbl, NULL },
|
||||
{ "^", ProdPowDbl, NULL },
|
||||
{ "<", ProdLTDbl, ProdLTStr },
|
||||
{ "<=", ProdLTEDbl, ProdLTEStr },
|
||||
{ ">", ProdGTDbl, ProdGTStr },
|
||||
{ ">=", ProdGTEDbl, ProdGTEStr },
|
||||
{ "=", ProdEqDbl, ProdEqStr },
|
||||
{ "==", ProdEqDbl, ProdEqStr },
|
||||
{ "!=", ProdNeqDbl, ProdNeqStr },
|
||||
{ "<>", ProdNeqDbl, ProdNeqStr },
|
||||
{ "xor", ProdXorDbl, NULL },
|
||||
{ "&", ProdAndDbl, NULL },
|
||||
{ "|", ProdOrDbl, NULL },
|
||||
{ "&&", ProdLAndDbl, NULL },
|
||||
{ "||", ProdLOrDbl, NULL }
|
||||
};
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ParseExpression
|
||||
//
|
||||
// Builds a production from an expression. The supported syntax is LISP-like
|
||||
// but without parentheses.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FProduction *ParseExpression (FCommandLine &argv, int &parsept)
|
||||
{
|
||||
if (parsept >= argv.argc())
|
||||
return NULL;
|
||||
|
||||
const char *token = argv[parsept++];
|
||||
FProduction *prod1 = NULL, *prod2 = NULL, *prod3 = NULL;
|
||||
|
||||
if (IsFloat (token))
|
||||
{
|
||||
return NewDoubleProd (atof(token));
|
||||
}
|
||||
else if (stricmp (token, "true") == 0)
|
||||
{
|
||||
return NewDoubleProd (1.0);
|
||||
}
|
||||
else if (stricmp (token, "false") == 0)
|
||||
{
|
||||
return NewDoubleProd (0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < countof(Producers); ++i)
|
||||
{
|
||||
if (strcmp (Producers[i].Token, token) == 0)
|
||||
{
|
||||
prod1 = ParseExpression (argv, parsept);
|
||||
prod2 = ParseExpression (argv, parsept);
|
||||
if (prod1 == NULL || prod2 == NULL)
|
||||
{
|
||||
goto missing;
|
||||
}
|
||||
if (Producers[i].StringProducer == NULL)
|
||||
{
|
||||
DoubleCoerce (prod1, prod2);
|
||||
}
|
||||
else if (Producers[i].DoubleProducer == NULL)
|
||||
{
|
||||
MustStringCoerce (prod1, prod2);
|
||||
}
|
||||
else
|
||||
{
|
||||
MaybeStringCoerce (prod1, prod2);
|
||||
}
|
||||
if (prod1->Type == PROD_String)
|
||||
{
|
||||
prod3 = Producers[i].StringProducer ((FStringProd *)prod1, (FStringProd *)prod2);
|
||||
}
|
||||
else
|
||||
{
|
||||
prod3 = Producers[i].DoubleProducer ((FDoubleProd *)prod1, (FDoubleProd *)prod2);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (strcmp ("!", token) == 0)
|
||||
{
|
||||
prod1 = ParseExpression (argv, parsept);
|
||||
if (prod1 == NULL)
|
||||
{
|
||||
goto missing;
|
||||
}
|
||||
if (prod1->Type == PROD_String)
|
||||
{
|
||||
prod1 = StringToDouble (prod1);
|
||||
}
|
||||
prod3 = NewDoubleProd (!static_cast<FDoubleProd *>(prod1)->Value);
|
||||
goto done;
|
||||
}
|
||||
return NewStringProd (token);
|
||||
}
|
||||
|
||||
missing:
|
||||
Printf ("Missing argument to %s\n", token);
|
||||
|
||||
done:
|
||||
if (prod2 != NULL) M_Free (prod2);
|
||||
if (prod1 != NULL) M_Free (prod1);
|
||||
return prod3;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsFloat
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool IsFloat (const char *str)
|
||||
{
|
||||
const char *pt;
|
||||
|
||||
if (*str == '+' || *str == '-')
|
||||
str++;
|
||||
|
||||
if (*str == '.')
|
||||
{
|
||||
pt = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
pt = CIsNum (str);
|
||||
if (pt == NULL)
|
||||
return false;
|
||||
}
|
||||
if (*pt == '.')
|
||||
{
|
||||
pt = CIsNum (pt+1);
|
||||
if (pt == NULL)
|
||||
return false;
|
||||
}
|
||||
if (*pt == 'e' || *pt == 'E')
|
||||
{
|
||||
pt++;
|
||||
if (*pt == '+' || *pt == '-')
|
||||
pt++;
|
||||
pt = CIsNum (pt);
|
||||
}
|
||||
return pt != NULL && *pt == 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsNum
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static const char *CIsNum (const char *str)
|
||||
{
|
||||
const char *start = str;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
if (*str >= '0' && *str <= '9')
|
||||
str++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return (str > start) ? str : NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// NewStringProd (from a string)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FStringProd *NewStringProd (const char *str)
|
||||
{
|
||||
FStringProd *prod = (FStringProd *)M_Malloc (sizeof(FStringProd)+strlen(str));
|
||||
prod->Type = PROD_String;
|
||||
strcpy (prod->Value, str);
|
||||
return prod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// NewStringProd (from a length)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FStringProd *NewStringProd (size_t len)
|
||||
{
|
||||
FStringProd *prod = (FStringProd *)M_Malloc (sizeof(FStringProd)+len);
|
||||
prod->Type = PROD_String;
|
||||
prod->Value[0] = 0;
|
||||
return prod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// NewDoubleProd
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FDoubleProd *NewDoubleProd (double val)
|
||||
{
|
||||
FDoubleProd *prod = (FDoubleProd *)M_Malloc (sizeof(FDoubleProd));
|
||||
prod->Type = PROD_Double;
|
||||
prod->Value = val;
|
||||
return prod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DoubleToString
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FStringProd *DoubleToString (FProduction *prod)
|
||||
{
|
||||
char buf[128];
|
||||
FStringProd *newprod;
|
||||
|
||||
mysnprintf (buf, countof(buf), "%g", static_cast<FDoubleProd *>(prod)->Value);
|
||||
newprod = NewStringProd (buf);
|
||||
M_Free (prod);
|
||||
return newprod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// StringToDouble
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FDoubleProd *StringToDouble (FProduction *prod)
|
||||
{
|
||||
FDoubleProd *newprod;
|
||||
|
||||
newprod = NewDoubleProd (atof (static_cast<FStringProd *>(prod)->Value));
|
||||
M_Free (prod);
|
||||
return newprod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MaybeStringCoerce
|
||||
//
|
||||
// If one of the parameters is a string, convert the other to a string.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MaybeStringCoerce (FProduction *&prod1, FProduction *&prod2)
|
||||
{
|
||||
if (prod1->Type == PROD_String)
|
||||
{
|
||||
if (prod2->Type == PROD_Double)
|
||||
{
|
||||
prod2 = DoubleToString (prod2);
|
||||
}
|
||||
}
|
||||
else if (prod2->Type == PROD_String)
|
||||
{
|
||||
prod1 = DoubleToString (prod1);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MustStringCoerce
|
||||
//
|
||||
// Ensures that both parameters are strings
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MustStringCoerce (FProduction *&prod1, FProduction *&prod2)
|
||||
{
|
||||
if (prod1->Type == PROD_Double)
|
||||
{
|
||||
prod1 = DoubleToString (prod1);
|
||||
}
|
||||
if (prod2->Type == PROD_Double)
|
||||
{
|
||||
prod2 = DoubleToString (prod2);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DoubleCoerce
|
||||
//
|
||||
// Ensures that both parameters are doubles
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DoubleCoerce (FProduction *&prod1, FProduction *&prod2)
|
||||
{
|
||||
if (prod1->Type == PROD_String)
|
||||
{
|
||||
prod1 = StringToDouble (prod1);
|
||||
}
|
||||
if (prod2->Type == PROD_String)
|
||||
{
|
||||
prod2 = StringToDouble (prod2);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdAddDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdAddDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value + prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdAddStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdAddStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
size_t len = strlen (prod1->Value) + strlen (prod2->Value) + 1;
|
||||
FStringProd *prod = NewStringProd (len);
|
||||
strcpy (prod->Value, prod1->Value);
|
||||
strcat (prod->Value, prod2->Value);
|
||||
return prod;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdSubDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdSubDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value - prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdMulDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdMulDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value * prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdDivDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdDivDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value / prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdModDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdModDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (fmod (prod1->Value, prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdPowDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdPowDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (pow (prod1->Value, prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLTDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLTDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value < prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLTEDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLTEDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value <= prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdGTDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdGTDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value > prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdGTEDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdGTEDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value >= prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdEqDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdEqDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value == prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdNeqDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdNeqDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (prod1->Value != prod2->Value);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLTStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLTStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) < 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLTEStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLTEStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) <= 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdGTStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdGTStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) > 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdGTEStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdGTEStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) >= 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdEqStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdEqStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) == 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdNeqStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdNeqStr (FStringProd *prod1, FStringProd *prod2)
|
||||
{
|
||||
return NewDoubleProd (stricmp (prod1->Value, prod2->Value) != 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdXorDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdXorDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd ((double)((int64_t)prod1->Value ^ (int64_t)prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdAndDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdAndDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd ((double)((int64_t)prod1->Value & (int64_t)prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdOrDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdOrDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd ((double)((int64_t)prod1->Value | (int64_t)prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLAndDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLAndDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd ((double)((int64_t)prod1->Value && (int64_t)prod2->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ProdLOrDbl
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FProduction *ProdLOrDbl (FDoubleProd *prod1, FDoubleProd *prod2)
|
||||
{
|
||||
return NewDoubleProd ((double)((int64_t)prod1->Value || (int64_t)prod2->Value));
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CCMD test
|
||||
//
|
||||
// If <expr> is non-zero, execute <true cmd>.
|
||||
// If <expr> is zero, execute [false cmd] if specified.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD (test)
|
||||
{
|
||||
int parsept = 1;
|
||||
FProduction *prod = ParseExpression (argv, parsept);
|
||||
|
||||
if (prod == NULL || parsept >= argv.argc())
|
||||
{
|
||||
Printf ("Usage: test <expr> <true cmd> [false cmd]\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prod->Type == PROD_String)
|
||||
{
|
||||
prod = StringToDouble (prod);
|
||||
}
|
||||
|
||||
if (static_cast<FDoubleProd *>(prod)->Value != 0.0)
|
||||
{
|
||||
AddCommandString (argv[parsept]);
|
||||
}
|
||||
else if (++parsept < argv.argc())
|
||||
{
|
||||
AddCommandString (argv[parsept]);
|
||||
}
|
||||
}
|
||||
if (prod != NULL)
|
||||
{
|
||||
M_Free (prod);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CCMD eval
|
||||
//
|
||||
// Evaluates an expression and either prints it to the console or stores
|
||||
// it in an existing cvar.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD (eval)
|
||||
{
|
||||
if (argv.argc() >= 2)
|
||||
{
|
||||
int parsept = 1;
|
||||
FProduction *prod = ParseExpression (argv, parsept);
|
||||
|
||||
if (prod != NULL)
|
||||
{
|
||||
if (parsept < argv.argc())
|
||||
{
|
||||
FBaseCVar *var = FindCVar (argv[parsept], NULL);
|
||||
if (var == NULL)
|
||||
{
|
||||
Printf ("Unknown variable %s\n", argv[parsept]);
|
||||
}
|
||||
else
|
||||
{
|
||||
UCVarValue val;
|
||||
|
||||
if (prod->Type == PROD_Double)
|
||||
{
|
||||
val.Float = (float)static_cast<FDoubleProd *>(prod)->Value;
|
||||
var->SetGenericRep (val, CVAR_Float);
|
||||
}
|
||||
else
|
||||
{
|
||||
val.String = static_cast<FStringProd *>(prod)->Value;
|
||||
var->SetGenericRep (val, CVAR_String);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prod->Type == PROD_Double)
|
||||
{
|
||||
Printf ("%g\n", static_cast<FDoubleProd *>(prod)->Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("%s\n", static_cast<FStringProd *>(prod)->Value);
|
||||
}
|
||||
}
|
||||
M_Free (prod);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Printf ("Usage: eval <expression> [variable]\n");
|
||||
}
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
//
|
||||
// Keyboard definition. Everything below = 0x100 matches
|
||||
// a mode 1 keyboard scan code.
|
||||
//
|
||||
|
||||
enum EKeyCodes
|
||||
{
|
||||
KEY_PAUSE = 0xc5, // DIK_PAUSE
|
||||
KEY_RIGHTARROW = 0xcd, // DIK_RIGHT
|
||||
KEY_LEFTARROW = 0xcb, // DIK_LEFT
|
||||
KEY_UPARROW = 0xc8, // DIK_UP
|
||||
KEY_DOWNARROW = 0xd0, // DIK_DOWN
|
||||
KEY_ESCAPE = 0x01, // DIK_ESCAPE
|
||||
KEY_ENTER = 0x1c, // DIK_RETURN
|
||||
KEY_SPACE = 0x39, // DIK_SPACE
|
||||
KEY_TAB = 0x0f, // DIK_TAB
|
||||
KEY_F1 = 0x3b, // DIK_F1
|
||||
KEY_F2 = 0x3c, // DIK_F2
|
||||
KEY_F3 = 0x3d, // DIK_F3
|
||||
KEY_F4 = 0x3e, // DIK_F4
|
||||
KEY_F5 = 0x3f, // DIK_F5
|
||||
KEY_F6 = 0x40, // DIK_F6
|
||||
KEY_F7 = 0x41, // DIK_F7
|
||||
KEY_F8 = 0x42, // DIK_F8
|
||||
KEY_F9 = 0x43, // DIK_F9
|
||||
KEY_F10 = 0x44, // DIK_F10
|
||||
KEY_F11 = 0x57, // DIK_F11
|
||||
KEY_F12 = 0x58, // DIK_F12
|
||||
KEY_GRAVE = 0x29, // DIK_GRAVE
|
||||
|
||||
KEY_BACKSPACE = 0x0e, // DIK_BACK
|
||||
|
||||
KEY_EQUALS = 0x0d, // DIK_EQUALS
|
||||
KEY_MINUS = 0x0c, // DIK_MINUS
|
||||
|
||||
KEY_LSHIFT = 0x2A, // DIK_LSHIFT
|
||||
KEY_LCTRL = 0x1d, // DIK_LCONTROL
|
||||
KEY_LALT = 0x38, // DIK_LMENU
|
||||
|
||||
KEY_RSHIFT = 0x36,
|
||||
KEY_RCTRL = 0x9d,
|
||||
KEY_RALT = 0xb8,
|
||||
|
||||
KEY_INS = 0xd2, // DIK_INSERT
|
||||
KEY_DEL = 0xd3, // DIK_DELETE
|
||||
KEY_END = 0xcf, // DIK_END
|
||||
KEY_HOME = 0xc7, // DIK_HOME
|
||||
KEY_PGUP = 0xc9, // DIK_PRIOR
|
||||
KEY_PGDN = 0xd1, // DIK_NEXT
|
||||
|
||||
KEY_FIRSTMOUSEBUTTON = 0x100,
|
||||
KEY_MOUSE1 = 0x100,
|
||||
KEY_MOUSE2 = 0x101,
|
||||
KEY_MOUSE3 = 0x102,
|
||||
KEY_MOUSE4 = 0x103,
|
||||
KEY_MOUSE5 = 0x104,
|
||||
KEY_MOUSE6 = 0x105,
|
||||
KEY_MOUSE7 = 0x106,
|
||||
KEY_MOUSE8 = 0x107,
|
||||
|
||||
KEY_FIRSTJOYBUTTON = 0x108,
|
||||
KEY_JOY1 = KEY_FIRSTJOYBUTTON+0,
|
||||
KEY_JOY2,
|
||||
KEY_JOY3,
|
||||
KEY_JOY4,
|
||||
KEY_JOY5,
|
||||
KEY_JOY6,
|
||||
KEY_JOY7,
|
||||
KEY_JOY8,
|
||||
KEY_LASTJOYBUTTON = 0x187,
|
||||
KEY_JOYPOV1_UP = 0x188,
|
||||
KEY_JOYPOV1_RIGHT = 0x189,
|
||||
KEY_JOYPOV1_DOWN = 0x18a,
|
||||
KEY_JOYPOV1_LEFT = 0x18b,
|
||||
KEY_JOYPOV2_UP = 0x18c,
|
||||
KEY_JOYPOV3_UP = 0x190,
|
||||
KEY_JOYPOV4_UP = 0x194,
|
||||
|
||||
KEY_MWHEELUP = 0x198,
|
||||
KEY_MWHEELDOWN = 0x199,
|
||||
KEY_MWHEELRIGHT = 0x19A,
|
||||
KEY_MWHEELLEFT = 0x19B,
|
||||
|
||||
KEY_JOYAXIS1PLUS = 0x19C,
|
||||
KEY_JOYAXIS1MINUS = 0x19D,
|
||||
KEY_JOYAXIS2PLUS = 0x19E,
|
||||
KEY_JOYAXIS2MINUS = 0x19F,
|
||||
KEY_JOYAXIS3PLUS = 0x1A0,
|
||||
KEY_JOYAXIS3MINUS = 0x1A1,
|
||||
KEY_JOYAXIS4PLUS = 0x1A2,
|
||||
KEY_JOYAXIS4MINUS = 0x1A3,
|
||||
KEY_JOYAXIS5PLUS = 0x1A4,
|
||||
KEY_JOYAXIS5MINUS = 0x1A5,
|
||||
KEY_JOYAXIS6PLUS = 0x1A6,
|
||||
KEY_JOYAXIS6MINUS = 0x1A7,
|
||||
KEY_JOYAXIS7PLUS = 0x1A8,
|
||||
KEY_JOYAXIS7MINUS = 0x1A9,
|
||||
KEY_JOYAXIS8PLUS = 0x1AA,
|
||||
KEY_JOYAXIS8MINUS = 0x1AB,
|
||||
|
||||
KEY_PAD_LTHUMB_RIGHT = 0x1AC,
|
||||
KEY_PAD_LTHUMB_LEFT = 0x1AD,
|
||||
KEY_PAD_LTHUMB_DOWN = 0x1AE,
|
||||
KEY_PAD_LTHUMB_UP = 0x1AF,
|
||||
|
||||
KEY_PAD_RTHUMB_RIGHT = 0x1B0,
|
||||
KEY_PAD_RTHUMB_LEFT = 0x1B1,
|
||||
KEY_PAD_RTHUMB_DOWN = 0x1B2,
|
||||
KEY_PAD_RTHUMB_UP = 0x1B3,
|
||||
|
||||
KEY_PAD_DPAD_UP = 0x1B4,
|
||||
KEY_PAD_DPAD_DOWN = 0x1B5,
|
||||
KEY_PAD_DPAD_LEFT = 0x1B6,
|
||||
KEY_PAD_DPAD_RIGHT = 0x1B7,
|
||||
KEY_PAD_START = 0x1B8,
|
||||
KEY_PAD_BACK = 0x1B9,
|
||||
KEY_PAD_LTHUMB = 0x1BA,
|
||||
KEY_PAD_RTHUMB = 0x1BB,
|
||||
KEY_PAD_LSHOULDER = 0x1BC,
|
||||
KEY_PAD_RSHOULDER = 0x1BD,
|
||||
KEY_PAD_LTRIGGER = 0x1BE,
|
||||
KEY_PAD_RTRIGGER = 0x1BF,
|
||||
KEY_PAD_A = 0x1C0,
|
||||
KEY_PAD_B = 0x1C1,
|
||||
KEY_PAD_X = 0x1C2,
|
||||
KEY_PAD_Y = 0x1C3,
|
||||
|
||||
NUM_KEYS = 0x1C4,
|
||||
|
||||
NUM_JOYAXISBUTTONS = 8,
|
||||
};
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue