1 /* NetHack 3.7 mhrip.c $NHDT-Date: 1596498358 2020/08/03 23:45:58 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.24 $ */
2 /* Copyright (C) 2001 by Alex Kompel */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 #include "win10.h"
6 #include "winMS.h"
7 #include "resource.h"
8 #include "mhrip.h"
9 #include "mhmsg.h"
10 #include "mhfont.h"
11
12 #define RIP_WIDTH 400
13 #define RIP_HEIGHT 200
14
15 #define RIP_GRAVE_HEIGHT 120
16 #define RIP_GRAVE_WIDTH 115
17 #define RIP_GRAVE_X 90
18 #define RIP_GRAVE_Y 60
19
20 #define RIP_OFFSET_X 10
21 #define RIP_OFFSET_Y 10
22
23 PNHWinApp GetNHApp(void);
24
25 typedef struct mswin_nethack_text_window {
26 HANDLE rip_bmp;
27 TCHAR *window_text;
28 TCHAR *rip_text;
29 int x;
30 int y;
31 int width;
32 int height;
33 int graveX;
34 int graveY;
35 int graveHeight;
36 int graveWidth;
37 } NHRIPWindow, *PNHRIPWindow;
38
39 INT_PTR CALLBACK NHRIPWndProc(HWND, UINT, WPARAM, LPARAM);
40 static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
41
42 HWND
mswin_init_RIP_window(void)43 mswin_init_RIP_window(void)
44 {
45 HWND ret;
46 PNHRIPWindow data;
47
48 ret = CreateDialog(GetNHApp()->hApp, MAKEINTRESOURCE(IDD_NHRIP),
49 GetNHApp()->hMainWnd, NHRIPWndProc);
50 if (!ret)
51 panic("Cannot create rip window");
52
53 data = (PNHRIPWindow) malloc(sizeof(NHRIPWindow));
54 if (!data)
55 panic("out of memory");
56
57 ZeroMemory(data, sizeof(NHRIPWindow));
58 SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR) data);
59 return ret;
60 }
61
62 void
mswin_display_RIP_window(HWND hWnd)63 mswin_display_RIP_window(HWND hWnd)
64 {
65 MSG msg;
66 RECT rt;
67 PNHRIPWindow data;
68 HWND mapWnd;
69 RECT riprt;
70 RECT clientrect;
71 RECT textrect;
72 HFONT OldFont;
73 MonitorInfo monitorInfo;
74
75 win10_monitor_info(hWnd, &monitorInfo);
76
77 data = (PNHRIPWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
78
79 data->x = (int)(RIP_OFFSET_X * monitorInfo.scale);
80 data->y = (int)(RIP_OFFSET_Y * monitorInfo.scale);
81 data->width = (int)(RIP_WIDTH * monitorInfo.scale);
82 data->height = (int)(RIP_HEIGHT * monitorInfo.scale);
83 data->graveX = (int)(RIP_GRAVE_X * monitorInfo.scale);
84 data->graveY = (int)(RIP_GRAVE_Y * monitorInfo.scale);
85 data->graveWidth = (int)(RIP_GRAVE_WIDTH * monitorInfo.scale);
86 data->graveHeight = (int)(RIP_GRAVE_HEIGHT * monitorInfo.scale);
87
88 GetNHApp()->hPopupWnd = hWnd;
89 mapWnd = mswin_hwnd_from_winid(WIN_MAP);
90 if (!IsWindow(mapWnd))
91 mapWnd = GetNHApp()->hMainWnd;
92 GetWindowRect(mapWnd, &rt);
93 GetWindowRect(hWnd, &riprt);
94 GetClientRect(hWnd, &clientrect);
95 textrect = clientrect;
96 textrect.top += data->y;
97 textrect.left += data->x;
98 textrect.right -= data->x;
99 if (data->window_text) {
100 HDC hdc = GetDC(hWnd);
101 OldFont = SelectObject(hdc, mswin_get_font(NHW_TEXT, 0, hdc, FALSE)->hFont);
102 DrawText(hdc, data->window_text, strlen(data->window_text), &textrect,
103 DT_LEFT | DT_NOPREFIX | DT_CALCRECT);
104 SelectObject(hdc, OldFont);
105 ReleaseDC(hWnd, hdc);
106 }
107 if (textrect.right - textrect.left > data->width)
108 clientrect.right = textrect.right + data->y - clientrect.right;
109 else
110 clientrect.right =
111 textrect.left + 2 * data->x + data->width - clientrect.right;
112 clientrect.bottom =
113 textrect.bottom + data->height + data->y - clientrect.bottom;
114 GetWindowRect(GetDlgItem(hWnd, IDOK), &textrect);
115 textrect.right -= textrect.left;
116 textrect.bottom -= textrect.top;
117 clientrect.bottom += textrect.bottom + data->y;
118 riprt.right -= riprt.left;
119 riprt.bottom -= riprt.top;
120 riprt.right += clientrect.right;
121 riprt.bottom += clientrect.bottom;
122 rt.left += (rt.right - rt.left - riprt.right) / 2;
123 rt.top += (rt.bottom - rt.top - riprt.bottom) / 2;
124
125 MoveWindow(hWnd, rt.left, rt.top, riprt.right, riprt.bottom, TRUE);
126 GetClientRect(hWnd, &clientrect);
127 MoveWindow(GetDlgItem(hWnd, IDOK),
128 (clientrect.right - clientrect.left - textrect.right) / 2,
129 clientrect.bottom - textrect.bottom - data->y,
130 textrect.right, textrect.bottom, TRUE);
131 ShowWindow(hWnd, SW_SHOW);
132
133 while (IsWindow(hWnd) && GetMessage(&msg, NULL, 0, 0) != 0) {
134 if (!IsDialogMessage(hWnd, &msg)) {
135 TranslateMessage(&msg);
136 DispatchMessage(&msg);
137 }
138 }
139
140 GetNHApp()->hPopupWnd = NULL;
141 }
142
143 INT_PTR CALLBACK
NHRIPWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)144 NHRIPWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
145 {
146 PNHRIPWindow data = (PNHRIPWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
147 switch (message) {
148 case WM_INITDIALOG: {
149 HDC hdc = GetDC(hWnd);
150 cached_font * font = mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE);
151
152 /* set text control font */
153 SendMessage(hWnd, WM_SETFONT, (WPARAM)font->hFont, 0);
154 ReleaseDC(hWnd, hdc);
155
156 SetFocus(GetDlgItem(hWnd, IDOK));
157 } break;
158
159 case WM_MSNH_COMMAND:
160 onMSNHCommand(hWnd, wParam, lParam);
161 break;
162
163 case WM_PAINT: {
164 int bitmap_offset;
165 RECT clientrect;
166 RECT textrect;
167 HDC hdcBitmap;
168 HANDLE OldBitmap;
169 PAINTSTRUCT ps;
170 HFONT OldFont;
171 HDC hdc = BeginPaint(hWnd, &ps);
172 cached_font * font = mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE);
173
174 OldFont = SelectObject(hdc, font->hFont);
175 hdcBitmap = CreateCompatibleDC(hdc);
176 SetBkMode(hdc, TRANSPARENT);
177 GetClientRect(hWnd, &clientrect);
178 textrect = clientrect;
179 textrect.top += data->y;
180 textrect.left += data->x;
181 textrect.right -= data->x;
182 if (data->window_text) {
183 DrawText(hdc, data->window_text, strlen(data->window_text),
184 &textrect, DT_LEFT | DT_NOPREFIX | DT_CALCRECT);
185 DrawText(hdc, data->window_text, strlen(data->window_text),
186 &textrect, DT_LEFT | DT_NOPREFIX);
187 }
188 OldBitmap = SelectObject(hdcBitmap, GetNHApp()->bmpRip);
189 SetBkMode(hdc, OPAQUE);
190 bitmap_offset = (textrect.right - textrect.left - data->width) / 2;
191 StretchBlt(hdc, textrect.left + bitmap_offset, textrect.bottom,
192 data->width, data->height,
193 hdcBitmap, 0, 0, RIP_WIDTH, RIP_HEIGHT, SRCCOPY);
194 SetBkMode(hdc, TRANSPARENT);
195 if (data->rip_text) {
196 textrect.left += data->graveX + bitmap_offset;
197 textrect.top = textrect.bottom + data->graveY;
198 textrect.right = textrect.left + data->graveWidth;
199 textrect.bottom = textrect.top + data->graveHeight;
200 DrawText(hdc, data->rip_text, strlen(data->rip_text), &textrect,
201 DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_WORDBREAK);
202 }
203 SelectObject(hdcBitmap, OldBitmap);
204 SelectObject(hdc, OldFont);
205 DeleteDC(hdcBitmap);
206 EndPaint(hWnd, &ps);
207 } break;
208
209 case WM_COMMAND:
210 switch (LOWORD(wParam)) {
211 case IDOK:
212 mswin_window_mark_dead(mswin_winid_from_handle(hWnd));
213 if (GetNHApp()->hMainWnd == hWnd)
214 GetNHApp()->hMainWnd = NULL;
215 DestroyWindow(hWnd);
216 SetFocus(GetNHApp()->hMainWnd);
217 return TRUE;
218 }
219 break;
220
221 case WM_CLOSE:
222 /* if we get this here, we saved the bones so we can just force a quit
223 */
224
225 mswin_window_mark_dead(mswin_winid_from_handle(hWnd));
226 if (GetNHApp()->hMainWnd == hWnd)
227 GetNHApp()->hMainWnd = NULL;
228 DestroyWindow(hWnd);
229 SetFocus(GetNHApp()->hMainWnd);
230 g.program_state.stopprint++;
231 return TRUE;
232
233 case WM_DESTROY:
234 if (data) {
235 if (data->window_text)
236 free(data->window_text);
237 if (data->rip_text)
238 free(data->rip_text);
239 if (data->rip_bmp != NULL)
240 DeleteObject(data->rip_bmp);
241 free(data);
242 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) 0);
243 }
244 break;
245 }
246 return FALSE;
247 }
248
249 void
onMSNHCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)250 onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
251 {
252 PNHRIPWindow data;
253 static int InRipText = 1;
254 data = (PNHRIPWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
255 switch (wParam) {
256 case MSNH_MSG_PUTSTR: {
257 PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr) lParam;
258 TCHAR wbuf[BUFSZ];
259 size_t text_size;
260
261 if (!data->window_text) {
262 text_size = strlen(msg_data->text) + 4;
263 data->window_text =
264 (TCHAR *) malloc(text_size * sizeof(data->window_text[0]));
265 ZeroMemory(data->window_text,
266 text_size * sizeof(data->window_text[0]));
267 } else {
268 text_size =
269 _tcslen(data->window_text) + strlen(msg_data->text) + 4;
270 data->window_text = (TCHAR *) realloc(
271 data->window_text, text_size * sizeof(data->window_text[0]));
272 }
273 if (!data->window_text)
274 break;
275
276 _tcscat(data->window_text, NH_A2W(msg_data->text, wbuf, BUFSZ));
277 _tcscat(data->window_text, TEXT("\r\n"));
278 break;
279 }
280 case MSNH_MSG_DIED: {
281 data->rip_text = data->window_text;
282 data->window_text = NULL;
283 break;
284 }
285
286 case MSNH_MSG_RANDOM_INPUT:
287 nhassert(0); // unexpected
288 break;
289
290 }
291 }
292
293 void
mswin_finish_rip_text(winid wid)294 mswin_finish_rip_text(winid wid)
295 {
296 SendMessage(mswin_hwnd_from_winid(wid), WM_MSNH_COMMAND, MSNH_MSG_DIED,
297 0);
298 }
299