123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- /* GCSx
- ** CONFIG.CPP
- **
- ** Configuration loading and saving
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** 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, USA.
- *****************************************************************************/
- #include "all.h"
- Config* config = NULL;
- Config::Config() : configS(), configN(), configK(), configFile() { start_func
- configLoaded = 0;
- needsSaving = 0;
- }
- Config::~Config() { start_func
- }
- void Config::loadConfig() { start_func
- if (!configLoaded) {
- FILE* file = NULL;
- char* value = NULL;
- // Config filename
- createFilename(mainDir->c_str(), FILENAME_CFG, configFile);
- initConfigDefaults(configN);
- defaultShortcuts();
- // Load from file
- file = fopen(configFile.c_str(), "rb");
- if (file) {
- while (!feof(file)) {
- // We manually break it into 8bits for cross-compatibility
- int setting = fgetc(file) | (fgetc(file) << 8);
- if (setting == CONFIG_NO_SETTING) break;
- if ((setting >= CONFIG_FIRST_STRING_SETTING) &&
- (setting <= CONFIG_LAST_STRING_SETTING)) {
- unsigned int len = fgetc(file);
- value = new char[len];
- if (fread(value, 1, len, file) == len) {
- configS[setting] = value;
- }
- delete[] value;
- value = NULL;
- }
- else if (setting <= CONFIG_MAX_SETTING) {
- // We manually break it into 8bits for cross-compatibility
- Sint32 result = fgetc(file) | (fgetc(file) << 8) | (fgetc(file) << 16) | (fgetc(file) << 24);
- // This handles shortcut key reverses, etc.
- write(setting, result);
- }
- }
- fclose(file);
- }
-
- configLoaded = 1;
- needsSaving = 0;
- }
- }
- // Just marks us as needing saving
- void Config::saveConfig() { start_func
- needsSaving = 1;
- }
- void Config::performSave() { start_func
- if (needsSaving) {
- FILE* file = NULL;
- needsSaving = 0;
- // Save to file
- file = fopen(configFile.c_str(), "wb");
- if (file) {
- map<Uint16, string>::iterator endS = configS.end();
- for (map<Uint16, string>::iterator pos = configS.begin(); pos != endS; ++pos) {
- int code = (*pos).first;
- // We manually break it into 8bits for cross-compatibility
- fputc(code & 0xFF, file);
- fputc((code >> 8) & 0xFF, file);
- fputc((*pos).second.size(), file);
- fwrite((*pos).second.c_str(), 1, (*pos).second.size(), file);
- }
- map<Uint16, Sint32>::iterator endN = configN.end();
- for (map<Uint16, Sint32>::iterator pos = configN.begin(); pos != endN; ++pos) {
- int code = (*pos).first;
- if ((code < CONFIG_FIRST_VOLATILE_SETTING) || (code >= CONFIG_ADD_SHORTCUT)) {
- Sint32 value = (*pos).second;
- // We manually break it into 8bits for cross-compatibility
- fputc(code & 0xFF, file);
- fputc((code >> 8) & 0xFF, file);
- fputc(value & 0xFF, file);
- fputc((value >> 8) & 0xFF, file);
- fputc((value >> 16) & 0xFF, file);
- fputc((value >> 24) & 0xFF, file);
- }
- }
- fputc(CONFIG_NO_SETTING & 0xFF, file);
- fputc((CONFIG_NO_SETTING >> 8) & 0xFF, file);
- fclose(file);
- }
- }
- }
- Sint32 Config::readNum(Uint16 key) { start_func
- assert(key <= CONFIG_MAX_SETTING);
- assert(key > CONFIG_NO_SETTING);
- assert((key < CONFIG_FIRST_STRING_SETTING) || (key > CONFIG_LAST_STRING_SETTING));
- loadConfig();
- map<Uint16, Sint32>::iterator found = configN.find(key);
- if (found == configN.end()) return 0;
- return (*found).second;
- }
- const string& Config::readStr(Uint16 key) { start_func
- assert(key <= CONFIG_MAX_SETTING);
- assert(key > CONFIG_NO_SETTING);
- assert((key >= CONFIG_FIRST_STRING_SETTING) && (key <= CONFIG_LAST_STRING_SETTING));
- loadConfig();
- map<Uint16, string>::iterator found = configS.find(key);
- if (found == configS.end()) return blankString;
- return (*found).second;
- }
- void Config::addKey(Sint32 key, Uint16 cmd) { start_func
- configK[key].push_back(cmd);
- }
- void Config::delKey(Sint32 key, Uint16 cmd) { start_func
- SKeyMap::iterator pos = configK.find(key);
- if (pos != configK.end()) {
- vector<Uint16>::iterator end2 = (*pos).second.end();
- for (vector<Uint16>::iterator pos2 = (*pos).second.begin(); pos2 != end2; ++pos2) {
- if (*pos2 == cmd) {
- (*pos).second.erase(pos2);
- break;
- }
- }
- if ((*pos).second.empty()) {
- configK.erase(pos);
- }
- }
- }
- void Config::write(Uint16 key, Sint32 value) { start_func
- assert(key <= CONFIG_MAX_SETTING);
- assert(key > CONFIG_NO_SETTING);
- assert((key < CONFIG_FIRST_STRING_SETTING) || (key > CONFIG_LAST_STRING_SETTING));
- // If this is a shortcut key, update shortcut reverse lookup
- if (key >= CONFIG_ADD_SHORTCUT) {
- Uint16 shortkey = (key - CONFIG_ADD_SHORTCUT) % CONFIG_ADD_SHORTCUT_ALTERNATE;
-
- // Previous key? Erase
- map<Uint16, Sint32>::iterator found = configN.find(key);
- if (found != configN.end()) {
- delKey((*found).second, shortkey);
- }
-
- // Add new key
- addKey(value, shortkey);
- // If this was a "first" (non alternate) shortcut key, we need
- // to delete any alternates that may be there also!
- if (key < CONFIG_ADD_SHORTCUT + CONFIG_ADD_SHORTCUT_ALTERNATE) {
- int altKey = key + CONFIG_ADD_SHORTCUT_ALTERNATE;
- map<Uint16, Sint32>::iterator endN = configN.end();
-
- while ((found = configN.find(altKey)) != endN) {
- delKey((*found).second, shortkey);
- configN.erase(found);
- altKey += CONFIG_ADD_SHORTCUT_ALTERNATE;
- }
- }
- }
- // Skip saving if no change
- else if (configN[key] == value) return;
- // Store setting
- configN[key] = value;
- if ((key < CONFIG_FIRST_VOLATILE_SETTING) || (key >= CONFIG_ADD_SHORTCUT))
- saveConfig();
- }
- void Config::write(Uint16 key, const string& value) { start_func
- assert(key <= CONFIG_MAX_SETTING);
- assert(key > CONFIG_NO_SETTING);
- assert((key >= CONFIG_FIRST_STRING_SETTING) && (key <= CONFIG_LAST_STRING_SETTING));
-
- if (value.size() > 255) return;
- configS[key] = value;
- saveConfig();
- }
- void Config::clearShortcuts() { start_func
- map<Uint16, Sint32>::iterator end = configN.end();
- map<Uint16, Sint32>::iterator next;
- for (map<Uint16, Sint32>::iterator pos = configN.begin(); pos != end; pos = next) {
- // Get next element in case we delete
- next = pos;
- ++next;
-
- // Is this in the shortcuts range?
- if ((*pos).first >= CONFIG_ADD_SHORTCUT) {
- // Remove
- configN.erase(pos);
- }
- }
-
- configK.clear();
- }
- void Config::defaultShortcuts() { start_func
- clearShortcuts();
- map<Uint16, Sint32>::iterator end = configN.end();
- for (int pos = 0; shortcutDefault[pos].cmd; ++pos) {
- int addAlt = 0;
- while (configN.find(shortcutDefault[pos].cmd + CONFIG_ADD_SHORTCUT + addAlt) != end) {
- addAlt += CONFIG_ADD_SHORTCUT_ALTERNATE;
- }
-
- // Found an empty position; make sure we're within the max alternates
- if (addAlt / CONFIG_ADD_SHORTCUT_ALTERNATE <= CONFIG_MAX_SHORTCUT_ALTERNATE) {
- // Add to config, update reverse lookups
- write(shortcutDefault[pos].cmd + CONFIG_ADD_SHORTCUT + addAlt,
- combineKey(shortcutDefault[pos].key, shortcutDefault[pos].mod));
- }
- }
- }
- int Config::readShortcut(Uint16 key, Uint16 mod, int pos) { start_func
- SKeyMap::iterator posK = configK.find(combineKey(key, mod));
- if (posK != configK.end()) {
- int size = (*posK).second.size();
- if (pos == 0) return size;
- if (pos <= size) return (*posK).second[pos - 1];
- }
- return 0;
- }
- Sint32 Config::readShortcut(Uint16 cmd) { start_func
- return readNum(cmd + CONFIG_ADD_SHORTCUT);
- }
|