Sync with trunk r43123
[reactos.git] / reactos / base / applications / notepad / dialog.c
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #include <notepad.h>
24
25 LRESULT CALLBACK EDIT_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
26
27 static const TCHAR helpfile[] = _T("notepad.hlp");
28 static const TCHAR empty_str[] = _T("");
29 static const TCHAR szDefaultExt[] = _T("txt");
30 static const TCHAR txt_files[] = _T("*.txt");
31
32 static INT_PTR WINAPI DIALOG_PAGESETUP_DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
33
34 #ifndef UNICODE
35 static LPSTR ConvertToASCII(LPSTR pszText)
36 {
37 int sz;
38 LPWSTR pszTextW = (LPWSTR)pszText;
39
40 /* default return value */
41 pszText = NULL;
42 do {
43 /* query about requested size for conversion */
44 sz = WideCharToMultiByte(CP_ACP, 0, pszTextW, -1, NULL, 0, NULL, NULL);
45 if (!sz)
46 break;
47
48 /* get space for ASCII buffer */
49 pszText = (LPSTR)HeapAlloc(GetProcessHeap(), 0, sz);
50 if (pszText == NULL)
51 break;
52
53 /* if previous diagnostic call worked fine,
54 * then this one will work too,
55 * so no need to test return value here
56 */
57 WideCharToMultiByte(CP_ACP, 0, pszTextW, -1, pszText, sz, NULL, NULL);
58 } while (0);
59
60 HeapFree(GetProcessHeap(), 0, pszTextW);
61 return pszText;
62 }
63
64 static LPWSTR ConvertToUNICODE(LPSTR pszText, DWORD *pdwSize)
65 {
66 int sz;
67 LPWSTR pszTextW = NULL;
68
69 do {
70 /* query about requested size for conversion */
71 sz = MultiByteToWideChar(CP_ACP, 0, pszText, -1, NULL, 0);
72 if (!sz)
73 break;
74
75 /* get space for UNICODE buffer */
76 pszTextW = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));
77 if (pszText == NULL)
78 break;
79
80 /* if previous diagnostic call worked fine,
81 * then this one will work too,
82 * so no need to test return value here
83 */
84 MultiByteToWideChar(CP_ACP, 0, pszText, -1, pszTextW, sz);
85
86 /* report the new size of the text to the caller */
87 *pdwSize = sz;
88 } while (0);
89
90 HeapFree(GetProcessHeap(), 0, pszText);
91 return pszTextW;
92 }
93 #endif
94
95 VOID ShowLastError(void)
96 {
97 DWORD error = GetLastError();
98 if (error != NO_ERROR)
99 {
100 LPTSTR lpMsgBuf = NULL;
101 TCHAR szTitle[MAX_STRING_LEN];
102
103 LoadString(Globals.hInstance, STRING_ERROR, szTitle, SIZEOF(szTitle));
104 FormatMessage(
105 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
106 NULL, error, 0,
107 (LPTSTR) &lpMsgBuf, 0, NULL);
108 MessageBox(NULL, lpMsgBuf, szTitle, MB_OK | MB_ICONERROR);
109 LocalFree(lpMsgBuf);
110 }
111 }
112
113 /**
114 * Sets the caption of the main window according to Globals.szFileTitle:
115 * Notepad - (untitled) if no file is open
116 * Notepad - [filename] if a file is given
117 */
118 static void UpdateWindowCaption(void)
119 {
120 TCHAR szCaption[MAX_STRING_LEN];
121 TCHAR szUntitled[MAX_STRING_LEN];
122
123 LoadString(Globals.hInstance, STRING_NOTEPAD, szCaption, SIZEOF(szCaption));
124
125 if (Globals.szFileTitle[0] != '\0') {
126 static const TCHAR bracket_l[] = _T(" - [");
127 static const TCHAR bracket_r[] = _T("]");
128 _tcscat(szCaption, bracket_l);
129 _tcscat(szCaption, Globals.szFileTitle);
130 _tcscat(szCaption, bracket_r);
131 }
132 else
133 {
134 static const TCHAR hyphen[] = _T(" - ");
135 LoadString(Globals.hInstance, STRING_UNTITLED, szUntitled, SIZEOF(szUntitled));
136 _tcscat(szCaption, hyphen);
137 _tcscat(szCaption, szUntitled);
138 }
139
140 SetWindowText(Globals.hMainWnd, szCaption);
141 }
142
143 static void AlertFileNotFound(LPCTSTR szFileName)
144 {
145 TCHAR szMessage[MAX_STRING_LEN];
146 TCHAR szResource[MAX_STRING_LEN];
147
148 /* Load and format szMessage */
149 LoadString(Globals.hInstance, STRING_NOTFOUND, szResource, SIZEOF(szResource));
150 wsprintf(szMessage, szResource, szFileName);
151
152 /* Load szCaption */
153 LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, SIZEOF(szResource));
154
155 /* Display Modal Dialog */
156 MessageBox(Globals.hMainWnd, szMessage, szResource, MB_ICONEXCLAMATION);
157 }
158
159 static int AlertFileNotSaved(LPCTSTR szFileName)
160 {
161 TCHAR szMessage[MAX_STRING_LEN];
162 TCHAR szResource[MAX_STRING_LEN];
163 TCHAR szUntitled[MAX_STRING_LEN];
164
165 LoadString(Globals.hInstance, STRING_UNTITLED, szUntitled, SIZEOF(szUntitled));
166
167 /* Load and format Message */
168 LoadString(Globals.hInstance, STRING_NOTSAVED, szResource, SIZEOF(szResource));
169 wsprintf(szMessage, szResource, szFileName[0] ? szFileName : szUntitled);
170
171 /* Load Caption */
172 LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, SIZEOF(szResource));
173
174 /* Display modal */
175 return MessageBox(Globals.hMainWnd, szMessage, szResource, MB_ICONEXCLAMATION|MB_YESNOCANCEL);
176 }
177
178 /**
179 * Returns:
180 * TRUE - if file exists
181 * FALSE - if file does not exist
182 */
183 BOOL FileExists(LPCTSTR szFilename)
184 {
185 WIN32_FIND_DATA entry;
186 HANDLE hFile;
187
188 hFile = FindFirstFile(szFilename, &entry);
189 FindClose(hFile);
190
191 return (hFile != INVALID_HANDLE_VALUE);
192 }
193
194
195 BOOL HasFileExtension(LPCTSTR szFilename)
196 {
197 LPCTSTR s;
198
199 s = _tcsrchr(szFilename, _T('\\'));
200 if (s)
201 szFilename = s;
202 return _tcsrchr(szFilename, _T('.')) != NULL;
203 }
204
205
206 static VOID DoSaveFile(VOID)
207 {
208 HANDLE hFile;
209 LPTSTR pTemp;
210 DWORD size;
211
212 hFile = CreateFile(Globals.szFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
213 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
214 if(hFile == INVALID_HANDLE_VALUE)
215 {
216 ShowLastError();
217 return;
218 }
219
220 size = GetWindowTextLength(Globals.hEdit) + 1;
221 pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*pTemp));
222 if (!pTemp)
223 {
224 CloseHandle(hFile);
225 ShowLastError();
226 return;
227 }
228 size = GetWindowText(Globals.hEdit, pTemp, size);
229
230 #ifndef UNICODE
231 pTemp = (LPTSTR)ConvertToUNICODE(pTemp, &size);
232 if (!pTemp) {
233 /* original "pTemp" already freed */
234 CloseHandle(hFile);
235 ShowLastError();
236 return;
237 }
238 #endif
239
240 if (size)
241 {
242 if (!WriteText(hFile, (LPWSTR)pTemp, size, Globals.iEncoding, Globals.iEoln))
243 ShowLastError();
244 else
245 SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0);
246 }
247
248 CloseHandle(hFile);
249 HeapFree(GetProcessHeap(), 0, pTemp);
250 }
251
252 /**
253 * Returns:
254 * TRUE - User agreed to close (both save/don't save)
255 * FALSE - User cancelled close by selecting "Cancel"
256 */
257 BOOL DoCloseFile(void)
258 {
259 int nResult;
260
261 if (SendMessage(Globals.hEdit, EM_GETMODIFY, 0, 0))
262 {
263 /* prompt user to save changes */
264 nResult = AlertFileNotSaved(Globals.szFileName);
265 switch (nResult) {
266 case IDYES: DIALOG_FileSave();
267 break;
268
269 case IDNO: break;
270
271 case IDCANCEL: return(FALSE);
272 break;
273
274 default: return(FALSE);
275 break;
276 } /* switch */
277 } /* if */
278
279 SetFileName(empty_str);
280
281 UpdateWindowCaption();
282 return(TRUE);
283 }
284
285 void DoOpenFile(LPCTSTR szFileName)
286 {
287 static const TCHAR dotlog[] = _T(".LOG");
288 HANDLE hFile;
289 LPTSTR pszText;
290 DWORD dwTextLen;
291 TCHAR log[5];
292
293 /* Close any files and prompt to save changes */
294 if (!DoCloseFile())
295 return;
296
297 hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
298 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
299 if (hFile == INVALID_HANDLE_VALUE)
300 {
301 ShowLastError();
302 goto done;
303 }
304
305 if (!ReadText(hFile, (LPWSTR *)&pszText, &dwTextLen, &Globals.iEncoding, &Globals.iEoln))
306 {
307 ShowLastError();
308 goto done;
309 }
310 #ifndef UNICODE
311 pszText = ConvertToASCII(pszText);
312 if (pszText == NULL) {
313 ShowLastError();
314 goto done;
315 }
316 #endif
317 SetWindowText(Globals.hEdit, pszText);
318
319 SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0);
320 SendMessage(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0);
321 SetFocus(Globals.hEdit);
322
323 /* If the file starts with .LOG, add a time/date at the end and set cursor after
324 * See http://support.microsoft.com/?kbid=260563
325 */
326 if (GetWindowText(Globals.hEdit, log, SIZEOF(log)) && !_tcscmp(log, dotlog))
327 {
328 static const TCHAR lf[] = _T("\r\n");
329 SendMessage(Globals.hEdit, EM_SETSEL, GetWindowTextLength(Globals.hEdit), -1);
330 SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)lf);
331 DIALOG_EditTimeDate();
332 SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)lf);
333 }
334
335 SetFileName(szFileName);
336 UpdateWindowCaption();
337 NOTEPAD_EnableSearchMenu();
338 done:
339 if (hFile != INVALID_HANDLE_VALUE)
340 CloseHandle(hFile);
341 if (pszText)
342 HeapFree(GetProcessHeap(), 0, pszText);
343 }
344
345 VOID DIALOG_FileNew(VOID)
346 {
347 /* Close any files and prompt to save changes */
348 if (DoCloseFile()) {
349 SetWindowText(Globals.hEdit, empty_str);
350 SendMessage(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0);
351 SetFocus(Globals.hEdit);
352 NOTEPAD_EnableSearchMenu();
353 }
354 }
355
356 VOID DIALOG_FileOpen(VOID)
357 {
358 OPENFILENAME openfilename;
359 TCHAR szDir[MAX_PATH];
360 TCHAR szPath[MAX_PATH];
361
362 ZeroMemory(&openfilename, sizeof(openfilename));
363
364 GetCurrentDirectory(SIZEOF(szDir), szDir);
365 if (Globals.szFileName[0] == 0)
366 _tcscpy(szPath, txt_files);
367 else
368 _tcscpy(szPath, Globals.szFileName);
369
370 openfilename.lStructSize = sizeof(openfilename);
371 openfilename.hwndOwner = Globals.hMainWnd;
372 openfilename.hInstance = Globals.hInstance;
373 openfilename.lpstrFilter = Globals.szFilter;
374 openfilename.lpstrFile = szPath;
375 openfilename.nMaxFile = SIZEOF(szPath);
376 openfilename.lpstrInitialDir = szDir;
377 openfilename.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST |
378 OFN_HIDEREADONLY;
379 openfilename.lpstrDefExt = szDefaultExt;
380
381
382 if (GetOpenFileName(&openfilename)) {
383 if (FileExists(openfilename.lpstrFile))
384 DoOpenFile(openfilename.lpstrFile);
385 else
386 AlertFileNotFound(openfilename.lpstrFile);
387 }
388 }
389
390
391 VOID DIALOG_FileSave(VOID)
392 {
393 if (Globals.szFileName[0] == '\0')
394 DIALOG_FileSaveAs();
395 else
396 DoSaveFile();
397 }
398
399 static UINT_PTR CALLBACK DIALOG_FileSaveAs_Hook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
400 {
401 TCHAR szText[128];
402 HWND hCombo;
403 OFNOTIFY *pNotify;
404
405 UNREFERENCED_PARAMETER(wParam);
406
407 switch(msg)
408 {
409 case WM_INITDIALOG:
410 hCombo = GetDlgItem(hDlg, ID_ENCODING);
411
412 LoadString(Globals.hInstance, STRING_ANSI, szText, SIZEOF(szText));
413 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
414
415 LoadString(Globals.hInstance, STRING_UNICODE, szText, SIZEOF(szText));
416 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
417
418 LoadString(Globals.hInstance, STRING_UNICODE_BE, szText, SIZEOF(szText));
419 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
420
421 LoadString(Globals.hInstance, STRING_UTF8, szText, SIZEOF(szText));
422 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
423
424 SendMessage(hCombo, CB_SETCURSEL, Globals.iEncoding, 0);
425
426 hCombo = GetDlgItem(hDlg, ID_EOLN);
427
428 LoadString(Globals.hInstance, STRING_CRLF, szText, SIZEOF(szText));
429 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
430
431 LoadString(Globals.hInstance, STRING_LF, szText, SIZEOF(szText));
432 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
433
434 LoadString(Globals.hInstance, STRING_CR, szText, SIZEOF(szText));
435 SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
436
437 SendMessage(hCombo, CB_SETCURSEL, Globals.iEoln, 0);
438 break;
439
440 case WM_NOTIFY:
441 if (((NMHDR *) lParam)->code == CDN_FILEOK)
442 {
443 pNotify = (OFNOTIFY *) lParam;
444
445 hCombo = GetDlgItem(hDlg, ID_ENCODING);
446 if (hCombo)
447 Globals.iEncoding = (int) SendMessage(hCombo, CB_GETCURSEL, 0, 0);
448
449 hCombo = GetDlgItem(hDlg, ID_EOLN);
450 if (hCombo)
451 Globals.iEoln = (int) SendMessage(hCombo, CB_GETCURSEL, 0, 0);
452 }
453 break;
454 }
455 return 0;
456 }
457
458 VOID DIALOG_FileSaveAs(VOID)
459 {
460 OPENFILENAME saveas;
461 TCHAR szDir[MAX_PATH];
462 TCHAR szPath[MAX_PATH];
463
464 ZeroMemory(&saveas, sizeof(saveas));
465
466 GetCurrentDirectory(SIZEOF(szDir), szDir);
467 if (Globals.szFileName[0] == 0)
468 _tcscpy(szPath, txt_files);
469 else
470 _tcscpy(szPath, Globals.szFileName);
471
472 saveas.lStructSize = sizeof(OPENFILENAME);
473 saveas.hwndOwner = Globals.hMainWnd;
474 saveas.hInstance = Globals.hInstance;
475 saveas.lpstrFilter = Globals.szFilter;
476 saveas.lpstrFile = szPath;
477 saveas.nMaxFile = SIZEOF(szPath);
478 saveas.lpstrInitialDir = szDir;
479 saveas.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT |
480 OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
481 saveas.lpstrDefExt = szDefaultExt;
482 saveas.lpTemplateName = MAKEINTRESOURCE(DIALOG_ENCODING);
483 saveas.lpfnHook = DIALOG_FileSaveAs_Hook;
484
485 if (GetSaveFileName(&saveas)) {
486 SetFileName(szPath);
487 UpdateWindowCaption();
488 DoSaveFile();
489 }
490 }
491
492 VOID DIALOG_FilePrint(VOID)
493 {
494 DOCINFO di;
495 PRINTDLG printer;
496 SIZE szMetric;
497 int cWidthPels, cHeightPels, border;
498 int xLeft, yTop, pagecount, dopage, copycount;
499 unsigned int i;
500 LOGFONT hdrFont;
501 HFONT font, old_font=0;
502 DWORD size;
503 LPTSTR pTemp;
504 static const TCHAR times_new_roman[] = _T("Times New Roman");
505
506 /* Get a small font and print some header info on each page */
507 ZeroMemory(&hdrFont, sizeof(hdrFont));
508 hdrFont.lfHeight = 100;
509 hdrFont.lfWeight = FW_BOLD;
510 hdrFont.lfCharSet = ANSI_CHARSET;
511 hdrFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
512 hdrFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
513 hdrFont.lfQuality = PROOF_QUALITY;
514 hdrFont.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
515 _tcscpy(hdrFont.lfFaceName, times_new_roman);
516
517 font = CreateFontIndirect(&hdrFont);
518
519 /* Get Current Settings */
520 ZeroMemory(&printer, sizeof(printer));
521 printer.lStructSize = sizeof(printer);
522 printer.hwndOwner = Globals.hMainWnd;
523 printer.hInstance = Globals.hInstance;
524
525 /* Set some default flags */
526 printer.Flags = PD_RETURNDC;
527 printer.nFromPage = 0;
528 printer.nMinPage = 1;
529 /* we really need to calculate number of pages to set nMaxPage and nToPage */
530 printer.nToPage = 0;
531 printer.nMaxPage = (WORD) -1;
532
533 /* Let commdlg manage copy settings */
534 printer.nCopies = (WORD)PD_USEDEVMODECOPIES;
535
536 if (!PrintDlg(&printer)) return;
537
538 assert(printer.hDC != 0);
539
540 /* initialize DOCINFO */
541 di.cbSize = sizeof(DOCINFO);
542 di.lpszDocName = Globals.szFileTitle;
543 di.lpszOutput = NULL;
544 di.lpszDatatype = NULL;
545 di.fwType = 0;
546
547 if (StartDoc(printer.hDC, &di) <= 0) return;
548
549 /* Get the page dimensions in pixels. */
550 cWidthPels = GetDeviceCaps(printer.hDC, HORZRES);
551 cHeightPels = GetDeviceCaps(printer.hDC, VERTRES);
552
553 /* Get the file text */
554 size = GetWindowTextLength(Globals.hEdit) + 1;
555 pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(TCHAR));
556 if (!pTemp)
557 {
558 ShowLastError();
559 return;
560 }
561 size = GetWindowText(Globals.hEdit, pTemp, size);
562
563 border = 150;
564 for (copycount=1; copycount <= printer.nCopies; copycount++) {
565 i = 0;
566 pagecount = 1;
567 do {
568 static const TCHAR letterM[] = _T("M");
569
570 if (pagecount >= printer.nFromPage &&
571 /* ((printer.Flags & PD_PAGENUMS) == 0 || pagecount <= printer.nToPage))*/
572 pagecount <= printer.nToPage)
573 dopage = 1;
574 else
575 dopage = 0;
576
577 old_font = SelectObject(printer.hDC, font);
578 GetTextExtentPoint32(printer.hDC, letterM, 1, &szMetric);
579
580 if (dopage) {
581 if (StartPage(printer.hDC) <= 0) {
582 static const TCHAR failed[] = _T("StartPage failed");
583 static const TCHAR error[] = _T("Print Error");
584 MessageBox(Globals.hMainWnd, failed, error, MB_ICONEXCLAMATION);
585 return;
586 }
587 /* Write a rectangle and header at the top of each page */
588 Rectangle(printer.hDC, border, border, cWidthPels-border, border+szMetric.cy*2);
589 /* I don't know what's up with this TextOut command. This comes out
590 kind of mangled.
591 */
592 TextOut(printer.hDC, border*2, border+szMetric.cy/2, Globals.szFileTitle, lstrlen(Globals.szFileTitle));
593 }
594
595 /* The starting point for the main text */
596 xLeft = border*2;
597 yTop = border+szMetric.cy*4;
598
599 SelectObject(printer.hDC, old_font);
600 GetTextExtentPoint32(printer.hDC, letterM, 1, &szMetric);
601
602 /* Since outputting strings is giving me problems, output the main
603 text one character at a time.
604 */
605 do {
606 if (pTemp[i] == '\n') {
607 xLeft = border*2;
608 yTop += szMetric.cy;
609 }
610 else if (pTemp[i] != '\r') {
611 if (dopage)
612 TextOut(printer.hDC, xLeft, yTop, &pTemp[i], 1);
613 xLeft += szMetric.cx;
614 }
615 } while (i++<size && yTop<(cHeightPels-border*2));
616
617 if (dopage)
618 EndPage(printer.hDC);
619 pagecount++;
620 } while (i<size);
621 }
622
623 EndDoc(printer.hDC);
624 DeleteDC(printer.hDC);
625 HeapFree(GetProcessHeap(), 0, pTemp);
626 }
627
628 VOID DIALOG_FilePrinterSetup(VOID)
629 {
630 PRINTDLG printer;
631
632 ZeroMemory(&printer, sizeof(printer));
633 printer.lStructSize = sizeof(printer);
634 printer.hwndOwner = Globals.hMainWnd;
635 printer.hInstance = Globals.hInstance;
636 printer.Flags = PD_PRINTSETUP;
637 printer.nCopies = 1;
638
639 PrintDlg(&printer);
640 }
641
642 VOID DIALOG_FileExit(VOID)
643 {
644 PostMessage(Globals.hMainWnd, WM_CLOSE, 0, 0l);
645 }
646
647 VOID DIALOG_EditUndo(VOID)
648 {
649 SendMessage(Globals.hEdit, EM_UNDO, 0, 0);
650 }
651
652 VOID DIALOG_EditCut(VOID)
653 {
654 SendMessage(Globals.hEdit, WM_CUT, 0, 0);
655 }
656
657 VOID DIALOG_EditCopy(VOID)
658 {
659 SendMessage(Globals.hEdit, WM_COPY, 0, 0);
660 }
661
662 VOID DIALOG_EditPaste(VOID)
663 {
664 SendMessage(Globals.hEdit, WM_PASTE, 0, 0);
665 }
666
667 VOID DIALOG_EditDelete(VOID)
668 {
669 SendMessage(Globals.hEdit, WM_CLEAR, 0, 0);
670 }
671
672 VOID DIALOG_EditSelectAll(VOID)
673 {
674 SendMessage(Globals.hEdit, EM_SETSEL, 0, (LPARAM)-1);
675 }
676
677 VOID DIALOG_EditTimeDate(VOID)
678 {
679 SYSTEMTIME st;
680 TCHAR szDate[MAX_STRING_LEN];
681 TCHAR szText[MAX_STRING_LEN * 2 + 2];
682
683 GetLocalTime(&st);
684
685 GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, szDate, MAX_STRING_LEN);
686 _tcscpy(szText, szDate);
687 _tcscat(szText, _T(" "));
688 GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szDate, MAX_STRING_LEN);
689 _tcscat(szText, szDate);
690 SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)szDate);
691 }
692
693 VOID DIALOG_EditWrap(VOID)
694 {
695 static const TCHAR edit[] = _T("edit");
696 DWORD dwStyle;
697 RECT rc, rcstatus;
698 DWORD size;
699 LPTSTR pTemp;
700 TCHAR buff[MAX_PATH];
701
702 Globals.bWrapLongLines = !Globals.bWrapLongLines;
703
704 size = GetWindowTextLength(Globals.hEdit) + 1;
705 pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
706 if (!pTemp)
707 {
708 ShowLastError();
709 return;
710 }
711 GetWindowText(Globals.hEdit, pTemp, size);
712 DestroyWindow(Globals.hEdit);
713 GetClientRect(Globals.hMainWnd, &rc);
714 dwStyle = Globals.bWrapLongLines ? EDIT_STYLE_WRAP : EDIT_STYLE;
715 EnableMenuItem(GetMenu(Globals.hMainWnd), CMD_STATUSBAR,
716 MF_BYCOMMAND | (Globals.bWrapLongLines ? MF_DISABLED | MF_GRAYED : MF_ENABLED));
717 if ( Globals.hStatusBar )
718 {
719 if ( Globals.bWrapLongLines )
720 ShowWindow(Globals.hStatusBar, SW_HIDE);
721 else if ( Globals.bShowStatusBar )
722 {
723 GetClientRect(Globals.hStatusBar, &rcstatus);
724 rc.bottom -= (rcstatus.bottom - rcstatus.top);
725 ShowWindow(Globals.hStatusBar, SW_SHOW);
726 }
727 }
728 Globals.hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, edit, NULL, dwStyle,
729 0, 0, rc.right, rc.bottom, Globals.hMainWnd,
730 NULL, Globals.hInstance, NULL);
731 SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, FALSE);
732 SendMessage(Globals.hEdit, EM_LIMITTEXT, 0, 0);
733 SetWindowText(Globals.hEdit, pTemp);
734 SetFocus(Globals.hEdit);
735 Globals.EditProc = (WNDPROC) SetWindowLongPtr(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)EDIT_WndProc);
736 _stprintf(buff, Globals.szStatusBarLineCol, 1, 1);
737 SendMessage(Globals.hStatusBar, SB_SETTEXT, SB_SIMPLEID, (LPARAM)buff);
738 HeapFree(GetProcessHeap(), 0, pTemp);
739 DrawMenuBar(Globals.hMainWnd);
740 }
741
742 VOID DIALOG_SelectFont(VOID)
743 {
744 CHOOSEFONT cf;
745 LOGFONT lf=Globals.lfFont;
746
747 ZeroMemory( &cf, sizeof(cf) );
748 cf.lStructSize=sizeof(cf);
749 cf.hwndOwner=Globals.hMainWnd;
750 cf.lpLogFont=&lf;
751 cf.Flags=CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT;
752
753 if( ChooseFont(&cf) )
754 {
755 HFONT currfont=Globals.hFont;
756
757 Globals.hFont=CreateFontIndirect( &lf );
758 Globals.lfFont=lf;
759 SendMessage( Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, (LPARAM)TRUE );
760 if( currfont!=NULL )
761 DeleteObject( currfont );
762 }
763 }
764
765 typedef HWND (WINAPI *FINDPROC)(LPFINDREPLACE lpfr);
766
767 static VOID DIALOG_SearchDialog(FINDPROC pfnProc)
768 {
769 ZeroMemory(&Globals.find, sizeof(Globals.find));
770 Globals.find.lStructSize = sizeof(Globals.find);
771 Globals.find.hwndOwner = Globals.hMainWnd;
772 Globals.find.hInstance = Globals.hInstance;
773 Globals.find.lpstrFindWhat = Globals.szFindText;
774 Globals.find.wFindWhatLen = SIZEOF(Globals.szFindText);
775 Globals.find.lpstrReplaceWith = Globals.szReplaceText;
776 Globals.find.wReplaceWithLen = SIZEOF(Globals.szReplaceText);
777 Globals.find.Flags = FR_DOWN;
778
779 /* We only need to create the modal FindReplace dialog which will */
780 /* notify us of incoming events using hMainWnd Window Messages */
781
782 Globals.hFindReplaceDlg = pfnProc(&Globals.find);
783 assert(Globals.hFindReplaceDlg !=0);
784 }
785
786 VOID DIALOG_Search(VOID)
787 {
788 DIALOG_SearchDialog(FindText);
789 }
790
791 VOID DIALOG_SearchNext(VOID)
792 {
793 if (Globals.find.lpstrFindWhat != NULL)
794 NOTEPAD_FindNext(&Globals.find, FALSE, TRUE);
795 else
796 DIALOG_Search();
797 }
798
799 VOID DIALOG_Replace(VOID)
800 {
801 DIALOG_SearchDialog(ReplaceText);
802 }
803
804 static INT_PTR CALLBACK DIALOG_GoTo_DialogProc(HWND hwndDialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
805 {
806 BOOL bResult = FALSE;
807 HWND hTextBox;
808 TCHAR szText[32];
809
810 switch(uMsg) {
811 case WM_INITDIALOG:
812 hTextBox = GetDlgItem(hwndDialog, ID_LINENUMBER);
813 _sntprintf(szText, SIZEOF(szText), _T("%d"), lParam);
814 SetWindowText(hTextBox, szText);
815 break;
816 case WM_COMMAND:
817 if (HIWORD(wParam) == BN_CLICKED)
818 {
819 if (LOWORD(wParam) == IDOK)
820 {
821 hTextBox = GetDlgItem(hwndDialog, ID_LINENUMBER);
822 GetWindowText(hTextBox, szText, SIZEOF(szText));
823 EndDialog(hwndDialog, _ttoi(szText));
824 bResult = TRUE;
825 }
826 else if (LOWORD(wParam) == IDCANCEL)
827 {
828 EndDialog(hwndDialog, 0);
829 bResult = TRUE;
830 }
831 }
832 break;
833 }
834
835 return bResult;
836 }
837
838 VOID DIALOG_GoTo(VOID)
839 {
840 INT_PTR nLine;
841 LPTSTR pszText;
842 int nLength, i;
843 DWORD dwStart, dwEnd;
844
845 nLength = GetWindowTextLength(Globals.hEdit);
846 pszText = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(*pszText));
847 if (!pszText)
848 return;
849
850 /* Retrieve current text */
851 GetWindowText(Globals.hEdit, pszText, nLength + 1);
852 SendMessage(Globals.hEdit, EM_GETSEL, (WPARAM) &dwStart, (LPARAM) &dwEnd);
853
854 nLine = 1;
855 for (i = 0; pszText[i] && (i < (int) dwStart); i++)
856 {
857 if (pszText[i] == '\n')
858 nLine++;
859 }
860
861 nLine = DialogBoxParam(Globals.hInstance, MAKEINTRESOURCE(DIALOG_GOTO),
862 Globals.hMainWnd, DIALOG_GoTo_DialogProc, nLine);
863
864 if (nLine >= 1)
865 {
866 for (i = 0; pszText[i] && (nLine > 1) && (i < nLength - 1); i++)
867 {
868 if (pszText[i] == '\n')
869 nLine--;
870 }
871 SendMessage(Globals.hEdit, EM_SETSEL, i, i);
872 SendMessage(Globals.hEdit, EM_SCROLLCARET, 0, 0);
873 }
874 HeapFree(GetProcessHeap(), 0, pszText);
875 }
876
877 VOID DIALOG_StatusBarUpdateCaretPos(VOID)
878 {
879 int line, col;
880 TCHAR buff[MAX_PATH];
881 DWORD dwStart, dwSize;
882
883 SendMessage(Globals.hEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwSize);
884 line = SendMessage(Globals.hEdit, EM_LINEFROMCHAR, (WPARAM)dwStart, 0);
885 col = dwStart - SendMessage(Globals.hEdit, EM_LINEINDEX, (WPARAM)line, 0);
886
887 _stprintf(buff, Globals.szStatusBarLineCol, line+1, col+1);
888 SendMessage(Globals.hStatusBar, SB_SETTEXT, SB_SIMPLEID, (LPARAM)buff);
889 }
890
891 VOID DIALOG_ViewStatusBar(VOID)
892 {
893 RECT rc;
894 RECT rcstatus;
895
896 Globals.bShowStatusBar = !Globals.bShowStatusBar;
897 if ( !Globals.hStatusBar )
898 {
899 Globals.hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE | WS_EX_STATICEDGE, TEXT("test"), Globals.hMainWnd, CMD_STATUSBAR_WND_ID );
900 LoadString(Globals.hInstance, STRING_LINE_COLUMN, Globals.szStatusBarLineCol, MAX_PATH-1);
901 SendMessage(Globals.hStatusBar, SB_SIMPLE, (WPARAM)TRUE, (LPARAM)0);
902 }
903 CheckMenuItem(GetMenu(Globals.hMainWnd), CMD_STATUSBAR,
904 MF_BYCOMMAND | (Globals.bShowStatusBar ? MF_CHECKED : MF_UNCHECKED));
905 DrawMenuBar(Globals.hMainWnd);
906 GetClientRect(Globals.hMainWnd, &rc);
907 GetClientRect(Globals.hStatusBar, &rcstatus);
908 if ( Globals.bShowStatusBar )
909 rc.bottom -= (rcstatus.bottom - rcstatus.top);
910
911 MoveWindow(Globals.hEdit, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
912 ShowWindow(Globals.hStatusBar, Globals.bShowStatusBar);
913 DIALOG_StatusBarUpdateCaretPos();
914 }
915
916 VOID DIALOG_HelpContents(VOID)
917 {
918 WinHelp(Globals.hMainWnd, helpfile, HELP_INDEX, 0);
919 }
920
921 VOID DIALOG_HelpSearch(VOID)
922 {
923 /* Search Help */
924 }
925
926 VOID DIALOG_HelpHelp(VOID)
927 {
928 WinHelp(Globals.hMainWnd, helpfile, HELP_HELPONHELP, 0);
929 }
930
931 #ifdef _MSC_VER
932 #pragma warning(disable : 4100)
933 #endif
934 INT_PTR CALLBACK
935 AboutDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
936 {
937 HWND hLicenseEditWnd;
938 TCHAR *strLicense;
939
940 switch (message)
941 {
942 case WM_INITDIALOG:
943
944 hLicenseEditWnd = GetDlgItem(hDlg, IDC_LICENSE);
945
946 /* 0x1000 should be enought */
947 strLicense = (TCHAR *)_alloca(0x1000);
948 LoadString(GetModuleHandle(NULL), STRING_LICENSE, strLicense, 0x1000);
949
950 SetWindowText(hLicenseEditWnd, strLicense);
951
952 return TRUE;
953
954 case WM_COMMAND:
955
956 if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL))
957 {
958 EndDialog(hDlg, LOWORD(wParam));
959 return TRUE;
960 }
961
962 break;
963 }
964
965 return 0;
966 }
967
968
969
970 VOID DIALOG_HelpAboutWine(VOID)
971 {
972 TCHAR szNotepad[MAX_STRING_LEN];
973 HICON notepadIcon = LoadIcon(Globals.hInstance, MAKEINTRESOURCE(IDI_NPICON));
974
975 LoadString(Globals.hInstance, STRING_NOTEPAD, szNotepad, SIZEOF(szNotepad));
976 ShellAbout(Globals.hMainWnd, szNotepad, 0, notepadIcon);
977 DeleteObject(notepadIcon);
978 }
979
980
981 /***********************************************************************
982 *
983 * DIALOG_FilePageSetup
984 */
985 VOID DIALOG_FilePageSetup(void)
986 {
987 DialogBox(Globals.hInstance, MAKEINTRESOURCE(DIALOG_PAGESETUP),
988 Globals.hMainWnd, DIALOG_PAGESETUP_DlgProc);
989 }
990
991
992 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
993 *
994 * DIALOG_PAGESETUP_DlgProc
995 */
996
997 static INT_PTR WINAPI DIALOG_PAGESETUP_DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
998 {
999
1000 switch (msg)
1001 {
1002 case WM_COMMAND:
1003 if (HIWORD(wParam) == BN_CLICKED)
1004 {
1005 switch (LOWORD(wParam))
1006 {
1007 case IDOK:
1008 /* save user input and close dialog */
1009 GetDlgItemText(hDlg, 0x141, Globals.szHeader, SIZEOF(Globals.szHeader));
1010 GetDlgItemText(hDlg, 0x143, Globals.szFooter, SIZEOF(Globals.szFooter));
1011 GetDlgItemText(hDlg, 0x14A, Globals.szMarginTop, SIZEOF(Globals.szMarginTop));
1012 GetDlgItemText(hDlg, 0x150, Globals.szMarginBottom, SIZEOF(Globals.szMarginBottom));
1013 GetDlgItemText(hDlg, 0x147, Globals.szMarginLeft, SIZEOF(Globals.szMarginLeft));
1014 GetDlgItemText(hDlg, 0x14D, Globals.szMarginRight, SIZEOF(Globals.szMarginRight));
1015 EndDialog(hDlg, IDOK);
1016 return TRUE;
1017
1018 case IDCANCEL:
1019 /* discard user input and close dialog */
1020 EndDialog(hDlg, IDCANCEL);
1021 return TRUE;
1022
1023 case IDHELP:
1024 {
1025 /* FIXME: Bring this to work */
1026 static const TCHAR sorry[] = _T("Sorry, no help available");
1027 static const TCHAR help[] = _T("Help");
1028 MessageBox(Globals.hMainWnd, sorry, help, MB_ICONEXCLAMATION);
1029 return TRUE;
1030 }
1031
1032 default:
1033 break;
1034 }
1035 }
1036 break;
1037
1038 case WM_INITDIALOG:
1039 /* fetch last user input prior to display dialog */
1040 SetDlgItemText(hDlg, 0x141, Globals.szHeader);
1041 SetDlgItemText(hDlg, 0x143, Globals.szFooter);
1042 SetDlgItemText(hDlg, 0x14A, Globals.szMarginTop);
1043 SetDlgItemText(hDlg, 0x150, Globals.szMarginBottom);
1044 SetDlgItemText(hDlg, 0x147, Globals.szMarginLeft);
1045 SetDlgItemText(hDlg, 0x14D, Globals.szMarginRight);
1046 break;
1047 }
1048
1049 return FALSE;
1050 }