| /* | |
| * Wordpad implementation - Registry functions | |
| * | |
| * Copyright 2007 by Alexander N. Sørnes <alex@thehandofagony.com> | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #include <windows.h> | |
| #include <shlobj.h> | |
| #include <richedit.h> | |
| #include "wordpad.h" | |
| static const WCHAR key_recentfiles[] = {'R','e','c','e','n','t',' ','f','i','l','e', | |
| ' ','l','i','s','t',0}; | |
| static const WCHAR key_options[] = {'O','p','t','i','o','n','s',0}; | |
| static const WCHAR key_rtf[] = {'R','T','F',0}; | |
| static const WCHAR key_text[] = {'T','e','x','t',0}; | |
| static const WCHAR var_file[] = {'F','i','l','e','%','d',0}; | |
| static const WCHAR var_framerect[] = {'F','r','a','m','e','R','e','c','t',0}; | |
| static const WCHAR var_barstate0[] = {'B','a','r','S','t','a','t','e','0',0}; | |
| static const WCHAR var_maximized[] = {'M','a','x','i','m','i','z','e','d',0}; | |
| static LRESULT registry_get_handle(HKEY *hKey, LPDWORD action, LPCWSTR subKey) | |
| { | |
| LONG ret; | |
| static const WCHAR wszProgramKey[] = {'S','o','f','t','w','a','r','e','\\', | |
| 'M','i','c','r','o','s','o','f','t','\\', | |
| 'W','i','n','d','o','w','s','\\', | |
| 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', | |
| 'A','p','p','l','e','t','s','\\', | |
| 'W','o','r','d','p','a','d',0}; | |
| LPWSTR key = (LPWSTR)wszProgramKey; | |
| if(subKey) | |
| { | |
| WCHAR backslash[] = {'\\',0}; | |
| key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, | |
| (lstrlenW(wszProgramKey)+lstrlenW(subKey)+lstrlenW(backslash)+1) | |
| *sizeof(WCHAR)); | |
| if(!key) | |
| return 1; | |
| lstrcpyW(key, wszProgramKey); | |
| lstrcatW(key, backslash); | |
| lstrcatW(key, subKey); | |
| } | |
| if(action) | |
| { | |
| ret = RegCreateKeyExW(HKEY_CURRENT_USER, key, 0, NULL, REG_OPTION_NON_VOLATILE, | |
| KEY_READ | KEY_WRITE, NULL, hKey, action); | |
| } else | |
| { | |
| ret = RegOpenKeyExW(HKEY_CURRENT_USER, key, 0, KEY_READ | KEY_WRITE, hKey); | |
| } | |
| if(subKey) | |
| HeapFree(GetProcessHeap(), 0, key); | |
| return ret; | |
| } | |
| void registry_set_options(HWND hMainWnd) | |
| { | |
| HKEY hKey = 0; | |
| DWORD action; | |
| if(registry_get_handle(&hKey, &action, key_options) == ERROR_SUCCESS) | |
| { | |
| WINDOWPLACEMENT wp; | |
| DWORD isMaximized; | |
| wp.length = sizeof(WINDOWPLACEMENT); | |
| GetWindowPlacement(hMainWnd, &wp); | |
| isMaximized = (wp.showCmd == SW_SHOWMAXIMIZED); | |
| RegSetValueExW(hKey, var_framerect, 0, REG_BINARY, (LPBYTE)&wp.rcNormalPosition, sizeof(RECT)); | |
| RegSetValueExW(hKey, var_maximized, 0, REG_DWORD, (LPBYTE)&isMaximized, sizeof(DWORD)); | |
| registry_set_pagemargins(hKey); | |
| } | |
| RegCloseKey(hKey); | |
| } | |
| void registry_read_winrect(RECT* rc) | |
| { | |
| HKEY hKey = 0; | |
| DWORD size = sizeof(RECT); | |
| if(registry_get_handle(&hKey, 0, key_options) != ERROR_SUCCESS || | |
| RegQueryValueExW(hKey, var_framerect, 0, NULL, (LPBYTE)rc, &size) != | |
| ERROR_SUCCESS || size != sizeof(RECT)) | |
| { | |
| rc->top = 0; | |
| rc->left = 0; | |
| rc->bottom = 300; | |
| rc->right = 600; | |
| } | |
| RegCloseKey(hKey); | |
| } | |
| void registry_read_maximized(DWORD *bMaximized) | |
| { | |
| HKEY hKey = 0; | |
| DWORD size = sizeof(DWORD); | |
| if(registry_get_handle(&hKey, 0, key_options) != ERROR_SUCCESS || | |
| RegQueryValueExW(hKey, var_maximized, 0, NULL, (LPBYTE)bMaximized, &size) != | |
| ERROR_SUCCESS || size != sizeof(DWORD)) | |
| { | |
| *bMaximized = FALSE; | |
| } | |
| RegCloseKey(hKey); | |
| } | |
| static void truncate_path(LPWSTR file, LPWSTR out, LPWSTR pos1, LPWSTR pos2) | |
| { | |
| static const WCHAR dots[] = {'.','.','.',0}; | |
| *++pos1 = 0; | |
| lstrcatW(out, file); | |
| lstrcatW(out, dots); | |
| lstrcatW(out, pos2); | |
| } | |
| static void format_filelist_filename(LPWSTR file, LPWSTR out) | |
| { | |
| LPWSTR pos_basename; | |
| LPWSTR truncpos1, truncpos2; | |
| WCHAR myDocs[MAX_STRING_LEN]; | |
| SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, (LPWSTR)&myDocs); | |
| pos_basename = file_basename(file); | |
| truncpos1 = NULL; | |
| truncpos2 = NULL; | |
| *(pos_basename-1) = 0; | |
| if(!lstrcmpiW(file, myDocs) || (lstrlenW(pos_basename) > FILELIST_ENTRY_LENGTH)) | |
| { | |
| truncpos1 = pos_basename; | |
| *(pos_basename-1) = '\\'; | |
| } else | |
| { | |
| LPWSTR pos; | |
| BOOL morespace = FALSE; | |
| *(pos_basename-1) = '\\'; | |
| for(pos = file; pos < pos_basename; pos++) | |
| { | |
| if(*pos == '\\' || *pos == '/') | |
| { | |
| if(truncpos1) | |
| { | |
| if((pos - file + lstrlenW(pos_basename)) > FILELIST_ENTRY_LENGTH) | |
| break; | |
| truncpos1 = pos; | |
| morespace = TRUE; | |
| break; | |
| } | |
| if((pos - file + lstrlenW(pos_basename)) > FILELIST_ENTRY_LENGTH) | |
| break; | |
| truncpos1 = pos; | |
| } | |
| } | |
| if(morespace) | |
| { | |
| for(pos = pos_basename; pos >= truncpos1; pos--) | |
| { | |
| if(*pos == '\\' || *pos == '/') | |
| { | |
| if((truncpos1 - file + lstrlenW(pos_basename) + pos_basename - pos) > FILELIST_ENTRY_LENGTH) | |
| break; | |
| truncpos2 = pos; | |
| } | |
| } | |
| } | |
| } | |
| if(truncpos1 == pos_basename) | |
| lstrcatW(out, pos_basename); | |
| else if(truncpos1 == truncpos2 || !truncpos2) | |
| lstrcatW(out, file); | |
| else | |
| truncate_path(file, out, truncpos1, truncpos2); | |
| } | |
| void registry_read_filelist(HWND hMainWnd) | |
| { | |
| HKEY hFileKey; | |
| if(registry_get_handle(&hFileKey, 0, key_recentfiles) == ERROR_SUCCESS) | |
| { | |
| WCHAR itemText[MAX_PATH+3], buffer[MAX_PATH]; | |
| /* The menu item name is not the same as the file name, so we need to store | |
| the file name here */ | |
| static WCHAR file1[MAX_PATH], file2[MAX_PATH], file3[MAX_PATH], file4[MAX_PATH]; | |
| WCHAR numFormat[] = {'&','%','d',' ',0}; | |
| LPWSTR pFile[] = {file1, file2, file3, file4}; | |
| DWORD pathSize = MAX_PATH*sizeof(WCHAR); | |
| int i; | |
| WCHAR key[6]; | |
| MENUITEMINFOW mi; | |
| HMENU hMenu = GetMenu(hMainWnd); | |
| mi.cbSize = sizeof(MENUITEMINFOW); | |
| mi.fMask = MIIM_ID | MIIM_DATA | MIIM_STRING | MIIM_FTYPE; | |
| mi.fType = MFT_STRING; | |
| mi.dwTypeData = itemText; | |
| mi.wID = ID_FILE_RECENT1; | |
| RemoveMenu(hMenu, ID_FILE_RECENT_SEPARATOR, MF_BYCOMMAND); | |
| for(i = 0; i < FILELIST_ENTRIES; i++) | |
| { | |
| wsprintfW(key, var_file, i+1); | |
| RemoveMenu(hMenu, ID_FILE_RECENT1+i, MF_BYCOMMAND); | |
| if(RegQueryValueExW(hFileKey, (LPWSTR)key, 0, NULL, (LPBYTE)pFile[i], &pathSize) | |
| != ERROR_SUCCESS) | |
| break; | |
| mi.dwItemData = (ULONG_PTR)pFile[i]; | |
| wsprintfW(itemText, numFormat, i+1); | |
| lstrcpyW(buffer, pFile[i]); | |
| format_filelist_filename(buffer, itemText); | |
| InsertMenuItemW(hMenu, ID_FILE_EXIT, FALSE, &mi); | |
| mi.wID++; | |
| pathSize = MAX_PATH*sizeof(WCHAR); | |
| } | |
| mi.fType = MFT_SEPARATOR; | |
| mi.fMask = MIIM_FTYPE | MIIM_ID; | |
| InsertMenuItemW(hMenu, ID_FILE_EXIT, FALSE, &mi); | |
| RegCloseKey(hFileKey); | |
| } | |
| } | |
| void registry_set_filelist(LPCWSTR newFile, HWND hMainWnd) | |
| { | |
| HKEY hKey; | |
| DWORD action; | |
| if(registry_get_handle(&hKey, &action, key_recentfiles) == ERROR_SUCCESS) | |
| { | |
| LPCWSTR pFiles[FILELIST_ENTRIES]; | |
| int i; | |
| HMENU hMenu = GetMenu(hMainWnd); | |
| MENUITEMINFOW mi; | |
| WCHAR buffer[6]; | |
| mi.cbSize = sizeof(MENUITEMINFOW); | |
| mi.fMask = MIIM_DATA; | |
| for(i = 0; i < FILELIST_ENTRIES; i++) | |
| pFiles[i] = NULL; | |
| for(i = 0; GetMenuItemInfoW(hMenu, ID_FILE_RECENT1+i, FALSE, &mi); i++) | |
| pFiles[i] = (LPWSTR)mi.dwItemData; | |
| if(lstrcmpiW(newFile, pFiles[0])) | |
| { | |
| for(i = 0; pFiles[i] && i < FILELIST_ENTRIES; i++) | |
| { | |
| if(!lstrcmpiW(pFiles[i], newFile)) | |
| { | |
| int j; | |
| for(j = 0; pFiles[j] && j < i; j++) | |
| { | |
| pFiles[i-j] = pFiles[i-j-1]; | |
| } | |
| pFiles[0] = NULL; | |
| break; | |
| } | |
| } | |
| if(!pFiles[0]) | |
| { | |
| pFiles[0] = newFile; | |
| } else | |
| { | |
| for(i = 0; i < FILELIST_ENTRIES-1; i++) | |
| pFiles[FILELIST_ENTRIES-1-i] = pFiles[FILELIST_ENTRIES-2-i]; | |
| pFiles[0] = newFile; | |
| } | |
| for(i = 0; pFiles[i] && i < FILELIST_ENTRIES; i++) | |
| { | |
| wsprintfW(buffer, var_file, i+1); | |
| RegSetValueExW(hKey, (LPWSTR)&buffer, 0, REG_SZ, (const BYTE*)pFiles[i], | |
| (lstrlenW(pFiles[i])+1)*sizeof(WCHAR)); | |
| } | |
| } | |
| RegCloseKey(hKey); | |
| } | |
| registry_read_filelist(hMainWnd); | |
| } | |
| int reg_formatindex(WPARAM format) | |
| { | |
| return (format & SF_TEXT) ? 1 : 0; | |
| } | |
| void registry_read_options(void) | |
| { | |
| HKEY hKey; | |
| if(registry_get_handle(&hKey, 0, key_options) != ERROR_SUCCESS) | |
| registry_read_pagemargins(NULL); | |
| else | |
| { | |
| registry_read_pagemargins(hKey); | |
| RegCloseKey(hKey); | |
| } | |
| } | |
| static void registry_read_formatopts(int index, LPCWSTR key, DWORD barState[], DWORD wordWrap[]) | |
| { | |
| HKEY hKey; | |
| DWORD action = 0; | |
| BOOL fetched = FALSE; | |
| barState[index] = 0; | |
| wordWrap[index] = 0; | |
| if(registry_get_handle(&hKey, &action, key) != ERROR_SUCCESS) | |
| return; | |
| if(action == REG_OPENED_EXISTING_KEY) | |
| { | |
| DWORD size = sizeof(DWORD); | |
| if(RegQueryValueExW(hKey, var_barstate0, 0, NULL, (LPBYTE)&barState[index], | |
| &size) == ERROR_SUCCESS) | |
| fetched = TRUE; | |
| } | |
| if(!fetched) | |
| barState[index] = (1 << BANDID_TOOLBAR) | (1 << BANDID_FORMATBAR) | (1 << BANDID_RULER) | (1 << BANDID_STATUSBAR); | |
| if(index == reg_formatindex(SF_RTF)) | |
| wordWrap[index] = ID_WORDWRAP_WINDOW; | |
| else if(index == reg_formatindex(SF_TEXT)) | |
| wordWrap[index] = ID_WORDWRAP_NONE; | |
| RegCloseKey(hKey); | |
| } | |
| void registry_read_formatopts_all(DWORD barState[], DWORD wordWrap[]) | |
| { | |
| registry_read_formatopts(reg_formatindex(SF_RTF), key_rtf, barState, wordWrap); | |
| registry_read_formatopts(reg_formatindex(SF_TEXT), key_text, barState, wordWrap); | |
| } | |
| static void registry_set_formatopts(int index, LPCWSTR key, DWORD barState[]) | |
| { | |
| HKEY hKey; | |
| DWORD action = 0; | |
| if(registry_get_handle(&hKey, &action, key) == ERROR_SUCCESS) | |
| { | |
| RegSetValueExW(hKey, var_barstate0, 0, REG_DWORD, (LPBYTE)&barState[index], | |
| sizeof(DWORD)); | |
| RegCloseKey(hKey); | |
| } | |
| } | |
| void registry_set_formatopts_all(DWORD barState[]) | |
| { | |
| registry_set_formatopts(reg_formatindex(SF_RTF), key_rtf, barState); | |
| registry_set_formatopts(reg_formatindex(SF_TEXT), key_text, barState); | |
| } |