1 /* NetHack 3.7	mhtext.c	$NHDT-Date: 1596498362 2020/08/03 23:46:02 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.31 $ */
2 /* Copyright (C) 2001 by Alex Kompel 	 */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "winMS.h"
6 #include "resource.h"
7 #include "mhtext.h"
8 #include "mhmsg.h"
9 #include "mhfont.h"
10 
11 PNHWinApp GetNHApp(void);
12 
13 typedef struct mswin_nethack_text_window {
14     TCHAR *window_text;
15 } NHTextWindow, *PNHTextWindow;
16 
17 static WNDPROC editControlWndProc = 0;
18 #define DEFAULT_COLOR_BG_TEXT COLOR_WINDOW
19 #define DEFAULT_COLOR_FG_TEXT COLOR_WINDOWTEXT
20 
21 INT_PTR CALLBACK NHTextWndProc(HWND, UINT, WPARAM, LPARAM);
22 LRESULT CALLBACK NHEditHookWndProc(HWND, UINT, WPARAM, LPARAM);
23 static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
24 static void LayoutText(HWND hwnd);
25 
26 HWND
mswin_init_text_window(void)27 mswin_init_text_window(void)
28 {
29     HWND ret;
30     RECT rt;
31 
32     /* get window position */
33     if (GetNHApp()->bAutoLayout) {
34         SetRect(&rt, 0, 0, 0, 0);
35     } else {
36         mswin_get_window_placement(NHW_TEXT, &rt);
37     }
38 
39     /* create text widnow object */
40     ret = CreateDialog(GetNHApp()->hApp, MAKEINTRESOURCE(IDD_NHTEXT),
41                        GetNHApp()->hMainWnd, NHTextWndProc);
42     if (!ret)
43         panic("Cannot create text window");
44 
45     /* move it in the predefined position */
46     if (!GetNHApp()->bAutoLayout) {
47         MoveWindow(ret, rt.left, rt.top, rt.right - rt.left,
48                    rt.bottom - rt.top, TRUE);
49     }
50 
51     /* Set window caption */
52     SetWindowText(ret, "Text");
53 
54     mswin_apply_window_style(ret);
55 
56     return ret;
57 }
58 
59 void
mswin_display_text_window(HWND hWnd)60 mswin_display_text_window(HWND hWnd)
61 {
62     PNHTextWindow data;
63 
64     data = (PNHTextWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
65     if (data && data->window_text) {
66         HWND control;
67         control = GetDlgItem(hWnd, IDC_TEXT_CONTROL);
68         SendMessage(control, EM_FMTLINES, 1, 0);
69         SetWindowText(control, data->window_text);
70     }
71 
72     mswin_popup_display(hWnd, NULL);
73     mswin_popup_destroy(hWnd);
74 }
75 
76 INT_PTR CALLBACK
NHTextWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)77 NHTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
78 {
79     PNHTextWindow data = (PNHTextWindow)GetWindowLongPtr(hWnd, GWLP_USERDATA);
80 
81     switch (message) {
82     case WM_INITDIALOG: {
83         data = (PNHTextWindow)malloc(sizeof(NHTextWindow));
84         if (!data)
85             panic("out of memory");
86         ZeroMemory(data, sizeof(NHTextWindow));
87         SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)data);
88 
89         HWND control = GetDlgItem(hWnd, IDC_TEXT_CONTROL);
90         HDC hdc = GetDC(control);
91         cached_font * font = mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE);
92         /* set text control font */
93 
94         if (!control) {
95             panic("cannot get text view window");
96         }
97 
98         SendMessage(control, WM_SETFONT, (WPARAM) font->hFont, 0);
99         ReleaseDC(control, hdc);
100 
101         /* subclass edit control */
102         editControlWndProc =
103             (WNDPROC)GetWindowLongPtr(control, GWLP_WNDPROC);
104         SetWindowLongPtr(control, GWLP_WNDPROC, (LONG_PTR)NHEditHookWndProc);
105 
106         SetFocus(control);
107 
108         /* Even though the dialog has no caption, you can still set the title
109            which shows on Alt-Tab */
110         TCHAR title[MAX_LOADSTRING];
111         LoadString(GetNHApp()->hApp, IDS_APP_TITLE, title, MAX_LOADSTRING);
112         SetWindowText(hWnd, title);
113     } break;
114 
115     case WM_MSNH_COMMAND:
116         onMSNHCommand(hWnd, wParam, lParam);
117         break;
118 
119     case WM_SIZE: {
120         RECT rt;
121 
122         GetWindowRect(hWnd, &rt);
123         ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT) &rt);
124         ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT) &rt) + 1);
125         mswin_update_window_placement(NHW_TEXT, &rt);
126 
127         LayoutText(hWnd);
128     }
129         return FALSE;
130 
131     case WM_MOVE: {
132         RECT rt;
133         GetWindowRect(hWnd, &rt);
134         ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT) &rt);
135         ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT) &rt) + 1);
136         mswin_update_window_placement(NHW_TEXT, &rt);
137     }
138         return FALSE;
139 
140     case WM_COMMAND:
141         switch (LOWORD(wParam)) {
142         case IDOK:
143         case IDCANCEL:
144             mswin_window_mark_dead(mswin_winid_from_handle(hWnd));
145             if (GetNHApp()->hMainWnd == hWnd)
146                 GetNHApp()->hMainWnd = NULL;
147             DestroyWindow(hWnd);
148             SetFocus(GetNHApp()->hMainWnd);
149             return TRUE;
150         }
151         break;
152 
153     case WM_CTLCOLORSTATIC: { /* sent by edit control before it is drawn */
154         HDC hdcEdit = (HDC) wParam;
155         HWND hwndEdit = (HWND) lParam;
156         if (hwndEdit == GetDlgItem(hWnd, IDC_TEXT_CONTROL)) {
157             SetBkColor(hdcEdit, text_bg_brush ? text_bg_color
158                                               : (COLORREF) GetSysColor(
159                                                     DEFAULT_COLOR_BG_TEXT));
160             SetTextColor(hdcEdit, text_fg_brush ? text_fg_color
161                                                 : (COLORREF) GetSysColor(
162                                                       DEFAULT_COLOR_FG_TEXT));
163             return (INT_PTR)(text_bg_brush
164                                  ? text_bg_brush
165                                  : SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_TEXT));
166         }
167     }
168         return FALSE;
169 
170     case WM_DESTROY:
171         if (data) {
172             if (data->window_text)
173                 free(data->window_text);
174             free(data);
175             SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) 0);
176         }
177         break;
178 
179     }
180 
181 
182     return FALSE;
183 }
184 
185 void
onMSNHCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)186 onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
187 {
188     PNHTextWindow data;
189 
190     data = (PNHTextWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
191     switch (wParam) {
192     case MSNH_MSG_PUTSTR: {
193         PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr) lParam;
194         TCHAR wbuf[BUFSZ];
195         size_t text_size;
196 
197         if (!data->window_text) {
198             text_size = strlen(msg_data->text) + 4;
199             data->window_text =
200                 (TCHAR *) malloc(text_size * sizeof(data->window_text[0]));
201             ZeroMemory(data->window_text,
202                        text_size * sizeof(data->window_text[0]));
203         } else {
204             text_size =
205                 _tcslen(data->window_text) + strlen(msg_data->text) + 4;
206             data->window_text = (TCHAR *) realloc(
207                 data->window_text, text_size * sizeof(data->window_text[0]));
208         }
209         if (!data->window_text)
210             break;
211 
212         _tcscat(data->window_text, NH_A2W(msg_data->text, wbuf, BUFSZ));
213         _tcscat(data->window_text, TEXT("\r\n"));
214         break;
215     }
216 
217 	case MSNH_MSG_RANDOM_INPUT: {
218         PostMessage(GetDlgItem(hWnd, IDC_TEXT_CONTROL),
219             WM_MSNH_COMMAND, MSNH_MSG_RANDOM_INPUT, 0);
220 	}
221 	break;
222 
223     }
224 }
225 
226 void
LayoutText(HWND hWnd)227 LayoutText(HWND hWnd)
228 {
229     HWND btn_ok;
230     HWND text;
231     RECT clrt, rt;
232     POINT pt_elem, pt_ok;
233     SIZE sz_elem, sz_ok;
234 
235     text = GetDlgItem(hWnd, IDC_TEXT_CONTROL);
236     btn_ok = GetDlgItem(hWnd, IDOK);
237 
238     /* get window coordinates */
239     GetClientRect(hWnd, &clrt);
240 
241     if( !GetNHApp()->regNetHackMode ) {
242         /* set window placements */
243         GetWindowRect(btn_ok, &rt);
244         sz_ok.cx = clrt.right - clrt.left;
245         sz_ok.cy = rt.bottom - rt.top;
246         pt_ok.x = clrt.left;
247         pt_ok.y = clrt.bottom - sz_ok.cy;
248 
249         pt_elem.x = clrt.left;
250         pt_elem.y = clrt.top;
251         sz_elem.cx = clrt.right - clrt.left;
252         sz_elem.cy = pt_ok.y;
253 
254         MoveWindow(text, pt_elem.x, pt_elem.y, sz_elem.cx, sz_elem.cy, TRUE);
255         MoveWindow(btn_ok, pt_ok.x, pt_ok.y, sz_ok.cx, sz_ok.cy, TRUE);
256     } else {
257         sz_ok.cx = sz_ok.cy = 0;
258 
259         pt_ok.x = pt_ok.y = 0;
260         pt_elem.x = clrt.left;
261         pt_elem.y = clrt.top;
262 
263         sz_elem.cx = clrt.right - clrt.left;
264         sz_elem.cy = clrt.bottom - clrt.top;
265 
266         ShowWindow(btn_ok, SW_HIDE);
267         MoveWindow(text, pt_elem.x, pt_elem.y, sz_elem.cx, sz_elem.cy, TRUE );
268     }
269     mswin_apply_window_style(text);
270 }
271 
272 /* Edit box hook */
273 LRESULT CALLBACK
NHEditHookWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)274 NHEditHookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
275 {
276     HWND hWndParent = GetParent(hWnd);
277     HDC hDC;
278     RECT rc;
279 
280     switch (message) {
281     case WM_ERASEBKGND:
282         hDC = (HDC) wParam;
283         GetClientRect(hWnd, &rc);
284         FillRect(hDC, &rc, text_bg_brush
285                                ? text_bg_brush
286                                : SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_TEXT));
287         return 1;
288 
289     case WM_KEYDOWN:
290         switch (wParam) {
291         /* close on space in Windows mode
292            page down on space in NetHack mode */
293         case VK_SPACE: {
294             SCROLLINFO si;
295 
296             si.cbSize = sizeof(SCROLLINFO);
297             si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE;
298             GetScrollInfo(hWnd, SB_VERT, &si);
299             /* If nethackmode and not at the end of the list */
300             if (GetNHApp()->regNetHackMode
301                 && (si.nPos + (int) si.nPage) <= (si.nMax - si.nMin))
302                 SendMessage(hWnd, EM_SCROLL, SB_PAGEDOWN, 0);
303             else
304                 PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDOK, 0), 0);
305             return 0;
306         }
307         case VK_NEXT:
308             SendMessage(hWnd, EM_SCROLL, SB_PAGEDOWN, 0);
309             return 0;
310         case VK_PRIOR:
311             SendMessage(hWnd, EM_SCROLL, SB_PAGEUP, 0);
312             return 0;
313         case VK_UP:
314             SendMessage(hWnd, EM_SCROLL, SB_LINEUP, 0);
315             return 0;
316         case VK_DOWN:
317             SendMessage(hWnd, EM_SCROLL, SB_LINEDOWN, 0);
318             return 0;
319         }
320         break;
321 
322     case WM_CHAR:
323         switch(wParam) {
324         case MENU_FIRST_PAGE:
325             SendMessage(hWnd, EM_SCROLL, SB_TOP, 0);
326             return 0;
327         case MENU_LAST_PAGE:
328             SendMessage(hWnd, EM_SCROLL, SB_BOTTOM, 0);
329             return 0;
330         case MENU_NEXT_PAGE:
331             SendMessage(hWnd, EM_SCROLL, SB_PAGEDOWN, 0);
332             return 0;
333         case MENU_PREVIOUS_PAGE:
334             SendMessage(hWnd, EM_SCROLL, SB_PAGEUP, 0);
335             return 0;
336         }
337         break;
338 
339     /* edit control needs to know nothing of focus. We will take care of it
340      * for it */
341     case WM_SETFOCUS:
342         HideCaret(hWnd);
343         return 0;
344 
345     case WM_MSNH_COMMAND:
346         if (wParam == MSNH_MSG_RANDOM_INPUT) {
347             char c = randomkey();
348             if (c == '\n')
349                 PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDOK, 0), 0);
350             else if (c == '\033')
351                 PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDCANCEL, 0), 0);
352             else
353                 PostMessage(hWnd, WM_CHAR, c, 0);
354             return 0;
355         }
356         break;
357 
358     }
359 
360     if (editControlWndProc)
361         return CallWindowProc(editControlWndProc, hWnd, message, wParam,
362                               lParam);
363     else
364         return 0;
365 }
366