diff --git a/programs/notepad/Makefile.in b/programs/notepad/Makefile.in index ecf3e4e..7ffb45a 100644 --- a/programs/notepad/Makefile.in +++ b/programs/notepad/Makefile.in @@ -1,6 +1,6 @@ MODULE = notepad.exe APPMODE = -mwindows -mno-cygwin -IMPORTS = comdlg32 shell32 shlwapi user32 gdi32 advapi32 +IMPORTS = comdlg32 shell32 shlwapi user32 gdi32 advapi32 comctl32 EXTRAINCL = -I$(top_srcdir)/include/msvcrt MODCFLAGS = @BUILTINFLAG@ EXTRADEFS = -DNO_LIBWINE_PORT diff --git a/programs/notepad/dialog.c b/programs/notepad/dialog.c index 5878da8..2e8200b 100644 --- a/programs/notepad/dialog.c +++ b/programs/notepad/dialog.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "main.h" #include "dialog.h" @@ -36,7 +37,10 @@ #define SPACES_IN_TAB 8 #define PRINT_LEN_MAX 500 +LRESULT CALLBACK EDIT_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + static const WCHAR helpfileW[] = { 'n','o','t','e','p','a','d','.','h','l','p',0 }; +static const WCHAR editW[] = { 'e', 'd', 'i', 't', 0 }; static INT_PTR WINAPI DIALOG_PAGESETUP_DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); @@ -483,6 +487,7 @@ void DoOpenFile(LPCWSTR szFileName, ENCODING enc) SetFileNameAndEncoding(szFileName, enc); UpdateWindowCaption(); + NOTEPAD_EnableSearchMenu(); } VOID DIALOG_FileNew(VOID) @@ -494,6 +499,7 @@ VOID DIALOG_FileNew(VOID) SetWindowTextW(Globals.hEdit, empty_strW); SendMessageW(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0); SetFocus(Globals.hEdit); + NOTEPAD_EnableSearchMenu(); } } @@ -923,7 +929,7 @@ VOID DIALOG_FilePrint(VOID) di.lpszDocName = Globals.szFileTitle; di.lpszOutput = NULL; di.lpszDatatype = NULL; - di.fwType = 0; + di.fwType = 0; if(printer.Flags & PD_PRINTTOFILE) { @@ -1073,40 +1079,185 @@ VOID DIALOG_EditTimeDate(VOID) SendMessageW(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)szDate); } -VOID DIALOG_EditWrap(VOID) +VOID DoCreateStatusBar(VOID) { - BOOL modify = FALSE; - static const WCHAR editW[] = { 'e','d','i','t',0 }; - DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | - ES_AUTOVSCROLL | ES_MULTILINE; RECT rc; - DWORD size; - LPWSTR pTemp; + RECT rcstatus; + BOOL bStatusBarVisible; - size = GetWindowTextLengthW(Globals.hEdit) + 1; - pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); - if (!pTemp) + /* Check if status bar object already exists. */ + if (Globals.hStatusBar == NULL) + { + /* Try to create the status bar */ + Globals.hStatusBar = CreateStatusWindowW( + WS_CHILD | WS_VISIBLE | WS_EX_STATICEDGE, + NULL, + Globals.hMainWnd, + CMD_STATUSBAR_WND_ID); + + if (Globals.hStatusBar == NULL) + { + ShowLastError(); + return; + } + + /* Load the string for formatting column/row text output */ + LoadStringW(Globals.hInstance, STRING_LINE_COLUMN, Globals.szStatusBarLineCol, MAX_PATH-1); + + /* Set the status bar for single-text output */ + SendMessageW(Globals.hStatusBar, SB_SIMPLE, (WPARAM)TRUE, (LPARAM)0); + } + + /* Set status bar visible or not accordind the the settings. */ + if (Globals.bWrapLongLines == TRUE || + Globals.bShowStatusBar == FALSE) + { + bStatusBarVisible = FALSE; + ShowWindow(Globals.hStatusBar, SW_HIDE); + } + else + { + bStatusBarVisible = TRUE; + ShowWindow(Globals.hStatusBar, SW_SHOW); + SendMessageW(Globals.hStatusBar, WM_SIZE, 0, 0); + } + + /* Set check state in show status bar item. */ + if (Globals.bShowStatusBar == TRUE) + { + CheckMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_CHECKED); + } + else + { + CheckMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_UNCHECKED); + } + + /* Update menu mar with the previous changes */ + DrawMenuBar(Globals.hMainWnd); + + /* Sefety test is edit control exists */ + if (Globals.hEdit != NULL) + { + /* Retrieve the sizes of the controls */ + GetClientRect(Globals.hMainWnd, &rc); + GetClientRect(Globals.hStatusBar, &rcstatus); + + /* If status bar is currently visible, update dimensions of edir control */ + if (bStatusBarVisible) + rc.bottom -= (rcstatus.bottom - rcstatus.top); + + /* Resize edit control to right size. */ + MoveWindow(Globals.hEdit, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); + } + + /* Update content with current row/column text */ + DIALOG_StatusBarUpdateCaretPos(); +} + +VOID DoCreateEditWindow(VOID) +{ + DWORD dwStyle; + int iSize; + LPWSTR pTemp = NULL; + BOOL bModified; + + iSize = 0; + bModified = FALSE; + + /* If the edit control already exists, try to save its content */ + if (Globals.hEdit != NULL) + { + /* Recover modification flag */ + bModified = (BOOL)SendMessageW(Globals.hEdit, EM_GETMODIFY, 0, 0); + + /* number of chars currently written into the editor. */ + iSize = GetWindowTextLengthW(Globals.hEdit); + + if (iSize) + { + /* Allocates temporary buffer. */ + pTemp = HeapAlloc(GetProcessHeap(), 0, (iSize + 1) * sizeof(WCHAR)); + + if (!pTemp) + { + ShowLastError(); + return; + } + + /* Recover the text into the control. */ + GetWindowTextW(Globals.hEdit, pTemp, iSize + 1); + } + + /* Restore original window procedure */ + SetWindowLongPtrW(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)Globals.EditProc); + + /* Destroy the edit control */ + DestroyWindow(Globals.hEdit); + } + + /* Update wrap status into the main menu and recover style flags */ + if (Globals.bWrapLongLines) + { + dwStyle = EDIT_STYLE_WRAP; + EnableMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + } else { + dwStyle = EDIT_STYLE; + EnableMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_ENABLED); + } + + /* Update previous changes */ + DrawMenuBar(Globals.hMainWnd); + + /* Create the new edit control */ + Globals.hEdit = CreateWindowExW( + WS_EX_CLIENTEDGE, + editW, + NULL, + dwStyle, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + Globals.hMainWnd, + NULL, + Globals.hInstance, + NULL); + + if (Globals.hEdit == NULL) { ShowLastError(); return; } - GetWindowTextW(Globals.hEdit, pTemp, size); - modify = SendMessageW(Globals.hEdit, EM_GETMODIFY, 0, 0); - DestroyWindow(Globals.hEdit); - GetClientRect(Globals.hMainWnd, &rc); - if( Globals.bWrapLongLines ) dwStyle |= WS_HSCROLL | ES_AUTOHSCROLL; - Globals.hEdit = CreateWindowExW(WS_EX_CLIENTEDGE, editW, NULL, dwStyle, - 0, 0, rc.right, rc.bottom, Globals.hMainWnd, - NULL, Globals.hInstance, NULL); + SendMessageW(Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, FALSE); - SetWindowTextW(Globals.hEdit, pTemp); - SendMessageW(Globals.hEdit, EM_SETMODIFY, modify, 0); + SendMessageW(Globals.hEdit, EM_LIMITTEXT, 0, 0); + + /* If some text was previously saved, restore it. */ + if (iSize != 0) + { + SetWindowTextW(Globals.hEdit, pTemp); + HeapFree(GetProcessHeap(), 0, pTemp); + + /* Restore modification flag */ + SendMessageW(Globals.hEdit, EM_SETMODIFY, (WPARAM)bModified, 0); + } + + /* Sub-class a new window callback for row/column detection. */ + Globals.EditProc = (WNDPROC) SetWindowLongPtrW(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)EDIT_WndProc); + + /* Create/update status bar */ + DoCreateStatusBar(); + + /* Finally shows new edit control and set focus into it. */ + ShowWindow(Globals.hEdit, SW_SHOW); SetFocus(Globals.hEdit); - HeapFree(GetProcessHeap(), 0, pTemp); - +} + +VOID DIALOG_EditWrap(VOID) +{ Globals.bWrapLongLines = !Globals.bWrapLongLines; - CheckMenuItem(GetMenu(Globals.hMainWnd), CMD_WRAP, - MF_BYCOMMAND | (Globals.bWrapLongLines ? MF_CHECKED : MF_UNCHECKED)); + + DoCreateEditWindow(); } VOID DIALOG_SelectFont(VOID) @@ -1132,28 +1283,38 @@ VOID DIALOG_SelectFont(VOID) } } -VOID DIALOG_Search(VOID) +static VOID DIALOG_SearchDialog(BOOL bIsReplace) { - /* Allow only one search/replace dialog to open */ - if(Globals.hFindReplaceDlg != NULL) - { - SetActiveWindow(Globals.hFindReplaceDlg); - return; - } + /* Allow only one search/replace dialog to open */ + if(Globals.hFindReplaceDlg != NULL) + { + SetActiveWindow(Globals.hFindReplaceDlg); + return; + } - ZeroMemory(&Globals.find, sizeof(Globals.find)); - Globals.find.lStructSize = sizeof(Globals.find); - Globals.find.hwndOwner = Globals.hMainWnd; - Globals.find.hInstance = Globals.hInstance; - Globals.find.lpstrFindWhat = Globals.szFindText; - Globals.find.wFindWhatLen = ARRAY_SIZE(Globals.szFindText); - Globals.find.Flags = FR_DOWN|FR_HIDEWHOLEWORD; + ZeroMemory(&Globals.find, sizeof(Globals.find)); + Globals.find.lStructSize = sizeof(Globals.find); + Globals.find.hwndOwner = Globals.hMainWnd; + Globals.find.hInstance = Globals.hInstance; + Globals.find.lpstrFindWhat = Globals.szFindText; + Globals.find.wFindWhatLen = ARRAY_SIZE(Globals.szFindText); + Globals.find.lpstrReplaceWith = Globals.szReplaceText; + Globals.find.wReplaceWithLen = ARRAY_SIZE(Globals.szReplaceText); + Globals.find.Flags = FR_DOWN|FR_HIDEWHOLEWORD; + + /* We only need to create the modal FindReplace dialog which will */ + /* notify us of incoming events using hMainWnd Window Messages */ + if (bIsReplace) + Globals.hFindReplaceDlg = ReplaceTextW(&Globals.find); + else + Globals.hFindReplaceDlg = FindTextW(&Globals.find); - /* We only need to create the modal FindReplace dialog which will */ - /* notify us of incoming events using hMainWnd Window Messages */ + assert(Globals.hFindReplaceDlg !=0); +} - Globals.hFindReplaceDlg = FindTextW(&Globals.find); - assert(Globals.hFindReplaceDlg !=0); +VOID DIALOG_Search(VOID) +{ + DIALOG_SearchDialog(FALSE); } VOID DIALOG_SearchNext(VOID) @@ -1166,28 +1327,97 @@ VOID DIALOG_SearchNext(VOID) VOID DIALOG_Replace(VOID) { - /* Allow only one search/replace dialog to open */ - if(Globals.hFindReplaceDlg != NULL) + DIALOG_SearchDialog(TRUE); +} + +static INT_PTR CALLBACK DIALOG_GoTo_DialogProc(HWND hwndDialog, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + BOOL bResult = FALSE; + UINT uiLine; + + switch(uMsg) { + case WM_INITDIALOG: + SetDlgItemInt(hwndDialog, ID_LINENUMBER, lParam, FALSE); + break; + case WM_COMMAND: + if (HIWORD(wParam) == BN_CLICKED) { - SetActiveWindow(Globals.hFindReplaceDlg); - return; + if (LOWORD(wParam) == IDOK) + { + uiLine = GetDlgItemInt(hwndDialog, ID_LINENUMBER, NULL, FALSE); + EndDialog(hwndDialog, uiLine); + bResult = TRUE; + } + else if (LOWORD(wParam) == IDCANCEL) + { + EndDialog(hwndDialog, 0); + bResult = TRUE; + } } + break; + } - ZeroMemory(&Globals.find, sizeof(Globals.find)); - Globals.find.lStructSize = sizeof(Globals.find); - Globals.find.hwndOwner = Globals.hMainWnd; - Globals.find.hInstance = Globals.hInstance; - Globals.find.lpstrFindWhat = Globals.szFindText; - Globals.find.wFindWhatLen = ARRAY_SIZE(Globals.szFindText); - Globals.find.lpstrReplaceWith = Globals.szReplaceText; - Globals.find.wReplaceWithLen = ARRAY_SIZE(Globals.szReplaceText); - Globals.find.Flags = FR_DOWN|FR_HIDEWHOLEWORD; + return bResult; +} - /* We only need to create the modal FindReplace dialog which will */ - /* notify us of incoming events using hMainWnd Window Messages */ +VOID DIALOG_GoTo(VOID) +{ + INT_PTR nLine; + LPWSTR pszText; + int nLength, i; + DWORD dwStart, dwEnd; + + nLength = GetWindowTextLengthW(Globals.hEdit); + pszText = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(*pszText)); + if (!pszText) + return; - Globals.hFindReplaceDlg = ReplaceTextW(&Globals.find); - assert(Globals.hFindReplaceDlg !=0); + /* Retrieve current text */ + GetWindowTextW(Globals.hEdit, pszText, nLength + 1); + SendMessageW(Globals.hEdit, EM_GETSEL, (WPARAM) &dwStart, (LPARAM) &dwEnd); + + nLine = 1; + for (i = 0; pszText[i] && (i < (int) dwStart); i++) + { + if (pszText[i] == '\n') + nLine++; + } + + nLine = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(DIALOG_GOTO), + Globals.hMainWnd, DIALOG_GoTo_DialogProc, nLine); + + if (nLine >= 1) + { + for (i = 0; pszText[i] && (nLine > 1) && (i < nLength - 1); i++) + { + if (pszText[i] == '\n') + nLine--; + } + SendMessageW(Globals.hEdit, EM_SETSEL, i, i); + SendMessageW(Globals.hEdit, EM_SCROLLCARET, 0, 0); + } + HeapFree(GetProcessHeap(), 0, pszText); +} + +VOID DIALOG_StatusBarUpdateCaretPos(VOID) +{ + int line, col; + WCHAR buff[MAX_PATH]; + DWORD dwStart, dwSize; + + SendMessageW(Globals.hEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwSize); + line = SendMessageW(Globals.hEdit, EM_LINEFROMCHAR, (WPARAM)dwStart, 0); + col = dwStart - SendMessageW(Globals.hEdit, EM_LINEINDEX, (WPARAM)line, 0); + + wnsprintfW(buff, MAX_PATH, Globals.szStatusBarLineCol, line+1, col+1); + SendMessageW(Globals.hStatusBar, SB_SETTEXTW, SB_SIMPLEID, (LPARAM)buff); +} + +VOID DIALOG_ViewStatusBar(VOID) +{ + Globals.bShowStatusBar = !Globals.bShowStatusBar; + + DoCreateStatusBar(); } VOID DIALOG_HelpContents(VOID) @@ -1273,5 +1503,5 @@ static INT_PTR WINAPI DIALOG_PAGESETUP_DlgProc(HWND hDlg, UINT msg, WPARAM wPara break; } - return FALSE; + return FALSE; } diff --git a/programs/notepad/dialog.h b/programs/notepad/dialog.h index ae41ac2..a98f2b3 100644 --- a/programs/notepad/dialog.h +++ b/programs/notepad/dialog.h @@ -39,9 +39,13 @@ VOID DIALOG_EditWrap(VOID); VOID DIALOG_Search(VOID); VOID DIALOG_SearchNext(VOID); VOID DIALOG_Replace(VOID); +VOID DIALOG_GoTo(VOID); VOID DIALOG_SelectFont(VOID); +VOID DIALOG_ViewStatusBar(VOID); +VOID DIALOG_StatusBarUpdateCaretPos(VOID); + VOID DIALOG_HelpContents(VOID); VOID DIALOG_HelpSearch(VOID); VOID DIALOG_HelpAboutNotepad(VOID); @@ -55,3 +59,5 @@ void UpdateWindowCaption(void); BOOL FileExists(LPCWSTR szFilename); BOOL DoCloseFile(void); void DoOpenFile(LPCWSTR szFileName, ENCODING enc); +VOID DoCreateStatusBar(VOID); +VOID DoCreateEditWindow(VOID); diff --git a/programs/notepad/main.c b/programs/notepad/main.c index 235981f..5c6e2ec 100644 --- a/programs/notepad/main.c +++ b/programs/notepad/main.c @@ -40,6 +40,7 @@ static RECT main_rect; static const WCHAR notepad_reg_key[] = {'S','o','f','t','w','a','r','e','\\', 'M','i','c','r','o','s','o','f','t','\\','N','o','t','e','p','a','d','\0'}; static const WCHAR value_fWrap[] = {'f','W','r','a','p','\0'}; +static const WCHAR value_fStatusBar[] = {'f','S','t','a','t','u','s','B','a','r','\0'}; static const WCHAR value_iPointSize[] = {'i','P','o','i','n','t','S','i','z','e','\0'}; static const WCHAR value_iWindowPosDX[] = {'i','W','i','n','d','o','w','P','o','s','D','X','\0'}; static const WCHAR value_iWindowPosDY[] = {'i','W','i','n','d','o','w','P','o','s','D','Y','\0'}; @@ -64,6 +65,18 @@ static const WCHAR value_iMarginRight[] = {'i','M','a','r','g','i','n','R',' static const WCHAR value_szHeader[] = {'s','z','H','e','a','d','e','r','\0'}; static const WCHAR value_szFooter[] = {'s','z','T','r','a','i','l','e','r','\0'}; +VOID NOTEPAD_EnableSearchMenu(VOID) +{ + int iLen; + + iLen = GetWindowTextLengthW(Globals.hEdit); + + EnableMenuItem(Globals.hMenu, CMD_SEARCH, + MF_BYCOMMAND | ((iLen == 0) ? MF_DISABLED | MF_GRAYED : MF_ENABLED)); + EnableMenuItem(Globals.hMenu, CMD_SEARCH_NEXT, + MF_BYCOMMAND | ((iLen == 0) ? MF_DISABLED | MF_GRAYED : MF_ENABLED)); +} + /*********************************************************************** * * SetFileNameAndEncoding @@ -130,6 +143,7 @@ static VOID NOTEPAD_SaveSettingToRegistry(void) #define SET_NOTEPAD_REG(hkey, value_name, value_data) do { DWORD data = value_data; RegSetValueExW(hkey, value_name, 0, REG_DWORD, (LPBYTE)&data, sizeof(DWORD)); }while(0) SET_NOTEPAD_REG(hkey, value_fWrap, Globals.bWrapLongLines); + SET_NOTEPAD_REG(hkey, value_fStatusBar, Globals.bShowStatusBar); SET_NOTEPAD_REG(hkey, value_iWindowPosX, main_rect.left); SET_NOTEPAD_REG(hkey, value_iWindowPosY, main_rect.top); SET_NOTEPAD_REG(hkey, value_iWindowPosDX, main_rect.right - main_rect.left); @@ -220,6 +234,7 @@ static VOID NOTEPAD_LoadSettingFromRegistry(void) #define QUERY_NOTEPAD_REG(hkey, value_name, ret) do { DWORD type, data; DWORD size = sizeof(DWORD); if(RegQueryValueExW(hkey, value_name, 0, &type, (LPBYTE)&data, &size) == ERROR_SUCCESS) if(type == REG_DWORD) ret = data; } while(0) QUERY_NOTEPAD_REG(hkey, value_fWrap, Globals.bWrapLongLines); + QUERY_NOTEPAD_REG(hkey, value_fStatusBar, Globals.bShowStatusBar); QUERY_NOTEPAD_REG(hkey, value_iWindowPosX, main_rect.left); QUERY_NOTEPAD_REG(hkey, value_iWindowPosY, main_rect.top); QUERY_NOTEPAD_REG(hkey, value_iWindowPosDX, dx); @@ -241,6 +256,9 @@ static VOID NOTEPAD_LoadSettingFromRegistry(void) QUERY_NOTEPAD_REG(hkey, value_iMarginRight, Globals.iMarginRight); #undef QUERY_NOTEPAD_REG + /* Invert value because DIALOG_ViewStatusBar will be called to show it */ + Globals.bShowStatusBar = !Globals.bShowStatusBar; + main_rect.right = main_rect.left + dx; main_rect.bottom = main_rect.top + dy; @@ -298,10 +316,13 @@ static int NOTEPAD_MenuCommand(WPARAM wParam) case CMD_SEARCH: DIALOG_Search(); break; case CMD_SEARCH_NEXT: DIALOG_SearchNext(); break; case CMD_REPLACE: DIALOG_Replace(); break; - + case CMD_GOTO: DIALOG_GoTo(); break; + case CMD_WRAP: DIALOG_EditWrap(); break; case CMD_FONT: DIALOG_SelectFont(); break; + case CMD_STATUSBAR: DIALOG_ViewStatusBar(); break; + case CMD_HELP_CONTENTS: DIALOG_HelpContents(); break; case CMD_HELP_ABOUT_NOTEPAD: DIALOG_HelpAboutNotepad(); break; @@ -489,6 +510,35 @@ static void NOTEPAD_DoReplaceAll(FINDREPLACEW *fr) /*********************************************************************** * + * Forward notifications to status bar + */ +LRESULT CALLBACK EDIT_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_KEYUP: + switch (wParam) { + case VK_HOME: + case VK_END: + case VK_PRIOR: + case VK_NEXT: + case VK_UP: + case VK_DOWN: + case VK_LEFT: + case VK_RIGHT: + DIALOG_StatusBarUpdateCaretPos(); + break; + } + break; + + case WM_LBUTTONUP: + DIALOG_StatusBarUpdateCaretPos(); + break; + } + return CallWindowProcW(Globals.EditProc, hWnd, msg, wParam, lParam); +} + +/*********************************************************************** + * * NOTEPAD_WndProc */ static LRESULT WINAPI NOTEPAD_WndProc(HWND hWnd, UINT msg, WPARAM wParam, @@ -521,27 +571,25 @@ static LRESULT WINAPI NOTEPAD_WndProc(HWND hWnd, UINT msg, WPARAM wParam, switch (msg) { case WM_CREATE: - { - static const WCHAR editW[] = { 'e','d','i','t',0 }; - DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | - ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL; - RECT rc; - GetClientRect(hWnd, &rc); - - if (!Globals.bWrapLongLines) dwStyle |= WS_HSCROLL | ES_AUTOHSCROLL; - - Globals.hEdit = CreateWindowExW(WS_EX_CLIENTEDGE, editW, NULL, - dwStyle, 0, 0, rc.right, rc.bottom, hWnd, - NULL, Globals.hInstance, NULL); - + Globals.hMenu = GetMenu(hWnd); Globals.hFont = CreateFontIndirectW(&Globals.lfFont); - SendMessageW(Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, FALSE); - SendMessageW(Globals.hEdit, EM_LIMITTEXT, 0, 0); break; - } case WM_COMMAND: - NOTEPAD_MenuCommand(LOWORD(wParam)); + switch (HIWORD(wParam)) { + case EN_CHANGE: + NOTEPAD_EnableSearchMenu(); + /* Fall down... */ + + case EN_HSCROLL: + case EN_VSCROLL: + DIALOG_StatusBarUpdateCaretPos(); + break; + + case BN_CLICKED: + NOTEPAD_MenuCommand(LOWORD(wParam)); + break; + } break; case WM_DESTROYCLIPBOARD: @@ -561,16 +609,47 @@ static LRESULT WINAPI NOTEPAD_WndProc(HWND hWnd, UINT msg, WPARAM wParam, break; case WM_DESTROY: + SetWindowLongPtrW(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)Globals.EditProc); NOTEPAD_SaveSettingToRegistry(); PostQuitMessage(0); break; case WM_SIZE: - SetWindowPos(Globals.hEdit, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), - SWP_NOOWNERZORDER | SWP_NOZORDER); + if (Globals.bShowStatusBar == TRUE && + Globals.bWrapLongLines == FALSE) + { + RECT rcStatusBar; + HDWP hdwp; + + if (!GetWindowRect(Globals.hStatusBar, &rcStatusBar)) + break; + + hdwp = BeginDeferWindowPos(2); + if (hdwp == NULL) + break; + + hdwp = DeferWindowPos(hdwp, Globals.hEdit, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam) - (rcStatusBar.bottom - rcStatusBar.top), SWP_NOZORDER | SWP_NOMOVE); + if (hdwp == NULL) + break; + + hdwp = DeferWindowPos(hdwp, Globals.hStatusBar, NULL, 0, 0, LOWORD(lParam), LOWORD(wParam), SWP_NOZORDER); + + if (hdwp != NULL) + EndDeferWindowPos(hdwp); + } + else + SetWindowPos(Globals.hEdit, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER | SWP_NOMOVE); + break; + /* The entire client area is covered by edit control and by + * the status bar. So there is no need to erase main background. + * This resolves the horrible fliker effect during windows resizes. + */ + case WM_ERASEBKGND: + return 1; + case WM_SETFOCUS: SetFocus(Globals.hEdit); break; @@ -725,7 +804,7 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show) { MSG msg; HACCEL hAccel; - WNDCLASSEXW class; + WNDCLASSEXW wndclass; HMONITOR monitor; MONITORINFO info; INT x, y; @@ -738,20 +817,20 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show) Globals.hInstance = hInstance; NOTEPAD_LoadSettingFromRegistry(); - ZeroMemory(&class, sizeof(class)); - class.cbSize = sizeof(class); - class.lpfnWndProc = NOTEPAD_WndProc; - class.hInstance = Globals.hInstance; - class.hIcon = LoadIconW(Globals.hInstance, MAKEINTRESOURCEW(IDI_NOTEPAD)); - class.hIconSm = LoadImageW(Globals.hInstance, MAKEINTRESOURCEW(IDI_NOTEPAD), IMAGE_ICON, + ZeroMemory(&wndclass, sizeof(wndclass)); + wndclass.cbSize = sizeof(wndclass); + wndclass.lpfnWndProc = NOTEPAD_WndProc; + wndclass.hInstance = Globals.hInstance; + wndclass.hIcon = LoadIconW(Globals.hInstance, MAKEINTRESOURCEW(IDI_NOTEPAD)); + wndclass.hIconSm = LoadImageW(Globals.hInstance, MAKEINTRESOURCEW(IDI_NOTEPAD), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED); - class.hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW); - class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - class.lpszMenuName = MAKEINTRESOURCEW(MAIN_MENU); - class.lpszClassName = className; + wndclass.hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wndclass.lpszMenuName = MAKEINTRESOURCEW(MAIN_MENU); + wndclass.lpszClassName = className; - if (!RegisterClassExW(&class)) return FALSE; + if (!RegisterClassExW(&wndclass)) return FALSE; /* Setup windows */ @@ -777,6 +856,8 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show) ExitProcess(1); } + DoCreateEditWindow(); + NOTEPAD_InitData(); DIALOG_FileNew(); @@ -784,6 +865,8 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show) UpdateWindow(Globals.hMainWnd); DragAcceptFiles(Globals.hMainWnd, TRUE); + DIALOG_ViewStatusBar(); + HandleCommandLine(GetCommandLineW()); hAccel = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(ID_ACCEL)); diff --git a/programs/notepad/main.h b/programs/notepad/main.h index b672be6..7c59a7b 100644 --- a/programs/notepad/main.h +++ b/programs/notepad/main.h @@ -23,6 +23,10 @@ #include "notepad_res.h" +#define EDIT_STYLE_WRAP (WS_CHILD | WS_VSCROLL \ + | ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL) +#define EDIT_STYLE (EDIT_STYLE_WRAP | WS_HSCROLL | ES_AUTOHSCROLL) + #define MAX_STRING_LEN 255 /* Values are indexes of the items in the Encoding combobox. */ @@ -40,32 +44,37 @@ typedef enum typedef struct { - HANDLE hInstance; - HWND hMainWnd; - HWND hFindReplaceDlg; - HWND hEdit; - HFONT hFont; /* Font used by the edit control */ - LOGFONTW lfFont; - BOOL bWrapLongLines; - WCHAR szFindText[MAX_PATH]; - WCHAR szReplaceText[MAX_PATH]; - WCHAR szFileName[MAX_PATH]; - WCHAR szFileTitle[MAX_PATH]; - ENCODING encFile; - WCHAR szFilter[2 * MAX_STRING_LEN + 100]; - ENCODING encOfnCombo; /* Encoding selected in IDC_OFN_ENCCOMBO */ - BOOL bOfnIsOpenDialog; - INT iMarginTop; - INT iMarginBottom; - INT iMarginLeft; - INT iMarginRight; - WCHAR szHeader[MAX_PATH]; - WCHAR szFooter[MAX_PATH]; + HINSTANCE hInstance; + HWND hMainWnd; + HWND hFindReplaceDlg; + HWND hEdit; + HWND hStatusBar; + HFONT hFont; /* Font used by the edit control */ + HMENU hMenu; + LOGFONTW lfFont; + BOOL bWrapLongLines; + BOOL bShowStatusBar; + WCHAR szFindText[MAX_PATH]; + WCHAR szReplaceText[MAX_PATH]; + WCHAR szFileName[MAX_PATH]; + WCHAR szFileTitle[MAX_PATH]; + ENCODING encFile; + WCHAR szFilter[2 * MAX_STRING_LEN + 100]; + ENCODING encOfnCombo; /* Encoding selected in IDC_OFN_ENCCOMBO */ + BOOL bOfnIsOpenDialog; + INT iMarginTop; + INT iMarginBottom; + INT iMarginLeft; + INT iMarginRight; + WCHAR szHeader[MAX_PATH]; + WCHAR szFooter[MAX_PATH]; + WCHAR szStatusBarLineCol[MAX_PATH]; FINDREPLACEW find; FINDREPLACEW lastFind; HGLOBAL hDevMode; /* printer mode */ HGLOBAL hDevNames; /* printer names */ + WNDPROC EditProc; } NOTEPAD_GLOBALS; extern NOTEPAD_GLOBALS Globals; @@ -73,3 +82,4 @@ extern NOTEPAD_GLOBALS Globals; VOID SetFileNameAndEncoding(LPCWSTR szFileName, ENCODING enc); void NOTEPAD_DoFind(FINDREPLACEW *fr); DWORD get_dpi(void); +VOID NOTEPAD_EnableSearchMenu(VOID); diff --git a/programs/notepad/notepad.rc b/programs/notepad/notepad.rc index a8c8bb3..7fe6719 100644 --- a/programs/notepad/notepad.rc +++ b/programs/notepad/notepad.rc @@ -22,46 +22,58 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT MAIN_MENU MENU -{ - POPUP "&File" { - MENUITEM "&New\tCtrl+N", CMD_NEW - MENUITEM "&Open...\tCtrl+O", CMD_OPEN - MENUITEM "&Save\tCtrl+S", CMD_SAVE - MENUITEM "Save &as...", CMD_SAVE_AS - MENUITEM SEPARATOR - MENUITEM "&Print...\tCtrl+P", CMD_PRINT - MENUITEM "Page Se&tup...", CMD_PAGE_SETUP - MENUITEM "P&rinter Setup...", CMD_PRINTER_SETUP - MENUITEM SEPARATOR - MENUITEM "E&xit", CMD_EXIT - } -POPUP "&Edit" { - MENUITEM "&Undo\tCtrl+Z", CMD_UNDO - MENUITEM SEPARATOR - MENUITEM "Cu&t\tCtrl+X", CMD_CUT - MENUITEM "&Copy\tCtrl+C", CMD_COPY - MENUITEM "&Paste\tCtrl+V", CMD_PASTE - MENUITEM "&Delete\tDel", CMD_DELETE - MENUITEM SEPARATOR - MENUITEM "Select &all\tCtrl+A", CMD_SELECT_ALL - MENUITEM "&Time/Date\tF5", CMD_TIME_DATE - MENUITEM SEPARATOR - MENUITEM "&Wrap long lines", CMD_WRAP - MENUITEM "&Font...", CMD_FONT - } -POPUP "&Search" { - MENUITEM "&Search...\tCtrl+F", CMD_SEARCH - MENUITEM "&Search next\tF3", CMD_SEARCH_NEXT - MENUITEM "&Replace...\tCtrl+H", CMD_REPLACE - } -POPUP "&Help" { - MENUITEM "&Contents\tF1", CMD_HELP_CONTENTS - MENUITEM "&About Notepad", CMD_HELP_ABOUT_NOTEPAD - } -} +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New\tCtrl+N", CMD_NEW + MENUITEM "&Open...\tCtrl+O", CMD_OPEN + MENUITEM "&Save\tCtrl+S", CMD_SAVE + MENUITEM "Save &as...", CMD_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "Page Se&tup...", CMD_PAGE_SETUP + MENUITEM "&Print...\tCtrl+P", CMD_PRINT + MENUITEM "P&rinter Setup...", CMD_PRINTER_SETUP + MENUITEM SEPARATOR + MENUITEM "E&xit", CMD_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo\tCtrl+Z", CMD_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\tCtrl+X", CMD_CUT + MENUITEM "&Copy\tCtrl+C", CMD_COPY + MENUITEM "&Paste\tCtrl+V", CMD_PASTE + MENUITEM "&Delete\tDel", CMD_DELETE + MENUITEM SEPARATOR + MENUITEM "&Find...\tCtrl+F", CMD_SEARCH + MENUITEM "Find &next\tF3", CMD_SEARCH_NEXT + MENUITEM "&Replace...\tCtrl+H", CMD_REPLACE + MENUITEM "Go To...\tCtrl+G", CMD_GOTO + MENUITEM SEPARATOR + MENUITEM "Select &all\tCtrl+A", CMD_SELECT_ALL + MENUITEM "&Time/Date\tF5", CMD_TIME_DATE + END + POPUP "F&ormat" + BEGIN + MENUITEM "&Wrap long lines", CMD_WRAP + MENUITEM "&Font...", CMD_FONT + END + POPUP "&View" + BEGIN + MENUITEM "Status&bar", CMD_STATUSBAR + END + POPUP "&Help" + BEGIN + MENUITEM "&Contents", CMD_HELP_CONTENTS + MENUITEM "&Search...", CMD_HELP_SEARCH + MENUITEM "&Help on help", CMD_HELP_ON_HELP + MENUITEM SEPARATOR + MENUITEM "&About", CMD_HELP_ABOUT_NOTEPAD + END +END STRINGTABLE -{ +BEGIN STRING_PAGESETUP_HEADERVALUE, "#msgctxt#do not translate#&f" STRING_PAGESETUP_FOOTERVALUE, "Page &p" @@ -89,13 +101,14 @@ you save this file in the %2 encoding.\n\ To keep these characters, click Cancel, and then select\n\ one of the Unicode options in the Encoding drop down list.\n\ Continue?" -} +STRING_LINE_COLUMN, "Line %d, column %d" +END DIALOG_PAGESETUP DIALOG 0, 0, 240, 95 STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU FONT 8, "MS Shell Dlg" CAPTION "Page Setup" -{ +BEGIN LTEXT "&Header:", 0x140, 10, 07, 68, 15 EDITTEXT IDC_PAGESETUP_HEADERVALUE, 78, 5,110, 12, WS_BORDER | WS_TABSTOP LTEXT "&Footer:", 0x142, 10, 24, 68, 15 @@ -114,7 +127,7 @@ EDITTEXT IDC_PAGESETUP_BOTTOMVALUE, 148, 73, 35, 11, WS_CHILD | WS_BORDER | WS_ DEFPUSHBUTTON "OK", IDOK, 195, 3, 40, 15, WS_TABSTOP PUSHBUTTON "Cancel", IDCANCEL, 195, 21, 40, 15, WS_TABSTOP PUSHBUTTON "&Help", IDHELP, 195, 39, 40, 15, WS_TABSTOP -} +END IDD_OFN_TEMPLATE DIALOG 50,50,300,15 STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER @@ -124,8 +137,20 @@ BEGIN COMBOBOX IDC_OFN_ENCCOMBO, 63,0, 150,48, WS_CHILD | WS_VSCROLL | CBS_DROPDOWNLIST END +/* Dialog 'Go To' */ +DIALOG_GOTO DIALOGEX 0,0,165,50 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +CAPTION "Goto line" +BEGIN +EDITTEXT ID_LINENUMBER,54,10,106,12,WS_CHILD | WS_BORDER | WS_TABSTOP +LTEXT "Line number:",0x155,5,12,41,12,WS_CHILD | WS_TABSTOP | ES_NUMBER +DEFPUSHBUTTON "OK", IDOK, 75, 30, 40, 15, WS_CHILD | WS_TABSTOP +PUSHBUTTON "Cancel", IDCANCEL, 120, 30, 40, 15, WS_CHILD | WS_TABSTOP +END + ID_ACCEL ACCELERATORS -{ +BEGIN "#msgctxt#accelerator Select All#A", CMD_SELECT_ALL, VIRTKEY, CONTROL "#msgctxt#accelerator Copy#C", CMD_COPY, VIRTKEY, CONTROL "#msgctxt#accelerator Find#F", CMD_SEARCH, VIRTKEY, CONTROL @@ -143,7 +168,7 @@ ID_ACCEL ACCELERATORS VK_F5, CMD_TIME_DATE, VIRTKEY VK_INSERT, CMD_COPY, VIRTKEY, CONTROL VK_INSERT, CMD_PASTE, VIRTKEY, SHIFT -} +END LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL diff --git a/programs/notepad/notepad_res.h b/programs/notepad/notepad_res.h index 4fed2f8..60a8a60 100644 --- a/programs/notepad/notepad_res.h +++ b/programs/notepad/notepad_res.h @@ -25,6 +25,8 @@ #define MAIN_MENU 0x201 #define DIALOG_PAGESETUP 0x202 #define ID_ACCEL 0x203 +#define DIALOG_GOTO 0x207 +#define ID_LINENUMBER 0x208 #define IDI_NOTEPAD 0x300 @@ -49,11 +51,17 @@ #define CMD_SEARCH 0x120 #define CMD_SEARCH_NEXT 0x121 #define CMD_REPLACE 0x122 +#define CMD_GOTO 0x123 #define CMD_WRAP 0x119 #define CMD_FONT 0x140 +#define CMD_STATUSBAR 0x150 +#define CMD_STATUSBAR_WND_ID 0x151 + #define CMD_HELP_CONTENTS 0x130 +#define CMD_HELP_SEARCH 0x131 +#define CMD_HELP_ON_HELP 0x132 #define CMD_HELP_ABOUT_NOTEPAD 0x134 /* Control IDs */ @@ -84,6 +92,8 @@ #define STRING_LOSS_OF_UNICODE_CHARACTERS 0x183 +#define STRING_LINE_COLUMN 0x186 + /* Open/Save As dialog template */ #define IDD_OFN_TEMPLATE 0x190 #define IDC_OFN_ENCCOMBO 0x191