1 /* 2 * Notepad (dialog.c) 3 * 4 * Copyright 1998,99 Marcel Baur <mbaur@g26.ethz.ch> 5 * Copyright 2002 Sylvain Petreolle <spetreolle@yahoo.fr> 6 * Copyright 2002 Andriy Palamarchuk 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23 #include "notepad.h" 24 25 #include <assert.h> 26 #include <commctrl.h> 27 #include <strsafe.h> 28 29 LRESULT CALLBACK EDIT_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 30 31 static const TCHAR helpfile[] = _T("notepad.hlp"); 32 static const TCHAR empty_str[] = _T(""); 33 static const TCHAR szDefaultExt[] = _T("txt"); 34 static const TCHAR txt_files[] = _T("*.txt"); 35 36 /* Status bar parts index */ 37 #define SBPART_CURPOS 0 38 #define SBPART_EOLN 1 39 #define SBPART_ENCODING 2 40 41 /* Line endings - string resource ID mapping table */ 42 static UINT EolnToStrId[] = { 43 STRING_CRLF, 44 STRING_LF, 45 STRING_CR 46 }; 47 48 /* Encoding - string resource ID mapping table */ 49 static UINT EncToStrId[] = { 50 STRING_ANSI, 51 STRING_UNICODE, 52 STRING_UNICODE_BE, 53 STRING_UTF8, 54 STRING_UTF8_BOM 55 }; 56 57 static UINT_PTR CALLBACK DIALOG_PAGESETUP_Hook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); 58 59 VOID ShowLastError(VOID) 60 { 61 DWORD error = GetLastError(); 62 if (error != NO_ERROR) 63 { 64 LPTSTR lpMsgBuf = NULL; 65 TCHAR szTitle[MAX_STRING_LEN]; 66 67 LoadString(Globals.hInstance, STRING_ERROR, szTitle, ARRAY_SIZE(szTitle)); 68 69 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 70 NULL, 71 error, 72 0, 73 (LPTSTR) &lpMsgBuf, 74 0, 75 NULL); 76 77 MessageBox(NULL, lpMsgBuf, szTitle, MB_OK | MB_ICONERROR); 78 LocalFree(lpMsgBuf); 79 } 80 } 81 82 /** 83 * Sets the caption of the main window according to Globals.szFileTitle: 84 * (untitled) - Notepad if no file is open 85 * [filename] - Notepad if a file is given 86 */ 87 void UpdateWindowCaption(BOOL clearModifyAlert) 88 { 89 TCHAR szCaption[MAX_STRING_LEN]; 90 TCHAR szNotepad[MAX_STRING_LEN]; 91 TCHAR szFilename[MAX_STRING_LEN]; 92 BOOL isModified; 93 94 if (clearModifyAlert) 95 { 96 /* When a file is being opened or created, there is no need to have 97 * the edited flag shown when the file has not been edited yet. */ 98 isModified = FALSE; 99 } 100 else 101 { 102 /* Check whether the user has modified the file or not. If we are 103 * in the same state as before, don't change the caption. */ 104 isModified = !!SendMessage(Globals.hEdit, EM_GETMODIFY, 0, 0); 105 if (isModified == Globals.bWasModified) 106 return; 107 } 108 109 /* Remember the state for later calls */ 110 Globals.bWasModified = isModified; 111 112 /* Load the name of the application */ 113 LoadString(Globals.hInstance, STRING_NOTEPAD, szNotepad, ARRAY_SIZE(szNotepad)); 114 115 /* Determine if the file has been saved or if this is a new file */ 116 if (Globals.szFileTitle[0] != 0) 117 StringCchCopy(szFilename, ARRAY_SIZE(szFilename), Globals.szFileTitle); 118 else 119 LoadString(Globals.hInstance, STRING_UNTITLED, szFilename, ARRAY_SIZE(szFilename)); 120 121 /* Update the window caption based upon whether the user has modified the file or not */ 122 StringCbPrintf(szCaption, sizeof(szCaption), _T("%s%s - %s"), 123 (isModified ? _T("*") : _T("")), szFilename, szNotepad); 124 125 SetWindowText(Globals.hMainWnd, szCaption); 126 } 127 128 VOID DIALOG_StatusBarAlignParts(VOID) 129 { 130 static const int defaultWidths[] = {120, 120, 120}; 131 RECT rcStatusBar; 132 int parts[3]; 133 134 GetClientRect(Globals.hStatusBar, &rcStatusBar); 135 136 parts[0] = rcStatusBar.right - (defaultWidths[1] + defaultWidths[2]); 137 parts[1] = rcStatusBar.right - defaultWidths[2]; 138 parts[2] = -1; // the right edge of the status bar 139 140 parts[0] = max(parts[0], defaultWidths[0]); 141 parts[1] = max(parts[1], defaultWidths[0] + defaultWidths[1]); 142 143 SendMessageW(Globals.hStatusBar, SB_SETPARTS, (WPARAM)ARRAY_SIZE(parts), (LPARAM)parts); 144 } 145 146 static VOID DIALOG_StatusBarUpdateLineEndings(VOID) 147 { 148 WCHAR szText[128]; 149 150 LoadStringW(Globals.hInstance, EolnToStrId[Globals.iEoln], szText, ARRAY_SIZE(szText)); 151 152 SendMessageW(Globals.hStatusBar, SB_SETTEXTW, SBPART_EOLN, (LPARAM)szText); 153 } 154 155 static VOID DIALOG_StatusBarUpdateEncoding(VOID) 156 { 157 WCHAR szText[128] = L""; 158 159 if (Globals.encFile != ENCODING_AUTO) 160 { 161 LoadStringW(Globals.hInstance, EncToStrId[Globals.encFile], szText, ARRAY_SIZE(szText)); 162 } 163 164 SendMessageW(Globals.hStatusBar, SB_SETTEXTW, SBPART_ENCODING, (LPARAM)szText); 165 } 166 167 int DIALOG_StringMsgBox(HWND hParent, int formatId, LPCTSTR szString, DWORD dwFlags) 168 { 169 TCHAR szMessage[MAX_STRING_LEN]; 170 TCHAR szResource[MAX_STRING_LEN]; 171 172 /* Load and format szMessage */ 173 LoadString(Globals.hInstance, formatId, szResource, ARRAY_SIZE(szResource)); 174 _sntprintf(szMessage, ARRAY_SIZE(szMessage), szResource, szString); 175 176 /* Load szCaption */ 177 if ((dwFlags & MB_ICONMASK) == MB_ICONEXCLAMATION) 178 LoadString(Globals.hInstance, STRING_ERROR, szResource, ARRAY_SIZE(szResource)); 179 else 180 LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, ARRAY_SIZE(szResource)); 181 182 /* Display Modal Dialog */ 183 // if (hParent == NULL) 184 // hParent = Globals.hMainWnd; 185 return MessageBox(hParent, szMessage, szResource, dwFlags); 186 } 187 188 static void AlertFileNotFound(LPCTSTR szFileName) 189 { 190 DIALOG_StringMsgBox(Globals.hMainWnd, STRING_NOTFOUND, szFileName, MB_ICONEXCLAMATION | MB_OK); 191 } 192 193 static int AlertFileNotSaved(LPCTSTR szFileName) 194 { 195 TCHAR szUntitled[MAX_STRING_LEN]; 196 197 LoadString(Globals.hInstance, STRING_UNTITLED, szUntitled, ARRAY_SIZE(szUntitled)); 198 199 return DIALOG_StringMsgBox(Globals.hMainWnd, STRING_NOTSAVED, 200 szFileName[0] ? szFileName : szUntitled, 201 MB_ICONQUESTION | MB_YESNOCANCEL); 202 } 203 204 static void AlertPrintError(void) 205 { 206 TCHAR szUntitled[MAX_STRING_LEN]; 207 208 LoadString(Globals.hInstance, STRING_UNTITLED, szUntitled, ARRAY_SIZE(szUntitled)); 209 210 DIALOG_StringMsgBox(Globals.hMainWnd, STRING_PRINTERROR, 211 Globals.szFileName[0] ? Globals.szFileName : szUntitled, 212 MB_ICONEXCLAMATION | MB_OK); 213 } 214 215 /** 216 * Returns: 217 * TRUE - if file exists 218 * FALSE - if file does not exist 219 */ 220 BOOL FileExists(LPCTSTR szFilename) 221 { 222 WIN32_FIND_DATA entry; 223 HANDLE hFile; 224 225 hFile = FindFirstFile(szFilename, &entry); 226 FindClose(hFile); 227 228 return (hFile != INVALID_HANDLE_VALUE); 229 } 230 231 BOOL HasFileExtension(LPCTSTR szFilename) 232 { 233 LPCTSTR s; 234 235 s = _tcsrchr(szFilename, _T('\\')); 236 if (s) 237 szFilename = s; 238 return _tcsrchr(szFilename, _T('.')) != NULL; 239 } 240 241 int GetSelectionTextLength(HWND hWnd) 242 { 243 DWORD dwStart = 0; 244 DWORD dwEnd = 0; 245 246 SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd); 247 248 return dwEnd - dwStart; 249 } 250 251 int GetSelectionText(HWND hWnd, LPTSTR lpString, int nMaxCount) 252 { 253 DWORD dwStart = 0; 254 DWORD dwEnd = 0; 255 DWORD dwSize; 256 HRESULT hResult; 257 LPTSTR lpTemp; 258 259 if (!lpString) 260 { 261 return 0; 262 } 263 264 SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd); 265 266 if (dwStart == dwEnd) 267 { 268 return 0; 269 } 270 271 dwSize = GetWindowTextLength(hWnd) + 1; 272 lpTemp = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(TCHAR)); 273 if (!lpTemp) 274 { 275 return 0; 276 } 277 278 dwSize = GetWindowText(hWnd, lpTemp, dwSize); 279 280 if (!dwSize) 281 { 282 HeapFree(GetProcessHeap(), 0, lpTemp); 283 return 0; 284 } 285 286 hResult = StringCchCopyN(lpString, nMaxCount, lpTemp + dwStart, dwEnd - dwStart); 287 HeapFree(GetProcessHeap(), 0, lpTemp); 288 289 switch (hResult) 290 { 291 case S_OK: 292 { 293 return dwEnd - dwStart; 294 } 295 296 case STRSAFE_E_INSUFFICIENT_BUFFER: 297 { 298 return nMaxCount - 1; 299 } 300 301 default: 302 { 303 return 0; 304 } 305 } 306 } 307 308 static RECT 309 GetPrintingRect(HDC hdc, RECT margins) 310 { 311 int iLogPixelsX, iLogPixelsY; 312 int iHorzRes, iVertRes; 313 int iPhysPageX, iPhysPageY, iPhysPageW, iPhysPageH; 314 RECT rcPrintRect; 315 316 iPhysPageX = GetDeviceCaps(hdc, PHYSICALOFFSETX); 317 iPhysPageY = GetDeviceCaps(hdc, PHYSICALOFFSETY); 318 iPhysPageW = GetDeviceCaps(hdc, PHYSICALWIDTH); 319 iPhysPageH = GetDeviceCaps(hdc, PHYSICALHEIGHT); 320 iLogPixelsX = GetDeviceCaps(hdc, LOGPIXELSX); 321 iLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY); 322 iHorzRes = GetDeviceCaps(hdc, HORZRES); 323 iVertRes = GetDeviceCaps(hdc, VERTRES); 324 325 rcPrintRect.left = (margins.left * iLogPixelsX / 2540) - iPhysPageX; 326 rcPrintRect.top = (margins.top * iLogPixelsY / 2540) - iPhysPageY; 327 rcPrintRect.right = iHorzRes - (((margins.left * iLogPixelsX / 2540) - iPhysPageX) + ((margins.right * iLogPixelsX / 2540) - (iPhysPageW - iPhysPageX - iHorzRes))); 328 rcPrintRect.bottom = iVertRes - (((margins.top * iLogPixelsY / 2540) - iPhysPageY) + ((margins.bottom * iLogPixelsY / 2540) - (iPhysPageH - iPhysPageY - iVertRes))); 329 330 return rcPrintRect; 331 } 332 333 static BOOL DoSaveFile(VOID) 334 { 335 BOOL bRet = TRUE; 336 HANDLE hFile; 337 LPTSTR pTemp; 338 DWORD size; 339 340 hFile = CreateFile(Globals.szFileName, GENERIC_WRITE, FILE_SHARE_WRITE, 341 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 342 if(hFile == INVALID_HANDLE_VALUE) 343 { 344 ShowLastError(); 345 return FALSE; 346 } 347 348 size = GetWindowTextLength(Globals.hEdit) + 1; 349 pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*pTemp)); 350 if (!pTemp) 351 { 352 CloseHandle(hFile); 353 ShowLastError(); 354 return FALSE; 355 } 356 size = GetWindowText(Globals.hEdit, pTemp, size); 357 358 if (size) 359 { 360 if (!WriteText(hFile, (LPWSTR)pTemp, size, Globals.encFile, Globals.iEoln)) 361 { 362 ShowLastError(); 363 bRet = FALSE; 364 } 365 else 366 { 367 SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0); 368 bRet = TRUE; 369 } 370 } 371 372 CloseHandle(hFile); 373 HeapFree(GetProcessHeap(), 0, pTemp); 374 375 if (bRet) 376 { 377 SetFileName(Globals.szFileName); 378 } 379 380 return bRet; 381 } 382 383 /** 384 * Returns: 385 * TRUE - User agreed to close (both save/don't save) 386 * FALSE - User cancelled close by selecting "Cancel" 387 */ 388 BOOL DoCloseFile(VOID) 389 { 390 int nResult; 391 392 if (SendMessage(Globals.hEdit, EM_GETMODIFY, 0, 0)) 393 { 394 /* prompt user to save changes */ 395 nResult = AlertFileNotSaved(Globals.szFileName); 396 switch (nResult) 397 { 398 case IDYES: 399 if(!DIALOG_FileSave()) 400 return FALSE; 401 break; 402 403 case IDNO: 404 break; 405 406 case IDCANCEL: 407 return FALSE; 408 409 default: 410 return FALSE; 411 } 412 } 413 414 SetFileName(empty_str); 415 UpdateWindowCaption(TRUE); 416 417 return TRUE; 418 } 419 420 VOID DoOpenFile(LPCTSTR szFileName) 421 { 422 static const TCHAR dotlog[] = _T(".LOG"); 423 HANDLE hFile; 424 LPTSTR pszText = NULL; 425 DWORD dwTextLen; 426 TCHAR log[5]; 427 428 /* Close any files and prompt to save changes */ 429 if (!DoCloseFile()) 430 return; 431 432 hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 433 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 434 if (hFile == INVALID_HANDLE_VALUE) 435 { 436 ShowLastError(); 437 goto done; 438 } 439 440 if (!ReadText(hFile, (LPWSTR *)&pszText, &dwTextLen, &Globals.encFile, &Globals.iEoln)) 441 { 442 ShowLastError(); 443 goto done; 444 } 445 SetWindowText(Globals.hEdit, pszText); 446 447 SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0); 448 SendMessage(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0); 449 SetFocus(Globals.hEdit); 450 451 /* If the file starts with .LOG, add a time/date at the end and set cursor after 452 * See http://support.microsoft.com/?kbid=260563 453 */ 454 if (GetWindowText(Globals.hEdit, log, ARRAY_SIZE(log)) && !_tcscmp(log, dotlog)) 455 { 456 static const TCHAR lf[] = _T("\r\n"); 457 SendMessage(Globals.hEdit, EM_SETSEL, GetWindowTextLength(Globals.hEdit), -1); 458 SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)lf); 459 DIALOG_EditTimeDate(); 460 SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)lf); 461 } 462 463 SetFileName(szFileName); 464 UpdateWindowCaption(TRUE); 465 NOTEPAD_EnableSearchMenu(); 466 467 /* Update line endings and encoding on the status bar */ 468 DIALOG_StatusBarUpdateLineEndings(); 469 DIALOG_StatusBarUpdateEncoding(); 470 471 done: 472 if (hFile != INVALID_HANDLE_VALUE) 473 CloseHandle(hFile); 474 if (pszText) 475 HeapFree(GetProcessHeap(), 0, pszText); 476 } 477 478 VOID DIALOG_FileNew(VOID) 479 { 480 /* Close any files and prompt to save changes */ 481 if (DoCloseFile()) { 482 SetWindowText(Globals.hEdit, empty_str); 483 SendMessage(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0); 484 SetFocus(Globals.hEdit); 485 NOTEPAD_EnableSearchMenu(); 486 } 487 } 488 489 VOID DIALOG_FileNewWindow(VOID) 490 { 491 TCHAR pszNotepadExe[MAX_PATH]; 492 GetModuleFileName(NULL, pszNotepadExe, ARRAYSIZE(pszNotepadExe)); 493 ShellExecute(NULL, NULL, pszNotepadExe, NULL, NULL, SW_SHOWNORMAL); 494 } 495 496 VOID DIALOG_FileOpen(VOID) 497 { 498 OPENFILENAME openfilename; 499 TCHAR szPath[MAX_PATH]; 500 501 ZeroMemory(&openfilename, sizeof(openfilename)); 502 503 if (Globals.szFileName[0] == 0) 504 _tcscpy(szPath, txt_files); 505 else 506 _tcscpy(szPath, Globals.szFileName); 507 508 openfilename.lStructSize = sizeof(openfilename); 509 openfilename.hwndOwner = Globals.hMainWnd; 510 openfilename.hInstance = Globals.hInstance; 511 openfilename.lpstrFilter = Globals.szFilter; 512 openfilename.lpstrFile = szPath; 513 openfilename.nMaxFile = ARRAY_SIZE(szPath); 514 openfilename.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; 515 openfilename.lpstrDefExt = szDefaultExt; 516 517 if (GetOpenFileName(&openfilename)) { 518 if (FileExists(openfilename.lpstrFile)) 519 DoOpenFile(openfilename.lpstrFile); 520 else 521 AlertFileNotFound(openfilename.lpstrFile); 522 } 523 } 524 525 BOOL DIALOG_FileSave(VOID) 526 { 527 if (Globals.szFileName[0] == 0) 528 { 529 return DIALOG_FileSaveAs(); 530 } 531 else if (DoSaveFile()) 532 { 533 UpdateWindowCaption(TRUE); 534 return TRUE; 535 } 536 return FALSE; 537 } 538 539 static UINT_PTR 540 CALLBACK 541 DIALOG_FileSaveAs_Hook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) 542 { 543 TCHAR szText[128]; 544 HWND hCombo; 545 546 UNREFERENCED_PARAMETER(wParam); 547 548 switch(msg) 549 { 550 case WM_INITDIALOG: 551 hCombo = GetDlgItem(hDlg, ID_ENCODING); 552 553 LoadString(Globals.hInstance, STRING_ANSI, szText, ARRAY_SIZE(szText)); 554 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); 555 556 LoadString(Globals.hInstance, STRING_UNICODE, szText, ARRAY_SIZE(szText)); 557 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); 558 559 LoadString(Globals.hInstance, STRING_UNICODE_BE, szText, ARRAY_SIZE(szText)); 560 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); 561 562 LoadString(Globals.hInstance, STRING_UTF8, szText, ARRAY_SIZE(szText)); 563 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); 564 565 LoadString(Globals.hInstance, STRING_UTF8_BOM, szText, ARRAY_SIZE(szText)); 566 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); 567 568 SendMessage(hCombo, CB_SETCURSEL, Globals.encFile, 0); 569 570 hCombo = GetDlgItem(hDlg, ID_EOLN); 571 572 LoadString(Globals.hInstance, STRING_CRLF, szText, ARRAY_SIZE(szText)); 573 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); 574 575 LoadString(Globals.hInstance, STRING_LF, szText, ARRAY_SIZE(szText)); 576 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); 577 578 LoadString(Globals.hInstance, STRING_CR, szText, ARRAY_SIZE(szText)); 579 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText); 580 581 SendMessage(hCombo, CB_SETCURSEL, Globals.iEoln, 0); 582 break; 583 584 case WM_NOTIFY: 585 if (((NMHDR *) lParam)->code == CDN_FILEOK) 586 { 587 hCombo = GetDlgItem(hDlg, ID_ENCODING); 588 if (hCombo) 589 Globals.encFile = (ENCODING) SendMessage(hCombo, CB_GETCURSEL, 0, 0); 590 591 hCombo = GetDlgItem(hDlg, ID_EOLN); 592 if (hCombo) 593 Globals.iEoln = (int) SendMessage(hCombo, CB_GETCURSEL, 0, 0); 594 } 595 break; 596 } 597 return 0; 598 } 599 600 BOOL DIALOG_FileSaveAs(VOID) 601 { 602 OPENFILENAME saveas; 603 TCHAR szPath[MAX_PATH]; 604 605 ZeroMemory(&saveas, sizeof(saveas)); 606 607 if (Globals.szFileName[0] == 0) 608 _tcscpy(szPath, txt_files); 609 else 610 _tcscpy(szPath, Globals.szFileName); 611 612 saveas.lStructSize = sizeof(OPENFILENAME); 613 saveas.hwndOwner = Globals.hMainWnd; 614 saveas.hInstance = Globals.hInstance; 615 saveas.lpstrFilter = Globals.szFilter; 616 saveas.lpstrFile = szPath; 617 saveas.nMaxFile = ARRAY_SIZE(szPath); 618 saveas.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | 619 OFN_EXPLORER | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK; 620 saveas.lpstrDefExt = szDefaultExt; 621 saveas.lpTemplateName = MAKEINTRESOURCE(DIALOG_ENCODING); 622 saveas.lpfnHook = DIALOG_FileSaveAs_Hook; 623 624 if (GetSaveFileName(&saveas)) 625 { 626 /* HACK: Because in ROS, Save-As boxes don't check the validity 627 * of file names and thus, here, szPath can be invalid !! We only 628 * see its validity when we call DoSaveFile()... */ 629 SetFileName(szPath); 630 if (DoSaveFile()) 631 { 632 UpdateWindowCaption(TRUE); 633 634 /* Update line endings and encoding on the status bar */ 635 DIALOG_StatusBarUpdateLineEndings(); 636 DIALOG_StatusBarUpdateEncoding(); 637 638 return TRUE; 639 } 640 else 641 { 642 SetFileName(_T("")); 643 return FALSE; 644 } 645 } 646 else 647 { 648 return FALSE; 649 } 650 } 651 652 VOID DIALOG_FilePrint(VOID) 653 { 654 DOCINFO di; 655 TEXTMETRIC tm; 656 PRINTDLG printer; 657 SIZE szMetric; 658 int border; 659 int xLeft, yTop, pagecount, dopage, copycount; 660 unsigned int i; 661 LOGFONT hdrFont; 662 HFONT font, old_font=0; 663 DWORD size; 664 LPTSTR pTemp; 665 static const TCHAR times_new_roman[] = _T("Times New Roman"); 666 RECT rcPrintRect; 667 668 /* Get a small font and print some header info on each page */ 669 ZeroMemory(&hdrFont, sizeof(hdrFont)); 670 hdrFont.lfHeight = 100; 671 hdrFont.lfWeight = FW_BOLD; 672 hdrFont.lfCharSet = ANSI_CHARSET; 673 hdrFont.lfOutPrecision = OUT_DEFAULT_PRECIS; 674 hdrFont.lfClipPrecision = CLIP_DEFAULT_PRECIS; 675 hdrFont.lfQuality = PROOF_QUALITY; 676 hdrFont.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN; 677 _tcscpy(hdrFont.lfFaceName, times_new_roman); 678 679 font = CreateFontIndirect(&hdrFont); 680 681 /* Get Current Settings */ 682 ZeroMemory(&printer, sizeof(printer)); 683 printer.lStructSize = sizeof(printer); 684 printer.hwndOwner = Globals.hMainWnd; 685 printer.hInstance = Globals.hInstance; 686 687 /* Set some default flags */ 688 printer.Flags = PD_RETURNDC | PD_SELECTION; 689 690 /* Disable the selection radio button if there is no text selected */ 691 if (!GetSelectionTextLength(Globals.hEdit)) 692 { 693 printer.Flags = printer.Flags | PD_NOSELECTION; 694 } 695 696 printer.nFromPage = 0; 697 printer.nMinPage = 1; 698 /* we really need to calculate number of pages to set nMaxPage and nToPage */ 699 printer.nToPage = (WORD)-1; 700 printer.nMaxPage = (WORD)-1; 701 702 /* Let commdlg manage copy settings */ 703 printer.nCopies = (WORD)PD_USEDEVMODECOPIES; 704 705 printer.hDevMode = Globals.hDevMode; 706 printer.hDevNames = Globals.hDevNames; 707 708 if (!PrintDlg(&printer)) 709 { 710 DeleteObject(font); 711 return; 712 } 713 714 Globals.hDevMode = printer.hDevMode; 715 Globals.hDevNames = printer.hDevNames; 716 717 assert(printer.hDC != 0); 718 719 /* initialize DOCINFO */ 720 di.cbSize = sizeof(DOCINFO); 721 di.lpszDocName = Globals.szFileTitle; 722 di.lpszOutput = NULL; 723 di.lpszDatatype = NULL; 724 di.fwType = 0; 725 726 if (StartDoc(printer.hDC, &di) <= 0) 727 { 728 DeleteObject(font); 729 return; 730 } 731 732 733 /* Get the file text */ 734 if (printer.Flags & PD_SELECTION) 735 { 736 size = GetSelectionTextLength(Globals.hEdit) + 1; 737 } 738 else 739 { 740 size = GetWindowTextLength(Globals.hEdit) + 1; 741 } 742 743 pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(TCHAR)); 744 if (!pTemp) 745 { 746 EndDoc(printer.hDC); 747 DeleteObject(font); 748 ShowLastError(); 749 return; 750 } 751 752 if (printer.Flags & PD_SELECTION) 753 { 754 size = GetSelectionText(Globals.hEdit, pTemp, size); 755 } 756 else 757 { 758 size = GetWindowText(Globals.hEdit, pTemp, size); 759 } 760 761 /* Get the current printing area */ 762 rcPrintRect = GetPrintingRect(printer.hDC, Globals.lMargins); 763 764 /* Ensure that each logical unit maps to one pixel */ 765 SetMapMode(printer.hDC, MM_TEXT); 766 767 /* Needed to get the correct height of a text line */ 768 GetTextMetrics(printer.hDC, &tm); 769 770 border = 15; 771 for (copycount=1; copycount <= printer.nCopies; copycount++) { 772 i = 0; 773 pagecount = 1; 774 do { 775 /* Don't start a page if none of the conditions below are true */ 776 dopage = 0; 777 778 /* The user wants to print the current selection */ 779 if (printer.Flags & PD_SELECTION) 780 { 781 dopage = 1; 782 } 783 784 /* The user wants to print the entire document */ 785 if (!(printer.Flags & PD_PAGENUMS) && !(printer.Flags & PD_SELECTION)) 786 { 787 dopage = 1; 788 } 789 790 /* The user wants to print a specified range of pages */ 791 if ((pagecount >= printer.nFromPage && pagecount <= printer.nToPage)) 792 { 793 dopage = 1; 794 } 795 796 old_font = SelectObject(printer.hDC, font); 797 798 if (dopage) { 799 if (StartPage(printer.hDC) <= 0) { 800 SelectObject(printer.hDC, old_font); 801 EndDoc(printer.hDC); 802 DeleteDC(printer.hDC); 803 HeapFree(GetProcessHeap(), 0, pTemp); 804 DeleteObject(font); 805 AlertPrintError(); 806 return; 807 } 808 809 SetViewportOrgEx(printer.hDC, rcPrintRect.left, rcPrintRect.top, NULL); 810 811 /* Write a rectangle and header at the top of each page */ 812 Rectangle(printer.hDC, border, border, rcPrintRect.right - border, border + tm.tmHeight * 2); 813 /* I don't know what's up with this TextOut command. This comes out 814 kind of mangled. 815 */ 816 TextOut(printer.hDC, 817 border * 2, 818 border + tm.tmHeight / 2, 819 Globals.szFileTitle, 820 lstrlen(Globals.szFileTitle)); 821 } 822 823 /* The starting point for the main text */ 824 xLeft = 0; 825 yTop = border + tm.tmHeight * 4; 826 827 SelectObject(printer.hDC, old_font); 828 829 /* Since outputting strings is giving me problems, output the main 830 * text one character at a time. */ 831 do { 832 if (pTemp[i] == '\n') { 833 xLeft = 0; 834 yTop += tm.tmHeight; 835 } 836 else if (pTemp[i] != '\r') { 837 if (dopage) 838 TextOut(printer.hDC, xLeft, yTop, &pTemp[i], 1); 839 840 /* We need to get the width for each individual char, since a proportional font may be used */ 841 GetTextExtentPoint32(printer.hDC, &pTemp[i], 1, &szMetric); 842 xLeft += szMetric.cx; 843 844 /* Insert a line break if the current line does not fit into the printing area */ 845 if (xLeft > rcPrintRect.right) 846 { 847 xLeft = 0; 848 yTop = yTop + tm.tmHeight; 849 } 850 } 851 } while (i++ < size && yTop < rcPrintRect.bottom); 852 853 if (dopage) 854 EndPage(printer.hDC); 855 pagecount++; 856 } while (i < size); 857 } 858 859 if (old_font != 0) 860 SelectObject(printer.hDC, old_font); 861 EndDoc(printer.hDC); 862 DeleteDC(printer.hDC); 863 HeapFree(GetProcessHeap(), 0, pTemp); 864 DeleteObject(font); 865 } 866 867 VOID DIALOG_FileExit(VOID) 868 { 869 PostMessage(Globals.hMainWnd, WM_CLOSE, 0, 0l); 870 } 871 872 VOID DIALOG_EditUndo(VOID) 873 { 874 SendMessage(Globals.hEdit, EM_UNDO, 0, 0); 875 } 876 877 VOID DIALOG_EditCut(VOID) 878 { 879 SendMessage(Globals.hEdit, WM_CUT, 0, 0); 880 } 881 882 VOID DIALOG_EditCopy(VOID) 883 { 884 SendMessage(Globals.hEdit, WM_COPY, 0, 0); 885 } 886 887 VOID DIALOG_EditPaste(VOID) 888 { 889 SendMessage(Globals.hEdit, WM_PASTE, 0, 0); 890 } 891 892 VOID DIALOG_EditDelete(VOID) 893 { 894 SendMessage(Globals.hEdit, WM_CLEAR, 0, 0); 895 } 896 897 VOID DIALOG_EditSelectAll(VOID) 898 { 899 SendMessage(Globals.hEdit, EM_SETSEL, 0, (LPARAM)-1); 900 } 901 902 VOID DIALOG_EditTimeDate(VOID) 903 { 904 SYSTEMTIME st; 905 TCHAR szDate[MAX_STRING_LEN]; 906 TCHAR szText[MAX_STRING_LEN * 2 + 2]; 907 908 GetLocalTime(&st); 909 910 GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, szDate, MAX_STRING_LEN); 911 _tcscpy(szText, szDate); 912 _tcscat(szText, _T(" ")); 913 GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szDate, MAX_STRING_LEN); 914 _tcscat(szText, szDate); 915 SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)szText); 916 } 917 918 VOID DoCreateStatusBar(VOID) 919 { 920 RECT rc; 921 RECT rcstatus; 922 BOOL bStatusBarVisible; 923 924 /* Check if status bar object already exists. */ 925 if (Globals.hStatusBar == NULL) 926 { 927 /* Try to create the status bar */ 928 Globals.hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, 929 NULL, 930 Globals.hMainWnd, 931 CMD_STATUSBAR_WND_ID); 932 933 if (Globals.hStatusBar == NULL) 934 { 935 ShowLastError(); 936 return; 937 } 938 939 /* Load the string for formatting column/row text output */ 940 LoadString(Globals.hInstance, STRING_LINE_COLUMN, Globals.szStatusBarLineCol, MAX_PATH - 1); 941 } 942 943 /* Set status bar visiblity according to the settings. */ 944 if ((Globals.bWrapLongLines != FALSE) || (Globals.bShowStatusBar == FALSE)) 945 { 946 bStatusBarVisible = FALSE; 947 ShowWindow(Globals.hStatusBar, SW_HIDE); 948 } 949 else 950 { 951 bStatusBarVisible = TRUE; 952 ShowWindow(Globals.hStatusBar, SW_SHOW); 953 SendMessage(Globals.hStatusBar, WM_SIZE, 0, 0); 954 } 955 956 /* Set check state in show status bar item. */ 957 if (bStatusBarVisible) 958 { 959 CheckMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_CHECKED); 960 } 961 else 962 { 963 CheckMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_UNCHECKED); 964 } 965 966 /* Update menu mar with the previous changes */ 967 DrawMenuBar(Globals.hMainWnd); 968 969 /* Sefety test is edit control exists */ 970 if (Globals.hEdit != NULL) 971 { 972 /* Retrieve the sizes of the controls */ 973 GetClientRect(Globals.hMainWnd, &rc); 974 GetClientRect(Globals.hStatusBar, &rcstatus); 975 976 /* If status bar is currently visible, update dimensions of edit control */ 977 if (bStatusBarVisible) 978 rc.bottom -= (rcstatus.bottom - rcstatus.top); 979 980 /* Resize edit control to right size. */ 981 MoveWindow(Globals.hEdit, 982 rc.left, 983 rc.top, 984 rc.right - rc.left, 985 rc.bottom - rc.top, 986 TRUE); 987 } 988 989 /* Set the status bar for multiple-text output */ 990 DIALOG_StatusBarAlignParts(); 991 992 /* Update content with current row/column text */ 993 DIALOG_StatusBarUpdateCaretPos(); 994 995 /* Update line endings and encoding on the status bar */ 996 DIALOG_StatusBarUpdateLineEndings(); 997 DIALOG_StatusBarUpdateEncoding(); 998 } 999 1000 VOID DoCreateEditWindow(VOID) 1001 { 1002 DWORD dwStyle; 1003 int iSize; 1004 LPTSTR pTemp = NULL; 1005 BOOL bModified = FALSE; 1006 1007 iSize = 0; 1008 1009 /* If the edit control already exists, try to save its content */ 1010 if (Globals.hEdit != NULL) 1011 { 1012 /* number of chars currently written into the editor. */ 1013 iSize = GetWindowTextLength(Globals.hEdit); 1014 if (iSize) 1015 { 1016 /* Allocates temporary buffer. */ 1017 pTemp = HeapAlloc(GetProcessHeap(), 0, (iSize + 1) * sizeof(TCHAR)); 1018 if (!pTemp) 1019 { 1020 ShowLastError(); 1021 return; 1022 } 1023 1024 /* Recover the text into the control. */ 1025 GetWindowText(Globals.hEdit, pTemp, iSize + 1); 1026 1027 if (SendMessage(Globals.hEdit, EM_GETMODIFY, 0, 0)) 1028 bModified = TRUE; 1029 } 1030 1031 /* Restore original window procedure */ 1032 SetWindowLongPtr(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)Globals.EditProc); 1033 1034 /* Destroy the edit control */ 1035 DestroyWindow(Globals.hEdit); 1036 } 1037 1038 /* Update wrap status into the main menu and recover style flags */ 1039 if (Globals.bWrapLongLines) 1040 { 1041 dwStyle = EDIT_STYLE_WRAP; 1042 EnableMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); 1043 } else { 1044 dwStyle = EDIT_STYLE; 1045 EnableMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_ENABLED); 1046 } 1047 1048 /* Update previous changes */ 1049 DrawMenuBar(Globals.hMainWnd); 1050 1051 /* Create the new edit control */ 1052 Globals.hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, 1053 EDIT_CLASS, 1054 NULL, 1055 dwStyle, 1056 CW_USEDEFAULT, 1057 CW_USEDEFAULT, 1058 CW_USEDEFAULT, 1059 CW_USEDEFAULT, 1060 Globals.hMainWnd, 1061 NULL, 1062 Globals.hInstance, 1063 NULL); 1064 1065 if (Globals.hEdit == NULL) 1066 { 1067 if (pTemp) 1068 { 1069 HeapFree(GetProcessHeap(), 0, pTemp); 1070 } 1071 1072 ShowLastError(); 1073 return; 1074 } 1075 1076 SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, FALSE); 1077 SendMessage(Globals.hEdit, EM_LIMITTEXT, 0, 0); 1078 1079 /* If some text was previously saved, restore it. */ 1080 if (iSize != 0) 1081 { 1082 SetWindowText(Globals.hEdit, pTemp); 1083 HeapFree(GetProcessHeap(), 0, pTemp); 1084 1085 if (bModified) 1086 SendMessage(Globals.hEdit, EM_SETMODIFY, TRUE, 0); 1087 } 1088 1089 /* Sub-class a new window callback for row/column detection. */ 1090 Globals.EditProc = (WNDPROC)SetWindowLongPtr(Globals.hEdit, 1091 GWLP_WNDPROC, 1092 (LONG_PTR)EDIT_WndProc); 1093 1094 /* Create/update status bar */ 1095 DoCreateStatusBar(); 1096 1097 /* Finally shows new edit control and set focus into it. */ 1098 ShowWindow(Globals.hEdit, SW_SHOW); 1099 SetFocus(Globals.hEdit); 1100 } 1101 1102 VOID DIALOG_EditWrap(VOID) 1103 { 1104 Globals.bWrapLongLines = !Globals.bWrapLongLines; 1105 1106 if (Globals.bWrapLongLines) 1107 { 1108 EnableMenuItem(Globals.hMenu, CMD_GOTO, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); 1109 } 1110 else 1111 { 1112 EnableMenuItem(Globals.hMenu, CMD_GOTO, MF_BYCOMMAND | MF_ENABLED); 1113 } 1114 1115 DoCreateEditWindow(); 1116 } 1117 1118 VOID DIALOG_SelectFont(VOID) 1119 { 1120 CHOOSEFONT cf; 1121 LOGFONT lf = Globals.lfFont; 1122 1123 ZeroMemory( &cf, sizeof(cf) ); 1124 cf.lStructSize = sizeof(cf); 1125 cf.hwndOwner = Globals.hMainWnd; 1126 cf.lpLogFont = &lf; 1127 cf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT | CF_NOVERTFONTS; 1128 1129 if (ChooseFont(&cf)) 1130 { 1131 HFONT currfont = Globals.hFont; 1132 1133 Globals.hFont = CreateFontIndirect(&lf); 1134 Globals.lfFont = lf; 1135 SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, (LPARAM)TRUE); 1136 if (currfont != NULL) 1137 DeleteObject(currfont); 1138 } 1139 } 1140 1141 typedef HWND (WINAPI *FINDPROC)(LPFINDREPLACE lpfr); 1142 1143 static VOID DIALOG_SearchDialog(FINDPROC pfnProc) 1144 { 1145 if (Globals.hFindReplaceDlg != NULL) 1146 { 1147 SetFocus(Globals.hFindReplaceDlg); 1148 return; 1149 } 1150 1151 ZeroMemory(&Globals.find, sizeof(Globals.find)); 1152 Globals.find.lStructSize = sizeof(Globals.find); 1153 Globals.find.hwndOwner = Globals.hMainWnd; 1154 Globals.find.hInstance = Globals.hInstance; 1155 Globals.find.lpstrFindWhat = Globals.szFindText; 1156 Globals.find.wFindWhatLen = ARRAY_SIZE(Globals.szFindText); 1157 Globals.find.lpstrReplaceWith = Globals.szReplaceText; 1158 Globals.find.wReplaceWithLen = ARRAY_SIZE(Globals.szReplaceText); 1159 Globals.find.Flags = FR_DOWN; 1160 1161 /* We only need to create the modal FindReplace dialog which will */ 1162 /* notify us of incoming events using hMainWnd Window Messages */ 1163 1164 Globals.hFindReplaceDlg = pfnProc(&Globals.find); 1165 assert(Globals.hFindReplaceDlg != NULL); 1166 } 1167 1168 VOID DIALOG_Search(VOID) 1169 { 1170 DIALOG_SearchDialog(FindText); 1171 } 1172 1173 VOID DIALOG_SearchNext(VOID) 1174 { 1175 if (Globals.find.lpstrFindWhat != NULL) 1176 NOTEPAD_FindNext(&Globals.find, FALSE, TRUE); 1177 else 1178 DIALOG_Search(); 1179 } 1180 1181 VOID DIALOG_Replace(VOID) 1182 { 1183 DIALOG_SearchDialog(ReplaceText); 1184 } 1185 1186 static INT_PTR 1187 CALLBACK 1188 DIALOG_GoTo_DialogProc(HWND hwndDialog, UINT uMsg, WPARAM wParam, LPARAM lParam) 1189 { 1190 BOOL bResult = FALSE; 1191 HWND hTextBox; 1192 TCHAR szText[32]; 1193 1194 switch(uMsg) { 1195 case WM_INITDIALOG: 1196 hTextBox = GetDlgItem(hwndDialog, ID_LINENUMBER); 1197 _sntprintf(szText, ARRAY_SIZE(szText), _T("%Id"), lParam); 1198 SetWindowText(hTextBox, szText); 1199 break; 1200 case WM_COMMAND: 1201 if (HIWORD(wParam) == BN_CLICKED) 1202 { 1203 if (LOWORD(wParam) == IDOK) 1204 { 1205 hTextBox = GetDlgItem(hwndDialog, ID_LINENUMBER); 1206 GetWindowText(hTextBox, szText, ARRAY_SIZE(szText)); 1207 EndDialog(hwndDialog, _ttoi(szText)); 1208 bResult = TRUE; 1209 } 1210 else if (LOWORD(wParam) == IDCANCEL) 1211 { 1212 EndDialog(hwndDialog, 0); 1213 bResult = TRUE; 1214 } 1215 } 1216 break; 1217 } 1218 1219 return bResult; 1220 } 1221 1222 VOID DIALOG_GoTo(VOID) 1223 { 1224 INT_PTR nLine; 1225 LPTSTR pszText; 1226 int nLength, i; 1227 DWORD dwStart, dwEnd; 1228 1229 nLength = GetWindowTextLength(Globals.hEdit); 1230 pszText = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(*pszText)); 1231 if (!pszText) 1232 return; 1233 1234 /* Retrieve current text */ 1235 GetWindowText(Globals.hEdit, pszText, nLength + 1); 1236 SendMessage(Globals.hEdit, EM_GETSEL, (WPARAM) &dwStart, (LPARAM) &dwEnd); 1237 1238 nLine = 1; 1239 for (i = 0; (i < (int) dwStart) && pszText[i]; i++) 1240 { 1241 if (pszText[i] == '\n') 1242 nLine++; 1243 } 1244 1245 nLine = DialogBoxParam(Globals.hInstance, 1246 MAKEINTRESOURCE(DIALOG_GOTO), 1247 Globals.hMainWnd, 1248 DIALOG_GoTo_DialogProc, 1249 nLine); 1250 1251 if (nLine >= 1) 1252 { 1253 for (i = 0; pszText[i] && (nLine > 1) && (i < nLength - 1); i++) 1254 { 1255 if (pszText[i] == '\n') 1256 nLine--; 1257 } 1258 SendMessage(Globals.hEdit, EM_SETSEL, i, i); 1259 SendMessage(Globals.hEdit, EM_SCROLLCARET, 0, 0); 1260 } 1261 HeapFree(GetProcessHeap(), 0, pszText); 1262 } 1263 1264 VOID DIALOG_StatusBarUpdateCaretPos(VOID) 1265 { 1266 int line, col; 1267 TCHAR buff[MAX_PATH]; 1268 DWORD dwStart, dwSize; 1269 1270 SendMessage(Globals.hEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwSize); 1271 line = SendMessage(Globals.hEdit, EM_LINEFROMCHAR, (WPARAM)dwStart, 0); 1272 col = dwStart - SendMessage(Globals.hEdit, EM_LINEINDEX, (WPARAM)line, 0); 1273 1274 _stprintf(buff, Globals.szStatusBarLineCol, line + 1, col + 1); 1275 SendMessage(Globals.hStatusBar, SB_SETTEXT, SBPART_CURPOS, (LPARAM)buff); 1276 } 1277 1278 VOID DIALOG_ViewStatusBar(VOID) 1279 { 1280 Globals.bShowStatusBar = !Globals.bShowStatusBar; 1281 1282 DoCreateStatusBar(); 1283 } 1284 1285 VOID DIALOG_HelpContents(VOID) 1286 { 1287 WinHelp(Globals.hMainWnd, helpfile, HELP_INDEX, 0); 1288 } 1289 1290 VOID DIALOG_HelpAboutNotepad(VOID) 1291 { 1292 TCHAR szNotepad[MAX_STRING_LEN]; 1293 TCHAR szNotepadAuthors[MAX_STRING_LEN]; 1294 1295 HICON notepadIcon = LoadIcon(Globals.hInstance, MAKEINTRESOURCE(IDI_NPICON)); 1296 1297 LoadString(Globals.hInstance, STRING_NOTEPAD, szNotepad, ARRAY_SIZE(szNotepad)); 1298 LoadString(Globals.hInstance, STRING_NOTEPAD_AUTHORS, szNotepadAuthors, ARRAY_SIZE(szNotepadAuthors)); 1299 1300 ShellAbout(Globals.hMainWnd, szNotepad, szNotepadAuthors, notepadIcon); 1301 DeleteObject(notepadIcon); 1302 } 1303 1304 /*********************************************************************** 1305 * 1306 * DIALOG_FilePageSetup 1307 */ 1308 VOID DIALOG_FilePageSetup(void) 1309 { 1310 PAGESETUPDLG page; 1311 1312 ZeroMemory(&page, sizeof(page)); 1313 page.lStructSize = sizeof(page); 1314 page.hwndOwner = Globals.hMainWnd; 1315 page.Flags = PSD_ENABLEPAGESETUPTEMPLATE | PSD_ENABLEPAGESETUPHOOK | PSD_MARGINS; 1316 page.hInstance = Globals.hInstance; 1317 page.rtMargin = Globals.lMargins; 1318 page.hDevMode = Globals.hDevMode; 1319 page.hDevNames = Globals.hDevNames; 1320 page.lpPageSetupTemplateName = MAKEINTRESOURCE(DIALOG_PAGESETUP); 1321 page.lpfnPageSetupHook = DIALOG_PAGESETUP_Hook; 1322 1323 PageSetupDlg(&page); 1324 1325 Globals.hDevMode = page.hDevMode; 1326 Globals.hDevNames = page.hDevNames; 1327 Globals.lMargins = page.rtMargin; 1328 } 1329 1330 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1331 * 1332 * DIALOG_PAGESETUP_Hook 1333 */ 1334 1335 static UINT_PTR CALLBACK DIALOG_PAGESETUP_Hook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) 1336 { 1337 switch (msg) 1338 { 1339 case WM_COMMAND: 1340 if (HIWORD(wParam) == BN_CLICKED) 1341 { 1342 switch (LOWORD(wParam)) 1343 { 1344 case IDOK: 1345 /* save user input and close dialog */ 1346 GetDlgItemText(hDlg, 0x141, Globals.szHeader, ARRAY_SIZE(Globals.szHeader)); 1347 GetDlgItemText(hDlg, 0x143, Globals.szFooter, ARRAY_SIZE(Globals.szFooter)); 1348 return FALSE; 1349 1350 case IDCANCEL: 1351 /* discard user input and close dialog */ 1352 return FALSE; 1353 1354 case IDHELP: 1355 { 1356 /* FIXME: Bring this to work */ 1357 static const TCHAR sorry[] = _T("Sorry, no help available"); 1358 static const TCHAR help[] = _T("Help"); 1359 MessageBox(Globals.hMainWnd, sorry, help, MB_ICONEXCLAMATION); 1360 return TRUE; 1361 } 1362 1363 default: 1364 break; 1365 } 1366 } 1367 break; 1368 1369 case WM_INITDIALOG: 1370 /* fetch last user input prior to display dialog */ 1371 SetDlgItemText(hDlg, 0x141, Globals.szHeader); 1372 SetDlgItemText(hDlg, 0x143, Globals.szFooter); 1373 break; 1374 } 1375 1376 return FALSE; 1377 } 1378