blob: c7edc5b1e50dfbb9ddbd9310327a36a699b4f9ca [file] [log] [blame]
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +01001/*
2 * Wordpad implementation - Registry functions
3 *
4 * Copyright 2007 by Alexander N. Sørnes <alex@thehandofagony.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <windows.h>
22#include <shlobj.h>
23#include <richedit.h>
24
25#include "wordpad.h"
26
27static const WCHAR key_recentfiles[] = {'R','e','c','e','n','t',' ','f','i','l','e',
28 ' ','l','i','s','t',0};
29static const WCHAR key_options[] = {'O','p','t','i','o','n','s',0};
30static const WCHAR key_rtf[] = {'R','T','F',0};
31static const WCHAR key_text[] = {'T','e','x','t',0};
32
33static const WCHAR var_file[] = {'F','i','l','e','%','d',0};
34static const WCHAR var_framerect[] = {'F','r','a','m','e','R','e','c','t',0};
35static const WCHAR var_barstate0[] = {'B','a','r','S','t','a','t','e','0',0};
Dylan Smithfcaa5992008-07-03 12:51:17 -040036static const WCHAR var_maximized[] = {'M','a','x','i','m','i','z','e','d',0};
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +010037
38static LRESULT registry_get_handle(HKEY *hKey, LPDWORD action, LPCWSTR subKey)
39{
40 LONG ret;
41 static const WCHAR wszProgramKey[] = {'S','o','f','t','w','a','r','e','\\',
42 'M','i','c','r','o','s','o','f','t','\\',
43 'W','i','n','d','o','w','s','\\',
44 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
45 'A','p','p','l','e','t','s','\\',
46 'W','o','r','d','p','a','d',0};
47 LPWSTR key = (LPWSTR)wszProgramKey;
48
49 if(subKey)
50 {
51 WCHAR backslash[] = {'\\',0};
52 key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
53 (lstrlenW(wszProgramKey)+lstrlenW(subKey)+lstrlenW(backslash)+1)
54 *sizeof(WCHAR));
55
56 if(!key)
57 return 1;
58
59 lstrcpyW(key, wszProgramKey);
60 lstrcatW(key, backslash);
61 lstrcatW(key, subKey);
62 }
63
64 if(action)
65 {
66 ret = RegCreateKeyExW(HKEY_CURRENT_USER, key, 0, NULL, REG_OPTION_NON_VOLATILE,
67 KEY_READ | KEY_WRITE, NULL, hKey, action);
68 } else
69 {
70 ret = RegOpenKeyExW(HKEY_CURRENT_USER, key, 0, KEY_READ | KEY_WRITE, hKey);
71 }
72
73 if(subKey)
74 HeapFree(GetProcessHeap(), 0, key);
75
76 return ret;
77}
78
79void registry_set_options(HWND hMainWnd)
80{
Andrey Turkin71c01bb2008-10-15 00:24:41 +040081 HKEY hKey = 0;
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +010082 DWORD action;
83
Andrey Turkinfbfb1652008-10-09 22:34:27 +040084 if(registry_get_handle(&hKey, &action, key_options) == ERROR_SUCCESS)
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +010085 {
Dylan Smithfcaa5992008-07-03 12:51:17 -040086 WINDOWPLACEMENT wp;
87 DWORD isMaximized;
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +010088
Dylan Smithfcaa5992008-07-03 12:51:17 -040089 wp.length = sizeof(WINDOWPLACEMENT);
90 GetWindowPlacement(hMainWnd, &wp);
91 isMaximized = (wp.showCmd == SW_SHOWMAXIMIZED);
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +010092
Dylan Smithfcaa5992008-07-03 12:51:17 -040093 RegSetValueExW(hKey, var_framerect, 0, REG_BINARY, (LPBYTE)&wp.rcNormalPosition, sizeof(RECT));
94 RegSetValueExW(hKey, var_maximized, 0, REG_DWORD, (LPBYTE)&isMaximized, sizeof(DWORD));
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +010095
96 registry_set_pagemargins(hKey);
97 }
98
99 RegCloseKey(hKey);
100}
101
102void registry_read_winrect(RECT* rc)
103{
Andrey Turkin71c01bb2008-10-15 00:24:41 +0400104 HKEY hKey = 0;
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100105 DWORD size = sizeof(RECT);
106
Andrey Turkinfbfb1652008-10-09 22:34:27 +0400107 if(registry_get_handle(&hKey, 0, key_options) != ERROR_SUCCESS ||
Alexandre Julliardc7278c22007-12-12 22:32:38 +0100108 RegQueryValueExW(hKey, var_framerect, 0, NULL, (LPBYTE)rc, &size) !=
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100109 ERROR_SUCCESS || size != sizeof(RECT))
110 {
111 rc->top = 0;
112 rc->left = 0;
113 rc->bottom = 300;
114 rc->right = 600;
115 }
116
117 RegCloseKey(hKey);
118}
119
Dylan Smithfcaa5992008-07-03 12:51:17 -0400120void registry_read_maximized(DWORD *bMaximized)
121{
Andrey Turkin71c01bb2008-10-15 00:24:41 +0400122 HKEY hKey = 0;
Dylan Smithfcaa5992008-07-03 12:51:17 -0400123 DWORD size = sizeof(DWORD);
124
Andrey Turkinfbfb1652008-10-09 22:34:27 +0400125 if(registry_get_handle(&hKey, 0, key_options) != ERROR_SUCCESS ||
Dylan Smithfcaa5992008-07-03 12:51:17 -0400126 RegQueryValueExW(hKey, var_maximized, 0, NULL, (LPBYTE)bMaximized, &size) !=
127 ERROR_SUCCESS || size != sizeof(DWORD))
128 {
129 *bMaximized = FALSE;
130 }
131
132 RegCloseKey(hKey);
133}
134
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100135static void truncate_path(LPWSTR file, LPWSTR out, LPWSTR pos1, LPWSTR pos2)
136{
137 static const WCHAR dots[] = {'.','.','.',0};
138
139 *++pos1 = 0;
140
141 lstrcatW(out, file);
142 lstrcatW(out, dots);
143 lstrcatW(out, pos2);
144}
145
146static void format_filelist_filename(LPWSTR file, LPWSTR out)
147{
148 LPWSTR pos_basename;
149 LPWSTR truncpos1, truncpos2;
150 WCHAR myDocs[MAX_STRING_LEN];
151
152 SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, (LPWSTR)&myDocs);
153 pos_basename = file_basename(file);
154 truncpos1 = NULL;
155 truncpos2 = NULL;
156
157 *(pos_basename-1) = 0;
158 if(!lstrcmpiW(file, myDocs) || (lstrlenW(pos_basename) > FILELIST_ENTRY_LENGTH))
159 {
160 truncpos1 = pos_basename;
161 *(pos_basename-1) = '\\';
162 } else
163 {
164 LPWSTR pos;
165 BOOL morespace = FALSE;
166
167 *(pos_basename-1) = '\\';
168
169 for(pos = file; pos < pos_basename; pos++)
170 {
171 if(*pos == '\\' || *pos == '/')
172 {
173 if(truncpos1)
174 {
175 if((pos - file + lstrlenW(pos_basename)) > FILELIST_ENTRY_LENGTH)
176 break;
177
178 truncpos1 = pos;
179 morespace = TRUE;
180 break;
181 }
182
183 if((pos - file + lstrlenW(pos_basename)) > FILELIST_ENTRY_LENGTH)
184 break;
185
186 truncpos1 = pos;
187 }
188 }
189
190 if(morespace)
191 {
192 for(pos = pos_basename; pos >= truncpos1; pos--)
193 {
194 if(*pos == '\\' || *pos == '/')
195 {
196 if((truncpos1 - file + lstrlenW(pos_basename) + pos_basename - pos) > FILELIST_ENTRY_LENGTH)
197 break;
198
199 truncpos2 = pos;
200 }
201 }
202 }
203 }
204
205 if(truncpos1 == pos_basename)
206 lstrcatW(out, pos_basename);
207 else if(truncpos1 == truncpos2 || !truncpos2)
208 lstrcatW(out, file);
209 else
Marcus Meissnerfa6937f2008-01-26 09:32:41 +0100210 truncate_path(file, out, truncpos1, truncpos2);
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100211}
212
213void registry_read_filelist(HWND hMainWnd)
214{
215 HKEY hFileKey;
216
217 if(registry_get_handle(&hFileKey, 0, key_recentfiles) == ERROR_SUCCESS)
218 {
219 WCHAR itemText[MAX_PATH+3], buffer[MAX_PATH];
220 /* The menu item name is not the same as the file name, so we need to store
221 the file name here */
222 static WCHAR file1[MAX_PATH], file2[MAX_PATH], file3[MAX_PATH], file4[MAX_PATH];
223 WCHAR numFormat[] = {'&','%','d',' ',0};
224 LPWSTR pFile[] = {file1, file2, file3, file4};
225 DWORD pathSize = MAX_PATH*sizeof(WCHAR);
226 int i;
227 WCHAR key[6];
228 MENUITEMINFOW mi;
229 HMENU hMenu = GetMenu(hMainWnd);
230
231 mi.cbSize = sizeof(MENUITEMINFOW);
232 mi.fMask = MIIM_ID | MIIM_DATA | MIIM_STRING | MIIM_FTYPE;
233 mi.fType = MFT_STRING;
234 mi.dwTypeData = itemText;
235 mi.wID = ID_FILE_RECENT1;
236
237 RemoveMenu(hMenu, ID_FILE_RECENT_SEPARATOR, MF_BYCOMMAND);
238 for(i = 0; i < FILELIST_ENTRIES; i++)
239 {
240 wsprintfW(key, var_file, i+1);
241 RemoveMenu(hMenu, ID_FILE_RECENT1+i, MF_BYCOMMAND);
242 if(RegQueryValueExW(hFileKey, (LPWSTR)key, 0, NULL, (LPBYTE)pFile[i], &pathSize)
243 != ERROR_SUCCESS)
244 break;
245
Dmitry Timoshkov2c8476a2008-04-09 21:24:27 +0900246 mi.dwItemData = (ULONG_PTR)pFile[i];
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100247 wsprintfW(itemText, numFormat, i+1);
248
249 lstrcpyW(buffer, pFile[i]);
250
251 format_filelist_filename(buffer, itemText);
252
253 InsertMenuItemW(hMenu, ID_FILE_EXIT, FALSE, &mi);
254 mi.wID++;
255 pathSize = MAX_PATH*sizeof(WCHAR);
256 }
257 mi.fType = MFT_SEPARATOR;
258 mi.fMask = MIIM_FTYPE | MIIM_ID;
259 InsertMenuItemW(hMenu, ID_FILE_EXIT, FALSE, &mi);
260
261 RegCloseKey(hFileKey);
262 }
263}
264
265void registry_set_filelist(LPCWSTR newFile, HWND hMainWnd)
266{
267 HKEY hKey;
268 DWORD action;
269
270 if(registry_get_handle(&hKey, &action, key_recentfiles) == ERROR_SUCCESS)
271 {
272 LPCWSTR pFiles[FILELIST_ENTRIES];
273 int i;
274 HMENU hMenu = GetMenu(hMainWnd);
275 MENUITEMINFOW mi;
276 WCHAR buffer[6];
277
278 mi.cbSize = sizeof(MENUITEMINFOW);
279 mi.fMask = MIIM_DATA;
280
281 for(i = 0; i < FILELIST_ENTRIES; i++)
282 pFiles[i] = NULL;
283
284 for(i = 0; GetMenuItemInfoW(hMenu, ID_FILE_RECENT1+i, FALSE, &mi); i++)
285 pFiles[i] = (LPWSTR)mi.dwItemData;
286
287 if(lstrcmpiW(newFile, pFiles[0]))
288 {
289 for(i = 0; pFiles[i] && i < FILELIST_ENTRIES; i++)
290 {
291 if(!lstrcmpiW(pFiles[i], newFile))
292 {
293 int j;
294 for(j = 0; pFiles[j] && j < i; j++)
295 {
296 pFiles[i-j] = pFiles[i-j-1];
297 }
298 pFiles[0] = NULL;
299 break;
300 }
301 }
302
303 if(!pFiles[0])
304 {
305 pFiles[0] = newFile;
306 } else
307 {
Dylan Smith8769e702008-06-17 21:20:19 -0400308 for(i = 0; i < FILELIST_ENTRIES-1; i++)
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100309 pFiles[FILELIST_ENTRIES-1-i] = pFiles[FILELIST_ENTRIES-2-i];
310
311 pFiles[0] = newFile;
312 }
313
314 for(i = 0; pFiles[i] && i < FILELIST_ENTRIES; i++)
315 {
316 wsprintfW(buffer, var_file, i+1);
Andrey Turkinfbfb1652008-10-09 22:34:27 +0400317 RegSetValueExW(hKey, (LPWSTR)&buffer, 0, REG_SZ, (const BYTE*)pFiles[i],
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100318 (lstrlenW(pFiles[i])+1)*sizeof(WCHAR));
319 }
320 }
Andrey Turkin71c01bb2008-10-15 00:24:41 +0400321 RegCloseKey(hKey);
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100322 }
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100323 registry_read_filelist(hMainWnd);
324}
325
326int reg_formatindex(WPARAM format)
327{
328 return (format & SF_TEXT) ? 1 : 0;
329}
330
331void registry_read_options(void)
332{
333 HKEY hKey;
334
335 if(registry_get_handle(&hKey, 0, key_options) != ERROR_SUCCESS)
336 registry_read_pagemargins(NULL);
337 else
Andrey Turkin71c01bb2008-10-15 00:24:41 +0400338 {
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100339 registry_read_pagemargins(hKey);
Andrey Turkin71c01bb2008-10-15 00:24:41 +0400340 RegCloseKey(hKey);
341 }
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100342}
343
344static void registry_read_formatopts(int index, LPCWSTR key, DWORD barState[], DWORD wordWrap[])
345{
346 HKEY hKey;
347 DWORD action = 0;
348 BOOL fetched = FALSE;
349 barState[index] = 0;
350 wordWrap[index] = 0;
351
352 if(registry_get_handle(&hKey, &action, key) != ERROR_SUCCESS)
353 return;
354
355 if(action == REG_OPENED_EXISTING_KEY)
356 {
357 DWORD size = sizeof(DWORD);
358
359 if(RegQueryValueExW(hKey, var_barstate0, 0, NULL, (LPBYTE)&barState[index],
360 &size) == ERROR_SUCCESS)
361 fetched = TRUE;
362 }
363
364 if(!fetched)
365 barState[index] = (1 << BANDID_TOOLBAR) | (1 << BANDID_FORMATBAR) | (1 << BANDID_RULER) | (1 << BANDID_STATUSBAR);
366
367 if(index == reg_formatindex(SF_RTF))
368 wordWrap[index] = ID_WORDWRAP_WINDOW;
369 else if(index == reg_formatindex(SF_TEXT))
Dylan Smithf124a582008-10-13 18:48:41 -0400370 wordWrap[index] = ID_WORDWRAP_NONE;
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100371
372 RegCloseKey(hKey);
373}
374
375void registry_read_formatopts_all(DWORD barState[], DWORD wordWrap[])
376{
377 registry_read_formatopts(reg_formatindex(SF_RTF), key_rtf, barState, wordWrap);
378 registry_read_formatopts(reg_formatindex(SF_TEXT), key_text, barState, wordWrap);
379}
380
381static void registry_set_formatopts(int index, LPCWSTR key, DWORD barState[])
382{
383 HKEY hKey;
384 DWORD action = 0;
385
386 if(registry_get_handle(&hKey, &action, key) == ERROR_SUCCESS)
387 {
388 RegSetValueExW(hKey, var_barstate0, 0, REG_DWORD, (LPBYTE)&barState[index],
389 sizeof(DWORD));
390
391 RegCloseKey(hKey);
392 }
393}
394
395void registry_set_formatopts_all(DWORD barState[])
396{
397 registry_set_formatopts(reg_formatindex(SF_RTF), key_rtf, barState);
398 registry_set_formatopts(reg_formatindex(SF_TEXT), key_text, barState);
399}