registry.c 12 KB

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