* New alpha version 2.24.1
[alpine.git] / pico / osdep / mswin_tw.c
blob5187b80ff264580e891f6b9ab7ddea4f1326728f
1 /*
2 * ========================================================================
3 * Copyright 2006-2007 University of Washington
4 * Copyright 2013-2021 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 * ========================================================================
14 #define STRICT
15 #define UNICODE
16 #define _UNICODE
17 #include <windows.h>
18 #include <windowsx.h>
19 #include <tchar.h>
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
26 Rich Edit version DLL
27 1.0 Riched32.dll
28 2.0 Riched20.dll
29 3.0 Riched20.dll
30 4.1 Msftedit.dll
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
46 already there.
48 #define _RICHEDIT_VER 0x0200
49 #include <richedit.h>
50 #include "resource.h"
52 #include "mswin_tw.h"
55 * Globals
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;
64 * Function prototypes
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.
74 int
75 mswin_tw_create(MSWIN_TEXTWINDOW *mswin_tw, LPCTSTR title)
77 int width, height;
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)
85 WNDCLASS wndclass;
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,
115 WS_OVERLAPPEDWINDOW,
116 mswin_tw->rcSize.left,
117 mswin_tw->rcSize.top,
118 width,
119 height,
120 HWND_DESKTOP, NULL,
121 mswin_tw->hInstance, mswin_tw);
122 if(!mswin_tw->hwnd)
123 return 0;
125 return 1;
129 * mswin_tw_close() - close the mswin textwindow.
131 void
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.
151 BOOL
152 mswin_tw_write_to_file(MSWIN_TEXTWINDOW *mswin_tw, LPCTSTR file)
154 BOOL fSuccess = FALSE;
155 HANDLE hFile = CreateFile(file, GENERIC_WRITE, 0,
156 0, OPEN_ALWAYS,
157 FILE_ATTRIBUTE_NORMAL, NULL);
158 if(hFile != INVALID_HANDLE_VALUE)
160 EDITSTREAM es;
162 es.dwCookie = (DWORD_PTR)hFile;
163 es.dwError = 0;
164 es.pfnCallback = EditStreamOutCallback;
166 if(SendMessage(mswin_tw->hwnd_edit, EM_STREAMOUT, SF_TEXT, (LPARAM)&es) &&
167 es.dwError == 0)
169 fSuccess = TRUE;
173 CloseHandle(hFile);
174 return fSuccess;
178 #ifdef ALTED_DOT
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.
194 BOOL
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,
199 0, OPEN_EXISTING,
200 FILE_FLAG_SEQUENTIAL_SCAN, NULL);
201 if(hFile != INVALID_HANDLE_VALUE)
203 EDITSTREAM es;
205 es.dwCookie = (DWORD_PTR)hFile;
206 es.dwError = 0;
207 es.pfnCallback = EditStreamInCallback;
209 if(SendMessage(mswin_tw->hwnd_edit, EM_STREAMIN, SF_TEXT, (LPARAM)&es) &&
210 es.dwError == 0)
212 fSuccess = TRUE;
216 CloseHandle(hFile);
217 return fSuccess;
220 #endif /* ALTED_DOT */
223 * mswin_tw_showwindow() - show the main hwnd (SW_SHOWNORMAL, etc.).
225 void
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.
235 void
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.
246 void
247 mswin_tw_setcolor(MSWIN_TEXTWINDOW *mswin_tw,
248 COLORREF TextColor, COLORREF BackColor)
250 if(mswin_tw == (MSWIN_TEXTWINDOW *)-1)
252 HWND hwnd = NULL;
254 while(hwnd = FindWindowEx(NULL, hwnd, g_mswin_tw_class_name, NULL))
256 mswin_tw = (MSWIN_TEXTWINDOW *)(LONG_PTR)GetWindowLongPtr(
257 hwnd, GWLP_USERDATA);
258 if(mswin_tw)
260 mswin_tw_setcolor(mswin_tw, TextColor, BackColor);
264 else if(mswin_tw && mswin_tw->hwnd_edit)
266 CHARFORMAT2W cf2;
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
280 * control.
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);
295 return 1;
298 return 0;
302 * mswin_tw_printf() - printf version of mswin_tw_puts_lptstr.
305 mswin_tw_printf(MSWIN_TEXTWINDOW *mswin_tw, LPCTSTR fmt, ...)
307 TCHAR msg[1024];
308 va_list vlist;
310 va_start(vlist, fmt);
311 _vsntprintf(msg, ARRAYSIZE(msg), fmt, vlist);
312 va_end(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.
321 UINT
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);
327 return 0;
331 * mswin_tw_gettext() - Return value is the number of TCHARs copied into the
332 * output buffer.
334 UINT
335 mswin_tw_gettext(MSWIN_TEXTWINDOW *mswin_tw, LPTSTR lptstr_ret, int lptstr_len)
337 if(mswin_tw && mswin_tw->hwnd_edit)
339 GETTEXTEX gt;
340 LRESULT lresult;
342 gt.cb = lptstr_len * sizeof(TCHAR);
343 gt.flags = GT_DEFAULT | GT_USECRLF;
344 gt.codepage = 1200;
345 gt.lpDefaultChar = NULL;
346 gt.lpUsedDefChar = NULL;
348 lptstr_ret[0] = 0;
349 lresult = SendMessage(mswin_tw->hwnd_edit, EM_GETTEXTEX,
350 (WPARAM)&gt, (LPARAM)lptstr_ret);
351 return (int)lresult;
354 return 0;
358 * mswin_tw_setsel() - Set edit control selection.
360 void
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.
372 void
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.
382 void
383 mswin_tw_clear(MSWIN_TEXTWINDOW *mswin_tw)
385 if(mswin_tw && mswin_tw->hwnd_edit)
387 SETTEXTEX stex;
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.
405 static LONG_PTR
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);
413 #pragma warning(pop)
417 * mswin_tw_wm_command() - WM_CONTEXTMENU handler for textwindows
419 static void
420 mswin_tw_wm_contextmenu(MSWIN_TEXTWINDOW *mswin_tw, HWND hwnd, HWND hwndContext,
421 int xPos, int yPos)
423 HMENU hMenu;
425 hMenu = CreatePopupMenu();
426 if(hMenu)
428 int i;
429 CHARRANGE cr;
430 MENUITEMINFO mitem;
431 static const struct
433 UINT wID;
434 LPTSTR dwTypeData;
435 } s_popup_menu[] =
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)
453 case IDM_EDIT_CLEAR:
454 // Only enable it if there is a clear callback set.
455 mitem.fState = (mswin_tw->clear_callback) ?
456 MFS_ENABLED : MFS_GRAYED;
457 break;
458 case IDM_EDIT_COPY:
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;
463 break;
464 default:
465 mitem.fState = MFS_ENABLED;
466 break;
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);
480 DestroyMenu(hMenu);
485 * mswin_tw_wm_command() - WM_COMMAND handler for textwindows
487 static void
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);
494 switch(id)
496 case IDM_FILE_CLOSE:
497 DestroyWindow(hwnd);
498 break;
500 case IDM_FILE_PRINT:
501 if(mswin_tw->print_callback)
502 mswin_tw->print_callback(mswin_tw);
503 break;
505 case IDM_EDIT_COPY:
506 SendMessage(mswin_tw->hwnd_edit, WM_COPY, 0, 0);
507 break;
509 case IDM_EDIT_CLEAR:
510 mswin_tw_clear(mswin_tw);
511 break;
513 case IDM_EDIT_COPY_APPEND:
515 CHARRANGE cr;
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);
533 // Get new length.
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);
547 break;
550 case IDM_EDIT_SEL_ALL:
551 Edit_ExSetSel(mswin_tw->hwnd_edit, 0, -1);
552 break;
557 * mswin_tw_wm_notify() - WM_NOTIFY handler for textwindows
559 static LRESULT
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
576 // buffer.
577 if(control_down && shift_down)
578 Edit_SetReadOnly(hwnd_edit, !Edit_ExIsReadOnly(hwnd_edit));
579 return TRUE;
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)
589 case 'k':
590 SendMessage(hwnd_edit, EM_SCROLL, SB_LINEUP, 0);
591 return TRUE;
592 case 'j':
593 SendMessage(hwnd_edit, EM_SCROLL, SB_LINEDOWN, 0);
594 return TRUE;
595 case '-':
596 case 'b':
597 SendMessage(hwnd_edit, EM_SCROLL, SB_PAGEUP, 0);
598 return TRUE;
599 case ' ':
600 case 'f':
601 SendMessage(hwnd_edit, EM_SCROLL, SB_PAGEDOWN, 0);
602 return TRUE;
607 else if(nmhdr->code == EN_LINK)
609 ENLINK *enlink = (ENLINK *)nmhdr;
611 if(enlink->msg == WM_LBUTTONDOWN)
613 TEXTRANGE tr;
614 TCHAR link_buf[1024];
616 link_buf[0] = 0;
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);
625 return TRUE;
629 return FALSE;
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);
642 switch(msg)
644 case WM_CREATE:
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,
658 0, 0, 1, 1,
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);
670 break;
673 case WM_CONTEXTMENU:
674 mswin_tw_wm_contextmenu(mswin_tw, hwnd, (HWND)wp, GET_X_LPARAM(lp), GET_Y_LPARAM(lp));
675 break;
677 case WM_NOTIFY:
678 return mswin_tw_wm_notify(hwnd, (int)wp, (NMHDR *)lp);
680 case WM_COMMAND:
681 HANDLE_WM_COMMAND(hwnd, wp, lp, mswin_tw_wm_command);
682 break;
684 case WM_SETFOCUS:
685 SetFocus(mswin_tw->hwnd_edit);
686 return TRUE;
688 case WM_SIZE:
689 MoveWindow(mswin_tw->hwnd_edit, 0, 0, LOWORD(lp), HIWORD(lp), TRUE);
690 break;
692 case WM_WINDOWPOSCHANGED:
693 if(!IsIconic(hwnd))
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;
702 break;
704 case WM_DESTROY:
705 if(mswin_tw->out_file)
707 mswin_tw->out_file_ret = mswin_tw_write_to_file(mswin_tw,
708 mswin_tw->out_file);
711 mswin_tw->hwnd = NULL;
712 mswin_tw->hwnd_edit = NULL;
714 if(mswin_tw->close_callback)
715 mswin_tw->close_callback(mswin_tw);
716 return TRUE;
718 default:
719 break;
722 return DefWindowProc(hwnd, msg, wp, lp);
726 * Edit_ExGetTextLen() - Helper routine for getting count of chars.
728 static UINT
729 Edit_ExGetTextLen(HWND hwnd_edit, DWORD flags)
731 GETTEXTLENGTHEX gtl;
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)&gtl, 0);
739 * Edit_ExSetSel() - Helper routine for setting edit selection.
741 static UINT
742 Edit_ExSetSel(HWND hwnd_edit, LONG cpMin, LONG cpMax)
744 CHARRANGE cr;
746 if(cpMin == -1)
747 cpMin = Edit_ExGetTextLen(hwnd_edit, 0);
749 cr.cpMin = cpMin;
750 cr.cpMax = cpMax;
751 return (UINT)SendMessage(hwnd_edit, EM_EXSETSEL, (WPARAM)0, (LPARAM)&cr);
755 * Edit_ExIsReadOnly() - TRUE if edit buffer is read only.
757 static BOOL
758 Edit_ExIsReadOnly(HWND hwnd_edit)
760 LRESULT edit_opts;
762 edit_opts = SendMessage(hwnd_edit, EM_GETOPTIONS, 0, 0);
763 return !!(edit_opts & ECO_READONLY);