mssip32: Stubs for DllRegisterServer() and DllUnregisterServer().
[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_rtf[] = {'R','T','F',0};
31 static const WCHAR key_text[] = {'T','e','x','t',0};
32
33 static const WCHAR var_file[] = {'F','i','l','e','%','d',0};
34 static const WCHAR var_framerect[] = {'F','r','a','m','e','R','e','c','t',0};
35 static const WCHAR var_barstate0[] = {'B','a','r','S','t','a','t','e','0',0};
36 static const WCHAR var_maximized[] = {'M','a','x','i','m','i','z','e','d',0};
37
38 static 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
79 void registry_set_options(HWND hMainWnd)
80 {
81     HKEY hKey = 0;
82     DWORD action;
83
84     if(registry_get_handle(&hKey, &action, key_options) == ERROR_SUCCESS)
85     {
86         WINDOWPLACEMENT wp;
87         DWORD isMaximized;
88
89         wp.length = sizeof(WINDOWPLACEMENT);
90         GetWindowPlacement(hMainWnd, &wp);
91         isMaximized = (wp.showCmd == SW_SHOWMAXIMIZED);
92
93         RegSetValueExW(hKey, var_framerect, 0, REG_BINARY, (LPBYTE)&wp.rcNormalPosition, sizeof(RECT));
94         RegSetValueExW(hKey, var_maximized, 0, REG_DWORD, (LPBYTE)&isMaximized, sizeof(DWORD));
95
96         registry_set_pagemargins(hKey);
97     }
98
99     RegCloseKey(hKey);
100 }
101
102 void registry_read_winrect(RECT* rc)
103 {
104     HKEY hKey = 0;
105     DWORD size = sizeof(RECT);
106
107     if(registry_get_handle(&hKey, 0, key_options) != ERROR_SUCCESS ||
108        RegQueryValueExW(hKey, var_framerect, 0, NULL, (LPBYTE)rc, &size) !=
109        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
120 void registry_read_maximized(DWORD *bMaximized)
121 {
122     HKEY hKey = 0;
123     DWORD size = sizeof(DWORD);
124
125     if(registry_get_handle(&hKey, 0, key_options) != ERROR_SUCCESS ||
126        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
135 static 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
146 static 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
210         truncate_path(file, out, truncpos1, truncpos2);
211 }
212
213 void 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
246             mi.dwItemData = (ULONG_PTR)pFile[i];
247             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
265 void 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             {
308                 for(i = 0; i < FILELIST_ENTRIES-1; i++)
309                     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);
317                 RegSetValueExW(hKey, (LPWSTR)&buffer, 0, REG_SZ, (const BYTE*)pFiles[i],
318                                (lstrlenW(pFiles[i])+1)*sizeof(WCHAR));
319             }
320         }
321         RegCloseKey(hKey);
322     }
323     registry_read_filelist(hMainWnd);
324 }
325
326 int reg_formatindex(WPARAM format)
327 {
328     return (format & SF_TEXT) ? 1 : 0;
329 }
330
331 void 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
338     {
339         registry_read_pagemargins(hKey);
340         RegCloseKey(hKey);
341     }
342 }
343
344 static 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))
370         wordWrap[index] = ID_WORDWRAP_NONE;
371
372     RegCloseKey(hKey);
373 }
374
375 void 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
381 static 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
395 void 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 }