4 * Copyright 1998,99 Marcel Baur <mbaur@g26.ethz.ch>
5 * Copyright 2002 Sylvain Petreolle <spetreolle@yahoo.fr>
6 * Copyright 2002 Andriy Palamarchuk
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.
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.
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
29 LRESULT CALLBACK
EDIT_WndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
);
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");
36 static UINT_PTR CALLBACK
DIALOG_PAGESETUP_Hook(HWND hDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
);
38 VOID
ShowLastError(VOID
)
40 DWORD error
= GetLastError();
41 if (error
!= NO_ERROR
)
43 LPTSTR lpMsgBuf
= NULL
;
44 TCHAR szTitle
[MAX_STRING_LEN
];
46 LoadString(Globals
.hInstance
, STRING_ERROR
, szTitle
, ARRAY_SIZE(szTitle
));
48 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
56 MessageBox(NULL
, lpMsgBuf
, szTitle
, MB_OK
| MB_ICONERROR
);
62 * Sets the caption of the main window according to Globals.szFileTitle:
63 * (untitled) - Notepad if no file is open
64 * [filename] - Notepad if a file is given
66 void UpdateWindowCaption(BOOL clearModifyAlert
)
68 TCHAR szCaption
[MAX_STRING_LEN
];
69 TCHAR szNotepad
[MAX_STRING_LEN
];
70 TCHAR szFilename
[MAX_STRING_LEN
];
72 /* Load the name of the application */
73 LoadString(Globals
.hInstance
, STRING_NOTEPAD
, szNotepad
, ARRAY_SIZE(szNotepad
));
75 /* Determine if the file has been saved or if this is a new file */
76 if (Globals
.szFileTitle
[0] != 0)
77 StringCchCopy(szFilename
, ARRAY_SIZE(szFilename
), Globals
.szFileTitle
);
79 LoadString(Globals
.hInstance
, STRING_UNTITLED
, szFilename
, ARRAY_SIZE(szFilename
));
81 /* When a file is being opened or created, there is no need to have the edited flag shown
82 when the new or opened file has not been edited yet */
84 StringCbPrintf(szCaption
, ARRAY_SIZE(szCaption
), _T("%s - %s"), szFilename
, szNotepad
);
87 BOOL isModified
= (SendMessage(Globals
.hEdit
, EM_GETMODIFY
, 0, 0) ? TRUE
: FALSE
);
89 /* Update the caption based upon if the user has modified the contents of the file or not */
90 StringCbPrintf(szCaption
, ARRAY_SIZE(szCaption
), _T("%s%s - %s"),
91 (isModified
? _T("*") : _T("")), szFilename
, szNotepad
);
94 /* Update the window caption */
95 SetWindowText(Globals
.hMainWnd
, szCaption
);
98 int DIALOG_StringMsgBox(HWND hParent
, int formatId
, LPCTSTR szString
, DWORD dwFlags
)
100 TCHAR szMessage
[MAX_STRING_LEN
];
101 TCHAR szResource
[MAX_STRING_LEN
];
103 /* Load and format szMessage */
104 LoadString(Globals
.hInstance
, formatId
, szResource
, ARRAY_SIZE(szResource
));
105 _sntprintf(szMessage
, ARRAY_SIZE(szMessage
), szResource
, szString
);
108 if ((dwFlags
& MB_ICONMASK
) == MB_ICONEXCLAMATION
)
109 LoadString(Globals
.hInstance
, STRING_ERROR
, szResource
, ARRAY_SIZE(szResource
));
111 LoadString(Globals
.hInstance
, STRING_NOTEPAD
, szResource
, ARRAY_SIZE(szResource
));
113 /* Display Modal Dialog */
114 // if (hParent == NULL)
115 // hParent = Globals.hMainWnd;
116 return MessageBox(hParent
, szMessage
, szResource
, dwFlags
);
119 static void AlertFileNotFound(LPCTSTR szFileName
)
121 DIALOG_StringMsgBox(Globals
.hMainWnd
, STRING_NOTFOUND
, szFileName
, MB_ICONEXCLAMATION
| MB_OK
);
124 static int AlertFileNotSaved(LPCTSTR szFileName
)
126 TCHAR szUntitled
[MAX_STRING_LEN
];
128 LoadString(Globals
.hInstance
, STRING_UNTITLED
, szUntitled
, ARRAY_SIZE(szUntitled
));
130 return DIALOG_StringMsgBox(Globals
.hMainWnd
, STRING_NOTSAVED
,
131 szFileName
[0] ? szFileName
: szUntitled
,
132 MB_ICONQUESTION
| MB_YESNOCANCEL
);
135 static void AlertPrintError(void)
137 TCHAR szUntitled
[MAX_STRING_LEN
];
139 LoadString(Globals
.hInstance
, STRING_UNTITLED
, szUntitled
, ARRAY_SIZE(szUntitled
));
141 DIALOG_StringMsgBox(Globals
.hMainWnd
, STRING_PRINTERROR
,
142 Globals
.szFileName
[0] ? Globals
.szFileName
: szUntitled
,
143 MB_ICONEXCLAMATION
| MB_OK
);
148 * TRUE - if file exists
149 * FALSE - if file does not exist
151 BOOL
FileExists(LPCTSTR szFilename
)
153 WIN32_FIND_DATA entry
;
156 hFile
= FindFirstFile(szFilename
, &entry
);
159 return (hFile
!= INVALID_HANDLE_VALUE
);
162 BOOL
HasFileExtension(LPCTSTR szFilename
)
166 s
= _tcsrchr(szFilename
, _T('\\'));
169 return _tcsrchr(szFilename
, _T('.')) != NULL
;
172 int GetSelectionTextLength(HWND hWnd
)
177 SendMessage(hWnd
, EM_GETSEL
, (WPARAM
)&dwStart
, (LPARAM
)&dwEnd
);
179 return dwEnd
- dwStart
;
182 int GetSelectionText(HWND hWnd
, LPTSTR lpString
, int nMaxCount
)
195 SendMessage(hWnd
, EM_GETSEL
, (WPARAM
)&dwStart
, (LPARAM
)&dwEnd
);
197 if (dwStart
== dwEnd
)
202 dwSize
= GetWindowTextLength(hWnd
) + 1;
203 lpTemp
= HeapAlloc(GetProcessHeap(), 0, dwSize
* sizeof(TCHAR
));
209 dwSize
= GetWindowText(hWnd
, lpTemp
, dwSize
);
213 HeapFree(GetProcessHeap(), 0, lpTemp
);
217 hResult
= StringCchCopyN(lpString
, nMaxCount
, lpTemp
+ dwStart
, dwEnd
- dwStart
);
218 HeapFree(GetProcessHeap(), 0, lpTemp
);
224 return dwEnd
- dwStart
;
227 case STRSAFE_E_INSUFFICIENT_BUFFER
:
229 return nMaxCount
- 1;
240 GetPrintingRect(HDC hdc
, RECT margins
)
242 int iLogPixelsX
, iLogPixelsY
;
243 int iHorzRes
, iVertRes
;
244 int iPhysPageX
, iPhysPageY
, iPhysPageW
, iPhysPageH
;
247 iPhysPageX
= GetDeviceCaps(hdc
, PHYSICALOFFSETX
);
248 iPhysPageY
= GetDeviceCaps(hdc
, PHYSICALOFFSETY
);
249 iPhysPageW
= GetDeviceCaps(hdc
, PHYSICALWIDTH
);
250 iPhysPageH
= GetDeviceCaps(hdc
, PHYSICALHEIGHT
);
251 iLogPixelsX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
252 iLogPixelsY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
253 iHorzRes
= GetDeviceCaps(hdc
, HORZRES
);
254 iVertRes
= GetDeviceCaps(hdc
, VERTRES
);
256 rcPrintRect
.left
= (margins
.left
* iLogPixelsX
/ 2540) - iPhysPageX
;
257 rcPrintRect
.top
= (margins
.top
* iLogPixelsY
/ 2540) - iPhysPageY
;
258 rcPrintRect
.right
= iHorzRes
- (((margins
.left
* iLogPixelsX
/ 2540) - iPhysPageX
) + ((margins
.right
* iLogPixelsX
/ 2540) - (iPhysPageW
- iPhysPageX
- iHorzRes
)));
259 rcPrintRect
.bottom
= iVertRes
- (((margins
.top
* iLogPixelsY
/ 2540) - iPhysPageY
) + ((margins
.bottom
* iLogPixelsY
/ 2540) - (iPhysPageH
- iPhysPageY
- iVertRes
)));
264 static BOOL
DoSaveFile(VOID
)
271 hFile
= CreateFile(Globals
.szFileName
, GENERIC_WRITE
, FILE_SHARE_WRITE
,
272 NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
273 if(hFile
== INVALID_HANDLE_VALUE
)
279 size
= GetWindowTextLength(Globals
.hEdit
) + 1;
280 pTemp
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(*pTemp
));
287 size
= GetWindowText(Globals
.hEdit
, pTemp
, size
);
291 if (!WriteText(hFile
, (LPWSTR
)pTemp
, size
, Globals
.encFile
, Globals
.iEoln
))
298 SendMessage(Globals
.hEdit
, EM_SETMODIFY
, FALSE
, 0);
304 HeapFree(GetProcessHeap(), 0, pTemp
);
310 * TRUE - User agreed to close (both save/don't save)
311 * FALSE - User cancelled close by selecting "Cancel"
313 BOOL
DoCloseFile(VOID
)
317 if (SendMessage(Globals
.hEdit
, EM_GETMODIFY
, 0, 0))
319 /* prompt user to save changes */
320 nResult
= AlertFileNotSaved(Globals
.szFileName
);
324 if(!DIALOG_FileSave())
339 SetFileName(empty_str
);
340 UpdateWindowCaption(TRUE
);
345 VOID
DoOpenFile(LPCTSTR szFileName
)
347 static const TCHAR dotlog
[] = _T(".LOG");
349 LPTSTR pszText
= NULL
;
353 /* Close any files and prompt to save changes */
357 hFile
= CreateFile(szFileName
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
358 OPEN_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
359 if (hFile
== INVALID_HANDLE_VALUE
)
365 if (!ReadText(hFile
, (LPWSTR
*)&pszText
, &dwTextLen
, &Globals
.encFile
, &Globals
.iEoln
))
370 SetWindowText(Globals
.hEdit
, pszText
);
372 SendMessage(Globals
.hEdit
, EM_SETMODIFY
, FALSE
, 0);
373 SendMessage(Globals
.hEdit
, EM_EMPTYUNDOBUFFER
, 0, 0);
374 SetFocus(Globals
.hEdit
);
376 /* If the file starts with .LOG, add a time/date at the end and set cursor after
377 * See http://support.microsoft.com/?kbid=260563
379 if (GetWindowText(Globals
.hEdit
, log
, ARRAY_SIZE(log
)) && !_tcscmp(log
, dotlog
))
381 static const TCHAR lf
[] = _T("\r\n");
382 SendMessage(Globals
.hEdit
, EM_SETSEL
, GetWindowTextLength(Globals
.hEdit
), -1);
383 SendMessage(Globals
.hEdit
, EM_REPLACESEL
, TRUE
, (LPARAM
)lf
);
384 DIALOG_EditTimeDate();
385 SendMessage(Globals
.hEdit
, EM_REPLACESEL
, TRUE
, (LPARAM
)lf
);
388 SetFileName(szFileName
);
389 UpdateWindowCaption(TRUE
);
390 NOTEPAD_EnableSearchMenu();
392 if (hFile
!= INVALID_HANDLE_VALUE
)
395 HeapFree(GetProcessHeap(), 0, pszText
);
398 VOID
DIALOG_FileNew(VOID
)
400 /* Close any files and prompt to save changes */
402 SetWindowText(Globals
.hEdit
, empty_str
);
403 SendMessage(Globals
.hEdit
, EM_EMPTYUNDOBUFFER
, 0, 0);
404 SetFocus(Globals
.hEdit
);
405 NOTEPAD_EnableSearchMenu();
409 VOID
DIALOG_FileOpen(VOID
)
411 OPENFILENAME openfilename
;
412 TCHAR szPath
[MAX_PATH
];
414 ZeroMemory(&openfilename
, sizeof(openfilename
));
416 if (Globals
.szFileName
[0] == 0)
417 _tcscpy(szPath
, txt_files
);
419 _tcscpy(szPath
, Globals
.szFileName
);
421 openfilename
.lStructSize
= sizeof(openfilename
);
422 openfilename
.hwndOwner
= Globals
.hMainWnd
;
423 openfilename
.hInstance
= Globals
.hInstance
;
424 openfilename
.lpstrFilter
= Globals
.szFilter
;
425 openfilename
.lpstrFile
= szPath
;
426 openfilename
.nMaxFile
= ARRAY_SIZE(szPath
);
427 openfilename
.Flags
= OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
| OFN_HIDEREADONLY
;
428 openfilename
.lpstrDefExt
= szDefaultExt
;
430 if (GetOpenFileName(&openfilename
)) {
431 if (FileExists(openfilename
.lpstrFile
))
432 DoOpenFile(openfilename
.lpstrFile
);
434 AlertFileNotFound(openfilename
.lpstrFile
);
438 BOOL
DIALOG_FileSave(VOID
)
440 if (Globals
.szFileName
[0] == 0)
442 return DIALOG_FileSaveAs();
444 else if (DoSaveFile())
446 UpdateWindowCaption(TRUE
);
454 DIALOG_FileSaveAs_Hook(HWND hDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
459 UNREFERENCED_PARAMETER(wParam
);
464 hCombo
= GetDlgItem(hDlg
, ID_ENCODING
);
466 LoadString(Globals
.hInstance
, STRING_ANSI
, szText
, ARRAY_SIZE(szText
));
467 SendMessage(hCombo
, CB_ADDSTRING
, 0, (LPARAM
) szText
);
469 LoadString(Globals
.hInstance
, STRING_UNICODE
, szText
, ARRAY_SIZE(szText
));
470 SendMessage(hCombo
, CB_ADDSTRING
, 0, (LPARAM
) szText
);
472 LoadString(Globals
.hInstance
, STRING_UNICODE_BE
, szText
, ARRAY_SIZE(szText
));
473 SendMessage(hCombo
, CB_ADDSTRING
, 0, (LPARAM
) szText
);
475 LoadString(Globals
.hInstance
, STRING_UTF8
, szText
, ARRAY_SIZE(szText
));
476 SendMessage(hCombo
, CB_ADDSTRING
, 0, (LPARAM
) szText
);
478 SendMessage(hCombo
, CB_SETCURSEL
, Globals
.encFile
, 0);
480 hCombo
= GetDlgItem(hDlg
, ID_EOLN
);
482 LoadString(Globals
.hInstance
, STRING_CRLF
, szText
, ARRAY_SIZE(szText
));
483 SendMessage(hCombo
, CB_ADDSTRING
, 0, (LPARAM
) szText
);
485 LoadString(Globals
.hInstance
, STRING_LF
, szText
, ARRAY_SIZE(szText
));
486 SendMessage(hCombo
, CB_ADDSTRING
, 0, (LPARAM
) szText
);
488 LoadString(Globals
.hInstance
, STRING_CR
, szText
, ARRAY_SIZE(szText
));
489 SendMessage(hCombo
, CB_ADDSTRING
, 0, (LPARAM
) szText
);
491 SendMessage(hCombo
, CB_SETCURSEL
, Globals
.iEoln
, 0);
495 if (((NMHDR
*) lParam
)->code
== CDN_FILEOK
)
497 hCombo
= GetDlgItem(hDlg
, ID_ENCODING
);
499 Globals
.encFile
= (int) SendMessage(hCombo
, CB_GETCURSEL
, 0, 0);
501 hCombo
= GetDlgItem(hDlg
, ID_EOLN
);
503 Globals
.iEoln
= (int) SendMessage(hCombo
, CB_GETCURSEL
, 0, 0);
510 BOOL
DIALOG_FileSaveAs(VOID
)
513 TCHAR szPath
[MAX_PATH
];
515 ZeroMemory(&saveas
, sizeof(saveas
));
517 if (Globals
.szFileName
[0] == 0)
518 _tcscpy(szPath
, txt_files
);
520 _tcscpy(szPath
, Globals
.szFileName
);
522 saveas
.lStructSize
= sizeof(OPENFILENAME
);
523 saveas
.hwndOwner
= Globals
.hMainWnd
;
524 saveas
.hInstance
= Globals
.hInstance
;
525 saveas
.lpstrFilter
= Globals
.szFilter
;
526 saveas
.lpstrFile
= szPath
;
527 saveas
.nMaxFile
= ARRAY_SIZE(szPath
);
528 saveas
.Flags
= OFN_PATHMUSTEXIST
| OFN_OVERWRITEPROMPT
| OFN_HIDEREADONLY
|
529 OFN_EXPLORER
| OFN_ENABLETEMPLATE
| OFN_ENABLEHOOK
;
530 saveas
.lpstrDefExt
= szDefaultExt
;
531 saveas
.lpTemplateName
= MAKEINTRESOURCE(DIALOG_ENCODING
);
532 saveas
.lpfnHook
= DIALOG_FileSaveAs_Hook
;
534 if (GetSaveFileName(&saveas
))
536 /* HACK: Because in ROS, Save-As boxes don't check the validity
537 * of file names and thus, here, szPath can be invalid !! We only
538 * see its validity when we call DoSaveFile()... */
542 UpdateWindowCaption(TRUE
);
557 VOID
DIALOG_FilePrint(VOID
)
564 int xLeft
, yTop
, pagecount
, dopage
, copycount
;
567 HFONT font
, old_font
=0;
570 static const TCHAR times_new_roman
[] = _T("Times New Roman");
573 /* Get a small font and print some header info on each page */
574 ZeroMemory(&hdrFont
, sizeof(hdrFont
));
575 hdrFont
.lfHeight
= 100;
576 hdrFont
.lfWeight
= FW_BOLD
;
577 hdrFont
.lfCharSet
= ANSI_CHARSET
;
578 hdrFont
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
579 hdrFont
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
580 hdrFont
.lfQuality
= PROOF_QUALITY
;
581 hdrFont
.lfPitchAndFamily
= VARIABLE_PITCH
| FF_ROMAN
;
582 _tcscpy(hdrFont
.lfFaceName
, times_new_roman
);
584 font
= CreateFontIndirect(&hdrFont
);
586 /* Get Current Settings */
587 ZeroMemory(&printer
, sizeof(printer
));
588 printer
.lStructSize
= sizeof(printer
);
589 printer
.hwndOwner
= Globals
.hMainWnd
;
590 printer
.hInstance
= Globals
.hInstance
;
592 /* Set some default flags */
593 printer
.Flags
= PD_RETURNDC
| PD_SELECTION
;
595 /* Disable the selection radio button if there is no text selected */
596 if (!GetSelectionTextLength(Globals
.hEdit
))
598 printer
.Flags
= printer
.Flags
| PD_NOSELECTION
;
601 printer
.nFromPage
= 0;
602 printer
.nMinPage
= 1;
603 /* we really need to calculate number of pages to set nMaxPage and nToPage */
604 printer
.nToPage
= (WORD
)-1;
605 printer
.nMaxPage
= (WORD
)-1;
607 /* Let commdlg manage copy settings */
608 printer
.nCopies
= (WORD
)PD_USEDEVMODECOPIES
;
610 printer
.hDevMode
= Globals
.hDevMode
;
611 printer
.hDevNames
= Globals
.hDevNames
;
613 if (!PrintDlg(&printer
))
619 Globals
.hDevMode
= printer
.hDevMode
;
620 Globals
.hDevNames
= printer
.hDevNames
;
622 assert(printer
.hDC
!= 0);
624 /* initialize DOCINFO */
625 di
.cbSize
= sizeof(DOCINFO
);
626 di
.lpszDocName
= Globals
.szFileTitle
;
627 di
.lpszOutput
= NULL
;
628 di
.lpszDatatype
= NULL
;
631 if (StartDoc(printer
.hDC
, &di
) <= 0)
638 /* Get the file text */
639 if (printer
.Flags
& PD_SELECTION
)
641 size
= GetSelectionTextLength(Globals
.hEdit
) + 1;
645 size
= GetWindowTextLength(Globals
.hEdit
) + 1;
648 pTemp
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(TCHAR
));
657 if (printer
.Flags
& PD_SELECTION
)
659 size
= GetSelectionText(Globals
.hEdit
, pTemp
, size
);
663 size
= GetWindowText(Globals
.hEdit
, pTemp
, size
);
666 /* Get the current printing area */
667 rcPrintRect
= GetPrintingRect(printer
.hDC
, Globals
.lMargins
);
669 /* Ensure that each logical unit maps to one pixel */
670 SetMapMode(printer
.hDC
, MM_TEXT
);
672 /* Needed to get the correct height of a text line */
673 GetTextMetrics(printer
.hDC
, &tm
);
676 for (copycount
=1; copycount
<= printer
.nCopies
; copycount
++) {
680 /* Don't start a page if none of the conditions below are true */
683 /* The user wants to print the current selection */
684 if (printer
.Flags
& PD_SELECTION
)
689 /* The user wants to print the entire document */
690 if (!(printer
.Flags
& PD_PAGENUMS
) && !(printer
.Flags
& PD_SELECTION
))
695 /* The user wants to print a specified range of pages */
696 if ((pagecount
>= printer
.nFromPage
&& pagecount
<= printer
.nToPage
))
701 old_font
= SelectObject(printer
.hDC
, font
);
704 if (StartPage(printer
.hDC
) <= 0) {
705 SelectObject(printer
.hDC
, old_font
);
707 DeleteDC(printer
.hDC
);
708 HeapFree(GetProcessHeap(), 0, pTemp
);
714 SetViewportOrgEx(printer
.hDC
, rcPrintRect
.left
, rcPrintRect
.top
, NULL
);
716 /* Write a rectangle and header at the top of each page */
717 Rectangle(printer
.hDC
, border
, border
, rcPrintRect
.right
- border
, border
+ tm
.tmHeight
* 2);
718 /* I don't know what's up with this TextOut command. This comes out
723 border
+ tm
.tmHeight
/ 2,
725 lstrlen(Globals
.szFileTitle
));
728 /* The starting point for the main text */
730 yTop
= border
+ tm
.tmHeight
* 4;
732 SelectObject(printer
.hDC
, old_font
);
734 /* Since outputting strings is giving me problems, output the main
735 * text one character at a time. */
737 if (pTemp
[i
] == '\n') {
741 else if (pTemp
[i
] != '\r') {
743 TextOut(printer
.hDC
, xLeft
, yTop
, &pTemp
[i
], 1);
745 /* We need to get the width for each individual char, since a proportional font may be used */
746 GetTextExtentPoint32(printer
.hDC
, &pTemp
[i
], 1, &szMetric
);
747 xLeft
+= szMetric
.cx
;
749 /* Insert a line break if the current line does not fit into the printing area */
750 if (xLeft
> rcPrintRect
.right
)
753 yTop
= yTop
+ tm
.tmHeight
;
756 } while (i
++ < size
&& yTop
< rcPrintRect
.bottom
);
759 EndPage(printer
.hDC
);
765 SelectObject(printer
.hDC
, old_font
);
767 DeleteDC(printer
.hDC
);
768 HeapFree(GetProcessHeap(), 0, pTemp
);
772 VOID
DIALOG_FileExit(VOID
)
774 PostMessage(Globals
.hMainWnd
, WM_CLOSE
, 0, 0l);
777 VOID
DIALOG_EditUndo(VOID
)
779 SendMessage(Globals
.hEdit
, EM_UNDO
, 0, 0);
782 VOID
DIALOG_EditCut(VOID
)
784 SendMessage(Globals
.hEdit
, WM_CUT
, 0, 0);
787 VOID
DIALOG_EditCopy(VOID
)
789 SendMessage(Globals
.hEdit
, WM_COPY
, 0, 0);
792 VOID
DIALOG_EditPaste(VOID
)
794 SendMessage(Globals
.hEdit
, WM_PASTE
, 0, 0);
797 VOID
DIALOG_EditDelete(VOID
)
799 SendMessage(Globals
.hEdit
, WM_CLEAR
, 0, 0);
802 VOID
DIALOG_EditSelectAll(VOID
)
804 SendMessage(Globals
.hEdit
, EM_SETSEL
, 0, (LPARAM
)-1);
807 VOID
DIALOG_EditTimeDate(VOID
)
810 TCHAR szDate
[MAX_STRING_LEN
];
811 TCHAR szText
[MAX_STRING_LEN
* 2 + 2];
815 GetTimeFormat(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, szDate
, MAX_STRING_LEN
);
816 _tcscpy(szText
, szDate
);
817 _tcscat(szText
, _T(" "));
818 GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, szDate
, MAX_STRING_LEN
);
819 _tcscat(szText
, szDate
);
820 SendMessage(Globals
.hEdit
, EM_REPLACESEL
, TRUE
, (LPARAM
)szText
);
823 VOID
DoCreateStatusBar(VOID
)
827 BOOL bStatusBarVisible
;
829 /* Check if status bar object already exists. */
830 if (Globals
.hStatusBar
== NULL
)
832 /* Try to create the status bar */
833 Globals
.hStatusBar
= CreateStatusWindow(WS_CHILD
| WS_VISIBLE
| WS_EX_STATICEDGE
,
836 CMD_STATUSBAR_WND_ID
);
838 if (Globals
.hStatusBar
== NULL
)
844 /* Load the string for formatting column/row text output */
845 LoadString(Globals
.hInstance
, STRING_LINE_COLUMN
, Globals
.szStatusBarLineCol
, MAX_PATH
- 1);
847 /* Set the status bar for single-text output */
848 SendMessage(Globals
.hStatusBar
, SB_SIMPLE
, (WPARAM
)TRUE
, (LPARAM
)0);
851 /* Set status bar visiblity according to the settings. */
852 if ((Globals
.bWrapLongLines
!= FALSE
) || (Globals
.bShowStatusBar
== FALSE
))
854 bStatusBarVisible
= FALSE
;
855 ShowWindow(Globals
.hStatusBar
, SW_HIDE
);
859 bStatusBarVisible
= TRUE
;
860 ShowWindow(Globals
.hStatusBar
, SW_SHOW
);
861 SendMessage(Globals
.hStatusBar
, WM_SIZE
, 0, 0);
864 /* Set check state in show status bar item. */
865 if (bStatusBarVisible
)
867 CheckMenuItem(Globals
.hMenu
, CMD_STATUSBAR
, MF_BYCOMMAND
| MF_CHECKED
);
871 CheckMenuItem(Globals
.hMenu
, CMD_STATUSBAR
, MF_BYCOMMAND
| MF_UNCHECKED
);
874 /* Update menu mar with the previous changes */
875 DrawMenuBar(Globals
.hMainWnd
);
877 /* Sefety test is edit control exists */
878 if (Globals
.hEdit
!= NULL
)
880 /* Retrieve the sizes of the controls */
881 GetClientRect(Globals
.hMainWnd
, &rc
);
882 GetClientRect(Globals
.hStatusBar
, &rcstatus
);
884 /* If status bar is currently visible, update dimensions of edit control */
885 if (bStatusBarVisible
)
886 rc
.bottom
-= (rcstatus
.bottom
- rcstatus
.top
);
888 /* Resize edit control to right size. */
889 MoveWindow(Globals
.hEdit
,
897 /* Update content with current row/column text */
898 DIALOG_StatusBarUpdateCaretPos();
901 VOID
DoCreateEditWindow(VOID
)
906 BOOL bModified
= FALSE
;
910 /* If the edit control already exists, try to save its content */
911 if (Globals
.hEdit
!= NULL
)
913 /* number of chars currently written into the editor. */
914 iSize
= GetWindowTextLength(Globals
.hEdit
);
917 /* Allocates temporary buffer. */
918 pTemp
= HeapAlloc(GetProcessHeap(), 0, (iSize
+ 1) * sizeof(TCHAR
));
925 /* Recover the text into the control. */
926 GetWindowText(Globals
.hEdit
, pTemp
, iSize
+ 1);
928 if (SendMessage(Globals
.hEdit
, EM_GETMODIFY
, 0, 0))
932 /* Restore original window procedure */
933 SetWindowLongPtr(Globals
.hEdit
, GWLP_WNDPROC
, (LONG_PTR
)Globals
.EditProc
);
935 /* Destroy the edit control */
936 DestroyWindow(Globals
.hEdit
);
939 /* Update wrap status into the main menu and recover style flags */
940 if (Globals
.bWrapLongLines
)
942 dwStyle
= EDIT_STYLE_WRAP
;
943 EnableMenuItem(Globals
.hMenu
, CMD_STATUSBAR
, MF_BYCOMMAND
| MF_DISABLED
| MF_GRAYED
);
945 dwStyle
= EDIT_STYLE
;
946 EnableMenuItem(Globals
.hMenu
, CMD_STATUSBAR
, MF_BYCOMMAND
| MF_ENABLED
);
949 /* Update previous changes */
950 DrawMenuBar(Globals
.hMainWnd
);
952 /* Create the new edit control */
953 Globals
.hEdit
= CreateWindowEx(WS_EX_CLIENTEDGE
,
966 if (Globals
.hEdit
== NULL
)
970 HeapFree(GetProcessHeap(), 0, pTemp
);
977 SendMessage(Globals
.hEdit
, WM_SETFONT
, (WPARAM
)Globals
.hFont
, FALSE
);
978 SendMessage(Globals
.hEdit
, EM_LIMITTEXT
, 0, 0);
980 /* If some text was previously saved, restore it. */
983 SetWindowText(Globals
.hEdit
, pTemp
);
984 HeapFree(GetProcessHeap(), 0, pTemp
);
987 SendMessage(Globals
.hEdit
, EM_SETMODIFY
, TRUE
, 0);
990 /* Sub-class a new window callback for row/column detection. */
991 Globals
.EditProc
= (WNDPROC
)SetWindowLongPtr(Globals
.hEdit
,
993 (LONG_PTR
)EDIT_WndProc
);
995 /* Create/update status bar */
998 /* Finally shows new edit control and set focus into it. */
999 ShowWindow(Globals
.hEdit
, SW_SHOW
);
1000 SetFocus(Globals
.hEdit
);
1003 VOID
DIALOG_EditWrap(VOID
)
1005 Globals
.bWrapLongLines
= !Globals
.bWrapLongLines
;
1007 if (Globals
.bWrapLongLines
)
1009 EnableMenuItem(Globals
.hMenu
, CMD_GOTO
, MF_BYCOMMAND
| MF_DISABLED
| MF_GRAYED
);
1013 EnableMenuItem(Globals
.hMenu
, CMD_GOTO
, MF_BYCOMMAND
| MF_ENABLED
);
1016 DoCreateEditWindow();
1019 VOID
DIALOG_SelectFont(VOID
)
1022 LOGFONT lf
= Globals
.lfFont
;
1024 ZeroMemory( &cf
, sizeof(cf
) );
1025 cf
.lStructSize
= sizeof(cf
);
1026 cf
.hwndOwner
= Globals
.hMainWnd
;
1028 cf
.Flags
= CF_SCREENFONTS
| CF_INITTOLOGFONTSTRUCT
| CF_NOVERTFONTS
;
1030 if (ChooseFont(&cf
))
1032 HFONT currfont
= Globals
.hFont
;
1034 Globals
.hFont
= CreateFontIndirect(&lf
);
1035 Globals
.lfFont
= lf
;
1036 SendMessage(Globals
.hEdit
, WM_SETFONT
, (WPARAM
)Globals
.hFont
, (LPARAM
)TRUE
);
1037 if (currfont
!= NULL
)
1038 DeleteObject(currfont
);
1042 typedef HWND (WINAPI
*FINDPROC
)(LPFINDREPLACE lpfr
);
1044 static VOID
DIALOG_SearchDialog(FINDPROC pfnProc
)
1046 if (Globals
.hFindReplaceDlg
!= NULL
)
1048 SetFocus(Globals
.hFindReplaceDlg
);
1052 ZeroMemory(&Globals
.find
, sizeof(Globals
.find
));
1053 Globals
.find
.lStructSize
= sizeof(Globals
.find
);
1054 Globals
.find
.hwndOwner
= Globals
.hMainWnd
;
1055 Globals
.find
.hInstance
= Globals
.hInstance
;
1056 Globals
.find
.lpstrFindWhat
= Globals
.szFindText
;
1057 Globals
.find
.wFindWhatLen
= ARRAY_SIZE(Globals
.szFindText
);
1058 Globals
.find
.lpstrReplaceWith
= Globals
.szReplaceText
;
1059 Globals
.find
.wReplaceWithLen
= ARRAY_SIZE(Globals
.szReplaceText
);
1060 Globals
.find
.Flags
= FR_DOWN
;
1062 /* We only need to create the modal FindReplace dialog which will */
1063 /* notify us of incoming events using hMainWnd Window Messages */
1065 Globals
.hFindReplaceDlg
= pfnProc(&Globals
.find
);
1066 assert(Globals
.hFindReplaceDlg
!= NULL
);
1069 VOID
DIALOG_Search(VOID
)
1071 DIALOG_SearchDialog(FindText
);
1074 VOID
DIALOG_SearchNext(VOID
)
1076 if (Globals
.find
.lpstrFindWhat
!= NULL
)
1077 NOTEPAD_FindNext(&Globals
.find
, FALSE
, TRUE
);
1082 VOID
DIALOG_Replace(VOID
)
1084 DIALOG_SearchDialog(ReplaceText
);
1089 DIALOG_GoTo_DialogProc(HWND hwndDialog
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1091 BOOL bResult
= FALSE
;
1097 hTextBox
= GetDlgItem(hwndDialog
, ID_LINENUMBER
);
1098 _sntprintf(szText
, ARRAY_SIZE(szText
), _T("%ld"), lParam
);
1099 SetWindowText(hTextBox
, szText
);
1102 if (HIWORD(wParam
) == BN_CLICKED
)
1104 if (LOWORD(wParam
) == IDOK
)
1106 hTextBox
= GetDlgItem(hwndDialog
, ID_LINENUMBER
);
1107 GetWindowText(hTextBox
, szText
, ARRAY_SIZE(szText
));
1108 EndDialog(hwndDialog
, _ttoi(szText
));
1111 else if (LOWORD(wParam
) == IDCANCEL
)
1113 EndDialog(hwndDialog
, 0);
1123 VOID
DIALOG_GoTo(VOID
)
1128 DWORD dwStart
, dwEnd
;
1130 nLength
= GetWindowTextLength(Globals
.hEdit
);
1131 pszText
= (LPTSTR
) HeapAlloc(GetProcessHeap(), 0, (nLength
+ 1) * sizeof(*pszText
));
1135 /* Retrieve current text */
1136 GetWindowText(Globals
.hEdit
, pszText
, nLength
+ 1);
1137 SendMessage(Globals
.hEdit
, EM_GETSEL
, (WPARAM
) &dwStart
, (LPARAM
) &dwEnd
);
1140 for (i
= 0; (i
< (int) dwStart
) && pszText
[i
]; i
++)
1142 if (pszText
[i
] == '\n')
1146 nLine
= DialogBoxParam(Globals
.hInstance
,
1147 MAKEINTRESOURCE(DIALOG_GOTO
),
1149 DIALOG_GoTo_DialogProc
,
1154 for (i
= 0; pszText
[i
] && (nLine
> 1) && (i
< nLength
- 1); i
++)
1156 if (pszText
[i
] == '\n')
1159 SendMessage(Globals
.hEdit
, EM_SETSEL
, i
, i
);
1160 SendMessage(Globals
.hEdit
, EM_SCROLLCARET
, 0, 0);
1162 HeapFree(GetProcessHeap(), 0, pszText
);
1165 VOID
DIALOG_StatusBarUpdateCaretPos(VOID
)
1168 TCHAR buff
[MAX_PATH
];
1169 DWORD dwStart
, dwSize
;
1171 SendMessage(Globals
.hEdit
, EM_GETSEL
, (WPARAM
)&dwStart
, (LPARAM
)&dwSize
);
1172 line
= SendMessage(Globals
.hEdit
, EM_LINEFROMCHAR
, (WPARAM
)dwStart
, 0);
1173 col
= dwStart
- SendMessage(Globals
.hEdit
, EM_LINEINDEX
, (WPARAM
)line
, 0);
1175 _stprintf(buff
, Globals
.szStatusBarLineCol
, line
+ 1, col
+ 1);
1176 SendMessage(Globals
.hStatusBar
, SB_SETTEXT
, SB_SIMPLEID
, (LPARAM
)buff
);
1179 VOID
DIALOG_ViewStatusBar(VOID
)
1181 Globals
.bShowStatusBar
= !Globals
.bShowStatusBar
;
1183 DoCreateStatusBar();
1186 VOID
DIALOG_HelpContents(VOID
)
1188 WinHelp(Globals
.hMainWnd
, helpfile
, HELP_INDEX
, 0);
1191 VOID
DIALOG_HelpAboutNotepad(VOID
)
1193 TCHAR szNotepad
[MAX_STRING_LEN
];
1194 HICON notepadIcon
= LoadIcon(Globals
.hInstance
, MAKEINTRESOURCE(IDI_NPICON
));
1196 LoadString(Globals
.hInstance
, STRING_NOTEPAD
, szNotepad
, ARRAY_SIZE(szNotepad
));
1197 ShellAbout(Globals
.hMainWnd
, szNotepad
, 0, notepadIcon
);
1198 DeleteObject(notepadIcon
);
1203 AboutDialogProc(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1205 HWND hLicenseEditWnd
;
1212 hLicenseEditWnd
= GetDlgItem(hDlg
, IDC_LICENSE
);
1214 /* 0x1000 should be enough */
1215 strLicense
= (TCHAR
*)_alloca(0x1000);
1216 LoadString(GetModuleHandle(NULL
), STRING_LICENSE
, strLicense
, 0x1000);
1218 SetWindowText(hLicenseEditWnd
, strLicense
);
1224 if ((LOWORD(wParam
) == IDOK
) || (LOWORD(wParam
) == IDCANCEL
))
1226 EndDialog(hDlg
, LOWORD(wParam
));
1236 /***********************************************************************
1238 * DIALOG_FilePageSetup
1240 VOID
DIALOG_FilePageSetup(void)
1244 ZeroMemory(&page
, sizeof(page
));
1245 page
.lStructSize
= sizeof(page
);
1246 page
.hwndOwner
= Globals
.hMainWnd
;
1247 page
.Flags
= PSD_ENABLEPAGESETUPTEMPLATE
| PSD_ENABLEPAGESETUPHOOK
| PSD_MARGINS
;
1248 page
.hInstance
= Globals
.hInstance
;
1249 page
.rtMargin
= Globals
.lMargins
;
1250 page
.hDevMode
= Globals
.hDevMode
;
1251 page
.hDevNames
= Globals
.hDevNames
;
1252 page
.lpPageSetupTemplateName
= MAKEINTRESOURCE(DIALOG_PAGESETUP
);
1253 page
.lpfnPageSetupHook
= DIALOG_PAGESETUP_Hook
;
1255 PageSetupDlg(&page
);
1257 Globals
.hDevMode
= page
.hDevMode
;
1258 Globals
.hDevNames
= page
.hDevNames
;
1259 Globals
.lMargins
= page
.rtMargin
;
1262 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1264 * DIALOG_PAGESETUP_Hook
1267 static UINT_PTR CALLBACK
DIALOG_PAGESETUP_Hook(HWND hDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1272 if (HIWORD(wParam
) == BN_CLICKED
)
1274 switch (LOWORD(wParam
))
1277 /* save user input and close dialog */
1278 GetDlgItemText(hDlg
, 0x141, Globals
.szHeader
, ARRAY_SIZE(Globals
.szHeader
));
1279 GetDlgItemText(hDlg
, 0x143, Globals
.szFooter
, ARRAY_SIZE(Globals
.szFooter
));
1283 /* discard user input and close dialog */
1288 /* FIXME: Bring this to work */
1289 static const TCHAR sorry
[] = _T("Sorry, no help available");
1290 static const TCHAR help
[] = _T("Help");
1291 MessageBox(Globals
.hMainWnd
, sorry
, help
, MB_ICONEXCLAMATION
);
1302 /* fetch last user input prior to display dialog */
1303 SetDlgItemText(hDlg
, 0x141, Globals
.szHeader
);
1304 SetDlgItemText(hDlg
, 0x143, Globals
.szFooter
);