1 /* NetHack 3.6 mhtext.c $NHDT-Date: 1432512813 2015/05/25 00:13:33 $ $NHDT-Branch: master $:$NHDT-Revision: 1.25 $ */
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()27 mswin_init_text_window()
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