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
whitequark 2015-12-26 23:54:26 +08:00
parent c84a3b6de3
commit 3ffbac38c6
10 changed files with 217 additions and 405 deletions

View File

@ -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}

View File

@ -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;
}
};

View File

@ -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 {

View File

@ -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;

View File

@ -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.

View File

@ -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:

View File

@ -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)); }
//-----------------------------------------------------------------------------

View File

@ -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;
}

View File

@ -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

View File

@ -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();