- 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:
Christoph Oelckers 2020-04-11 18:11:43 +02:00
commit c3a381ed92
19 changed files with 16 additions and 12 deletions

View file

@ -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;
}

View file

@ -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__

View file

@ -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);
}
}

View file

@ -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

View file

@ -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];
}

View file

@ -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;
};

View file

@ -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

View file

@ -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;
}
}

View file

@ -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

View file

@ -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

View file

@ -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__

View file

@ -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]));
}
}

View file

@ -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");
}

View file

@ -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,
};