/**
* @class UOPConfig
* @brief Handles preferences and configuration.
* @author Samuel Kaufman
* @date 2002
*/
/*****
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*****/
#include "uop.h"
#include <SDL/SDL.h>
#include <assert.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>
#ifdef WIN32
#include <windows.h>
#else
#include <stdlib.h>
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "uopconfig.h"
#define VALIDKEYS 8
#define KEYDEFAMNT 3
extern string validKeys[VALIDKEYS][KEYDEFAMNT];
/**
* Parse the config file and set the appropriate keys.
*/
UOPConfig::UOPConfig()
{
initDefaults();
}
UOPConfig::~UOPConfig()
{
}
bool UOPConfig::keyIsValid(string key)
{
for (unsigned int i = 0; i < VALIDKEYS; i++)
if (key == validKeys[i][0])
return true;
return false;
}
bool UOPConfig::getBoolean(string key)
{
assert(keyIsValid(key));
return boolValues[key];
}
Sint32 UOPConfig::getDWord(string key)
{
assert(keyIsValid(key));
return dWordValues[key];
}
string UOPConfig::getString(string key)
{
assert(keyIsValid(key));
return stringValues[key];
}
void UOPConfig::loadKeys()
{
}
void UOPConfig::saveKeys()
{
}
string UOPConfig::serverIP()
{
string str = getString("Server");
int portLoc = str.find_last_of(':');
return str.substr(0, portLoc);
}
Uint16 UOPConfig::serverPort()
{
string str = getString("Server");
int portLoc = str.find_last_of(':');
return (Uint16) atoi(str.substr(portLoc+1).c_str());
}
void UOPConfig::initDefaults()
{
for (unsigned int i = 0; i < VALIDKEYS; i++)
{
if (validKeys[i][1] == "String")
{
stringValues[validKeys[i][0]] = validKeys[i][2];
}
else if (validKeys[i][1] == "Boolean")
{
if (validKeys[i][2] == "True")
boolValues[validKeys[i][0]] = true;
else
boolValues[validKeys[i][0]] = false;
}
else if (validKeys[i][1] == "DWord")
{
istringstream conBuf(validKeys[i][2]);
conBuf >> dWordValues[validKeys[i][0]];
}
else
{
cerr << "There is a critical error in the validKeys table." << endl;
exit(1);
}
}
}
#ifdef WIN32
void WindowsConfig::loadKeys()
{
initRegistry();
for (unsigned int i = 0; i < VALIDKEYS; i++)
{
DWORD expectedType;
DWORD gotType;
DWORD regSize;
DWORD gotSize;
void *regData;
if ((validKeys[i][1] == "String") || (validKeys[i][1] == "Boolean"))
{
expectedType = REG_SZ;
regSize = 1024;
regData = new Uint8[1024];
}
else if (validKeys[i][1] == "DWord")
{
expectedType = REG_DWORD;
regSize = sizeof(DWORD);
regData = new DWORD;
}
else
assert(1);
gotType = expectedType;
gotSize = regSize;
LONG retValue = RegQueryValueEx(hKey, TEXT(validKeys[i][0].c_str()),
0, &gotType, (PBYTE)regData,
&gotSize);
if (retValue != ERROR_SUCCESS)
{
LPVOID msgBuf;
cerr << "Warning: Registry loading of " << validKeys[i][0].c_str()
<< " failed; default being used." << endl;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
retValue,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &msgBuf,
0,
NULL
);
cerr << "Warning: " << (char*)msgBuf << endl;
LocalFree(msgBuf);
}
else
{
if (expectedType == gotType)
{
if (validKeys[i][1] == "String")
{
stringValues[validKeys[i][0]] = (char*)regData;
}
else if (validKeys[i][1] == "Boolean")
{
string datString = (char*)regData;
if (datString == "True")
boolValues[validKeys[i][0]] = true;
else
boolValues[validKeys[i][0]] = false;
}
else if (validKeys[i][1] == "DWord")
{
dWordValues[validKeys[i][0]] = *((Sint32*)regData);
}
}
else
cerr << "Warning: Registry loading of " << validKeys[i][0].c_str()
<< " was abnormal. Recieved the wrong type." << endl;
}
delete [] regData;
}
deinitRegistry();
cout << stringValues["Language"] << endl;
}
void WindowsConfig::saveKeys()
{
string cTrue = "True";
string cFalse = "False";
initRegistry();
for (unsigned int i = 0; i < VALIDKEYS; i++)
{
DWORD regType;
DWORD regSize;
void *regValue;
if (validKeys[i][1] == "String")
{
regType = REG_SZ;
regSize = stringValues[validKeys[i][0]].length()+1;
regValue = (void*)stringValues[validKeys[i][0]].c_str();
}
else if (validKeys[i][1] == "Boolean")
{
regType = REG_SZ;
if (boolValues[validKeys[i][0]])
{
regSize = 5;
regValue = (void*)cTrue.c_str();
}
else
{
regSize = 6;
regValue = (void*)cFalse.c_str();
}
}
else if (validKeys[i][1] == "DWord")
{
regType = REG_DWORD;
regSize = 4;
regValue = (void*)&dWordValues[validKeys[i][0]];
}
LONG retValue = RegSetValueEx(hKey, validKeys[i][0].c_str(),
NULL, regType,
(CONST BYTE*) regValue,
regSize);
if (retValue != ERROR_SUCCESS)
{
LPVOID msgBuf;
cerr << "Warning: Registry saving of " << validKeys[i][0].c_str()
<< " failed; skipping." << endl;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &msgBuf,
0,
NULL
);
cerr << "Warning: " << (char*)msgBuf << endl;
LocalFree(msgBuf);
}
}
deinitRegistry();
}
void WindowsConfig::initRegistry()
{
DWORD retCheck;
LONG initRet = RegCreateKeyEx(HKEY_CURRENT_USER,
TEXT("Software\\UOP\\"), 0,
NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL,
&hKey, &retCheck);
if (initRet != ERROR_SUCCESS)
{
cerr << "Could not access the Windows Registry: " << initRet << "." << endl;
exit(1);
}
}
void WindowsConfig::deinitRegistry()
{
RegCloseKey(hKey);
}
#else
void TextConfig::loadKeys()
{
string fullpath;
ifstream configfile;
if (getenv("HOME") != NULL)
{
fullpath = getenv("HOME");
fullpath += "/.uop/uop.cfg";
configfile.open(fullpath.c_str());
if (!configfile.is_open())
{
fullpath = "";
}
}
if (fullpath == "")
{
fullpath = DATADIR;
fullpath += "/uop.cfg";
configfile.open(fullpath.c_str());
if (!configfile.is_open())
{
fullpath = "";
}
}
if (fullpath == "")
{
fullpath = "uop.cfg";
configfile.open(fullpath.c_str());
if (configfile.is_open())
cerr << "Warning: Using uop.cfg from current working directory." << endl;
}
if (!configfile.is_open())
{
cerr << "Error opening configuration file \"" << fullpath.c_str()
<< "\"" << endl;
exit(1);
}
sourcePath = fullpath;
parseFile(configfile);
configfile.close();
}
void TextConfig::saveKeys()
{
fstream configfile(sourcePath.c_str(), ios::out|ios::trunc);
if (!configfile.is_open())
{
cerr << "Warning: Couldn't open " << sourcePath
<< " to save configuration." << endl;
return;
}
for (unsigned int e = 0; e < VALIDKEYS; e++)
{
configfile << validKeys[e][0] << "=";
if (validKeys[e][1] == "String")
configfile << stringValues[validKeys[e][0]] << endl;
else if (validKeys[e][1] == "Boolean")
if (boolValues[validKeys[e][0]])
configfile << "True" << endl;
else
configfile << "False" << endl;
else if (validKeys[e][1] == "DWord")
configfile << dWordValues[validKeys[e][0]] << endl;
else
assert(1);
}
configfile.close();
}
void TextConfig::parseFile(ifstream &configfile)
{
string line;
while (std::getline(configfile,line,'\n'))
{
string keyval=line;
int comment=keyval.find_first_of('#');
if (comment>=0)
keyval.erase(comment);
int split=keyval.find_first_of('=');
if (split>0)
{
string spacekey=keyval.substr(0,split);
string spaceval=keyval.substr(split+1);
int kbegin=spacekey.find_first_not_of(" \t");
int kend=spacekey.find_last_not_of(" \t")+1;
int vbegin=spaceval.find_first_not_of(" \t");
int vend=spaceval.find_last_not_of(" \t")+1;
string key=spacekey.substr(kbegin,kend-kbegin);
string val=spaceval.substr(vbegin,vend-vbegin);
if (keyIsValid(key))
{
// Find entry in validKeys table
unsigned int e;
for (e = 0; e < VALIDKEYS; e++)
if (validKeys[e][0] == key)
break;
if (validKeys[e][1] == "String")
stringValues[key] = val;
else if (validKeys[e][1] == "Boolean")
if (key == "True")
boolValues[key] = true;
else
boolValues[key] = false;
else if (validKeys[e][1] == "DWord")
{
istringstream c(val);
c >> dWordValues[key];
}
else
assert(1);
}
}
}
}
#endif
string validKeys[VALIDKEYS][KEYDEFAMNT] =
{
{ "Server", "String", "127.0.0.1:2593" },
{ "SphereCompat", "Boolean", "False" },
{ "DataDir", "String", "C:/Program Files/Ultima Online Third Dawn" },
{ "Language", "String", "enu" },
{ "SoundOn", "Boolean", "True" },
{ "MusicOn", "Boolean", "True" },
{ "UseUOCursor", "Boolean", "True" },
{ "DoubleClickSpeed", "DWord", "300" }
};