|  | /* | 
|  | * 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_settings[] = {'S','e','t','t','i','n','g','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_wrap[] = {'W','r','a','p',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); | 
|  | } | 
|  |  | 
|  | if(registry_get_handle(&hKey, &action, key_settings) == ERROR_SUCCESS) | 
|  | { | 
|  | registry_set_previewpages(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); | 
|  | } | 
|  |  | 
|  | if(registry_get_handle(&hKey, 0, key_settings) != ERROR_SUCCESS) { | 
|  | registry_read_previewpages(NULL); | 
|  | } else { | 
|  | registry_read_previewpages(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); | 
|  |  | 
|  | fetched = FALSE; | 
|  | if(action == REG_OPENED_EXISTING_KEY) | 
|  | { | 
|  | DWORD size = sizeof(DWORD); | 
|  | if(RegQueryValueExW(hKey, var_wrap, 0, NULL, (LPBYTE)&wordWrap[index], | 
|  | &size) == ERROR_SUCCESS) | 
|  | fetched = TRUE; | 
|  | } | 
|  |  | 
|  | if (!fetched) | 
|  | { | 
|  | 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[], DWORD wordWrap[]) | 
|  | { | 
|  | 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)); | 
|  | RegSetValueExW(hKey, var_wrap, 0, REG_DWORD, (LPBYTE)&wordWrap[index], | 
|  | sizeof(DWORD)); | 
|  | RegCloseKey(hKey); | 
|  | } | 
|  | } | 
|  |  | 
|  | void registry_set_formatopts_all(DWORD barState[], DWORD wordWrap[]) | 
|  | { | 
|  | registry_set_formatopts(reg_formatindex(SF_RTF), key_rtf, barState, wordWrap); | 
|  | registry_set_formatopts(reg_formatindex(SF_TEXT), key_text, barState, wordWrap); | 
|  | } |