2 * Wordpad implementation
4 * Copyright 2004 by Krzysztof Foltman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define WIN32_LEAN_AND_MEAN
22 #define _WIN32_IE 0x0400
24 #define MAX_STRING_LEN 255
39 static const WCHAR xszAppTitle
[] = {'W','i','n','e',' ','W','o','r','d','p','a','d',0};
40 static const WCHAR xszMainMenu
[] = {'M','A','I','N','M','E','N','U',0};
42 static const WCHAR wszRichEditClass
[] = {'R','I','C','H','E','D','I','T','2','0','W',0};
43 static const WCHAR wszMainWndClass
[] = {'W','O','R','D','P','A','D','T','O','P',0};
44 static const WCHAR wszAppTitle
[] = {'W','i','n','e',' ','W','o','r','d','p','a','d',0};
47 static HWND hEditorWnd
;
49 static WCHAR wszFilter
[MAX_STRING_LEN
];
50 static WCHAR wszDefaultFileName
[MAX_STRING_LEN
];
51 static WCHAR wszSaveChanges
[MAX_STRING_LEN
];
53 static LRESULT
OnSize( HWND hWnd
, WPARAM wParam
, LPARAM lParam
);
55 /* Load string resources */
56 static void DoLoadStrings(void)
59 static const WCHAR files_rtf
[] = {'*','.','r','t','f','\0'};
60 static const WCHAR files_txt
[] = {'*','.','t','x','t','\0'};
61 static const WCHAR files_all
[] = {'*','.','*','\0'};
62 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongPtr(hMainWnd
, GWLP_HINSTANCE
);
64 LoadStringW(hInstance
, STRING_RICHTEXT_FILES_RTF
, p
, MAX_STRING_LEN
);
66 lstrcpyW(p
, files_rtf
);
68 LoadStringW(hInstance
, STRING_TEXT_FILES_TXT
, p
, MAX_STRING_LEN
);
70 lstrcpyW(p
, files_txt
);
72 LoadStringW(hInstance
, STRING_ALL_FILES
, p
, MAX_STRING_LEN
);
74 lstrcpyW(p
, files_all
);
78 p
= wszDefaultFileName
;
79 LoadStringW(hInstance
, STRING_DEFAULT_FILENAME
, p
, MAX_STRING_LEN
);
82 LoadStringW(hInstance
, STRING_PROMPT_SAVE_CHANGES
, p
, MAX_STRING_LEN
);
85 static void AddButton(HWND hwndToolBar
, int nImage
, int nCommand
)
89 ZeroMemory(&button
, sizeof(button
));
90 button
.iBitmap
= nImage
;
91 button
.idCommand
= nCommand
;
92 button
.fsState
= TBSTATE_ENABLED
;
93 button
.fsStyle
= TBSTYLE_BUTTON
;
96 SendMessageW(hwndToolBar
, TB_ADDBUTTONSW
, 1, (LPARAM
)&button
);
99 static void AddSeparator(HWND hwndToolBar
)
103 ZeroMemory(&button
, sizeof(button
));
105 button
.idCommand
= 0;
107 button
.fsStyle
= TBSTYLE_SEP
;
110 SendMessageW(hwndToolBar
, TB_ADDBUTTONSW
, 1, (LPARAM
)&button
);
113 static DWORD CALLBACK
stream_in(DWORD_PTR cookie
, LPBYTE buffer
, LONG cb
, LONG
*pcb
)
115 HANDLE hFile
= (HANDLE
)cookie
;
118 if(!ReadFile(hFile
, buffer
, cb
, &read
, 0))
126 static DWORD CALLBACK
stream_out(DWORD_PTR cookie
, LPBYTE buffer
, LONG cb
, LONG
*pcb
)
130 HANDLE hFile
= (HANDLE
)cookie
;
132 ret
= WriteFile(hFile
, buffer
, cb
, &written
, 0);
134 if(!ret
|| (cb
!= written
))
142 static WCHAR wszFileName
[MAX_PATH
];
144 static void set_caption(LPCWSTR wszNewFileName
)
146 static const WCHAR wszSeparator
[] = {' ','-',' '};
151 wszNewFileName
= wszDefaultFileName
;
153 wszCaption
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
154 lstrlenW(wszNewFileName
)*sizeof(WCHAR
)+sizeof(wszSeparator
)+sizeof(wszAppTitle
));
159 memcpy(wszCaption
, wszNewFileName
, lstrlenW(wszNewFileName
)*sizeof(WCHAR
));
160 length
+= lstrlenW(wszNewFileName
);
161 memcpy(wszCaption
+ length
, wszSeparator
, sizeof(wszSeparator
));
162 length
+= sizeof(wszSeparator
) / sizeof(WCHAR
);
163 memcpy(wszCaption
+ length
, wszAppTitle
, sizeof(wszAppTitle
));
165 SetWindowTextW(hMainWnd
, wszCaption
);
167 HeapFree(GetProcessHeap(), 0, wszCaption
);
170 static void DoOpenFile(LPCWSTR szOpenFileName
)
175 hFile
= CreateFileW(szOpenFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
176 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
177 if (hFile
== INVALID_HANDLE_VALUE
)
180 es
.dwCookie
= (DWORD_PTR
)hFile
;
181 es
.pfnCallback
= stream_in
;
183 /* FIXME: Handle different file formats */
184 SendMessageW(hEditorWnd
, EM_STREAMIN
, SF_RTF
, (LPARAM
)&es
);
188 SetFocus(hEditorWnd
);
190 set_caption(szOpenFileName
);
192 lstrcpyW(wszFileName
, szOpenFileName
);
193 SendMessageW(hEditorWnd
, EM_SETMODIFY
, FALSE
, 0);
196 static void DoSaveFile(LPCWSTR wszSaveFileName
)
202 hFile
= CreateFileW(wszSaveFileName
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
203 FILE_ATTRIBUTE_NORMAL
, NULL
);
205 if(hFile
== INVALID_HANDLE_VALUE
)
208 stream
.dwCookie
= (DWORD_PTR
)hFile
;
209 stream
.pfnCallback
= stream_out
;
211 /* FIXME: Handle different formats */
212 ret
= SendMessageW(hEditorWnd
, EM_STREAMOUT
, SF_RTF
, (LPARAM
)&stream
);
216 SetFocus(hEditorWnd
);
221 lstrcpyW(wszFileName
, wszSaveFileName
);
222 set_caption(wszFileName
);
223 SendMessageW(hEditorWnd
, EM_SETMODIFY
, FALSE
, 0);
226 static void DialogSaveFile(void)
230 WCHAR wszFile
[MAX_PATH
] = {'\0'};
231 static const WCHAR wszDefExt
[] = {'r','t','f','\0'};
233 ZeroMemory(&sfn
, sizeof(sfn
));
235 sfn
.lStructSize
= sizeof(sfn
);
236 sfn
.Flags
= OFN_HIDEREADONLY
| OFN_PATHMUSTEXIST
;
237 sfn
.hwndOwner
= hMainWnd
;
238 sfn
.lpstrFilter
= wszFilter
;
239 sfn
.lpstrFile
= wszFile
;
240 sfn
.nMaxFile
= MAX_PATH
;
241 sfn
.lpstrDefExt
= wszDefExt
;
243 if(!GetSaveFileNameW(&sfn
))
246 DoSaveFile(sfn
.lpstrFile
);
249 static BOOL
prompt_save_changes(void)
254 gt
.flags
= GTL_NUMCHARS
;
256 if(!SendMessageW(hEditorWnd
, EM_GETTEXTLENGTHEX
, (WPARAM
)>
, 0))
260 if(!SendMessageW(hEditorWnd
, EM_GETMODIFY
, 0, 0))
265 LPWSTR displayFileName
;
270 displayFileName
= wszDefaultFileName
;
272 displayFileName
= wszFileName
;
274 text
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
275 (lstrlenW(displayFileName
)+lstrlenW(wszSaveChanges
))*sizeof(WCHAR
));
280 wsprintfW(text
, wszSaveChanges
, displayFileName
);
282 ret
= MessageBoxW(hMainWnd
, text
, wszAppTitle
, MB_YESNOCANCEL
| MB_ICONEXCLAMATION
);
284 HeapFree(GetProcessHeap(), 0, text
);
293 DoSaveFile(wszFileName
);
304 static void DialogOpenFile(void)
308 WCHAR wszFile
[MAX_PATH
] = {'\0'};
309 static const WCHAR wszDefExt
[] = {'r','t','f','\0'};
311 ZeroMemory(&ofn
, sizeof(ofn
));
313 ofn
.lStructSize
= sizeof(ofn
);
314 ofn
.Flags
= OFN_HIDEREADONLY
| OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
;
315 ofn
.hwndOwner
= hMainWnd
;
316 ofn
.lpstrFilter
= wszFilter
;
317 ofn
.lpstrFile
= wszFile
;
318 ofn
.nMaxFile
= MAX_PATH
;
319 ofn
.lpstrDefExt
= wszDefExt
;
321 if(GetOpenFileNameW(&ofn
))
323 prompt_save_changes();
324 DoOpenFile(ofn
.lpstrFile
);
328 static void HandleCommandLine(LPWSTR cmdline
)
333 /* skip white space */
334 while (*cmdline
== ' ') cmdline
++;
336 /* skip executable name */
337 delimiter
= (*cmdline
== '"' ? '"' : ' ');
339 if (*cmdline
== delimiter
) cmdline
++;
340 while (*cmdline
&& *cmdline
!= delimiter
) cmdline
++;
341 if (*cmdline
== delimiter
) cmdline
++;
343 while (*cmdline
== ' ' || *cmdline
== '-' || *cmdline
== '/')
347 if (*cmdline
++ == ' ') continue;
350 if (option
) cmdline
++;
351 while (*cmdline
== ' ') cmdline
++;
364 /* file name is passed on the command line */
365 if (cmdline
[0] == '"')
368 cmdline
[lstrlenW(cmdline
) - 1] = 0;
371 InvalidateRect(hMainWnd
, NULL
, FALSE
);
375 MessageBox(hMainWnd
, "Printing not implemented", "WordPad", MB_OK
);
378 static void DoDefaultFont(void)
380 static const WCHAR szFaceName
[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n',0};
383 ZeroMemory(&fmt
, sizeof(fmt
));
385 fmt
.cbSize
= sizeof(fmt
);
386 fmt
.dwMask
= CFM_FACE
| CFM_BOLD
| CFM_ITALIC
| CFM_UNDERLINE
;
389 lstrcpyW(fmt
.szFaceName
, szFaceName
);
391 SendMessageW(hEditorWnd
, EM_SETCHARFORMAT
, SCF_DEFAULT
, (LPARAM
)&fmt
);
394 static void update_window(void)
398 GetWindowRect(hMainWnd
, &rect
);
400 (void) OnSize(hMainWnd
, SIZE_RESTORED
, MAKELONG(rect
.bottom
, rect
.right
));
403 static void toggle_toolbar(int bandId
)
405 HWND hwndReBar
= GetDlgItem(hMainWnd
, IDC_REBAR
);
406 REBARBANDINFOW rbbinfo
;
412 rbbinfo
.cbSize
= sizeof(rbbinfo
);
413 rbbinfo
.fMask
= RBBIM_STYLE
| RBBIM_SIZE
;
415 SendMessageW(hwndReBar
, RB_GETBANDINFO
, bandId
, (LPARAM
)&rbbinfo
);
417 if(rbbinfo
.fStyle
& RBBS_HIDDEN
)
420 SendMessageW(hwndReBar
, RB_SHOWBAND
, bandId
, hide
? 0 : 1);
422 if(bandId
== BANDID_TOOLBAR
)
424 rbbinfo
.fMask
^= RBBIM_SIZE
;
426 SendMessageW(hwndReBar
, RB_GETBANDINFO
, BANDID_FORMATBAR
, (LPARAM
)&rbbinfo
);
429 rbbinfo
.fStyle
^= RBBS_BREAK
;
431 rbbinfo
.fStyle
|= RBBS_BREAK
;
433 SendMessageW(hwndReBar
, RB_SETBANDINFO
, BANDID_FORMATBAR
, (LPARAM
)&rbbinfo
);
437 BOOL CALLBACK
datetime_proc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
443 WCHAR buffer
[MAX_STRING_LEN
];
445 HWND hListWnd
= GetDlgItem(hWnd
, IDC_DATETIME
);
448 GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_SHORTDATE
, &st
, 0, (LPWSTR
)&buffer
,
450 SendMessageW(hListWnd
, LB_ADDSTRING
, 0, (LPARAM
)&buffer
);
451 GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, 0, (LPWSTR
)&buffer
,
453 SendMessageW(hListWnd
, LB_ADDSTRING
, 0, (LPARAM
)&buffer
);
454 GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, 0, (LPWSTR
)&buffer
, MAX_STRING_LEN
);
455 SendMessageW(hListWnd
, LB_ADDSTRING
, 0, (LPARAM
)&buffer
);
457 SendMessageW(hListWnd
, LB_SETSEL
, TRUE
, 0);
462 switch(LOWORD(wParam
))
467 HWND hListWnd
= GetDlgItem(hWnd
, IDC_DATETIME
);
469 index
= SendMessageW(hListWnd
, LB_GETCURSEL
, 0, 0);
473 WCHAR buffer
[MAX_STRING_LEN
];
474 SendMessageW(hListWnd
, LB_GETTEXT
, index
, (LPARAM
)&buffer
);
475 SendMessageW(hEditorWnd
, EM_REPLACESEL
, TRUE
, (LPARAM
)&buffer
);
481 EndDialog(hWnd
, wParam
);
488 static LRESULT
OnCreate( HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
490 HWND hToolBarWnd
, hFormatBarWnd
, hReBarWnd
;
491 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongPtr(hWnd
, GWLP_HINSTANCE
);
497 static const WCHAR wszRichEditDll
[] = {'R','I','C','H','E','D','2','0','.','D','L','L','\0'};
498 static const WCHAR wszRichEditText
[] = {'R','i','c','h','E','d','i','t',' ','t','e','x','t','\0'};
500 CreateStatusWindowW(CCS_NODIVIDER
|WS_CHILD
|WS_VISIBLE
, wszRichEditText
, hWnd
, IDC_STATUSBAR
);
502 hReBarWnd
= CreateWindowExW(WS_EX_TOOLWINDOW
, REBARCLASSNAMEW
, NULL
,
503 CCS_NODIVIDER
|WS_CHILD
|WS_VISIBLE
|WS_CLIPSIBLINGS
|WS_CLIPCHILDREN
|RBS_VARHEIGHT
|CCS_TOP
,
504 CW_USEDEFAULT
, CW_USEDEFAULT
, 0, 0, hWnd
, (HMENU
)IDC_REBAR
, hInstance
, NULL
);
506 rbi
.cbSize
= sizeof(rbi
);
509 if(!SendMessageW(hReBarWnd
, RB_SETBARINFO
, 0, (LPARAM
)&rbi
))
512 hToolBarWnd
= CreateToolbarEx(hReBarWnd
, CCS_NOPARENTALIGN
|CCS_NOMOVEY
|WS_VISIBLE
|WS_CHILD
|TBSTYLE_TOOLTIPS
|TBSTYLE_BUTTON
,
514 1, hInstance
, IDB_TOOLBAR
,
516 24, 24, 16, 16, sizeof(TBBUTTON
));
518 ab
.hInst
= HINST_COMMCTRL
;
519 ab
.nID
= IDB_STD_SMALL_COLOR
;
520 nStdBitmaps
= SendMessageW(hToolBarWnd
, TB_ADDBITMAP
, 0, (LPARAM
)&ab
);
522 AddButton(hToolBarWnd
, nStdBitmaps
+STD_FILENEW
, ID_FILE_NEW
);
523 AddButton(hToolBarWnd
, nStdBitmaps
+STD_FILEOPEN
, ID_FILE_OPEN
);
524 AddButton(hToolBarWnd
, nStdBitmaps
+STD_FILESAVE
, ID_FILE_SAVE
);
525 AddSeparator(hToolBarWnd
);
526 AddButton(hToolBarWnd
, nStdBitmaps
+STD_PRINT
, ID_PRINT
);
527 AddButton(hToolBarWnd
, nStdBitmaps
+STD_PRINTPRE
, ID_PREVIEW
);
528 AddSeparator(hToolBarWnd
);
529 AddButton(hToolBarWnd
, nStdBitmaps
+STD_FIND
, ID_FIND
);
530 AddSeparator(hToolBarWnd
);
531 AddButton(hToolBarWnd
, nStdBitmaps
+STD_CUT
, ID_EDIT_CUT
);
532 AddButton(hToolBarWnd
, nStdBitmaps
+STD_COPY
, ID_EDIT_COPY
);
533 AddButton(hToolBarWnd
, nStdBitmaps
+STD_PASTE
, ID_EDIT_PASTE
);
534 AddButton(hToolBarWnd
, nStdBitmaps
+STD_UNDO
, ID_EDIT_UNDO
);
535 AddButton(hToolBarWnd
, nStdBitmaps
+STD_REDOW
, ID_EDIT_REDO
);
536 AddSeparator(hToolBarWnd
);
537 AddButton(hToolBarWnd
, 0, ID_DATETIME
);
539 SendMessageW(hToolBarWnd
, TB_AUTOSIZE
, 0, 0);
541 rbb
.cbSize
= sizeof(rbb
);
542 rbb
.fMask
= RBBIM_SIZE
| RBBIM_CHILDSIZE
| RBBIM_CHILD
| RBBIM_STYLE
;
543 rbb
.fStyle
= RBBS_CHILDEDGE
| RBBS_BREAK
| RBBS_NOGRIPPER
;
545 rbb
.hwndChild
= hToolBarWnd
;
547 rbb
.cyChild
= rbb
.cyMinChild
= HIWORD(SendMessageW(hToolBarWnd
, TB_GETBUTTONSIZE
, 0, 0));
549 SendMessageW(hReBarWnd
, RB_INSERTBAND
, BANDID_TOOLBAR
, (LPARAM
)&rbb
);
551 hFormatBarWnd
= CreateToolbarEx(hReBarWnd
,
552 CCS_NOPARENTALIGN
| CCS_NOMOVEY
| WS_VISIBLE
| TBSTYLE_TOOLTIPS
| TBSTYLE_BUTTON
,
553 IDC_FORMATBAR
, 6, hInstance
, IDB_FORMATBAR
, NULL
, 0, 24, 24, 16, 16, sizeof(TBBUTTON
));
555 ab
.hInst
= HINST_COMMCTRL
;
556 ab
.nID
= IDB_STD_SMALL_COLOR
;
557 nStdBitmaps
= SendMessageW(hFormatBarWnd
, TB_ADDBITMAP
, 6, (LPARAM
)&ab
);
559 AddButton(hFormatBarWnd
, 0, ID_FORMAT_BOLD
);
560 AddButton(hFormatBarWnd
, 1, ID_FORMAT_ITALIC
);
561 AddButton(hFormatBarWnd
, 2, ID_FORMAT_UNDERLINE
);
562 AddSeparator(hFormatBarWnd
);
563 AddButton(hFormatBarWnd
, 3, ID_ALIGN_LEFT
);
564 AddButton(hFormatBarWnd
, 4, ID_ALIGN_CENTER
);
565 AddButton(hFormatBarWnd
, 5, ID_ALIGN_RIGHT
);
567 SendMessageW(hFormatBarWnd
, TB_AUTOSIZE
, 0, 0);
569 rbb
.hwndChild
= hFormatBarWnd
;
571 SendMessageW(hReBarWnd
, RB_INSERTBAND
, BANDID_FORMATBAR
, (LPARAM
)&rbb
);
573 hDLL
= LoadLibraryW(wszRichEditDll
);
576 hEditorWnd
= CreateWindowExW(WS_EX_CLIENTEDGE
, wszRichEditClass
, NULL
,
577 WS_CHILD
|WS_VISIBLE
|ES_MULTILINE
|ES_AUTOVSCROLL
|ES_WANTRETURN
|WS_VSCROLL
,
578 0, 0, 1000, 100, hWnd
, (HMENU
)IDC_EDITOR
, hInstance
, NULL
);
582 fprintf(stderr
, "Error code %u\n", GetLastError());
587 SetFocus(hEditorWnd
);
588 SendMessageW(hEditorWnd
, EM_SETEVENTMASK
, 0, ENM_SELCHANGE
);
593 SendMessageW(hEditorWnd
, EM_SETMODIFY
, FALSE
, 0);
598 static LRESULT
OnUser( HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
600 HWND hwndEditor
= GetDlgItem(hWnd
, IDC_EDITOR
);
601 HWND hwndReBar
= GetDlgItem(hWnd
, IDC_REBAR
);
602 HWND hwndToolBar
= GetDlgItem(hwndReBar
, IDC_TOOLBAR
);
603 HWND hwndFormatBar
= GetDlgItem(hwndReBar
, IDC_FORMATBAR
);
608 ZeroMemory(&fmt
, sizeof(fmt
));
609 fmt
.cbSize
= sizeof(fmt
);
611 ZeroMemory(&pf
, sizeof(pf
));
612 pf
.cbSize
= sizeof(pf
);
614 SendMessageW(hwndEditor
, EM_GETCHARFORMAT
, TRUE
, (LPARAM
)&fmt
);
616 SendMessageW(hwndEditor
, EM_GETSEL
, (WPARAM
)&from
, (LPARAM
)&to
);
617 SendMessageW(hwndToolBar
, TB_ENABLEBUTTON
, ID_EDIT_UNDO
,
618 SendMessageW(hwndEditor
, EM_CANUNDO
, 0, 0));
619 SendMessageW(hwndToolBar
, TB_ENABLEBUTTON
, ID_EDIT_REDO
,
620 SendMessageW(hwndEditor
, EM_CANREDO
, 0, 0));
621 SendMessageW(hwndToolBar
, TB_ENABLEBUTTON
, ID_EDIT_CUT
, from
== to
? 0 : 1);
622 SendMessageW(hwndToolBar
, TB_ENABLEBUTTON
, ID_EDIT_COPY
, from
== to
? 0 : 1);
624 SendMessageW(hwndFormatBar
, TB_CHECKBUTTON
, ID_FORMAT_BOLD
, (fmt
.dwMask
& CFM_BOLD
) &&
625 (fmt
.dwEffects
& CFE_BOLD
));
626 SendMessageW(hwndFormatBar
, TB_INDETERMINATE
, ID_FORMAT_BOLD
, !(fmt
.dwMask
& CFM_BOLD
));
627 SendMessageW(hwndFormatBar
, TB_CHECKBUTTON
, ID_FORMAT_ITALIC
, (fmt
.dwMask
& CFM_ITALIC
) &&
628 (fmt
.dwEffects
& CFE_ITALIC
));
629 SendMessageW(hwndFormatBar
, TB_INDETERMINATE
, ID_FORMAT_ITALIC
, !(fmt
.dwMask
& CFM_ITALIC
));
630 SendMessageW(hwndFormatBar
, TB_CHECKBUTTON
, ID_FORMAT_UNDERLINE
, (fmt
.dwMask
& CFM_UNDERLINE
) &&
631 (fmt
.dwEffects
& CFE_UNDERLINE
));
632 SendMessageW(hwndFormatBar
, TB_INDETERMINATE
, ID_FORMAT_UNDERLINE
, !(fmt
.dwMask
& CFM_UNDERLINE
));
634 SendMessageW(hwndEditor
, EM_GETPARAFORMAT
, 0, (LPARAM
)&pf
);
635 SendMessageW(hwndFormatBar
, TB_CHECKBUTTON
, ID_ALIGN_LEFT
, (pf
.wAlignment
== PFA_LEFT
));
636 SendMessageW(hwndFormatBar
, TB_CHECKBUTTON
, ID_ALIGN_CENTER
, (pf
.wAlignment
== PFA_CENTER
));
637 SendMessageW(hwndFormatBar
, TB_CHECKBUTTON
, ID_ALIGN_RIGHT
, (pf
.wAlignment
== PFA_RIGHT
));
642 static LRESULT
OnNotify( HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
644 HWND hwndEditor
= GetDlgItem(hWnd
, IDC_EDITOR
);
645 NMHDR
*pHdr
= (NMHDR
*)lParam
;
647 if (pHdr
->hwndFrom
!= hwndEditor
)
650 if (pHdr
->code
== EN_SELCHANGE
)
652 SELCHANGE
*pSC
= (SELCHANGE
*)lParam
;
655 sprintf( buf
,"selection = %d..%d, line count=%ld",
656 pSC
->chrg
.cpMin
, pSC
->chrg
.cpMax
,
657 SendMessage(hwndEditor
, EM_GETLINECOUNT
, 0, 0));
658 SetWindowText(GetDlgItem(hWnd
, IDC_STATUSBAR
), buf
);
659 SendMessage(hWnd
, WM_USER
, 0, 0);
665 static LRESULT
OnCommand( HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
667 HWND hwndEditor
= GetDlgItem(hWnd
, IDC_EDITOR
);
668 HWND hwndStatus
= GetDlgItem(hWnd
, IDC_STATUSBAR
);
670 if ((HWND
)lParam
== hwndEditor
)
673 switch(LOWORD(wParam
))
676 PostMessageW(hWnd
, WM_CLOSE
, 0, 0);
680 if(prompt_save_changes())
683 wszFileName
[0] = '\0';
684 SetWindowTextW(hwndEditor
, wszFileName
);
685 SendMessageW(hEditorWnd
, EM_SETMODIFY
, FALSE
, 0);
686 /* FIXME: set default format too */
697 DoSaveFile(wszFileName
);
710 static const WCHAR wszNotImplemented
[] = {'N','o','t',' ',
711 'i','m','p','l','e','m','e','n','t','e','d','\0'};
712 MessageBoxW(hWnd
, wszNotImplemented
, wszAppTitle
, MB_OK
);
717 case ID_FORMAT_ITALIC
:
718 case ID_FORMAT_UNDERLINE
:
722 if (LOWORD(wParam
) == ID_FORMAT_ITALIC
) mask
= CFM_ITALIC
;
723 if (LOWORD(wParam
) == ID_FORMAT_UNDERLINE
) mask
= CFM_UNDERLINE
;
725 ZeroMemory(&fmt
, sizeof(fmt
));
726 fmt
.cbSize
= sizeof(fmt
);
727 SendMessageW(hwndEditor
, EM_GETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&fmt
);
728 if (!(fmt
.dwMask
&mask
))
729 fmt
.dwEffects
|= mask
;
731 fmt
.dwEffects
^= mask
;
733 SendMessageW(hwndEditor
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&fmt
);
738 PostMessageW(hwndEditor
, WM_CUT
, 0, 0);
742 PostMessageW(hwndEditor
, WM_COPY
, 0, 0);
746 PostMessageW(hwndEditor
, WM_PASTE
, 0, 0);
750 PostMessageW(hwndEditor
, WM_CLEAR
, 0, 0);
753 case ID_EDIT_SELECTALL
:
755 CHARRANGE range
= {0, -1};
756 SendMessageW(hwndEditor
, EM_EXSETSEL
, 0, (LPARAM
)&range
);
757 /* SendMessage(hwndEditor, EM_SETSEL, 0, -1); */
761 case ID_EDIT_GETTEXT
:
763 int nLen
= GetWindowTextLengthW(hwndEditor
);
764 LPWSTR data
= HeapAlloc( GetProcessHeap(), 0, (nLen
+1)*sizeof(WCHAR
) );
767 GetWindowTextW(hwndEditor
, data
, nLen
+1);
768 MessageBoxW(NULL
, data
, xszAppTitle
, MB_OK
);
770 HeapFree( GetProcessHeap(), 0, data
);
771 data
= HeapAlloc(GetProcessHeap(), 0, (nLen
+1)*sizeof(WCHAR
));
773 tr
.chrg
.cpMax
= nLen
;
775 SendMessage (hwndEditor
, EM_GETTEXTRANGE
, 0, (LPARAM
)&tr
);
776 MessageBoxW(NULL
, data
, xszAppTitle
, MB_OK
);
777 HeapFree( GetProcessHeap(), 0, data
);
779 /* SendMessage(hwndEditor, EM_SETSEL, 0, -1); */
783 case ID_EDIT_CHARFORMAT
:
784 case ID_EDIT_DEFCHARFORMAT
:
788 ZeroMemory(&cf
, sizeof(cf
));
789 cf
.cbSize
= sizeof(cf
);
791 i
= SendMessageW(hwndEditor
, EM_GETCHARFORMAT
,
792 LOWORD(wParam
) == ID_EDIT_CHARFORMAT
, (LPARAM
)&cf
);
796 case ID_EDIT_PARAFORMAT
:
799 ZeroMemory(&pf
, sizeof(pf
));
800 pf
.cbSize
= sizeof(pf
);
801 SendMessageW(hwndEditor
, EM_GETPARAFORMAT
, 0, (LPARAM
)&pf
);
805 case ID_EDIT_SELECTIONINFO
:
807 CHARRANGE range
= {0, -1};
811 SendMessage(hwndEditor
, EM_EXGETSEL
, 0, (LPARAM
)&range
);
812 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
) * (range
.cpMax
-range
.cpMin
+1));
813 SendMessage(hwndEditor
, EM_GETSELTEXT
, 0, (LPARAM
)data
);
814 sprintf(buf
, "Start = %d, End = %d", range
.cpMin
, range
.cpMax
);
815 MessageBoxA(hWnd
, buf
, "Editor", MB_OK
);
816 MessageBoxW(hWnd
, data
, xszAppTitle
, MB_OK
);
817 HeapFree( GetProcessHeap(), 0, data
);
818 /* SendMessage(hwndEditor, EM_SETSEL, 0, -1); */
822 case ID_EDIT_READONLY
:
824 long nStyle
= GetWindowLong(hwndEditor
, GWL_STYLE
);
825 if (nStyle
& ES_READONLY
)
826 SendMessageW(hwndEditor
, EM_SETREADONLY
, 0, 0);
828 SendMessageW(hwndEditor
, EM_SETREADONLY
, 1, 0);
832 case ID_EDIT_MODIFIED
:
833 if (SendMessageW(hwndEditor
, EM_GETMODIFY
, 0, 0))
834 SendMessageW(hwndEditor
, EM_SETMODIFY
, 0, 0);
836 SendMessageW(hwndEditor
, EM_SETMODIFY
, 1, 0);
840 SendMessageW(hwndEditor
, EM_UNDO
, 0, 0);
844 SendMessageW(hwndEditor
, EM_REDO
, 0, 0);
848 case ID_ALIGN_CENTER
:
853 pf
.cbSize
= sizeof(pf
);
854 pf
.dwMask
= PFM_ALIGNMENT
;
855 switch(LOWORD(wParam
)) {
856 case ID_ALIGN_LEFT
: pf
.wAlignment
= PFA_LEFT
; break;
857 case ID_ALIGN_CENTER
: pf
.wAlignment
= PFA_CENTER
; break;
858 case ID_ALIGN_RIGHT
: pf
.wAlignment
= PFA_RIGHT
; break;
860 SendMessageW(hwndEditor
, EM_SETPARAFORMAT
, 0, (LPARAM
)&pf
);
865 SendMessageW(hwndEditor
, EM_SETBKGNDCOLOR
, 1, 0);
869 SendMessageW(hwndEditor
, EM_SETBKGNDCOLOR
, 0, RGB(255,255,192));
872 case ID_TOGGLE_TOOLBAR
:
873 toggle_toolbar(BANDID_TOOLBAR
);
877 case ID_TOGGLE_FORMATBAR
:
878 toggle_toolbar(BANDID_FORMATBAR
);
882 case ID_TOGGLE_STATUSBAR
:
883 ShowWindow(hwndStatus
, IsWindowVisible(hwndStatus
) ? SW_HIDE
: SW_SHOW
);
889 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongPtr(hWnd
, GWLP_HINSTANCE
);
890 DialogBoxW(hInstance
, MAKEINTRESOURCEW(IDD_DATETIME
), hWnd
, (DLGPROC
)datetime_proc
);
895 SendMessageW(hwndEditor
, WM_COMMAND
, wParam
, lParam
);
901 static LRESULT
OnInitPopupMenu( HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
903 HMENU hMenu
= (HMENU
)wParam
;
904 HWND hwndEditor
= GetDlgItem(hWnd
, IDC_EDITOR
);
905 HWND hwndReBar
= GetDlgItem(hWnd
, IDC_REBAR
);
906 HWND hwndStatus
= GetDlgItem(hWnd
, IDC_STATUSBAR
);
909 REBARBANDINFOW rbbinfo
;
912 SendMessageW(hEditorWnd
, EM_GETSEL
, (WPARAM
)&selFrom
, (LPARAM
)&selTo
);
913 EnableMenuItem(hMenu
, ID_EDIT_COPY
, MF_BYCOMMAND
|(selFrom
== selTo
) ? MF_GRAYED
: MF_ENABLED
);
914 EnableMenuItem(hMenu
, ID_EDIT_CUT
, MF_BYCOMMAND
|(selFrom
== selTo
) ? MF_GRAYED
: MF_ENABLED
);
916 pf
.cbSize
= sizeof(PARAFORMAT
);
917 SendMessageW(hwndEditor
, EM_GETPARAFORMAT
, 0, (LPARAM
)&pf
);
918 CheckMenuItem(hMenu
, ID_EDIT_READONLY
,
919 MF_BYCOMMAND
|(GetWindowLong(hwndEditor
, GWL_STYLE
)&ES_READONLY
? MF_CHECKED
: MF_UNCHECKED
));
920 CheckMenuItem(hMenu
, ID_EDIT_MODIFIED
,
921 MF_BYCOMMAND
|(SendMessage(hwndEditor
, EM_GETMODIFY
, 0, 0) ? MF_CHECKED
: MF_UNCHECKED
));
922 if (pf
.dwMask
& PFM_ALIGNMENT
)
923 nAlignment
= pf
.wAlignment
;
924 CheckMenuItem(hMenu
, ID_ALIGN_LEFT
, MF_BYCOMMAND
|(nAlignment
== PFA_LEFT
) ?
925 MF_CHECKED
: MF_UNCHECKED
);
926 CheckMenuItem(hMenu
, ID_ALIGN_CENTER
, MF_BYCOMMAND
|(nAlignment
== PFA_CENTER
) ?
927 MF_CHECKED
: MF_UNCHECKED
);
928 CheckMenuItem(hMenu
, ID_ALIGN_RIGHT
, MF_BYCOMMAND
|(nAlignment
== PFA_RIGHT
) ?
929 MF_CHECKED
: MF_UNCHECKED
);
930 EnableMenuItem(hMenu
, ID_EDIT_UNDO
, MF_BYCOMMAND
|(SendMessageW(hwndEditor
, EM_CANUNDO
, 0, 0)) ?
931 MF_ENABLED
: MF_GRAYED
);
932 EnableMenuItem(hMenu
, ID_EDIT_REDO
, MF_BYCOMMAND
|(SendMessageW(hwndEditor
, EM_CANREDO
, 0, 0)) ?
933 MF_ENABLED
: MF_GRAYED
);
935 rbbinfo
.cbSize
= sizeof(rbbinfo
);
936 rbbinfo
.fMask
= RBBIM_STYLE
;
937 SendMessageW(hwndReBar
, RB_GETBANDINFO
, BANDID_TOOLBAR
, (LPARAM
)&rbbinfo
);
939 CheckMenuItem(hMenu
, ID_TOGGLE_TOOLBAR
, MF_BYCOMMAND
|(rbbinfo
.fStyle
& RBBS_HIDDEN
) ?
940 MF_UNCHECKED
: MF_CHECKED
);
942 SendMessageW(hwndReBar
, RB_GETBANDINFO
, BANDID_FORMATBAR
, (LPARAM
)&rbbinfo
);
944 CheckMenuItem(hMenu
, ID_TOGGLE_FORMATBAR
, MF_BYCOMMAND
|(rbbinfo
.fStyle
& RBBS_HIDDEN
) ?
945 MF_UNCHECKED
: MF_CHECKED
);
947 CheckMenuItem(hMenu
, ID_TOGGLE_STATUSBAR
, MF_BYCOMMAND
|IsWindowVisible(hwndStatus
) ?
948 MF_CHECKED
: MF_UNCHECKED
);
952 static LRESULT
OnSize( HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
956 HWND hwndEditor
= GetDlgItem(hWnd
, IDC_EDITOR
);
957 HWND hwndStatusBar
= GetDlgItem(hWnd
, IDC_STATUSBAR
);
958 HWND hwndReBar
= GetDlgItem(hWnd
, IDC_REBAR
);
960 REBARBANDINFOW rbbinfo
;
965 SendMessageW(hwndStatusBar
, WM_SIZE
, 0, 0);
966 if (IsWindowVisible(hwndStatusBar
))
968 GetClientRect(hwndStatusBar
, &rc
);
969 nStatusSize
= rc
.bottom
- rc
.top
;
977 rbbinfo
.cbSize
= sizeof(rbbinfo
);
978 rbbinfo
.fMask
= RBBIM_STYLE
;
980 SendMessageW(hwndReBar
, RB_GETBANDINFO
, BANDID_TOOLBAR
, (LPARAM
)&rbbinfo
);
981 if(rbbinfo
.fStyle
& RBBS_HIDDEN
)
984 SendMessageW(hwndReBar
, RB_GETBANDINFO
, BANDID_FORMATBAR
, (LPARAM
)&rbbinfo
);
985 if(rbbinfo
.fStyle
& RBBS_HIDDEN
)
988 rebarHeight
= rebarRows
? SendMessageW(hwndReBar
, RB_GETBARHEIGHT
, 0, 0) : 0;
990 rc
.top
= rc
.left
= 0;
991 rc
.bottom
= rebarHeight
;
992 rc
.right
= LOWORD(lParam
);
993 SendMessageW(hwndReBar
, RB_SIZETORECT
, 0, (LPARAM
)&rc
);
997 GetClientRect(hWnd
, &rc
);
998 MoveWindow(hwndEditor
, 0, rebarHeight
, rc
.right
, rc
.bottom
-nStatusSize
-rebarHeight
, TRUE
);
1001 return DefWindowProcW(hWnd
, WM_SIZE
, wParam
, lParam
);
1004 static LRESULT CALLBACK
WndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1009 return OnCreate( hWnd
, wParam
, lParam
);
1012 return OnUser( hWnd
, wParam
, lParam
);
1015 return OnNotify( hWnd
, wParam
, lParam
);
1018 return OnCommand( hWnd
, wParam
, lParam
);
1025 if(prompt_save_changes())
1031 SetFocus(GetDlgItem(hWnd
, IDC_EDITOR
));
1034 case WM_INITMENUPOPUP
:
1035 return OnInitPopupMenu( hWnd
, wParam
, lParam
);
1038 return OnSize( hWnd
, wParam
, lParam
);
1041 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1047 int CALLBACK
WinMain(HINSTANCE hInstance
, HINSTANCE hOldInstance
, LPSTR szCmdParagraph
, int res
)
1049 INITCOMMONCONTROLSEX classes
= {8, ICC_BAR_CLASSES
|ICC_COOL_CLASSES
};
1053 static const WCHAR wszAccelTable
[] = {'M','A','I','N','A','C','C','E','L',
1054 'T','A','B','L','E','\0'};
1056 InitCommonControlsEx(&classes
);
1058 hAccel
= LoadAcceleratorsW(hInstance
, wszAccelTable
);
1060 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1061 wc
.lpfnWndProc
= WndProc
;
1064 wc
.hInstance
= hInstance
;
1065 wc
.hIcon
= LoadIconW(hInstance
, MAKEINTRESOURCEW(IDI_WORDPAD
));
1066 wc
.hCursor
= LoadCursor(NULL
, IDC_IBEAM
);
1067 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
1068 wc
.lpszMenuName
= xszMainMenu
;
1069 wc
.lpszClassName
= wszMainWndClass
;
1070 RegisterClassW(&wc
);
1072 hMainWnd
= CreateWindowExW(0, wszMainWndClass
, wszAppTitle
, WS_OVERLAPPEDWINDOW
,
1073 CW_USEDEFAULT
, CW_USEDEFAULT
, 680, 260, NULL
, NULL
, hInstance
, NULL
);
1074 ShowWindow(hMainWnd
, SW_SHOWDEFAULT
);
1078 HandleCommandLine(GetCommandLineW());
1080 while(GetMessageW(&msg
,0,0,0))
1082 if (TranslateAcceleratorW(hMainWnd
, hAccel
, &msg
))
1084 TranslateMessage(&msg
);
1085 DispatchMessageW(&msg
);
1086 if (!PeekMessageW(&msg
, 0, 0, 0, PM_NOREMOVE
))
1087 SendMessageW(hMainWnd
, WM_USER
, 0, 0);