Skip to content

Commit f1b1bc9

Browse files
committed
QoL enhancements: Recent databases and queries (per-session, no registry) and command bar button to toggle execute-at-cursor mode for large query files. Empty query buffer no longer disables the execute button permanently, and shows a message in the status bar when there's nothing to execute.
1 parent 1c4679c commit f1b1bc9

9 files changed

Lines changed: 235 additions & 64 deletions

File tree

src/sqlite-ce-edit/database.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ int OpenDatabase(const wchar_t *path) {
136136
}
137137

138138
lstrcpyW(g_szDbPath, path);
139+
AddRecentFile(path);
139140
UpdateTitle();
140141
UpdateDbSize();
141142
SetStatusResult(L"");

src/sqlite-ce-edit/dialogs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@ void DoOptions(void) {
255255
g_showErrorMsgBox = g_optErrorMsgBox;
256256
lstrcpyW(g_szDefaultDbPath, g_optDbPath);
257257

258+
/* Sync toolbar button state */
259+
SendMessage(g_hwndCB, TB_CHECKBUTTON, IDM_EXECATCURSOR, g_execAtCursor);
260+
258261
/* Handle line numbers toggle */
259262
if (g_optLineNums != g_showLineNumbers) {
260263
g_showLineNumbers = g_optLineNums;

src/sqlite-ce-edit/editor.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ void SwitchView(int mode) {
118118
ShowWindow(g_hwndQuery, mode == 0 ? SW_SHOW : SW_HIDE);
119119
if (g_hwndLineNum) ShowWindow(g_hwndLineNum, (mode == 0 && g_showLineNumbers) ? SW_SHOW : SW_HIDE);
120120
ShowWindow(g_hwndResult, mode == 1 ? SW_SHOW : SW_HIDE);
121+
/* Disable exec-at-cursor button in results view */
122+
SendMessage(g_hwndCB, TB_ENABLEBUTTON, IDM_EXECATCURSOR, mode == 0);
121123
SetFocus(mode == 0 ? g_hwndQuery : g_hwndResult);
122124
if (mode == 0) {
123125
UpdateLineCount();

src/sqlite-ce-edit/execute.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ void ExecuteQuery(void) {
179179
if (!wsql || !sql) {
180180
if (wsql) LocalFree(wsql);
181181
if (sql) LocalFree(sql);
182+
EnableMenuItem(g_hMenu, IDM_EXECUTE, MF_ENABLED);
183+
SendMessage(g_hwndCB, TB_ENABLEBUTTON, IDM_EXECUTE, TRUE);
182184
return;
183185
}
184186
SendMessage(g_hwndQuery, EM_SETSEL, selStart, selEnd);
@@ -211,7 +213,11 @@ void ExecuteQuery(void) {
211213
}
212214

213215
full = (wchar_t *)LocalAlloc(LMEM_FIXED, (fullLen + 1) * sizeof(wchar_t));
214-
if (!full) return;
216+
if (!full) {
217+
EnableMenuItem(g_hMenu, IDM_EXECUTE, MF_ENABLED);
218+
SendMessage(g_hwndCB, TB_ENABLEBUTTON, IDM_EXECUTE, TRUE);
219+
return;
220+
}
215221
GetWindowTextW(g_hwndQuery, full, fullLen + 1);
216222

217223
/* Find statement boundaries */
@@ -253,13 +259,18 @@ void ExecuteQuery(void) {
253259
} else {
254260
/* Execute entire buffer */
255261
len = GetWindowTextLengthW(g_hwndQuery);
256-
if (len == 0) return;
262+
if (len == 0 || g_showingHint) {
263+
SendMessageW(g_hwndStatus, SB_SETTEXTW, 1, (LPARAM)L"Nothing to execute");
264+
return;
265+
}
257266

258267
wsql = (wchar_t *)LocalAlloc(LMEM_FIXED, (len + 1) * sizeof(wchar_t));
259268
sql = (char *)LocalAlloc(LMEM_FIXED, (len + 1) * 3);
260269
if (!wsql || !sql) {
261270
if (wsql) LocalFree(wsql);
262271
if (sql) LocalFree(sql);
272+
EnableMenuItem(g_hMenu, IDM_EXECUTE, MF_ENABLED);
273+
SendMessage(g_hwndCB, TB_ENABLEBUTTON, IDM_EXECUTE, TRUE);
263274
return;
264275
}
265276
GetWindowTextW(g_hwndQuery, wsql, len + 1);

src/sqlite-ce-edit/fileops.c

Lines changed: 134 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,149 @@ void DoFileOpen(void) {
6464
}
6565
}
6666

67+
/*============================================================================
68+
** Recent Files
69+
**============================================================================*/
70+
71+
void AddRecentFile(const wchar_t *path) {
72+
int i, j;
73+
/* Don't add :memory: */
74+
if (lstrcmpW(path, L":memory:") == 0) return;
75+
/* Check if already in list, move to top if so */
76+
for (i = 0; i < g_recentCount; i++) {
77+
if (lstrcmpiW(g_recentFiles[i], path) == 0) {
78+
/* Move to top */
79+
for (j = i; j > 0; j--)
80+
lstrcpyW(g_recentFiles[j], g_recentFiles[j-1]);
81+
lstrcpyW(g_recentFiles[0], path);
82+
UpdateRecentMenu();
83+
return;
84+
}
85+
}
86+
/* Shift down and add at top */
87+
for (i = MAX_RECENT_FILES - 1; i > 0; i--)
88+
lstrcpyW(g_recentFiles[i], g_recentFiles[i-1]);
89+
lstrcpyW(g_recentFiles[0], path);
90+
if (g_recentCount < MAX_RECENT_FILES) g_recentCount++;
91+
UpdateRecentMenu();
92+
}
93+
94+
void UpdateRecentMenu(void) {
95+
int i, j;
96+
97+
if (!g_hRecentDbMenu) return;
98+
99+
/* Clear and rebuild */
100+
while (RemoveMenu(g_hRecentDbMenu, 0, MF_BYPOSITION));
101+
102+
if (g_recentCount == 0) {
103+
AppendMenuW(g_hRecentDbMenu, MF_STRING | MF_GRAYED, 0, L"(none)");
104+
} else {
105+
for (i = 0; i < g_recentCount; i++) {
106+
wchar_t item[MAX_PATH + 8];
107+
const wchar_t *name = g_recentFiles[i];
108+
int len = lstrlenW(name);
109+
for (j = len - 1; j >= 0; j--)
110+
if (name[j] == '\\') { name = &g_recentFiles[i][j+1]; break; }
111+
wsprintfW(item, L"&%d %s", i + 1, name);
112+
AppendMenuW(g_hRecentDbMenu, MF_STRING, IDM_RECENT_BASE + i, item);
113+
}
114+
}
115+
}
116+
117+
void AddRecentQuery(const wchar_t *path) {
118+
int i, j;
119+
/* Check if already in list, move to top if so */
120+
for (i = 0; i < g_recentQueryCount; i++) {
121+
if (lstrcmpiW(g_recentQueries[i], path) == 0) {
122+
for (j = i; j > 0; j--)
123+
lstrcpyW(g_recentQueries[j], g_recentQueries[j-1]);
124+
lstrcpyW(g_recentQueries[0], path);
125+
UpdateRecentQueryMenu();
126+
return;
127+
}
128+
}
129+
/* Shift down and add at top */
130+
for (i = MAX_RECENT_FILES - 1; i > 0; i--)
131+
lstrcpyW(g_recentQueries[i], g_recentQueries[i-1]);
132+
lstrcpyW(g_recentQueries[0], path);
133+
if (g_recentQueryCount < MAX_RECENT_FILES) g_recentQueryCount++;
134+
UpdateRecentQueryMenu();
135+
}
136+
137+
void UpdateRecentQueryMenu(void) {
138+
int i, j;
139+
140+
if (!g_hRecentQueryMenu) return;
141+
142+
while (RemoveMenu(g_hRecentQueryMenu, 0, MF_BYPOSITION));
143+
144+
if (g_recentQueryCount == 0) {
145+
AppendMenuW(g_hRecentQueryMenu, MF_STRING | MF_GRAYED, 0, L"(none)");
146+
} else {
147+
for (i = 0; i < g_recentQueryCount; i++) {
148+
wchar_t item[MAX_PATH + 8];
149+
const wchar_t *name = g_recentQueries[i];
150+
int len = lstrlenW(name);
151+
for (j = len - 1; j >= 0; j--)
152+
if (name[j] == '\\') { name = &g_recentQueries[i][j+1]; break; }
153+
wsprintfW(item, L"&%d %s", i + 1, name);
154+
AppendMenuW(g_hRecentQueryMenu, MF_STRING, IDM_RECENT_QUERY_BASE + i, item);
155+
}
156+
}
157+
}
158+
67159
/*============================================================================
68160
** Query File Operations
69161
**============================================================================*/
70162

71-
void DoOpenQuery(void) {
72-
CE_OPENFILENAME ofn;
73-
wchar_t szFile[MAX_PATH] = L"";
163+
void OpenQueryFile(const wchar_t *path) {
74164
HANDLE hFile;
75165
DWORD dwSize, dwRead;
76166
char *buf;
77167
wchar_t *wbuf;
78168
int i, j, extraCR;
79169

170+
hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
171+
if (hFile != INVALID_HANDLE_VALUE) {
172+
dwSize = GetFileSize(hFile, NULL);
173+
if (dwSize < 65536) {
174+
buf = (char*)LocalAlloc(LMEM_FIXED, dwSize + 1);
175+
if (buf && ReadFile(hFile, buf, dwSize, &dwRead, NULL)) {
176+
buf[dwRead] = '\0';
177+
extraCR = 0;
178+
for (i = 0; i < (int)dwRead; i++)
179+
if (buf[i] == '\n' && (i == 0 || buf[i-1] != '\r')) extraCR++;
180+
wbuf = (wchar_t*)LocalAlloc(LMEM_FIXED, (dwRead + extraCR + 1) * sizeof(wchar_t));
181+
if (wbuf) {
182+
for (i = 0, j = 0; i < (int)dwRead; i++) {
183+
if (buf[i] == '\n' && (i == 0 || buf[i-1] != '\r'))
184+
wbuf[j++] = '\r';
185+
wbuf[j++] = (wchar_t)(unsigned char)buf[i];
186+
}
187+
wbuf[j] = 0;
188+
g_showingHint = 0;
189+
SetWindowTextW(g_hwndQuery, wbuf);
190+
UpdateWindow(g_hwndQuery);
191+
lstrcpyW(g_szQueryPath, path);
192+
AddRecentQuery(path);
193+
g_queryDirty = 0;
194+
UpdateTitle();
195+
UpdateLineNumbers();
196+
LocalFree(wbuf);
197+
}
198+
}
199+
if (buf) LocalFree(buf);
200+
}
201+
CloseHandle(hFile);
202+
}
203+
}
204+
205+
void DoOpenQuery(void) {
206+
CE_OPENFILENAME ofn;
207+
wchar_t szFile[MAX_PATH] = L"";
208+
int i;
209+
80210
memset(&ofn, 0, sizeof(ofn));
81211
ofn.lStructSize = sizeof(ofn);
82212
ofn.hwndOwner = g_hwndMain;
@@ -94,40 +224,7 @@ void DoOpenQuery(void) {
94224
if (g_szLastQueryDir[i] == '\\') { g_szLastQueryDir[i] = 0; break; }
95225
}
96226
if (g_szLastQueryDir[0] == 0) lstrcpyW(g_szLastQueryDir, L"\\");
97-
98-
hFile = CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
99-
if (hFile != INVALID_HANDLE_VALUE) {
100-
dwSize = GetFileSize(hFile, NULL);
101-
if (dwSize < 65536) {
102-
buf = (char*)LocalAlloc(LMEM_FIXED, dwSize + 1);
103-
if (buf && ReadFile(hFile, buf, dwSize, &dwRead, NULL)) {
104-
buf[dwRead] = '\0';
105-
/* Count LFs not preceded by CR */
106-
extraCR = 0;
107-
for (i = 0; i < (int)dwRead; i++)
108-
if (buf[i] == '\n' && (i == 0 || buf[i-1] != '\r')) extraCR++;
109-
wbuf = (wchar_t*)LocalAlloc(LMEM_FIXED, (dwRead + extraCR + 1) * sizeof(wchar_t));
110-
if (wbuf) {
111-
for (i = 0, j = 0; i < (int)dwRead; i++) {
112-
if (buf[i] == '\n' && (i == 0 || buf[i-1] != '\r'))
113-
wbuf[j++] = '\r';
114-
wbuf[j++] = (wchar_t)(unsigned char)buf[i];
115-
}
116-
wbuf[j] = 0;
117-
g_showingHint = 0;
118-
SetWindowTextW(g_hwndQuery, wbuf);
119-
UpdateWindow(g_hwndQuery);
120-
lstrcpyW(g_szQueryPath, szFile);
121-
g_queryDirty = 0;
122-
UpdateTitle();
123-
UpdateLineNumbers();
124-
LocalFree(wbuf);
125-
}
126-
}
127-
if (buf) LocalFree(buf);
128-
}
129-
CloseHandle(hFile);
130-
}
227+
OpenQueryFile(szFile);
131228
}
132229
}
133230

src/sqlite-ce-edit/globals.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ HWND g_hwndMain;
1313
HWND g_hwndCB;
1414
HWND g_hwndStatus;
1515
HMENU g_hMenu;
16+
HMENU g_hRecentDbMenu;
17+
HMENU g_hRecentQueryMenu;
1618
HACCEL g_hAccel;
1719
HBRUSH g_hBrushWhite = NULL;
1820
HWND g_hwndQuery;
@@ -49,3 +51,7 @@ wchar_t g_szLastQueryDir[MAX_PATH] = L"\\";
4951
int g_queryDirty = 0;
5052
int g_showErrorMsgBox = 0;
5153
wchar_t g_szDefaultDbPath[MAX_PATH] = L"\\My Documents\\Data";
54+
wchar_t g_recentFiles[MAX_RECENT_FILES][MAX_PATH] = {0};
55+
int g_recentCount = 0;
56+
wchar_t g_recentQueries[MAX_RECENT_FILES][MAX_PATH] = {0};
57+
int g_recentQueryCount = 0;

src/sqlite-ce-edit/globals.h

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,17 @@ BOOL WINAPI GetSaveFileNameW(CE_OPENFILENAME*);
8585
#define IDM_FIND 202
8686
#define IDM_FINDNEXT 203
8787
#define IDM_EXECATCURSOR 204
88+
#define IDM_EXECATCURSOR_PLACEHOLDER 205
8889
#define IDM_CLEAR 301
8990
#define IDM_VIEWQUERY 401
9091
#define IDM_VIEWRESULT 402
9192
#define IDM_FONTSIZE 403
9293
#define IDM_OPTIONS 404
9394
#define IDM_ABOUT 501
95+
#define IDM_RECENT_BASE 600
96+
#define IDM_RECENT_MAX 604
97+
#define IDM_RECENT_QUERY_BASE 610
98+
#define IDM_RECENT_QUERY_MAX 614
9499

95100
/*============================================================================
96101
** Resource IDs
@@ -105,13 +110,15 @@ BOOL WINAPI GetSaveFileNameW(CE_OPENFILENAME*);
105110
**============================================================================*/
106111

107112
#define TB_PLAY 0
108-
#define TB_QUERY 1
109-
#define TB_RESULTS 2
110-
#define TB_GRID 3
111-
#define TB_OPEN 4
112-
#define TB_CLOSE 5
113-
#define TB_NEW 6
114-
#define TB_STD_BASE 7
113+
#define TB_EXECAT 1
114+
#define TB_STOP 2
115+
#define TB_QUERY 3
116+
#define TB_RESULTS 4
117+
#define TB_GRID 5
118+
#define TB_OPEN 6
119+
#define TB_CLOSE 7
120+
#define TB_NEW 8
121+
#define TB_STD_BASE 9
115122
#define TB_VIEW_BASE (TB_STD_BASE + 15)
116123

117124
/*============================================================================
@@ -123,6 +130,8 @@ extern HWND g_hwndMain;
123130
extern HWND g_hwndCB;
124131
extern HWND g_hwndStatus;
125132
extern HMENU g_hMenu;
133+
extern HMENU g_hRecentDbMenu;
134+
extern HMENU g_hRecentQueryMenu;
126135
extern HACCEL g_hAccel;
127136
extern HBRUSH g_hBrushWhite;
128137
extern HWND g_hwndQuery;
@@ -160,6 +169,12 @@ extern int g_queryDirty;
160169
extern int g_showErrorMsgBox;
161170
extern wchar_t g_szDefaultDbPath[MAX_PATH];
162171

172+
#define MAX_RECENT_FILES 5
173+
extern wchar_t g_recentFiles[MAX_RECENT_FILES][MAX_PATH];
174+
extern int g_recentCount;
175+
extern wchar_t g_recentQueries[MAX_RECENT_FILES][MAX_PATH];
176+
extern int g_recentQueryCount;
177+
163178
/*============================================================================
164179
** Function Declarations - Output (output.c)
165180
**============================================================================*/
@@ -214,6 +229,11 @@ void DoExportCSV(void);
214229
void DoExportDb(void);
215230
void DoImportCSV(void);
216231
void DoImportCEDB(void);
232+
void AddRecentFile(const wchar_t *path);
233+
void UpdateRecentMenu(void);
234+
void AddRecentQuery(const wchar_t *path);
235+
void UpdateRecentQueryMenu(void);
236+
void OpenQueryFile(const wchar_t *path);
217237

218238
/*============================================================================
219239
** Function Declarations - Find (find.c)

0 commit comments

Comments
 (0)