blob: b8e52833f17c7ff5d5e4d74c3fdf6321e4288767 [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};
36
37static LRESULT registry_get_handle(HKEY *hKey, LPDWORD action, LPCWSTR subKey)
38{
39 LONG ret;
40 static const WCHAR wszProgramKey[] = {'S','o','f','t','w','a','r','e','\\',
41 'M','i','c','r','o','s','o','f','t','\\',
42 'W','i','n','d','o','w','s','\\',
43 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
44 'A','p','p','l','e','t','s','\\',
45 'W','o','r','d','p','a','d',0};
46 LPWSTR key = (LPWSTR)wszProgramKey;
47
48 if(subKey)
49 {
50 WCHAR backslash[] = {'\\',0};
51 key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
52 (lstrlenW(wszProgramKey)+lstrlenW(subKey)+lstrlenW(backslash)+1)
53 *sizeof(WCHAR));
54
55 if(!key)
56 return 1;
57
58 lstrcpyW(key, wszProgramKey);
59 lstrcatW(key, backslash);
60 lstrcatW(key, subKey);
61 }
62
63 if(action)
64 {
65 ret = RegCreateKeyExW(HKEY_CURRENT_USER, key, 0, NULL, REG_OPTION_NON_VOLATILE,
66 KEY_READ | KEY_WRITE, NULL, hKey, action);
67 } else
68 {
69 ret = RegOpenKeyExW(HKEY_CURRENT_USER, key, 0, KEY_READ | KEY_WRITE, hKey);
70 }
71
72 if(subKey)
73 HeapFree(GetProcessHeap(), 0, key);
74
75 return ret;
76}
77
78void registry_set_options(HWND hMainWnd)
79{
80 HKEY hKey;
81 DWORD action;
82
83 if(registry_get_handle(&hKey, &action, (LPWSTR)key_options) == ERROR_SUCCESS)
84 {
85 RECT rc;
86
87 GetWindowRect(hMainWnd, &rc);
88
89 RegSetValueExW(hKey, var_framerect, 0, REG_BINARY, (LPBYTE)&rc, sizeof(RECT));
90
91 registry_set_pagemargins(hKey);
92 }
93
94 RegCloseKey(hKey);
95}
96
97void registry_read_winrect(RECT* rc)
98{
99 HKEY hKey;
100 DWORD size = sizeof(RECT);
101
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100102 if(registry_get_handle(&hKey, 0, (LPWSTR)key_options) != ERROR_SUCCESS ||
Alexandre Julliardc7278c22007-12-12 22:32:38 +0100103 RegQueryValueExW(hKey, var_framerect, 0, NULL, (LPBYTE)rc, &size) !=
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100104 ERROR_SUCCESS || size != sizeof(RECT))
105 {
106 rc->top = 0;
107 rc->left = 0;
108 rc->bottom = 300;
109 rc->right = 600;
110 }
111
112 RegCloseKey(hKey);
113}
114
115static void truncate_path(LPWSTR file, LPWSTR out, LPWSTR pos1, LPWSTR pos2)
116{
117 static const WCHAR dots[] = {'.','.','.',0};
118
119 *++pos1 = 0;
120
121 lstrcatW(out, file);
122 lstrcatW(out, dots);
123 lstrcatW(out, pos2);
124}
125
126static void format_filelist_filename(LPWSTR file, LPWSTR out)
127{
128 LPWSTR pos_basename;
129 LPWSTR truncpos1, truncpos2;
130 WCHAR myDocs[MAX_STRING_LEN];
131
132 SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, (LPWSTR)&myDocs);
133 pos_basename = file_basename(file);
134 truncpos1 = NULL;
135 truncpos2 = NULL;
136
137 *(pos_basename-1) = 0;
138 if(!lstrcmpiW(file, myDocs) || (lstrlenW(pos_basename) > FILELIST_ENTRY_LENGTH))
139 {
140 truncpos1 = pos_basename;
141 *(pos_basename-1) = '\\';
142 } else
143 {
144 LPWSTR pos;
145 BOOL morespace = FALSE;
146
147 *(pos_basename-1) = '\\';
148
149 for(pos = file; pos < pos_basename; pos++)
150 {
151 if(*pos == '\\' || *pos == '/')
152 {
153 if(truncpos1)
154 {
155 if((pos - file + lstrlenW(pos_basename)) > FILELIST_ENTRY_LENGTH)
156 break;
157
158 truncpos1 = pos;
159 morespace = TRUE;
160 break;
161 }
162
163 if((pos - file + lstrlenW(pos_basename)) > FILELIST_ENTRY_LENGTH)
164 break;
165
166 truncpos1 = pos;
167 }
168 }
169
170 if(morespace)
171 {
172 for(pos = pos_basename; pos >= truncpos1; pos--)
173 {
174 if(*pos == '\\' || *pos == '/')
175 {
176 if((truncpos1 - file + lstrlenW(pos_basename) + pos_basename - pos) > FILELIST_ENTRY_LENGTH)
177 break;
178
179 truncpos2 = pos;
180 }
181 }
182 }
183 }
184
185 if(truncpos1 == pos_basename)
186 lstrcatW(out, pos_basename);
187 else if(truncpos1 == truncpos2 || !truncpos2)
188 lstrcatW(out, file);
189 else
Marcus Meissnerfa6937f2008-01-26 09:32:41 +0100190 truncate_path(file, out, truncpos1, truncpos2);
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100191}
192
193void registry_read_filelist(HWND hMainWnd)
194{
195 HKEY hFileKey;
196
197 if(registry_get_handle(&hFileKey, 0, key_recentfiles) == ERROR_SUCCESS)
198 {
199 WCHAR itemText[MAX_PATH+3], buffer[MAX_PATH];
200 /* The menu item name is not the same as the file name, so we need to store
201 the file name here */
202 static WCHAR file1[MAX_PATH], file2[MAX_PATH], file3[MAX_PATH], file4[MAX_PATH];
203 WCHAR numFormat[] = {'&','%','d',' ',0};
204 LPWSTR pFile[] = {file1, file2, file3, file4};
205 DWORD pathSize = MAX_PATH*sizeof(WCHAR);
206 int i;
207 WCHAR key[6];
208 MENUITEMINFOW mi;
209 HMENU hMenu = GetMenu(hMainWnd);
210
211 mi.cbSize = sizeof(MENUITEMINFOW);
212 mi.fMask = MIIM_ID | MIIM_DATA | MIIM_STRING | MIIM_FTYPE;
213 mi.fType = MFT_STRING;
214 mi.dwTypeData = itemText;
215 mi.wID = ID_FILE_RECENT1;
216
217 RemoveMenu(hMenu, ID_FILE_RECENT_SEPARATOR, MF_BYCOMMAND);
218 for(i = 0; i < FILELIST_ENTRIES; i++)
219 {
220 wsprintfW(key, var_file, i+1);
221 RemoveMenu(hMenu, ID_FILE_RECENT1+i, MF_BYCOMMAND);
222 if(RegQueryValueExW(hFileKey, (LPWSTR)key, 0, NULL, (LPBYTE)pFile[i], &pathSize)
223 != ERROR_SUCCESS)
224 break;
225
Dmitry Timoshkov2c8476a2008-04-09 21:24:27 +0900226 mi.dwItemData = (ULONG_PTR)pFile[i];
Alexander Nicolaysen Sørnes7f03c2f2007-12-12 09:36:41 +0100227 wsprintfW(itemText, numFormat, i+1);
228
229 lstrcpyW(buffer, pFile[i]);
230
231 format_filelist_filename(buffer, itemText);
232
233 InsertMenuItemW(hMenu, ID_FILE_EXIT, FALSE, &mi);
234 mi.wID++;
235 pathSize = MAX_PATH*sizeof(WCHAR);
236 }
237 mi.fType = MFT_SEPARATOR;
238 mi.fMask = MIIM_FTYPE | MIIM_ID;
239 InsertMenuItemW(hMenu, ID_FILE_EXIT, FALSE, &mi);
240
241 RegCloseKey(hFileKey);
242 }
243}
244
245void registry_set_filelist(LPCWSTR newFile, HWND hMainWnd)
246{
247 HKEY hKey;
248 DWORD action;
249
250 if(registry_get_handle(&hKey, &action, key_recentfiles) == ERROR_SUCCESS)
251 {
252 LPCWSTR pFiles[FILELIST_ENTRIES];
253 int i;
254 HMENU hMenu = GetMenu(hMainWnd);
255 MENUITEMINFOW mi;
256 WCHAR buffer[6];
257
258 mi.cbSize = sizeof(MENUITEMINFOW);
259 mi.fMask = MIIM_DATA;
260
261 for(i = 0; i < FILELIST_ENTRIES; i++)
262 pFiles[i] = NULL;
263
264 for(i = 0; GetMenuItemInfoW(hMenu, ID_FILE_RECENT1+i, FALSE, &mi); i++)
265 pFiles[i] = (LPWSTR)mi.dwItemData;
266
267 if(lstrcmpiW(newFile, pFiles[0]))
268 {
269 for(i = 0; pFiles[i] && i < FILELIST_ENTRIES; i++)
270 {
271 if(!lstrcmpiW(pFiles[i], newFile))
272 {
273 int j;
274 for(j = 0; pFiles[j] && j < i; j++)
275 {
276 pFiles[i-j] = pFiles[i-j-1];
277 }
278 pFiles[0] = NULL;
279 break;
280 }
281 }
282
283 if(!pFiles[0])
284 {
285 pFiles[0] = newFile;
286 } else
287 {
288 for(i = 0; pFiles[i] && i < FILELIST_ENTRIES-1; i++)
289 pFiles[FILELIST_ENTRIES-1-i] = pFiles[FILELIST_ENTRIES-2-i];
290
291 pFiles[0] = newFile;
292 }
293
294 for(i = 0; pFiles[i] && i < FILELIST_ENTRIES; i++)
295 {
296 wsprintfW(buffer, var_file, i+1);
297 RegSetValueExW(hKey, (LPWSTR)&buffer, 0, REG_SZ, (LPBYTE)pFiles[i],
298 (lstrlenW(pFiles[i])+1)*sizeof(WCHAR));
299 }
300 }
301 }
302 RegCloseKey(hKey);
303 registry_read_filelist(hMainWnd);
304}
305
306int reg_formatindex(WPARAM format)
307{
308 return (format & SF_TEXT) ? 1 : 0;
309}
310
311void registry_read_options(void)
312{
313 HKEY hKey;
314
315 if(registry_get_handle(&hKey, 0, key_options) != ERROR_SUCCESS)
316 registry_read_pagemargins(NULL);
317 else
318 registry_read_pagemargins(hKey);
319
320 RegCloseKey(hKey);
321}
322
323static void registry_read_formatopts(int index, LPCWSTR key, DWORD barState[], DWORD wordWrap[])
324{
325 HKEY hKey;
326 DWORD action = 0;
327 BOOL fetched = FALSE;
328 barState[index] = 0;
329 wordWrap[index] = 0;
330
331 if(registry_get_handle(&hKey, &action, key) != ERROR_SUCCESS)
332 return;
333
334 if(action == REG_OPENED_EXISTING_KEY)
335 {
336 DWORD size = sizeof(DWORD);
337
338 if(RegQueryValueExW(hKey, var_barstate0, 0, NULL, (LPBYTE)&barState[index],
339 &size) == ERROR_SUCCESS)
340 fetched = TRUE;
341 }
342
343 if(!fetched)
344 barState[index] = (1 << BANDID_TOOLBAR) | (1 << BANDID_FORMATBAR) | (1 << BANDID_RULER) | (1 << BANDID_STATUSBAR);
345
346 if(index == reg_formatindex(SF_RTF))
347 wordWrap[index] = ID_WORDWRAP_WINDOW;
348 else if(index == reg_formatindex(SF_TEXT))
349 wordWrap[index] = ID_WORDWRAP_WINDOW; /* FIXME: should be ID_WORDWRAP_NONE once we support it */
350
351 RegCloseKey(hKey);
352}
353
354void registry_read_formatopts_all(DWORD barState[], DWORD wordWrap[])
355{
356 registry_read_formatopts(reg_formatindex(SF_RTF), key_rtf, barState, wordWrap);
357 registry_read_formatopts(reg_formatindex(SF_TEXT), key_text, barState, wordWrap);
358}
359
360static void registry_set_formatopts(int index, LPCWSTR key, DWORD barState[])
361{
362 HKEY hKey;
363 DWORD action = 0;
364
365 if(registry_get_handle(&hKey, &action, key) == ERROR_SUCCESS)
366 {
367 RegSetValueExW(hKey, var_barstate0, 0, REG_DWORD, (LPBYTE)&barState[index],
368 sizeof(DWORD));
369
370 RegCloseKey(hKey);
371 }
372}
373
374void registry_set_formatopts_all(DWORD barState[])
375{
376 registry_set_formatopts(reg_formatindex(SF_RTF), key_rtf, barState);
377 registry_set_formatopts(reg_formatindex(SF_TEXT), key_text, barState);
378}