From 07d60bc727975aab002e658e2f583b55f6608bcb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alexander=20Nicolaysen=20S=C3=B8rnes?= Date: Wed, 18 Jul 2007 15:41:57 +0200 Subject: [PATCH] wordpad: Add recent file list. --- programs/wordpad/resource.h | 17 ++- programs/wordpad/wordpad.c | 272 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 285 insertions(+), 4 deletions(-) diff --git a/programs/wordpad/resource.h b/programs/wordpad/resource.h index 2e24503c6cb..82339b91884 100644 --- a/programs/wordpad/resource.h +++ b/programs/wordpad/resource.h @@ -22,11 +22,17 @@ #define ID_FILE_NEW 1003 #define ID_FILE_SAVEAS 1004 -#define ID_PRINT 1005 -#define ID_PREVIEW 1006 +#define ID_FILE_RECENT1 1005 +#define ID_FILE_RECENT2 1006 +#define ID_FILE_RECENT3 1007 +#define ID_FILE_RECENT4 1008 +#define ID_FILE_RECENT_SEPARATOR 1009 -#define ID_FIND 1007 -#define ID_FIND_NEXT 1008 +#define ID_PRINT 1010 +#define ID_PREVIEW 1011 + +#define ID_FIND 1012 +#define ID_FIND_NEXT 1013 #define ID_ALIGN_LEFT 1100 #define ID_ALIGN_CENTER 1101 @@ -62,6 +68,9 @@ #define BANDID_TOOLBAR 0 #define BANDID_FORMATBAR 1 +#define FILELIST_ENTRIES 4 +#define FILELIST_ENTRY_LENGTH 33 + #define ID_DATETIME 1600 #define IDC_STATUSBAR 2000 diff --git a/programs/wordpad/wordpad.c b/programs/wordpad/wordpad.c index d51d3936226..91ea140993c 100644 --- a/programs/wordpad/wordpad.c +++ b/programs/wordpad/wordpad.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "resource.h" @@ -43,6 +44,11 @@ static const WCHAR wszRichEditClass[] = {'R','I','C','H','E','D','I','T','2','0' static const WCHAR wszMainWndClass[] = {'W','O','R','D','P','A','D','T','O','P',0}; static const WCHAR wszAppTitle[] = {'W','i','n','e',' ','W','o','r','d','p','a','d',0}; +static const WCHAR key_recentfiles[] = {'R','e','c','e','n','t',' ','f','i','l','e', + ' ','l','i','s','t',0}; + +static const WCHAR var_file[] = {'F','i','l','e','%','d',0}; + static HWND hMainWnd; static HWND hEditorWnd; static HWND hFindWnd; @@ -142,6 +148,22 @@ static DWORD CALLBACK stream_out(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG return 0; } +static LPWSTR file_basename(LPWSTR path) +{ + LPWSTR pos = path + lstrlenW(path); + + while(pos > path) + { + if(*pos == '\\' || *pos == '/') + { + pos++; + break; + } + pos--; + } + return pos; +} + static WCHAR wszFileName[MAX_PATH]; static void set_caption(LPCWSTR wszNewFileName) @@ -170,6 +192,238 @@ static void set_caption(LPCWSTR wszNewFileName) HeapFree(GetProcessHeap(), 0, wszCaption); } +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; +} + +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 ? truncpos2 : (pos_basename-1)); +} + +static 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 = (DWORD)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); + } +} + +static void registry_set_filelist(LPCWSTR newFile) +{ + 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; pFiles[i] && 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, (LPBYTE)pFiles[i], + (lstrlenW(pFiles[i])+1)*sizeof(WCHAR)); + } + } + } + RegCloseKey(hKey); + registry_read_filelist(hMainWnd); +} + static void DoOpenFile(LPCWSTR szOpenFileName) { HANDLE hFile; @@ -194,6 +448,7 @@ static void DoOpenFile(LPCWSTR szOpenFileName) lstrcpyW(wszFileName, szOpenFileName); SendMessageW(hEditorWnd, EM_SETMODIFY, FALSE, 0); + registry_set_filelist(szOpenFileName); } static void DoSaveFile(LPCWSTR wszSaveFileName) @@ -710,6 +965,8 @@ static LRESULT OnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam) ID_FINDMSGSTRING = RegisterWindowMessageW(FINDMSGSTRINGW); + registry_read_filelist(hWnd); + return 0; } @@ -831,6 +1088,21 @@ static LRESULT OnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam) DialogSaveFile(); break; + case ID_FILE_RECENT1: + case ID_FILE_RECENT2: + case ID_FILE_RECENT3: + case ID_FILE_RECENT4: + { + HMENU hMenu = GetMenu(hWnd); + MENUITEMINFOW mi; + + mi.cbSize = sizeof(MENUITEMINFOW); + mi.fMask = MIIM_DATA; + if(GetMenuItemInfoW(hMenu, LOWORD(wParam), FALSE, &mi)) + DoOpenFile((LPWSTR)mi.dwItemData); + } + break; + case ID_FIND: dialog_find(&findreplace); break; -- 2.11.4.GIT