From 3ffbac38c61093ff64bede42c3853b1377a4ac02 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 26 Dec 2015 23:54:26 +0800 Subject: [PATCH] Refactor Cnf* functions. On Windows, freeze.{cpp,h} was factored into w32main.cpp. The old implementation was too redundant and leaked registry key handles. On all platforms, Cnf* functions now use std::string. This simplifies code everywhere, but will be particularly useful when the Windows port switches to the *W WinAPI functions. --- src/CMakeLists.txt | 5 - src/cocoa/cocoamain.mm | 31 +++--- src/gtk/gtkmain.cpp | 133 ++++++++++--------------- src/lib.cpp | 4 +- src/solvespace.cpp | 9 +- src/solvespace.h | 21 ++-- src/util.cpp | 8 +- src/win32/freeze.cpp | 219 ----------------------------------------- src/win32/freeze.h | 33 ------- src/win32/w32main.cpp | 159 ++++++++++++++++++++++++------ 10 files changed, 217 insertions(+), 405 deletions(-) delete mode 100644 src/win32/freeze.cpp delete mode 100644 src/win32/freeze.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ac0a2c06..1ff02088 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -116,11 +116,7 @@ set(generated_SOURCES # platform dependencies if(WIN32) - set(platform_HEADERS - win32/freeze.h) - set(platform_SOURCES - win32/freeze.cpp win32/w32main.cpp win32/resource.rc) @@ -300,7 +296,6 @@ add_executable(solvespace WIN32 MACOSX_BUNDLE ${libslvs_HEADERS} ${libslvs_SOURCES} ${util_SOURCES} - ${platform_HEADERS} ${platform_SOURCES} ${platform_BUNDLED_RESOURCES} ${generated_SOURCES} diff --git a/src/cocoa/cocoamain.mm b/src/cocoa/cocoamain.mm index 3a6b6dc7..34905c32 100644 --- a/src/cocoa/cocoamain.mm +++ b/src/cocoa/cocoamain.mm @@ -30,42 +30,43 @@ char SolveSpace::RecentFile[MAX_RECENT][MAX_PATH]; /* Settings */ namespace SolveSpace { -void CnfFreezeInt(uint32_t val, const char *key) { +void CnfFreezeInt(uint32_t val, const std::string &key) { [[NSUserDefaults standardUserDefaults] - setInteger:val forKey:[NSString stringWithUTF8String:key]]; + setInteger:val forKey:[NSString stringWithUTF8String:key.c_str()]]; } -uint32_t CnfThawInt(uint32_t val, const char *key) { - NSString *nsKey = [NSString stringWithUTF8String:key]; +uint32_t CnfThawInt(uint32_t val, const std::string &key) { + NSString *nsKey = [NSString stringWithUTF8String:key.c_str()]; if([[NSUserDefaults standardUserDefaults] objectForKey:nsKey]) return [[NSUserDefaults standardUserDefaults] integerForKey:nsKey]; return val; } -void CnfFreezeFloat(float val, const char *key) { +void CnfFreezeFloat(float val, const std::string &key) { [[NSUserDefaults standardUserDefaults] - setFloat:val forKey:[NSString stringWithUTF8String:key]]; + setFloat:val forKey:[NSString stringWithUTF8String:key.c_str()]]; } -float CnfThawFloat(float val, const char *key) { - NSString *nsKey = [NSString stringWithUTF8String:key]; +float CnfThawFloat(float val, const std::string &key) { + NSString *nsKey = [NSString stringWithUTF8String:key.c_str()]; if([[NSUserDefaults standardUserDefaults] objectForKey:nsKey]) return [[NSUserDefaults standardUserDefaults] floatForKey:nsKey]; return val; } -void CnfFreezeString(const char *val, const char *key) { +void CnfFreezeString(const std::string &val, const std::string &key) { [[NSUserDefaults standardUserDefaults] - setObject:[NSString stringWithUTF8String:val] - forKey:[NSString stringWithUTF8String:key]]; + setObject:[NSString stringWithUTF8String:val.c_str()] + forKey:[NSString stringWithUTF8String:key.c_str()]]; } -void CnfThawString(char *val, int valsz, const char *key) { - NSString *nsKey = [NSString stringWithUTF8String:key]; +std::string CnfThawString(const std::string &val, const std::string &key) { + NSString *nsKey = [NSString stringWithUTF8String:key.c_str()]; if([[NSUserDefaults standardUserDefaults] objectForKey:nsKey]) { - NSString *nsVal = [[NSUserDefaults standardUserDefaults] stringForKey:nsKey]; - snprintf(val, valsz, "%s", [nsVal UTF8String]); + NSString *nsNewVal = [[NSUserDefaults standardUserDefaults] stringForKey:nsKey]; + return [nsNewVal UTF8String]; } + return val; } }; diff --git a/src/gtk/gtkmain.cpp b/src/gtk/gtkmain.cpp index 7d974aef..2e96e92e 100644 --- a/src/gtk/gtkmain.cpp +++ b/src/gtk/gtkmain.cpp @@ -79,59 +79,47 @@ char RecentFile[MAX_RECENT][MAX_PATH]; a schema globally. */ static json_object *settings = NULL; -static int CnfPrepare(char *path, int pathsz) { +static std::string CnfPrepare() { // Refer to http://standards.freedesktop.org/basedir-spec/latest/ - const char *xdg_home, *home; - xdg_home = getenv("XDG_CONFIG_HOME"); - home = getenv("HOME"); - - char dir[MAX_PATH]; - int dirlen; - if(xdg_home) - dirlen = snprintf(dir, sizeof(dir), "%s/solvespace", xdg_home); - else if(home) - dirlen = snprintf(dir, sizeof(dir), "%s/.config/solvespace", home); - else { - dbp("neither XDG_CONFIG_HOME nor HOME is set"); - return 1; + std::string dir; + if(getenv("XDG_CONFIG_HOME")) { + dir = std::string(getenv("XDG_CONFIG_HOME")) + "/solvespace"; + } else if(getenv("HOME")) { + dir = std::string(getenv("HOME")) + "/.config/solvespace"; + } else { + dbp("neither XDG_CONFIG_HOME nor HOME are set"); + return ""; } - if(dirlen >= sizeof(dir)) - oops(); - struct stat st; - if(stat(dir, &st)) { + if(stat(dir.c_str(), &st)) { if(errno == ENOENT) { - if(mkdir(dir, 0777)) { - dbp("cannot mkdir %s: %s", dir, strerror(errno)); - return 1; + if(mkdir(dir.c_str(), 0777)) { + dbp("cannot mkdir %s: %s", dir.c_str(), strerror(errno)); + return ""; } } else { - dbp("cannot stat %s: %s", dir, strerror(errno)); - return 1; + dbp("cannot stat %s: %s", dir.c_str(), strerror(errno)); + return ""; } } else if(!S_ISDIR(st.st_mode)) { - dbp("%s is not a directory", dir); - return 1; + dbp("%s is not a directory", dir.c_str()); + return ""; } - int pathlen = snprintf(path, pathsz, "%s/settings.json", dir); - if(pathlen >= pathsz) - oops(); - - return 0; + return dir + "/settings.json"; } static void CnfLoad() { - char path[MAX_PATH]; - if(CnfPrepare(path, sizeof(path))) + std::string path = CnfPrepare(); + if(path.empty()) return; if(settings) json_object_put(settings); // deallocate - settings = json_object_from_file(path); + settings = json_object_from_file(path.c_str()); if(!settings) { if(errno != ENOENT) dbp("cannot load settings: %s", strerror(errno)); @@ -141,84 +129,74 @@ static void CnfLoad() { } static void CnfSave() { - char path[MAX_PATH]; - if(CnfPrepare(path, sizeof(path))) + std::string path = CnfPrepare(); + if(path.empty()) return; - if(json_object_to_file_ext(path, settings, JSON_C_TO_STRING_PRETTY)) + /* json-c <0.12 has the first argument non-const here */ + if(json_object_to_file_ext((char*) path.c_str(), settings, JSON_C_TO_STRING_PRETTY)) dbp("cannot save settings: %s", strerror(errno)); } -void CnfFreezeInt(uint32_t val, const char *key) { +void CnfFreezeInt(uint32_t val, const std::string &key) { struct json_object *jval = json_object_new_int(val); - json_object_object_add(settings, key, jval); + json_object_object_add(settings, key.c_str(), jval); CnfSave(); } -uint32_t CnfThawInt(uint32_t val, const char *key) { +uint32_t CnfThawInt(uint32_t val, const std::string &key) { struct json_object *jval; - if(json_object_object_get_ex(settings, key, &jval)) + if(json_object_object_get_ex(settings, key.c_str(), &jval)) return json_object_get_int(jval); else return val; } -void CnfFreezeFloat(float val, const char *key) { +void CnfFreezeFloat(float val, const std::string &key) { struct json_object *jval = json_object_new_double(val); - json_object_object_add(settings, key, jval); + json_object_object_add(settings, key.c_str(), jval); CnfSave(); } -float CnfThawFloat(float val, const char *key) { +float CnfThawFloat(float val, const std::string &key) { struct json_object *jval; - if(json_object_object_get_ex(settings, key, &jval)) + if(json_object_object_get_ex(settings, key.c_str(), &jval)) return json_object_get_double(jval); else return val; } -void CnfFreezeString(const char *val, const char *key) { - struct json_object *jval = json_object_new_string(val); - json_object_object_add(settings, key, jval); +void CnfFreezeString(const std::string &val, const std::string &key) { + struct json_object *jval = json_object_new_string(val.c_str()); + json_object_object_add(settings, key.c_str(), jval); CnfSave(); } -void CnfThawString(char *val, int valsz, const char *key) { +std::string CnfThawString(const std::string &val, const std::string &key) { struct json_object *jval; - if(json_object_object_get_ex(settings, key, &jval)) - snprintf(val, valsz, "%s", json_object_get_string(jval)); + if(json_object_object_get_ex(settings, key.c_str(), &jval)) + return json_object_get_string(jval); + return val; } -static void CnfFreezeWindowPos(Gtk::Window *win, const char *key) { +static void CnfFreezeWindowPos(Gtk::Window *win, const std::string &key) { int x, y, w, h; win->get_position(x, y); win->get_size(w, h); - char buf[100]; - snprintf(buf, sizeof(buf), "%s_left", key); - CnfFreezeInt(x, buf); - snprintf(buf, sizeof(buf), "%s_top", key); - CnfFreezeInt(y, buf); - snprintf(buf, sizeof(buf), "%s_width", key); - CnfFreezeInt(w, buf); - snprintf(buf, sizeof(buf), "%s_height", key); - CnfFreezeInt(h, buf); - - CnfSave(); + CnfFreezeInt(x, key + "_left"); + CnfFreezeInt(y, key + "_top"); + CnfFreezeInt(w, key + "_width"); + CnfFreezeInt(h, key + "_height"); } -static void CnfThawWindowPos(Gtk::Window *win, const char *key) { +static void CnfThawWindowPos(Gtk::Window *win, const std::string &key) { int x, y, w, h; win->get_position(x, y); win->get_size(w, h); - char buf[100]; - snprintf(buf, sizeof(buf), "%s_left", key); - x = CnfThawInt(x, buf); - snprintf(buf, sizeof(buf), "%s_top", key); - y = CnfThawInt(y, buf); - snprintf(buf, sizeof(buf), "%s_width", key); - w = CnfThawInt(w, buf); - snprintf(buf, sizeof(buf), "%s_height", key); - h = CnfThawInt(h, buf); + x = CnfThawInt(x, key + "_left"); + y = CnfThawInt(y, key + "_top"); + w = CnfThawInt(w, key + "_width"); + h = CnfThawInt(h, key + "_height"); win->move(x, y); win->resize(w, h); @@ -1105,10 +1083,7 @@ bool GetOpenFile(char *file, const char *active, const char *patterns) { chooser.set_filename(file); chooser.add_button("_Cancel", Gtk::RESPONSE_CANCEL); chooser.add_button("_Open", Gtk::RESPONSE_OK); - - char current_folder[MAX_PATH]; - CnfThawString(current_folder, sizeof(current_folder), "FileChooserPath"); - chooser.set_current_folder(current_folder); + chooser.set_current_folder(CnfThawString("", "FileChooserPath")); FiltersFromPattern(active, patterns, chooser); @@ -1168,9 +1143,7 @@ bool GetSaveFile(char *file, const char *active, const char *patterns) { FiltersFromPattern(active, patterns, chooser); - char current_folder[MAX_PATH]; - CnfThawString(current_folder, sizeof(current_folder), "FileChooserPath"); - chooser.set_current_folder(current_folder); + chooser.set_current_folder(CnfThawString("", "FileChooserPath")); chooser.set_current_name(std::string("untitled.") + active); /* Gtk's dialog doesn't change the extension when you change the filter, @@ -1179,7 +1152,7 @@ bool GetSaveFile(char *file, const char *active, const char *patterns) { connect(sigc::bind(sigc::ptr_fun(&ChooserFilterChanged), &chooser)); if(chooser.run() == Gtk::RESPONSE_OK) { - CnfFreezeString(chooser.get_current_folder().c_str(), "FileChooserPath"); + CnfFreezeString(chooser.get_current_folder(), "FileChooserPath"); strcpy(file, chooser.get_filename().c_str()); return true; } else { diff --git a/src/lib.cpp b/src/lib.cpp index bd9a0ed0..2c2b949c 100644 --- a/src/lib.cpp +++ b/src/lib.cpp @@ -17,12 +17,12 @@ void Group::GenerateEquations(IdList *l) { // Nothing to do for now. } -void SolveSpace::CnfFreezeInt(uint32_t v, const char *name) +void SolveSpace::CnfFreezeInt(uint32_t v, const std::string &name) { abort(); } -uint32_t SolveSpace::CnfThawInt(uint32_t v, const char *name) +uint32_t SolveSpace::CnfThawInt(uint32_t v, const std::string &name) { abort(); return 0; diff --git a/src/solvespace.cpp b/src/solvespace.cpp index cb6f8b61..154eb61c 100644 --- a/src/solvespace.cpp +++ b/src/solvespace.cpp @@ -5,7 +5,6 @@ // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- #include "solvespace.h" -#include SolveSpaceUI SolveSpace::SS = {}; Sketch SolveSpace::SK = {}; @@ -87,8 +86,8 @@ void SolveSpaceUI::Init() { for(i = 0; i < MAX_RECENT; i++) { char name[100]; sprintf(name, "RecentFile_%d", i); - strcpy(RecentFile[i], ""); - CnfThawString(RecentFile[i], MAX_PATH, name); + strncpy(RecentFile[i], CnfThawString("", name).c_str(), MAX_PATH); + } RefreshRecentMenus(); // Autosave timer @@ -486,9 +485,9 @@ void SolveSpaceUI::MenuFile(int id) { case GraphicsWindow::MNU_EXPORT_VIEW: { char exportFile[MAX_PATH] = "", exportExt[10] = VEC_EXT; - CnfThawString(exportExt, sizeof(exportExt), "2DExportFormat"); + strncpy(exportFile, CnfThawString("", "2DExportFormat").c_str(), MAX_PATH); if(!GetSaveFile(exportFile, exportExt, VEC_PATTERN)) break; - CnfFreezeString(Extname(exportFile).c_str(), "2DExportFormat"); + CnfFreezeString(Extname(exportFile), "2DExportFormat"); // If the user is exporting something where it would be // inappropriate to include the constraints, then warn. diff --git a/src/solvespace.h b/src/solvespace.h index aafadab6..6720d157 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef HAVE_STDINT_H # include #endif @@ -246,12 +247,12 @@ void SetAutosaveTimerFor(int minutes); void ScheduleLater(); void ExitNow(void); -void CnfFreezeString(const char *str, const char *name); -void CnfFreezeInt(uint32_t v, const char *name); -void CnfFreezeFloat(float v, const char *name); -void CnfThawString(char *str, int maxLen, const char *name); -uint32_t CnfThawInt(uint32_t v, const char *name); -float CnfThawFloat(float v, const char *name); +void CnfFreezeInt(uint32_t val, const std::string &name); +void CnfFreezeFloat(float val, const std::string &name); +void CnfFreezeString(const std::string &val, const std::string &name); +std::string CnfThawString(const std::string &val, const std::string &name); +uint32_t CnfThawInt(uint32_t val, const std::string &name); +float CnfThawFloat(float val, const std::string &name); void *AllocTemporary(size_t n); void FreeTemporary(void *p); @@ -340,10 +341,10 @@ bool StringAllPrintable(const char *str); bool StringEndsIn(const char *str, const char *ending); void Message(const char *str, ...); void Error(const char *str, ...); -void CnfFreezeBool(bool v, const char *name); -void CnfFreezeColor(RgbaColor v, const char *name); -bool CnfThawBool(bool v, const char *name); -RgbaColor CnfThawColor(RgbaColor v, const char *name); +void CnfFreezeBool(bool v, const std::string &name); +void CnfFreezeColor(RgbaColor v, const std::string &name); +bool CnfThawBool(bool v, const std::string &name); +RgbaColor CnfThawColor(RgbaColor v, const std::string &name); class System { public: diff --git a/src/util.cpp b/src/util.cpp index df832f5c..59ced5f7 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -207,16 +207,16 @@ void SolveSpace::Message(const char *str, ...) va_end(f); } -void SolveSpace::CnfFreezeBool(bool v, const char *name) +void SolveSpace::CnfFreezeBool(bool v, const std::string &name) { CnfFreezeInt(v ? 1 : 0, name); } -void SolveSpace::CnfFreezeColor(RgbaColor v, const char *name) +void SolveSpace::CnfFreezeColor(RgbaColor v, const std::string &name) { CnfFreezeInt(v.ToPackedInt(), name); } -bool SolveSpace::CnfThawBool(bool v, const char *name) +bool SolveSpace::CnfThawBool(bool v, const std::string &name) { return CnfThawInt(v ? 1 : 0, name) != 0; } -RgbaColor SolveSpace::CnfThawColor(RgbaColor v, const char *name) +RgbaColor SolveSpace::CnfThawColor(RgbaColor v, const std::string &name) { return RgbaColor::FromPackedInt(CnfThawInt(v.ToPackedInt(), name)); } //----------------------------------------------------------------------------- diff --git a/src/win32/freeze.cpp b/src/win32/freeze.cpp deleted file mode 100644 index 27e1c448..00000000 --- a/src/win32/freeze.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * A library for storing parameters in the registry. - * - * Jonathan Westhues, 2002 - */ -#include -#include -#include - -#define FREEZE_SUBKEY ---- -#include "freeze.h" - -/* - * store a window's position in the registry, or fail silently if the registry calls don't work - */ -void FreezeWindowPosF(HWND hwnd, const char *subKey, const char *name) -{ - RECT r; - GetWindowRect(hwnd, &r); - - HKEY software; - if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &software) != ERROR_SUCCESS) - return; - - char *keyName = (char *)malloc(strlen(name) + 30); - if(!keyName) - return; - - HKEY sub; - if(RegCreateKeyEx(software, subKey, 0, (LPTSTR)"", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &sub, NULL) != ERROR_SUCCESS) - return; - - sprintf(keyName, "%s_left", name); - if(RegSetValueEx(sub, keyName, 0, REG_DWORD, (BYTE *)&(r.left), sizeof(DWORD)) != ERROR_SUCCESS) - return; - - sprintf(keyName, "%s_right", name); - if(RegSetValueEx(sub, keyName, 0, REG_DWORD, (BYTE *)&(r.right), sizeof(DWORD)) != ERROR_SUCCESS) - return; - - sprintf(keyName, "%s_top", name); - if(RegSetValueEx(sub, keyName, 0, REG_DWORD, (BYTE *)&(r.top), sizeof(DWORD)) != ERROR_SUCCESS) - return; - - sprintf(keyName, "%s_bottom", name); - if(RegSetValueEx(sub, keyName, 0, REG_DWORD, (BYTE *)&(r.bottom), sizeof(DWORD)) != ERROR_SUCCESS) - return; - - sprintf(keyName, "%s_maximized", name); - DWORD v = IsZoomed(hwnd); - if(RegSetValueEx(sub, keyName, 0, REG_DWORD, (BYTE *)&(v), sizeof(DWORD)) != ERROR_SUCCESS) - return; - - free(keyName); -} - -static void Clamp(LONG *v, LONG min, LONG max) -{ - if(*v < min) *v = min; - if(*v > max) *v = max; -} - -/* - * retrieve a window's position from the registry, or do nothing if there is no info saved - */ -void ThawWindowPosF(HWND hwnd, const char *subKey, const char *name) -{ - HKEY software; - if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &software) != ERROR_SUCCESS) - return; - - HKEY sub; - if(RegOpenKeyEx(software, subKey, 0, KEY_ALL_ACCESS, &sub) != ERROR_SUCCESS) - return; - - char *keyName = (char *)malloc(strlen(name) + 30); - if(!keyName) - return; - - DWORD l; - RECT r; - - sprintf(keyName, "%s_left", name); - l = sizeof(DWORD); - if(RegQueryValueEx(sub, keyName, NULL, NULL, (BYTE *)&(r.left), &l) != ERROR_SUCCESS) - return; - - sprintf(keyName, "%s_right", name); - l = sizeof(DWORD); - if(RegQueryValueEx(sub, keyName, NULL, NULL, (BYTE *)&(r.right), &l) != ERROR_SUCCESS) - return; - - sprintf(keyName, "%s_top", name); - l = sizeof(DWORD); - if(RegQueryValueEx(sub, keyName, NULL, NULL, (BYTE *)&(r.top), &l) != ERROR_SUCCESS) - return; - - sprintf(keyName, "%s_bottom", name); - l = sizeof(DWORD); - if(RegQueryValueEx(sub, keyName, NULL, NULL, (BYTE *)&(r.bottom), &l) != ERROR_SUCCESS) - return; - - sprintf(keyName, "%s_maximized", name); - DWORD v; - l = sizeof(DWORD); - if(RegQueryValueEx(sub, keyName, NULL, NULL, (BYTE *)&v, &l) != ERROR_SUCCESS) - return; - if(v) - ShowWindow(hwnd, SW_MAXIMIZE); - - - HMONITOR hMonitor; - MONITORINFO mi; - RECT dr; - - hMonitor = MonitorFromRect(&r, MONITOR_DEFAULTTONEAREST); - - mi.cbSize = sizeof(mi); - GetMonitorInfo(hMonitor, &mi); - dr = mi.rcMonitor; - - // If it somehow ended up off-screen, then put it back. - Clamp(&(r.left), dr.left, dr.right); - Clamp(&(r.right), dr.left, dr.right); - Clamp(&(r.top), dr.top, dr.bottom); - Clamp(&(r.bottom), dr.top, dr.bottom); - if(r.right - r.left < 100) { - r.left -= 300; r.right += 300; - } - if(r.bottom - r.top < 100) { - r.top -= 300; r.bottom += 300; - } - Clamp(&(r.left), dr.left, dr.right); - Clamp(&(r.right), dr.left, dr.right); - Clamp(&(r.top), dr.top, dr.bottom); - Clamp(&(r.bottom), dr.top, dr.bottom); - - MoveWindow(hwnd, r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE); - - free(keyName); -} - -/* - * store a DWORD setting in the registry - */ -void FreezeDWORDF(DWORD val, const char *subKey, const char *name) -{ - HKEY software; - if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &software) != ERROR_SUCCESS) - return; - - HKEY sub; - if(RegCreateKeyEx(software, subKey, 0, (LPTSTR)"", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &sub, NULL) != ERROR_SUCCESS) - return; - - if(RegSetValueEx(sub, name, 0, REG_DWORD, (BYTE *)&val, sizeof(DWORD)) != ERROR_SUCCESS) - return; -} - -/* - * retrieve a DWORD setting, or return the default if that setting is unavailable - */ -DWORD ThawDWORDF(DWORD val, const char *subKey, const char *name) -{ - HKEY software; - if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &software) != ERROR_SUCCESS) - return val; - - HKEY sub; - if(RegOpenKeyEx(software, subKey, 0, KEY_ALL_ACCESS, &sub) != ERROR_SUCCESS) - return val; - - DWORD l = sizeof(DWORD); - DWORD v; - if(RegQueryValueEx(sub, name, NULL, NULL, (BYTE *)&v, &l) != ERROR_SUCCESS) - return val; - - return v; -} - -/* - * store a string setting in the registry - */ -void FreezeStringF(const char *val, const char *subKey, const char *name) -{ - HKEY software; - if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &software) != ERROR_SUCCESS) - return; - - HKEY sub; - if(RegCreateKeyEx(software, subKey, 0, (LPTSTR)"", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &sub, NULL) != ERROR_SUCCESS) - return; - - if(RegSetValueEx(sub, name, 0, REG_SZ, (const BYTE *)val, (DWORD)strlen(val)+1) != ERROR_SUCCESS) - return; -} - -/* - * retrieve a string setting, or return the default if that setting is unavailable - */ -void ThawStringF(char *val, int max, const char *subKey, const char *name) -{ - HKEY software; - if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &software) != ERROR_SUCCESS) - return; - - HKEY sub; - if(RegOpenKeyEx(software, subKey, 0, KEY_ALL_ACCESS, &sub) != ERROR_SUCCESS) - return; - - DWORD l = max; - if(RegQueryValueEx(sub, name, NULL, NULL, (BYTE *)val, &l) != ERROR_SUCCESS) - return; - if(l >= (DWORD)max) return; - - val[l] = '\0'; - return; -} - diff --git a/src/win32/freeze.h b/src/win32/freeze.h deleted file mode 100644 index f5bb549a..00000000 --- a/src/win32/freeze.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * A library for storing parameters in the registry. - * - * Jonathan Westhues, 2002 - */ - -#ifndef __FREEZE_H -#define __FREEZE_H - -#ifndef FREEZE_SUBKEY -#error must define FREEZE_SUBKEY to a string uniquely identifying the app -#endif - -#define FreezeWindowPos(hwnd) FreezeWindowPosF(hwnd, FREEZE_SUBKEY, #hwnd) -void FreezeWindowPosF(HWND hWnd, const char *subKey, const char *name); - -#define ThawWindowPos(hwnd) ThawWindowPosF(hwnd, FREEZE_SUBKEY, #hwnd) -void ThawWindowPosF(HWND hWnd, const char *subKey, const char *name); - -#define FreezeDWORD(val) FreezeDWORDF(val, FREEZE_SUBKEY, #val) -void FreezeDWORDF(DWORD val, const char *subKey, const char *name); - -#define ThawDWORD(val) val = ThawDWORDF(val, FREEZE_SUBKEY, #val) -DWORD ThawDWORDF(DWORD val, const char *subKey, const char *name); - -#define FreezeString(val) FreezeStringF(val, FREEZE_SUBKEY, #val) -void FreezeStringF(const char *val, const char *subKey, const char *name); - -#define ThawString(val, max) ThawStringF(val, max, FREEZE_SUBKEY, #val) -void ThawStringF(char *val, int max, const char *subKey, const char *name); - - -#endif diff --git a/src/win32/w32main.cpp b/src/win32/w32main.cpp index e60a6d80..a2da6a8b 100644 --- a/src/win32/w32main.cpp +++ b/src/win32/w32main.cpp @@ -21,9 +21,6 @@ # undef uint32_t // thanks but no thanks #endif -#define FREEZE_SUBKEY "SolveSpace" -#include "freeze.h" - // For the edit controls #define EDIT_WIDTH 220 #define EDIT_HEIGHT 21 @@ -286,35 +283,133 @@ void SolveSpace::ExitNow(void) { // Helpers so that we can read/write registry keys from the platform- // independent code. //----------------------------------------------------------------------------- -void SolveSpace::CnfFreezeString(const char *str, const char *name) - { FreezeStringF(str, FREEZE_SUBKEY, name); } - -void SolveSpace::CnfFreezeInt(uint32_t v, const char *name) - { FreezeDWORDF((DWORD)v, FREEZE_SUBKEY, name); } - -union floatDWORD { - float f; - DWORD d; -}; - -void SolveSpace::CnfFreezeFloat(float v, const char *name) { - if(sizeof(float) != sizeof(DWORD)) oops(); - floatDWORD u; - u.f = v; - FreezeDWORDF(u.d, FREEZE_SUBKEY, name); +inline int CLAMP(int v, int a, int b) { + // Clamp it to the range [a, b] + if(v <= a) return a; + if(v >= b) return b; + return v; } -void SolveSpace::CnfThawString(char *str, int maxLen, const char *name) - { ThawStringF(str, maxLen, FREEZE_SUBKEY, name); } +static HKEY GetRegistryKey() +{ + HKEY Software; + if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &Software) != ERROR_SUCCESS) + return NULL; -uint32_t SolveSpace::CnfThawInt(uint32_t v, const char *name) - { return (uint32_t)ThawDWORDF((DWORD)v, FREEZE_SUBKEY, name); } + HKEY SolveSpace; + if(RegCreateKeyEx(Software, "SolveSpace", 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &SolveSpace, NULL) != ERROR_SUCCESS) + return NULL; -float SolveSpace::CnfThawFloat(float v, const char *name) { - floatDWORD u; - u.f = v; - u.d = ThawDWORDF(u.d, FREEZE_SUBKEY, name); - return u.f; + RegCloseKey(Software); + + return SolveSpace; +} + +void SolveSpace::CnfFreezeInt(uint32_t val, const std::string &name) +{ + HKEY SolveSpace = GetRegistryKey(); + RegSetValueEx(SolveSpace, &name[0], 0, + REG_DWORD, (const BYTE*) &val, sizeof(DWORD)); + RegCloseKey(SolveSpace); +} +void SolveSpace::CnfFreezeFloat(float val, const std::string &name) +{ + static_assert(sizeof(float) == sizeof(DWORD), + "sizes of float and DWORD must match"); + HKEY SolveSpace = GetRegistryKey(); + RegSetValueEx(SolveSpace, &name[0], 0, + REG_DWORD, (const BYTE*) &val, sizeof(DWORD)); + RegCloseKey(SolveSpace); +} +void SolveSpace::CnfFreezeString(const std::string &str, const std::string &name) +{ + HKEY SolveSpace = GetRegistryKey(); + RegSetValueEx(SolveSpace, &name[0], 0, + REG_SZ, (const BYTE*) &str[0], str.length() + 1); + RegCloseKey(SolveSpace); +} +static void FreezeWindowPos(HWND hwnd, const std::string &name) +{ + RECT r; + GetWindowRect(hwnd, &r); + CnfFreezeInt(r.left, name + "_left"); + CnfFreezeInt(r.right, name + "_right"); + CnfFreezeInt(r.top, name + "_top"); + CnfFreezeInt(r.bottom, name + "_bottom"); + + CnfFreezeInt(IsZoomed(hwnd), name + "_maximized"); +} + +uint32_t SolveSpace::CnfThawInt(uint32_t val, const std::string &name) +{ + HKEY SolveSpace = GetRegistryKey(); + DWORD type, newval, len = sizeof(DWORD); + LONG result = RegQueryValueEx(SolveSpace, &name[0], NULL, &type, (BYTE*) &newval, &len); + RegCloseKey(SolveSpace); + + if(result == ERROR_SUCCESS && type == REG_DWORD) + return newval; + else + return val; +} +float SolveSpace::CnfThawFloat(float val, const std::string &name) +{ + HKEY SolveSpace = GetRegistryKey(); + DWORD type, len = sizeof(DWORD); + float newval; + LONG result = RegQueryValueEx(SolveSpace, &name[0], NULL, &type, (BYTE*) &newval, &len); + RegCloseKey(SolveSpace); + + if(result == ERROR_SUCCESS && type == REG_DWORD) + return newval; + else + return val; +} +std::string SolveSpace::CnfThawString(const std::string &val, const std::string &name) +{ + HKEY SolveSpace = GetRegistryKey(); + DWORD type, len; + if(RegQueryValueEx(SolveSpace, &name[0], NULL, + &type, NULL, &len) != ERROR_SUCCESS || type != REG_SZ) { + RegCloseKey(SolveSpace); + return val; + } + + std::string newval(len, '\0'); + if(RegQueryValueEx(SolveSpace, &name[0], NULL, + NULL, (BYTE*) &newval[0], &len) != ERROR_SUCCESS) { + RegCloseKey(SolveSpace); + return val; + } + + RegCloseKey(SolveSpace); + return newval; +} +static void ThawWindowPos(HWND hwnd, const std::string &name) +{ + RECT r; + GetWindowRect(hwnd, &r); + r.left = CnfThawInt(r.left, name + "_left"); + r.right = CnfThawInt(r.right, name + "_right"); + r.top = CnfThawInt(r.top, name + "_top"); + r.bottom = CnfThawInt(r.bottom, name + "_bottom"); + + HMONITOR hMonitor = MonitorFromRect(&r, MONITOR_DEFAULTTONEAREST);; + MONITORINFO mi; + mi.cbSize = sizeof(mi); + GetMonitorInfo(hMonitor, &mi); + + // If it somehow ended up off-screen, then put it back. + RECT dr = mi.rcMonitor; + r.left = CLAMP(r.left, dr.left, dr.right); + r.right = CLAMP(r.right, dr.left, dr.right); + r.top = CLAMP(r.top, dr.top, dr.bottom); + r.bottom = CLAMP(r.bottom, dr.top, dr.bottom); + MoveWindow(hwnd, r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE); + + if(CnfThawInt(FALSE, name + "_maximized")) + ShowWindow(hwnd, SW_MAXIMIZE); } void SolveSpace::SetCurrentFilename(const char *filename) { @@ -1216,8 +1311,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, // the graphics CreateMainWindows(); - ThawWindowPos(TextWnd); - ThawWindowPos(GraphicsWnd); + ThawWindowPos(TextWnd, "TextWnd"); + ThawWindowPos(GraphicsWnd, "GraphicsWnd"); ShowWindow(TextWnd, SW_SHOWNOACTIVATE); ShowWindow(GraphicsWnd, SW_SHOW); @@ -1301,8 +1396,8 @@ done: #endif // Write everything back to the registry - FreezeWindowPos(TextWnd); - FreezeWindowPos(GraphicsWnd); + FreezeWindowPos(TextWnd, "TextWnd"); + FreezeWindowPos(GraphicsWnd, "GraphicsWnd"); // Free the memory we've used; anything that remains is a leak. SK.Clear();