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