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.pull/4/head
parent
c84a3b6de3
commit
3ffbac38c6
|
@ -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}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -17,12 +17,12 @@ void Group::GenerateEquations(IdList<Equation,hEquation> *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;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
// Copyright 2008-2013 Jonathan Westhues.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "solvespace.h"
|
||||
#include <string>
|
||||
|
||||
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.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#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:
|
||||
|
|
|
@ -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)); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -1,219 +0,0 @@
|
|||
/*
|
||||
* A library for storing parameters in the registry.
|
||||
*
|
||||
* Jonathan Westhues, 2002
|
||||
*/
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue