Skip to content

Commit 89ab0fa

Browse files
committed
Implemented registry persistence for settings and recent files with new options dialog button to delete SQLiteCEdit registry keys for uninstallation or state reset
1 parent 24ac6a5 commit 89ab0fa

4 files changed

Lines changed: 230 additions & 1 deletion

File tree

src/sqlite-ce-edit/dialogs.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ int PromptForPath(const wchar_t *title, const wchar_t *defPath) {
148148
#define IDC_OPT_LINENUMS 1003
149149
#define IDC_OPT_ERRORMSGBOX 1004
150150
#define IDC_OPT_DBPATH 1005
151+
#define IDC_OPT_CLEARREG 1006
151152

152153
static int g_optClearExec, g_optExecAtCursor, g_optLineNums, g_optErrorMsgBox;
153154
static wchar_t g_optDbPath[MAX_PATH];
@@ -188,6 +189,11 @@ static LRESULT CALLBACK OptionsWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARA
188189
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
189190
185, 28, 180, 22, hwnd, (HMENU)IDC_OPT_DBPATH, g_hInst, NULL);
190191

192+
/* Clear settings button */
193+
CreateWindowW(L"BUTTON", L"Clear All Settings...",
194+
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
195+
185, 76, 130, 22, hwnd, (HMENU)IDC_OPT_CLEARREG, g_hInst, NULL);
196+
191197
SendMessage(GetDlgItem(hwnd, IDC_OPT_CLEAREXEC), BM_SETCHECK, g_optClearExec, 0);
192198
SendMessage(GetDlgItem(hwnd, IDC_OPT_EXECATCURSOR), BM_SETCHECK, g_optExecAtCursor, 0);
193199
SendMessage(GetDlgItem(hwnd, IDC_OPT_LINENUMS), BM_SETCHECK, g_optLineNums, 0);
@@ -200,6 +206,15 @@ static LRESULT CALLBACK OptionsWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARA
200206
DestroyWindow(hwnd);
201207
return 0;
202208
}
209+
if (LOWORD(wParam) == IDC_OPT_CLEARREG) {
210+
if (MessageBoxW(hwnd, L"Clear all saved settings and recent files?",
211+
L"Confirm", MB_YESNO | MB_ICONQUESTION) == IDYES) {
212+
ClearSettings();
213+
MessageBoxW(hwnd, L"Settings cleared. Restart to use defaults.",
214+
L"Settings", MB_OK | MB_ICONINFORMATION);
215+
}
216+
return 0;
217+
}
203218
break;
204219
case WM_CLOSE:
205220
DestroyWindow(hwnd);

src/sqlite-ce-edit/globals.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ BOOL WINAPI GetSaveFileNameW(CE_OPENFILENAME*);
8282
** Version
8383
**============================================================================*/
8484

85-
#define SQLITECEDIT_VERSION L"0.7.0.15"
85+
#define SQLITECEDIT_VERSION L"0.7.0.21"
8686

8787
/*============================================================================
8888
** Menu IDs
@@ -353,4 +353,12 @@ void DoAbout(void);
353353
void DoOptions(void);
354354
int PromptForPath(const wchar_t *title, const wchar_t *defPath);
355355

356+
/*============================================================================
357+
** Function Declarations - Settings (settings.c)
358+
**============================================================================*/
359+
360+
void LoadSettings(void);
361+
void SaveSettings(void);
362+
void ClearSettings(void);
363+
356364
#endif /* GLOBALS_H */

src/sqlite-ce-edit/main.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
507507
if (r == IDCANCEL) return 0;
508508
if (r == IDYES) DoSaveQuery();
509509
}
510+
SaveSettings();
510511
DestroyWindow(hwnd);
511512
return 0;
512513

@@ -537,6 +538,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR lpCmd, int nShow) {
537538

538539
g_hInst = hInst;
539540
InitCommonControls();
541+
LoadSettings();
540542

541543
/* Build accelerator table */
542544
accel[nAccel].fVirt = FCONTROL | FVIRTKEY; accel[nAccel].key = 'O'; accel[nAccel].cmd = IDM_OPENQUERY; nAccel++;
@@ -571,6 +573,10 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR lpCmd, int nShow) {
571573
SendMessage(g_hwndMain, WM_SETICON, ICON_SMALL,
572574
(LPARAM)LoadImage(hInst, MAKEINTRESOURCE(IDI_MAIN), IMAGE_ICON, 16, 16, 0));
573575

576+
/* Update menus with loaded recent files */
577+
UpdateRecentMenu();
578+
UpdateRecentQueryMenu();
579+
574580
OpenDatabase(L":memory:");
575581

576582
while (GetMessage(&msg, NULL, 0, 0)) {

src/sqlite-ce-edit/settings.c

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
** SQLiteCEdit - Centralized settings (registry persistence)
3+
**
4+
** All persistent settings are defined here. To add a new setting:
5+
** 1. Add the global variable to globals.c/h
6+
** 2. Add an entry to the appropriate SettingDef array below
7+
** 3. Call LoadSettings() at startup, SaveSettings() on exit
8+
*/
9+
10+
#include "globals.h"
11+
12+
#define REG_KEY L"Software\\IntermountainSystems\\SQLiteCEdit"
13+
14+
static int g_settingsCleared = 0; /* Block save after clear */
15+
16+
/*============================================================================
17+
** Setting Definitions
18+
**============================================================================*/
19+
20+
typedef enum { SET_INT, SET_STR } SettingType;
21+
22+
typedef struct {
23+
const wchar_t *name;
24+
SettingType type;
25+
void *pValue; /* Pointer to global variable */
26+
int defaultInt; /* Default for SET_INT */
27+
const wchar_t *defaultStr; /* Default for SET_STR */
28+
} SettingDef;
29+
30+
/* Integer settings */
31+
static SettingDef g_intSettings[] = {
32+
{ L"ClearOnExec", SET_INT, &g_clearOnExec, 1, NULL },
33+
{ L"ExecAtCursor", SET_INT, &g_execAtCursor, 0, NULL },
34+
{ L"ShowLineNumbers",SET_INT, &g_showLineNumbers, 1, NULL },
35+
{ L"ShowErrorMsgBox",SET_INT, &g_showErrorMsgBox, 0, NULL },
36+
{ L"ShowSizes", SET_INT, &g_showSizes, 0, NULL },
37+
{ L"GridAutoSize", SET_INT, &g_gridAutoSize, 1, NULL },
38+
{ NULL, 0, NULL, 0, NULL }
39+
};
40+
41+
/* String settings */
42+
static SettingDef g_strSettings[] = {
43+
{ L"DefaultDbPath", SET_STR, g_szDefaultDbPath, 0, L"\\My Documents\\Data" },
44+
{ NULL, 0, NULL, 0, NULL }
45+
};
46+
47+
/*============================================================================
48+
** Registry Helpers
49+
** Note: CE 2.0 uses simplified registry API without security attributes
50+
**============================================================================*/
51+
52+
static HKEY OpenSettingsKey(int forWrite) {
53+
HKEY hKey = NULL;
54+
DWORD disp;
55+
if (forWrite) {
56+
RegCreateKeyExW(HKEY_CURRENT_USER, REG_KEY, 0, NULL, 0, 0, NULL, &hKey, &disp);
57+
} else {
58+
RegOpenKeyExW(HKEY_CURRENT_USER, REG_KEY, 0, 0, &hKey);
59+
}
60+
return hKey;
61+
}
62+
63+
static int ReadRegInt(HKEY hKey, const wchar_t *name, int defaultVal) {
64+
DWORD val, size = sizeof(DWORD), type;
65+
if (RegQueryValueExW(hKey, name, NULL, &type, (LPBYTE)&val, &size) == ERROR_SUCCESS && type == REG_DWORD)
66+
return (int)val;
67+
return defaultVal;
68+
}
69+
70+
static void WriteRegInt(HKEY hKey, const wchar_t *name, int val) {
71+
DWORD dw = (DWORD)val;
72+
RegSetValueExW(hKey, name, 0, REG_DWORD, (LPBYTE)&dw, sizeof(DWORD));
73+
}
74+
75+
static void ReadRegStr(HKEY hKey, const wchar_t *name, wchar_t *buf, int bufLen, const wchar_t *defaultVal) {
76+
DWORD size = bufLen * sizeof(wchar_t), type;
77+
if (RegQueryValueExW(hKey, name, NULL, &type, (LPBYTE)buf, &size) != ERROR_SUCCESS || type != REG_SZ) {
78+
if (defaultVal) {
79+
int i;
80+
for (i = 0; i < bufLen - 1 && defaultVal[i]; i++) buf[i] = defaultVal[i];
81+
buf[i] = 0;
82+
} else {
83+
buf[0] = 0;
84+
}
85+
}
86+
}
87+
88+
static void WriteRegStr(HKEY hKey, const wchar_t *name, const wchar_t *val) {
89+
RegSetValueExW(hKey, name, 0, REG_SZ, (LPBYTE)val, (lstrlenW(val) + 1) * sizeof(wchar_t));
90+
}
91+
92+
/*============================================================================
93+
** Recent Files Persistence
94+
**============================================================================*/
95+
96+
static void LoadRecentList(HKEY hKey, const wchar_t *prefix, wchar_t list[][MAX_PATH], int *count, int max) {
97+
wchar_t name[32];
98+
int i;
99+
*count = 0;
100+
for (i = 0; i < max; i++) {
101+
wsprintfW(name, L"%s%d", prefix, i);
102+
ReadRegStr(hKey, name, list[i], MAX_PATH, NULL);
103+
if (list[i][0]) (*count)++;
104+
else break;
105+
}
106+
}
107+
108+
static void SaveRecentList(HKEY hKey, const wchar_t *prefix, wchar_t list[][MAX_PATH], int count, int max) {
109+
wchar_t name[32];
110+
int i;
111+
for (i = 0; i < max; i++) {
112+
wsprintfW(name, L"%s%d", prefix, i);
113+
if (i < count && list[i][0])
114+
WriteRegStr(hKey, name, list[i]);
115+
else
116+
RegDeleteValueW(hKey, name);
117+
}
118+
}
119+
120+
/*============================================================================
121+
** Public API
122+
**============================================================================*/
123+
124+
void LoadSettings(void) {
125+
HKEY hKey;
126+
SettingDef *s;
127+
128+
hKey = OpenSettingsKey(0); /* Read */
129+
if (!hKey) return;
130+
131+
/* Load integer settings */
132+
for (s = g_intSettings; s->name; s++) {
133+
*(int *)s->pValue = ReadRegInt(hKey, s->name, s->defaultInt);
134+
}
135+
136+
/* Load string settings */
137+
for (s = g_strSettings; s->name; s++) {
138+
ReadRegStr(hKey, s->name, (wchar_t *)s->pValue, MAX_PATH, s->defaultStr);
139+
}
140+
141+
/* Load recent files */
142+
LoadRecentList(hKey, L"RecentDb", g_recentFiles, &g_recentCount, MAX_RECENT_FILES);
143+
LoadRecentList(hKey, L"RecentQuery", g_recentQueries, &g_recentQueryCount, MAX_RECENT_FILES);
144+
145+
RegCloseKey(hKey);
146+
}
147+
148+
void SaveSettings(void) {
149+
HKEY hKey;
150+
SettingDef *s;
151+
152+
if (g_settingsCleared) return; /* Don't re-save after clear */
153+
154+
hKey = OpenSettingsKey(1); /* Write */
155+
if (!hKey) return;
156+
157+
/* Save integer settings */
158+
for (s = g_intSettings; s->name; s++) {
159+
WriteRegInt(hKey, s->name, *(int *)s->pValue);
160+
}
161+
162+
/* Save string settings */
163+
for (s = g_strSettings; s->name; s++) {
164+
WriteRegStr(hKey, s->name, (wchar_t *)s->pValue);
165+
}
166+
167+
/* Save recent files */
168+
SaveRecentList(hKey, L"RecentDb", g_recentFiles, g_recentCount, MAX_RECENT_FILES);
169+
SaveRecentList(hKey, L"RecentQuery", g_recentQueries, g_recentQueryCount, MAX_RECENT_FILES);
170+
171+
RegCloseKey(hKey);
172+
}
173+
174+
#define REG_PARENT L"Software\\IntermountainSystems"
175+
176+
void ClearSettings(void) {
177+
HKEY hKey;
178+
wchar_t name[256];
179+
DWORD nameLen;
180+
181+
/* Open and enumerate all values to delete them */
182+
if (RegOpenKeyExW(HKEY_CURRENT_USER, REG_KEY, 0, 0, &hKey) == ERROR_SUCCESS) {
183+
/* Delete values one at a time (index 0 each time since list shrinks) */
184+
while (1) {
185+
nameLen = 256;
186+
if (RegEnumValueW(hKey, 0, name, &nameLen, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
187+
break;
188+
RegDeleteValueW(hKey, name);
189+
}
190+
RegCloseKey(hKey);
191+
}
192+
193+
/* Now delete the empty key */
194+
RegDeleteKeyW(HKEY_CURRENT_USER, REG_KEY);
195+
196+
/* Try to delete parent if empty (will fail silently if not empty) */
197+
RegDeleteKeyW(HKEY_CURRENT_USER, REG_PARENT);
198+
199+
g_settingsCleared = 1; /* Block save on exit */
200+
}

0 commit comments

Comments
 (0)