stella/src/emucore/Settings.cxx

681 lines
25 KiB
C++
Raw Normal View History

//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include <cassert>
#include <sstream>
#include <fstream>
#include <algorithm>
#include "bspf.hxx"
#include "OSystem.hxx"
#include "Version.hxx"
#ifdef DEBUGGER_SUPPORT
#include "DebuggerDialog.hxx"
#endif
#include "Settings.hxx"
X11 and SDL versions now fully compile and fully support the new EventHandler class. All thats left to do there is integrate the Snapshot code into the core, but that will have to wait until I rewrite the PNG handler to not need the PNG library ... Changed the Settings class to a virtual abstract class, and created a SettingsUNIX class to derive from it and work with the X11 and SDL versions. Some notes on updating the DOS and Windows ports (which I will probably do eventually), and on porting to other toolkits: A port needs the following: - a main function which takes native events and converts to the core format, and generally acts as the dispatcher (mainXXX.cxx) - a specific frontend, derived from Frontend.hxx, which sets up port specific filename and locations (FrontendXXX.hxx) - a specific settings class, derived from Settings.hxx, which deals with settings/commandline arguments specific to that port (SettingsXXX.hxx) - probably some other stuff that I've forgotten The next step is get the DOS port working with the new EventHandler (easy) and attempt to bring the Windows port into the year 2003 (it hasn't been touched for almost a year, quite hard). I also have to write a GUI class that will draw menus, etc. and actually let you remap keys from the emulator itself. And that may have to wait until the fabled graphics rewrite that Brad and I will be working on. It never ends ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@181 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2003-09-11 20:53:51 +00:00
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Settings::Settings(OSystem& osystem)
: myOSystem(osystem)
{
// Video-related options
setInternal("video", "");
setInternal("vsync", "true");
setInternal("fullscreen", "false");
setInternal("center", "false");
setInternal("palette", "standard");
setInternal("colorloss", "false");
setInternal("timing", "sleep");
setInternal("uimessages", "true");
// TIA specific options
setInternal("tia.zoom", "3");
setInternal("tia.inter", "false");
setInternal("tia.aspectn", "90");
setInternal("tia.aspectp", "100");
setInternal("tia.fsfill", "false");
setInternal("tia.dbgcolors", "roygpb");
// TV filtering options
setInternal("tv.filter", "0");
setInternal("tv.phosphor", "50");
setInternal("tv.jitter", "false");
setInternal("tv.jitter_recovery", "10");
setInternal("tv.scanlines", "25");
setInternal("tv.scaninter", "true");
// TV options when using 'custom' mode
setInternal("tv.contrast", "0.0");
setInternal("tv.brightness", "0.0");
setInternal("tv.hue", "0.0");
setInternal("tv.saturation", "0.0");
setInternal("tv.gamma", "0.0");
setInternal("tv.sharpness", "0.0");
setInternal("tv.resolution", "0.0");
setInternal("tv.artifacts", "0.0");
setInternal("tv.fringing", "0.0");
setInternal("tv.bleed", "0.0");
// Sound options
setInternal("sound", "true");
setInternal("fragsize", "512");
setInternal("freq", "31400");
setInternal("volume", "100");
// Input event options
setInternal("keymap", "");
setInternal("joymap", "");
setInternal("combomap", "");
setInternal("joydeadzone", "13");
setInternal("joyallow4", "false");
setInternal("usemouse", "analog");
setInternal("grabmouse", "true");
setInternal("cursor", "2");
setInternal("dsense", "10");
setInternal("msense", "10");
setInternal("saport", "lr");
setInternal("ctrlcombo", "true");
// Snapshot options
setInternal("snapsavedir", "");
setInternal("snaploaddir", "");
setInternal("snapname", "int");
setInternal("sssingle", "false");
setInternal("ss1x", "false");
setInternal("ssinterval", "2");
// Config files and paths
setInternal("romdir", "");
setInternal("statedir", "");
setInternal("cheatfile", "");
setInternal("palettefile", "");
setInternal("propsfile", "");
setInternal("nvramdir", "");
setInternal("cfgdir", "");
// ROM browser options
setInternal("exitlauncher", "false");
setInternal("launcherres", GUI::Size(900, 600));
setInternal("launcherfont", "medium");
setInternal("launcherexts", "allroms");
setInternal("romviewer", "1");
setInternal("lastrom", "");
// UI-related options
#ifdef DEBUGGER_SUPPORT
setInternal("dbg.res",
GUI::Size(DebuggerDialog::kMediumFontMinW,
DebuggerDialog::kMediumFontMinH));
#endif
setInternal("uipalette", "standard");
setInternal("listdelay", "300");
setInternal("mwheel", "4");
// Misc options
setInternal("autoslot", "false");
setInternal("loglevel", "1");
setInternal("logtoconsole", "0");
setInternal("tiadriven", "false");
setInternal("cpurandom", "");
setInternal("ramrandom", "true");
setInternal("avoxport", "");
setInternal("stats", "false");
setInternal("fastscbios", "true");
setExternal("romloadcount", "0");
setExternal("maxres", "");
#ifdef DEBUGGER_SUPPORT
// Debugger/disassembly options
setInternal("dbg.fontstyle", "0");
setInternal("dbg.uhex", "true");
setInternal("dis.resolve", "true");
setInternal("dis.gfxformat", "2");
setInternal("dis.showaddr", "true");
setInternal("dis.relocate", "false");
#endif
#ifdef DTHUMB_SUPPORT
// Thumb ARM emulation options
setInternal("thumb.trapfatal", "true");
#endif
}
X11 and SDL versions now fully compile and fully support the new EventHandler class. All thats left to do there is integrate the Snapshot code into the core, but that will have to wait until I rewrite the PNG handler to not need the PNG library ... Changed the Settings class to a virtual abstract class, and created a SettingsUNIX class to derive from it and work with the X11 and SDL versions. Some notes on updating the DOS and Windows ports (which I will probably do eventually), and on porting to other toolkits: A port needs the following: - a main function which takes native events and converts to the core format, and generally acts as the dispatcher (mainXXX.cxx) - a specific frontend, derived from Frontend.hxx, which sets up port specific filename and locations (FrontendXXX.hxx) - a specific settings class, derived from Settings.hxx, which deals with settings/commandline arguments specific to that port (SettingsXXX.hxx) - probably some other stuff that I've forgotten The next step is get the DOS port working with the new EventHandler (easy) and attempt to bring the Windows port into the year 2003 (it hasn't been touched for almost a year, quite hard). I also have to write a GUI class that will draw menus, etc. and actually let you remap keys from the emulator itself. And that may have to wait until the fabled graphics rewrite that Brad and I will be working on. It never ends ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@181 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2003-09-11 20:53:51 +00:00
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Settings::loadConfig()
{
string line, key, value;
string::size_type equalPos, garbage;
ifstream in(myOSystem.configFile());
if(!in || !in.is_open())
{
myOSystem.logMessage("ERROR: Couldn't load settings file", 0);
return;
}
while(getline(in, line))
{
// Strip all whitespace and tabs from the line
while((garbage = line.find("\t")) != string::npos)
line.erase(garbage, 1);
// Ignore commented and empty lines
if((line.length() == 0) || (line[0] == ';'))
continue;
// Search for the equal sign and discard the line if its not found
if((equalPos = line.find("=")) == string::npos)
continue;
// Split the line into key/value pairs and trim any whitespace
key = line.substr(0, equalPos);
value = line.substr(equalPos + 1, line.length() - key.length() - 1);
key = trim(key);
value = trim(value);
// Check for absent key or value
if((key.length() == 0) || (value.length() == 0))
continue;
// Only settings which have been previously set are valid
if(int idx = getInternalPos(key) != -1)
setInternal(key, value, idx, true);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Settings::loadCommandLine(int argc, char** argv)
{
for(int i = 1; i < argc; ++i)
{
// strip off the '-' character
string key = argv[i];
if(key[0] == '-')
{
key = key.substr(1, key.length());
// Take care of the arguments which are meant to be executed immediately
// (and then Stella should exit)
if(key == "help" || key == "listrominfo")
{
setExternal(key, "true");
return "";
}
// Take care of arguments without an option or ones that shouldn't
// be saved to the config file
if(key == "rominfo" || key == "debug" || key == "holdreset" ||
key == "holdselect" || key == "takesnapshot")
{
setExternal(key, "true");
continue;
}
ostringstream buf;
if(++i >= argc)
{
buf << "Missing argument for '" << key << "'" << endl;
myOSystem.logMessage(buf.str(), 0);
return "";
}
string value = argv[i];
buf.str("");
buf << " key = '" << key << "', value = '" << value << "'";
// Settings read from the commandline must not be saved to
// the rc-file, unless they were previously set
if(int idx = getInternalPos(key) != -1)
{
setInternal(key, value, idx); // don't set initialValue here
buf << "(I)\n";
}
else
{
setExternal(key, value);
buf << "(E)\n";
}
myOSystem.logMessage(buf.str(), 2);
}
else
return key;
}
return EmptyString;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Settings::validate()
{
string s;
int i;
s = getString("timing");
if(s != "sleep" && s != "busy") setInternal("timing", "sleep");
i = getInt("tia.aspectn");
if(i < 80 || i > 120) setInternal("tia.aspectn", "90");
i = getInt("tia.aspectp");
if(i < 80 || i > 120) setInternal("tia.aspectp", "100");
s = getString("tia.dbgcolors");
sort(s.begin(), s.end());
if(s != "bgopry") setInternal("tia.dbgcolors", "roygpb");
i = getInt("tv.phosphor");
if(i < 0 || i > 100) setInternal("tv.phosphor", "50");
i = getInt("tv.filter");
if(i < 0 || i > 5) setInternal("tv.filter", "0");
i = getInt("tv.jitter_recovery");
if(i < 1 || i > 20) setInternal("tv.jitter_recovery", "10");
#ifdef SOUND_SUPPORT
i = getInt("volume");
if(i < 0 || i > 100) setInternal("volume", "100");
i = getInt("freq");
if(!(i == 11025 || i == 22050 || i == 31400 || i == 44100 || i == 48000))
setInternal("freq", "31400");
#endif
i = getInt("joydeadzone");
if(i < 0) setInternal("joydeadzone", "0");
else if(i > 29) setInternal("joydeadzone", "29");
i = getInt("cursor");
if(i < 0 || i > 3)
setInternal("cursor", "2");
i = getInt("dsense");
if(i < 1) setInternal("dsense", "1");
else if(i > 20) setInternal("dsense", "10");
i = getInt("msense");
if(i < 1) setInternal("msense", "1");
else if(i > 20) setInternal("msense", "15");
i = getInt("ssinterval");
if(i < 1) setInternal("ssinterval", "2");
else if(i > 10) setInternal("ssinterval", "10");
s = getString("palette");
if(s != "standard" && s != "z26" && s != "user")
setInternal("palette", "standard");
s = getString("launcherfont");
if(s != "small" && s != "medium" && s != "large")
setInternal("launcherfont", "medium");
i = getInt("romviewer");
if(i < 0) setInternal("romviewer", "0");
else if(i > 2) setInternal("romviewer", "2");
i = getInt("loglevel");
if(i < 0 || i > 2)
setInternal("loglevel", "1");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Settings::usage() const
{
cout << endl
<< "Stella version " << STELLA_VERSION << endl
<< endl
<< "Usage: stella [options ...] romfile" << endl
<< " Run without any options or romfile to use the ROM launcher" << endl
<< " Consult the manual for more in-depth information" << endl
<< endl
<< "Valid options are:" << endl
<< endl
<< " -video <type> Type is one of the following:\n"
#ifdef BSPF_WINDOWS
<< " direct3d Direct3D acceleration\n"
#endif
<< " opengl OpenGL acceleration\n"
<< " opengles2 OpenGLES 2 acceleration\n"
<< " opengles OpenGLES 1 acceleration\n"
<< " software Software mode (no acceleration)\n"
<< endl
<< " -vsync <1|0> Enable 'synchronize to vertical blank interrupt'\n"
<< " -fullscreen <1|0> Enable fullscreen mode\n"
<< " -center <1|0> Centers game window (if possible)\n"
<< " -palette <standard| Use the specified color palette\n"
<< " z26|\n"
<< " user>\n"
<< " -colorloss <1|0> Enable PAL color-loss effect\n"
<< " -framerate <number> Display the given number of frames per second (0 to auto-calculate)\n"
<< " -timing <sleep|busy> Use the given type of wait between frames\n"
<< " -uimessages <1|0> Show onscreen UI messages for different events\n"
<< endl
#ifdef SOUND_SUPPORT
<< " -sound <1|0> Enable sound generation\n"
<< " -fragsize <number> The size of sound fragments (must be a power of two)\n"
<< " -freq <number> Set sound sample output frequency (11025|22050|31400|44100|48000)\n"
<< " -volume <number> Set the volume (0 - 100)\n"
<< endl
#endif
<< " -tia.zoom <zoom> Use the specified zoom level (windowed mode) for TIA image\n"
<< " -tia.inter <1|0> Enable interpolated (smooth) scaling for TIA image\n"
<< " -tia.aspectn <number> Scale TIA width by the given percentage in NTSC mode\n"
<< " -tia.aspectp <number> Scale TIA width by the given percentage in PAL mode\n"
<< " -tia.fsfill <1|0> Stretch TIA image to fill fullscreen mode\n"
<< " -tia.dbgcolors <string> Debug colors to use for each object (see manual for description)\n"
<< endl
<< " -tv.filter <0-5> Set TV effects off (0) or to specified mode (1-5)\n"
<< " -tv.phosphor <0-100> Set default blend level in phosphor mode\n"
<< " -tv.jitter <1|0> Enable TV jitter effect\n"
<< " -tv.jitter_recovery <1-20> Set recovery time for TV jitter effect\n"
<< " -tv.scanlines <0-100> Set scanline intensity to percentage (0 disables completely)\n"
<< " -tv.scaninter <1|0> Enable interpolated (smooth) scanlines\n"
<< " -tv.contrast <value> Set TV effects custom contrast to value 1.0 - 1.0\n"
<< " -tv.brightness <value> Set TV effects custom brightness to value 1.0 - 1.0\n"
<< " -tv.hue <value> Set TV effects custom hue to value 1.0 - 1.0\n"
<< " -tv.saturation <value> Set TV effects custom saturation to value 1.0 - 1.0\n"
<< " -tv.gamma <value> Set TV effects custom gamma to value 1.0 - 1.0\n"
<< " -tv.sharpness <value> Set TV effects custom sharpness to value 1.0 - 1.0\n"
<< " -tv.resolution <value> Set TV effects custom resolution to value 1.0 - 1.0\n"
<< " -tv.artifacts <value> Set TV effects custom artifacts to value 1.0 - 1.0\n"
<< " -tv.fringing <value> Set TV effects custom fringing to value 1.0 - 1.0\n"
<< " -tv.bleed <value> Set TV effects custom bleed to value 1.0 - 1.0\n"
<< endl
<< " -cheat <code> Use the specified cheatcode (see manual for description)\n"
<< " -loglevel <0|1|2> Set level of logging during application run\n"
<< " -logtoconsole <1|0> Log output to console/commandline\n"
<< " -joydeadzone <number> Sets 'deadzone' area for analog joysticks (0-29)\n"
<< " -joyallow4 <1|0> Allow all 4 directions on a joystick to be pressed simultaneously\n"
<< " -usemouse <always|\n"
<< " analog|\n"
<< " never> Use mouse as a controller as specified by ROM properties in given mode(see manual)\n"
<< " -grabmouse <1|0> Locks the mouse cursor in the TIA window\n"
<< " -cursor <0,1,2,3> Set cursor state in UI/emulation modes\n"
<< " -dsense <number> Sensitivity of digital emulated paddle movement (1-20)\n"
<< " -msense <number> Sensitivity of mouse emulated paddle movement (1-20)\n"
<< " -saport <lr|rl> How to assign virtual ports to multiple Stelladaptor/2600-daptors\n"
<< " -ctrlcombo <1|0> Use key combos involving the Control key (Control-Q for quit may be disabled!)\n"
<< " -autoslot <1|0> Automatically switch to next save slot when state saving\n"
<< " -stats <1|0> Overlay console info during emulation\n"
<< " -fastscbios <1|0> Disable Supercharger BIOS progress loading bars\n"
<< " -snapsavedir <path> The directory to save snapshot files to\n"
<< " -snaploaddir <path> The directory to load snapshot files from\n"
<< " -snapname <int|rom> Name snapshots according to internal database or ROM\n"
<< " -sssingle <1|0> Generate single snapshot instead of many\n"
<< " -ss1x <1|0> Generate TIA snapshot in 1x mode (ignore scaling/effects)\n"
<< " -ssinterval <number Number of seconds between snapshots in continuous snapshot mode\n"
<< endl
<< " -rominfo <rom> Display detailed information for the given ROM\n"
<< " -listrominfo Display contents of stella.pro, one line per ROM entry\n"
<< " -exitlauncher <1|0> On exiting a ROM, go back to the ROM launcher\n"
<< " -launcherres <WxH> The resolution to use in ROM launcher mode\n"
<< " -launcherfont <small|medium| Use the specified font in the ROM launcher\n"
<< " large>\n"
<< " -launcherexts <allfiles| Show files with the given extensions in ROM launcher\n"
<< " allroms| (exts is a ':' separated list of extensions)\n"
<< " exts\n"
<< " -romviewer <0|1|2> Show ROM info viewer at given zoom level in ROM launcher (0 for off)\n"
<< " -listdelay <delay> Time to wait between keypresses in list widgets (300-1000)\n"
<< " -mwheel <lines> Number of lines the mouse wheel will scroll in UI\n"
<< " -romdir <dir> Directory in which to load ROM files\n"
<< " -statedir <dir> Directory in which to save/load state files\n"
<< " -cheatfile <file> Full pathname of cheatfile database\n"
<< " -palettefile <file> Full pathname of user-defined palette file\n"
<< " -propsfile <file> Full pathname of ROM properties file\n"
<< " -nvramdir <dir> Directory in which to save/load flash/EEPROM files\n"
<< " -cfgdir <dir> Directory in which to save Distella config files\n"
<< " -avoxport <name> The name of the serial port where an AtariVox is connected\n"
<< " -holdreset Start the emulator with the Game Reset switch held down\n"
<< " -holdselect Start the emulator with the Game Select switch held down\n"
<< " -holdjoy0 <U,D,L,R,F> Start the emulator with the left joystick direction/fire button held down\n"
<< " -holdjoy1 <U,D,L,R,F> Start the emulator with the right joystick direction/fire button held down\n"
<< " -tiadriven <1|0> Drive unused TIA pins randomly on a read/peek\n"
<< " -cpurandom <1|0> Randomize the contents of CPU registers on reset\n"
<< " -ramrandom <1|0> Randomize the contents of RAM on reset\n"
<< " -maxres <WxH> Used by developers to force the maximum size of the application window\n"
<< " -help Show the text you're now reading\n"
#ifdef DEBUGGER_SUPPORT
<< endl
<< " The following options are meant for developers\n"
<< " Arguments are more fully explained in the manual\n"
<< endl
<< " -dis.resolve <1|0> Attempt to resolve code sections in disassembler\n"
<< " -dis.gfxformat <2|16> Set base to use for displaying GFX sections in disassembler\n"
<< " -dis.showaddr <1|0> Show opcode addresses in disassembler\n"
<< " -dis.relocate <1|0> Relocate calls out of address range in disassembler\n"
<< endl
<< " -dbg.res <WxH> The resolution to use in debugger mode\n"
<< " -dbg.fontstyle <0-3> Font style to use in debugger window (bold vs. normal)\n"
<< " -break <address> Set a breakpoint at 'address'\n"
<< " -debug Start in debugger mode\n"
<< endl
<< " -bs <arg> Sets the 'Cartridge.Type' (bankswitch) property\n"
<< " -type <arg> Same as using -bs\n"
<< " -channels <arg> Sets the 'Cartridge.Sound' property\n"
<< " -ld <arg> Sets the 'Console.LeftDifficulty' property\n"
<< " -rd <arg> Sets the 'Console.RightDifficulty' property\n"
<< " -tv <arg> Sets the 'Console.TelevisionType' property\n"
<< " -sp <arg> Sets the 'Console.SwapPorts' property\n"
<< " -lc <arg> Sets the 'Controller.Left' property\n"
<< " -rc <arg> Sets the 'Controller.Right' property\n"
<< " -bc <arg> Same as using both -lc and -rc\n"
<< " -cp <arg> Sets the 'Controller.SwapPaddles' property\n"
<< " -format <arg> Sets the 'Display.Format' property\n"
<< " -ystart <arg> Sets the 'Display.YStart' property\n"
<< " -height <arg> Sets the 'Display.Height' property\n"
<< " -pp <arg> Sets the 'Display.Phosphor' property\n"
<< " -ppblend <arg> Sets the 'Display.PPBlend' property\n"
#endif
<< endl << std::flush;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Variant& Settings::value(const string& key) const
{
// Try to find the named setting and answer its value
int idx = -1;
if((idx = getInternalPos(key)) != -1)
return myInternalSettings[idx].value;
else if((idx = getExternalPos(key)) != -1)
return myExternalSettings[idx].value;
else
return EmptyVariant;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Settings::setValue(const string& key, const Variant& value)
{
if(int idx = getInternalPos(key) != -1)
setInternal(key, value, idx);
else
setExternal(key, value);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Settings::saveConfig()
{
// Do a quick scan of the internal settings to see if any have
// changed. If not, we don't need to save them at all.
bool settingsChanged = false;
for(const auto& s: myInternalSettings)
{
if(s.value != s.initialValue)
{
settingsChanged = true;
break;
}
}
if(!settingsChanged)
return;
ofstream out(myOSystem.configFile());
if(!out || !out.is_open())
{
myOSystem.logMessage("ERROR: Couldn't save settings file", 0);
return;
}
out << "; Stella configuration file" << endl
<< ";" << endl
<< "; Lines starting with ';' are comments and are ignored." << endl
<< "; Spaces and tabs are ignored." << endl
<< ";" << endl
<< "; Format MUST be as follows:" << endl
<< "; command = value" << endl
<< ";" << endl
<< "; Commmands are the same as those specified on the commandline," << endl
<< "; without the '-' character." << endl
<< ";" << endl
<< "; Values are the same as those allowed on the commandline." << endl
<< "; Boolean values are specified as 1 (or true) and 0 (or false)" << endl
<< ";" << endl;
// Write out each of the key and value pairs
for(const auto& s: myInternalSettings)
out << s.key << " = " << s.value << endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Settings::getInternalPos(const string& key) const
{
for(uInt32 i = 0; i < myInternalSettings.size(); ++i)
if(myInternalSettings[i].key == key)
return i;
return -1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Settings::getExternalPos(const string& key) const
{
for(uInt32 i = 0; i < myExternalSettings.size(); ++i)
if(myExternalSettings[i].key == key)
return i;
return -1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Settings::setInternal(const string& key, const Variant& value,
int pos, bool useAsInitial)
{
int idx = -1;
if(pos >= 0 && pos < int(myInternalSettings.size()) &&
myInternalSettings[pos].key == key)
{
idx = pos;
}
else
{
for(uInt32 i = 0; i < myInternalSettings.size(); ++i)
{
if(myInternalSettings[i].key == key)
{
idx = i;
break;
}
}
}
if(idx != -1)
{
myInternalSettings[idx].key = key;
myInternalSettings[idx].value = value;
if(useAsInitial) myInternalSettings[idx].initialValue = value;
/*cerr << "modify internal: key = " << key
<< ", value = " << value
<< ", ivalue = " << myInternalSettings[idx].initialValue
<< " @ index = " << idx
<< endl;*/
}
else
{
Setting setting;
setting.key = key;
setting.value = value;
if(useAsInitial) setting.initialValue = value;
myInternalSettings.push_back(setting);
idx = int(myInternalSettings.size()) - 1;
/*cerr << "insert internal: key = " << key
<< ", value = " << value
<< ", ivalue = " << setting.initialValue
<< " @ index = " << idx
<< endl;*/
}
return idx;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Settings::setExternal(const string& key, const Variant& value,
int pos, bool useAsInitial)
{
int idx = -1;
if(pos >= 0 && pos < int(myExternalSettings.size()) &&
myExternalSettings[pos].key == key)
{
idx = pos;
}
else
{
for(uInt32 i = 0; i < myExternalSettings.size(); ++i)
{
if(myExternalSettings[i].key == key)
{
idx = i;
break;
}
}
}
if(idx != -1)
{
myExternalSettings[idx].key = key;
myExternalSettings[idx].value = value;
if(useAsInitial) myExternalSettings[idx].initialValue = value;
/*cerr << "modify external: key = " << key
<< ", value = " << value
<< " @ index = " << idx
<< endl;*/
}
else
{
Setting setting;
setting.key = key;
setting.value = value;
if(useAsInitial) setting.initialValue = value;
myExternalSettings.push_back(setting);
idx = int(myExternalSettings.size()) - 1;
/*cerr << "insert external: key = " << key
<< ", value = " << value
<< " @ index = " << idx
<< endl;*/
}
return idx;
}