2 * ========================================================================
3 * Copyright 2006-2007 University of Washington
4 * Copyright 2013-2017 Eduardo Chappa
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
22 article entitled "About Rich Edit Controls" here (remove all spaces from url):
23 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/
24 platform/commctls/richedit/richeditcontrols/aboutricheditcontrols.asp
32 The following list describes which versions of Rich Edit are included in
33 which releases of Microsoft Windows.
34 Windows XP SP1 Includes Rich Edit 4.1, Rich Edit 3.0, and a Rich Edit 1.0 emulator.
35 Windows XP Includes Rich Edit 3.0 with a Rich Edit 1.0 emulator.
36 Windows Me Includes Rich Edit 1.0 and 3.0.
37 Windows 2000 Includes Rich Edit 3.0 with a Rich Edit 1.0 emulator.
38 Windows NT 4.0 Includes Rich Edit 1.0 and 2.0.
39 Windows 98 Includes Rich Edit 1.0 and 2.0.
40 Windows 95 Includes only Rich Edit 1.0. However, Riched20.dll is
41 compatible with Windows 95 and may be installed by an
42 application that requires it.
44 We're using richedit v2 since it is the first to have Unicode support. Does
45 potentially limit us to Win98 unless we install riched20.dll or it's
48 #define _RICHEDIT_VER 0x0200
57 static const TCHAR g_mswin_tw_class_name
[] = TEXT("PineTWClass");
59 // Maximum amount of text allowed in these textwindows.
60 // Set via a EM_EXLIMITTEXT message.
61 static const LPARAM g_max_text
= 8 * 1024 * 1024 - 1;
66 static LRESULT CALLBACK
mswin_tw_wndproc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
);
67 static UINT
Edit_ExSetSel(HWND hwnd_edit
, LONG cpMin
, LONG cpMax
);
68 static UINT
Edit_ExGetTextLen(HWND hwnd_edit
, DWORD flags
);
69 static BOOL
Edit_ExIsReadOnly(HWND hwnd_edit
);
72 * mswin_tw_create() - Create a mswin textwindow.
75 mswin_tw_create(MSWIN_TEXTWINDOW
*mswin_tw
, LPCTSTR title
)
78 static int s_mswin_tw_class_registered
= 0;
80 mswin_tw
->hwnd
= NULL
;
81 mswin_tw
->hwnd_edit
= NULL
;
83 if(!s_mswin_tw_class_registered
)
87 LoadLibrary(TEXT("riched20.dll"));
89 memset(&wndclass
, 0, sizeof(wndclass
));
90 wndclass
.style
= CS_BYTEALIGNWINDOW
;
91 wndclass
.lpfnWndProc
= mswin_tw_wndproc
;
92 wndclass
.cbClsExtra
= 0;
93 wndclass
.cbWndExtra
= sizeof(ULONG_PTR
);
94 wndclass
.hInstance
= mswin_tw
->hInstance
;
95 wndclass
.hIcon
= LoadIcon (mswin_tw
->hInstance
, MAKEINTRESOURCE( ALPINEICON
));
96 wndclass
.hCursor
= LoadCursor (NULL
, IDC_ARROW
);
97 wndclass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
98 wndclass
.lpszMenuName
= MAKEINTRESOURCE(TEXTWINMENU
);
99 wndclass
.lpszClassName
= g_mswin_tw_class_name
;
101 RegisterClass(&wndclass
);
103 s_mswin_tw_class_registered
= 1;
106 // If we're passed CW_USEDEFAULT as the position, then use right/bottom
107 // as the width/height. Otherwise use the full rect.
108 width
= (mswin_tw
->rcSize
.left
== CW_USEDEFAULT
) ?
109 mswin_tw
->rcSize
.right
: mswin_tw
->rcSize
.right
- mswin_tw
->rcSize
.left
;
110 height
= (mswin_tw
->rcSize
.top
== CW_USEDEFAULT
) ?
111 mswin_tw
->rcSize
.bottom
: mswin_tw
->rcSize
.bottom
- mswin_tw
->rcSize
.top
;
113 mswin_tw
->hwnd
= CreateWindow(
114 g_mswin_tw_class_name
, title
,
116 mswin_tw
->rcSize
.left
,
117 mswin_tw
->rcSize
.top
,
121 mswin_tw
->hInstance
, mswin_tw
);
129 * mswin_tw_close() - close the mswin textwindow.
132 mswin_tw_close(MSWIN_TEXTWINDOW
*mswin_tw
)
134 if(mswin_tw
&& mswin_tw
->hwnd
)
135 DestroyWindow(mswin_tw
->hwnd
);
139 * EditStreamOutCallback - callback for mswin_tw_write_to_file.
141 static DWORD CALLBACK
142 EditStreamOutCallback(DWORD_PTR dwCookie
, LPBYTE lpBuff
, LONG cb
, PLONG pcb
)
144 HANDLE hFile
= (HANDLE
)dwCookie
;
145 return !WriteFile(hFile
, lpBuff
, cb
, (DWORD
*)pcb
, NULL
);
149 * mswin_tw_fill_from_file() - write textwindow contents to a file.
152 mswin_tw_write_to_file(MSWIN_TEXTWINDOW
*mswin_tw
, LPCTSTR file
)
154 BOOL fSuccess
= FALSE
;
155 HANDLE hFile
= CreateFile(file
, GENERIC_WRITE
, 0,
157 FILE_ATTRIBUTE_NORMAL
, NULL
);
158 if(hFile
!= INVALID_HANDLE_VALUE
)
162 es
.dwCookie
= (DWORD_PTR
)hFile
;
164 es
.pfnCallback
= EditStreamOutCallback
;
166 if(SendMessage(mswin_tw
->hwnd_edit
, EM_STREAMOUT
, SF_TEXT
, (LPARAM
)&es
) &&
181 * EditStreamCallback - callback for mswin_tw_fill_from_file.
183 static DWORD CALLBACK
184 EditStreamInCallback(DWORD_PTR dwCookie
, LPBYTE lpBuff
, LONG cb
, PLONG pcb
)
186 HANDLE hFile
= (HANDLE
)dwCookie
;
187 return !ReadFile(hFile
, lpBuff
, cb
, (DWORD
*)pcb
, NULL
);
192 * mswin_tw_fill_from_file() - read file contents into the mswin textwindow.
195 mswin_tw_fill_from_file(MSWIN_TEXTWINDOW
*mswin_tw
, LPCTSTR file
)
197 BOOL fSuccess
= FALSE
;
198 HANDLE hFile
= CreateFile(file
, GENERIC_READ
, FILE_SHARE_READ
,
200 FILE_FLAG_SEQUENTIAL_SCAN
, NULL
);
201 if(hFile
!= INVALID_HANDLE_VALUE
)
205 es
.dwCookie
= (DWORD_PTR
)hFile
;
207 es
.pfnCallback
= EditStreamInCallback
;
209 if(SendMessage(mswin_tw
->hwnd_edit
, EM_STREAMIN
, SF_TEXT
, (LPARAM
)&es
) &&
220 #endif /* ALTED_DOT */
223 * mswin_tw_showwindow() - show the main hwnd (SW_SHOWNORMAL, etc.).
226 mswin_tw_showwindow(MSWIN_TEXTWINDOW
*mswin_tw
, int nCmdShow
)
228 if(mswin_tw
&& mswin_tw
->hwnd
)
229 ShowWindow(mswin_tw
->hwnd
, nCmdShow
);
233 * mswin_tw_setfont() - Sets the hfont for the entire edit control.
236 mswin_tw_setfont(MSWIN_TEXTWINDOW
*mswin_tw
, HFONT hfont
)
238 if(mswin_tw
&& mswin_tw
->hwnd_edit
)
239 SetWindowFont(mswin_tw
->hwnd_edit
, hfont
, TRUE
);
243 * mswin_tw_setcolor() - Set colors for entire edit control. If we're
244 * passed -1 for mswin_tw, then set the colors for all textwindows.
247 mswin_tw_setcolor(MSWIN_TEXTWINDOW
*mswin_tw
,
248 COLORREF TextColor
, COLORREF BackColor
)
250 if(mswin_tw
== (MSWIN_TEXTWINDOW
*)-1)
254 while(hwnd
= FindWindowEx(NULL
, hwnd
, g_mswin_tw_class_name
, NULL
))
256 mswin_tw
= (MSWIN_TEXTWINDOW
*)(LONG_PTR
)GetWindowLongPtr(
257 hwnd
, GWLP_USERDATA
);
260 mswin_tw_setcolor(mswin_tw
, TextColor
, BackColor
);
264 else if(mswin_tw
&& mswin_tw
->hwnd_edit
)
268 memset(&cf2
, 0, sizeof(cf2
));
269 cf2
.cbSize
= sizeof(cf2
);
270 cf2
.dwMask
= CFM_COLOR
;
271 cf2
.crTextColor
= TextColor
;
273 SendMessage(mswin_tw
->hwnd_edit
, EM_SETCHARFORMAT
, SCF_ALL
, (LPARAM
)&cf2
);
274 SendMessage(mswin_tw
->hwnd_edit
, EM_SETBKGNDCOLOR
, 0, BackColor
);
279 * mswin_tw_puts_lptstr() - Stuffs a LPTSTR string at the end of our edit
283 mswin_tw_puts_lptstr(MSWIN_TEXTWINDOW
*mswin_tw
, LPTSTR msg
)
285 if(mswin_tw
&& mswin_tw
->hwnd_edit
)
287 TCHAR lf_str
[] = TEXT("\n");
289 Edit_ExSetSel(mswin_tw
->hwnd_edit
, -1, -1);
290 Edit_ReplaceSel(mswin_tw
->hwnd_edit
, msg
);
292 Edit_ReplaceSel(mswin_tw
->hwnd_edit
, lf_str
);
294 Edit_ScrollCaret(mswin_tw
->hwnd_edit
);
302 * mswin_tw_printf() - printf version of mswin_tw_puts_lptstr.
305 mswin_tw_printf(MSWIN_TEXTWINDOW
*mswin_tw
, LPCTSTR fmt
, ...)
310 va_start(vlist
, fmt
);
311 _vsntprintf(msg
, ARRAYSIZE(msg
), fmt
, vlist
);
314 msg
[ARRAYSIZE(msg
) - 1] = 0;
315 return mswin_tw_puts_lptstr(mswin_tw
, msg
);
319 * mswin_tw_gettextlength() - Returns the number of TCHARs in the edit control.
322 mswin_tw_gettextlength(MSWIN_TEXTWINDOW
*mswin_tw
)
324 if(mswin_tw
&& mswin_tw
->hwnd_edit
)
325 return (UINT
)Edit_ExGetTextLen(mswin_tw
->hwnd_edit
, GTL_USECRLF
);
331 * mswin_tw_gettext() - Return value is the number of TCHARs copied into the
335 mswin_tw_gettext(MSWIN_TEXTWINDOW
*mswin_tw
, LPTSTR lptstr_ret
, int lptstr_len
)
337 if(mswin_tw
&& mswin_tw
->hwnd_edit
)
342 gt
.cb
= lptstr_len
* sizeof(TCHAR
);
343 gt
.flags
= GT_DEFAULT
| GT_USECRLF
;
345 gt
.lpDefaultChar
= NULL
;
346 gt
.lpUsedDefChar
= NULL
;
349 lresult
= SendMessage(mswin_tw
->hwnd_edit
, EM_GETTEXTEX
,
350 (WPARAM
)>
, (LPARAM
)lptstr_ret
);
358 * mswin_tw_setsel() - Set edit control selection.
361 mswin_tw_setsel(MSWIN_TEXTWINDOW
*mswin_tw
, LONG min
, LONG max
)
363 if(mswin_tw
&& mswin_tw
->hwnd_edit
)
365 Edit_ExSetSel(mswin_tw
->hwnd_edit
, min
, max
);
370 * mswin_set_readonly() - Set readonly status.
373 mswin_set_readonly(MSWIN_TEXTWINDOW
*mswin_tw
, BOOL read_only
)
375 if(mswin_tw
&& mswin_tw
->hwnd_edit
)
376 Edit_SetReadOnly(mswin_tw
->hwnd_edit
, read_only
);
380 * mswin_tw_clear() - Clear all text from edit control.
383 mswin_tw_clear(MSWIN_TEXTWINDOW
*mswin_tw
)
385 if(mswin_tw
&& mswin_tw
->hwnd_edit
)
389 stex
.flags
= ST_DEFAULT
;
390 stex
.codepage
= 1200; // Unicode (see richedit.h)
392 SendMessage(mswin_tw
->hwnd_edit
, EM_SETTEXTEX
,
393 (WPARAM
)&stex
, (LPARAM
)TEXT(""));
395 if(mswin_tw
->clear_callback
)
396 mswin_tw
->clear_callback(mswin_tw
);
401 * MySetWindowLongPtr() - Little wrapper routine which calls the
402 * Windows SetWindowLongPtr() and removes the stupid warning which is
403 * just seriously lame.
406 MySetWindowLongPtr(HWND hwnd
, int nIndex
, void *NewLongPtr
)
408 // warning C4244: 'function': conversion from 'LONG_PTR' to 'LONG',
409 // possible loss of data
410 #pragma warning(push)
411 #pragma warning(disable: 4244)
412 return SetWindowLongPtr(hwnd
, nIndex
, (LONG_PTR
)NewLongPtr
);
417 * mswin_tw_wm_command() - WM_CONTEXTMENU handler for textwindows
420 mswin_tw_wm_contextmenu(MSWIN_TEXTWINDOW
*mswin_tw
, HWND hwnd
, HWND hwndContext
,
425 hMenu
= CreatePopupMenu();
437 { IDM_EDIT_COPY
, TEXT("&Copy") },
438 { IDM_EDIT_COPY_APPEND
, TEXT("Copy &Append") },
439 { IDM_EDIT_CLEAR
, TEXT("Clea&r") },
442 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
443 mitem
.cbSize
= sizeof(MENUITEMINFO
);
444 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
445 mitem
.fType
= MFT_STRING
;
447 SendMessage(mswin_tw
->hwnd_edit
, EM_EXGETSEL
, (WPARAM
)0, (LPARAM
)&cr
);
449 for(i
= 0; i
< ARRAYSIZE(s_popup_menu
); i
++)
451 switch(s_popup_menu
[i
].wID
)
454 // Only enable it if there is a clear callback set.
455 mitem
.fState
= (mswin_tw
->clear_callback
) ?
456 MFS_ENABLED
: MFS_GRAYED
;
459 case IDM_EDIT_COPY_APPEND
:
460 // Only enable if there is a selection.
461 mitem
.fState
= (cr
.cpMax
> cr
.cpMin
) ?
462 MFS_ENABLED
: MFS_GRAYED
;
465 mitem
.fState
= MFS_ENABLED
;
469 mitem
.wID
= s_popup_menu
[i
].wID
;
470 mitem
.dwTypeData
= s_popup_menu
[i
].dwTypeData
;
471 mitem
.cch
= (UINT
)_tcslen(s_popup_menu
[i
].dwTypeData
);
472 InsertMenuItem(hMenu
, i
, FALSE
, &mitem
);
475 TrackPopupMenu(hMenu
,
476 TPM_LEFTALIGN
| TPM_TOPALIGN
|
477 TPM_RIGHTBUTTON
| TPM_LEFTBUTTON
,
478 xPos
, yPos
, 0, hwnd
, NULL
);
485 * mswin_tw_wm_command() - WM_COMMAND handler for textwindows
488 mswin_tw_wm_command(HWND hwnd
, int id
, HWND hwndCtl
, UINT codeNotify
)
490 MSWIN_TEXTWINDOW
*mswin_tw
;
492 mswin_tw
= (MSWIN_TEXTWINDOW
*)(LONG_PTR
)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
501 if(mswin_tw
->print_callback
)
502 mswin_tw
->print_callback(mswin_tw
);
506 SendMessage(mswin_tw
->hwnd_edit
, WM_COPY
, 0, 0);
510 mswin_tw_clear(mswin_tw
);
513 case IDM_EDIT_COPY_APPEND
:
516 int text_len0
, text_len1
;
517 HWND hwnd_edit
= mswin_tw
->hwnd_edit
;
518 BOOL EditIsReadOnly
= Edit_ExIsReadOnly(hwnd_edit
);
520 SetWindowRedraw(hwnd_edit
, FALSE
);
521 Edit_SetReadOnly(hwnd_edit
, FALSE
);
523 // Get current selection.
524 SendMessage(hwnd_edit
, EM_EXGETSEL
, (WPARAM
)0, (LPARAM
)&cr
);
526 // Get current length.
527 text_len0
= Edit_ExGetTextLen(hwnd_edit
, 0);
529 // Paste current clip right before our new selection.
530 Edit_ExSetSel(hwnd_edit
, cr
.cpMin
, cr
.cpMin
);
531 SendMessage(hwnd_edit
, WM_PASTE
, 0, 0);
534 text_len1
= Edit_ExGetTextLen(hwnd_edit
, 0);
536 // Select new and old clip and copy em.
537 Edit_ExSetSel(hwnd_edit
, cr
.cpMin
, cr
.cpMax
+ text_len1
- text_len0
);
538 SendMessage(hwnd_edit
, WM_COPY
, 0, 0);
540 // Undo our paste and restore original selection.
541 SendMessage(hwnd_edit
, WM_UNDO
, 0, 0);
542 SendMessage(hwnd_edit
, EM_EXSETSEL
, (WPARAM
)0, (LPARAM
)&cr
);
544 // Set back to read only.
545 Edit_SetReadOnly(hwnd_edit
, EditIsReadOnly
);
546 SetWindowRedraw(hwnd_edit
, TRUE
);
550 case IDM_EDIT_SEL_ALL
:
551 Edit_ExSetSel(mswin_tw
->hwnd_edit
, 0, -1);
557 * mswin_tw_wm_notify() - WM_NOTIFY handler for textwindows
560 mswin_tw_wm_notify(HWND hwnd
, int idCtrl
, NMHDR
*nmhdr
)
562 HWND hwnd_edit
= nmhdr
->hwndFrom
;
564 if(nmhdr
->code
== EN_MSGFILTER
)
566 MSGFILTER
*msg_filter
= (MSGFILTER
*)nmhdr
;
568 if(msg_filter
->msg
== WM_KEYDOWN
)
570 if(msg_filter
->wParam
== 'E')
572 int control_down
= GetKeyState(VK_CONTROL
) < 0;
573 int shift_down
= GetKeyState(VK_SHIFT
) < 0;
575 // Ctrl+Shift+E toggles the readonly attribute on the text
577 if(control_down
&& shift_down
)
578 Edit_SetReadOnly(hwnd_edit
, !Edit_ExIsReadOnly(hwnd_edit
));
582 else if(msg_filter
->msg
== WM_CHAR
)
584 // Only override these keys if this buffer is readonly.
585 if(Edit_ExIsReadOnly(hwnd_edit
))
587 switch(msg_filter
->wParam
)
590 SendMessage(hwnd_edit
, EM_SCROLL
, SB_LINEUP
, 0);
593 SendMessage(hwnd_edit
, EM_SCROLL
, SB_LINEDOWN
, 0);
597 SendMessage(hwnd_edit
, EM_SCROLL
, SB_PAGEUP
, 0);
601 SendMessage(hwnd_edit
, EM_SCROLL
, SB_PAGEDOWN
, 0);
607 else if(nmhdr
->code
== EN_LINK
)
609 ENLINK
*enlink
= (ENLINK
*)nmhdr
;
611 if(enlink
->msg
== WM_LBUTTONDOWN
)
614 TCHAR link_buf
[1024];
617 tr
.lpstrText
= link_buf
;
619 tr
.chrg
= enlink
->chrg
;
620 if(tr
.chrg
.cpMax
- tr
.chrg
.cpMin
> ARRAYSIZE(link_buf
))
621 tr
.chrg
.cpMax
= tr
.chrg
.cpMin
+ ARRAYSIZE(link_buf
);
623 SendMessage(hwnd_edit
, EM_GETTEXTRANGE
, 0, (LPARAM
)&tr
);
624 ShellExecute(hwnd
, TEXT("Open"), link_buf
, NULL
, NULL
, SW_SHOWNORMAL
);
633 * mswin_tw_wndproc() - Main window proc for mswin textwindows.
635 static LRESULT CALLBACK
636 mswin_tw_wndproc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
638 MSWIN_TEXTWINDOW
*mswin_tw
;
640 mswin_tw
= (MSWIN_TEXTWINDOW
*)(LONG_PTR
)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
646 CREATESTRUCT
*pcs
= (CREATESTRUCT
*)lp
;
648 mswin_tw
= (MSWIN_TEXTWINDOW
*)pcs
->lpCreateParams
;
650 MySetWindowLongPtr(hwnd
, GWLP_USERDATA
, mswin_tw
);
652 mswin_tw
->hwnd_edit
= CreateWindowEx(
653 WS_EX_CLIENTEDGE
, RICHEDIT_CLASS
, 0,
654 WS_VISIBLE
| WS_CHILD
|
655 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
656 WS_VSCROLL
| WS_HSCROLL
|
657 ES_MULTILINE
| ES_READONLY
| ES_NOHIDESEL
,
659 hwnd
, 0, mswin_tw
->hInstance
, 0);
661 // We want link and key event notifications.
662 SendMessage(mswin_tw
->hwnd_edit
, EM_SETEVENTMASK
,
663 0, (ENM_KEYEVENTS
| ENM_LINK
));
665 // Specifies the maximum amount of text that can be entered.
666 SendMessage(mswin_tw
->hwnd_edit
, EM_EXLIMITTEXT
, 0, g_max_text
);
668 // Enable automatic detection of URLs by our rich edit control.
669 SendMessage(mswin_tw
->hwnd_edit
, EM_AUTOURLDETECT
, TRUE
, 0);
674 mswin_tw_wm_contextmenu(mswin_tw
, hwnd
, (HWND
)wp
, GET_X_LPARAM(lp
), GET_Y_LPARAM(lp
));
678 return mswin_tw_wm_notify(hwnd
, (int)wp
, (NMHDR
*)lp
);
681 HANDLE_WM_COMMAND(hwnd
, wp
, lp
, mswin_tw_wm_command
);
685 SetFocus(mswin_tw
->hwnd_edit
);
689 MoveWindow(mswin_tw
->hwnd_edit
, 0, 0, LOWORD(lp
), HIWORD(lp
), TRUE
);
692 case WM_WINDOWPOSCHANGED
:
695 WINDOWPOS
*wpos
= (WINDOWPOS
*)lp
;
697 mswin_tw
->rcSize
.left
= wpos
->x
;
698 mswin_tw
->rcSize
.top
= wpos
->y
;
699 mswin_tw
->rcSize
.right
= wpos
->x
+ wpos
->cx
;
700 mswin_tw
->rcSize
.bottom
= wpos
->y
+ wpos
->cy
;
705 if(mswin_tw
->out_file
)
707 mswin_tw
->out_file_ret
= mswin_tw_write_to_file(mswin_tw
,
711 mswin_tw
->hwnd
= NULL
;
712 mswin_tw
->hwnd_edit
= NULL
;
714 if(mswin_tw
->close_callback
)
715 mswin_tw
->close_callback(mswin_tw
);
722 return DefWindowProc(hwnd
, msg
, wp
, lp
);
726 * Edit_ExGetTextLen() - Helper routine for getting count of chars.
729 Edit_ExGetTextLen(HWND hwnd_edit
, DWORD flags
)
733 gtl
.flags
= GTL_PRECISE
| GTL_NUMCHARS
| flags
;
734 gtl
.codepage
= 1200; // Unicode (see richedit.h)
735 return (UINT
)SendMessage(hwnd_edit
, EM_GETTEXTLENGTHEX
, (WPARAM
)>l
, 0);
739 * Edit_ExSetSel() - Helper routine for setting edit selection.
742 Edit_ExSetSel(HWND hwnd_edit
, LONG cpMin
, LONG cpMax
)
747 cpMin
= Edit_ExGetTextLen(hwnd_edit
, 0);
751 return (UINT
)SendMessage(hwnd_edit
, EM_EXSETSEL
, (WPARAM
)0, (LPARAM
)&cr
);
755 * Edit_ExIsReadOnly() - TRUE if edit buffer is read only.
758 Edit_ExIsReadOnly(HWND hwnd_edit
)
762 edit_opts
= SendMessage(hwnd_edit
, EM_GETOPTIONS
, 0, 0);
763 return !!(edit_opts
& ECO_READONLY
);