1 #ifndef RENDERTYPEWIN
2 #error Only for Windows
3 #endif
4
5 #define WIN32_LEAN_AND_MEAN
6 #define _WIN32_WINNT 0x0600
7 #define _WIN32_IE 0x0600
8
9 #include "compat.h"
10 #include "winlayer.h"
11 #include "build.h"
12 #include "editor.h"
13
14 #include <windows.h>
15 #include <windowsx.h>
16 #include <commctrl.h>
17 #include <uxtheme.h>
18 #include <stdio.h>
19
20 #include "buildres.h"
21
22 #define TAB_CONFIG 0
23 #define TAB_MESSAGES 1
24
25
26 static HWND startupdlg = NULL;
27 static HWND pages[2] = { NULL, NULL};
28 static int mode = TAB_CONFIG;
29 static struct startwin_settings *settings;
30 static BOOL quiteventonclose = FALSE;
31 static int retval = -1;
32
populate_video_modes(BOOL firstTime)33 static void populate_video_modes(BOOL firstTime)
34 {
35 int i, j, mode2d = -1, mode3d = -1;
36 int xdim = 0, ydim = 0, bpp = 0, fullscreen = 0;
37 int xdim2d = 0, ydim2d = 0;
38 char modestr[64];
39 int cd[] = { 32, 24, 16, 15, 8, 0 };
40 HWND hwnd, hwnd2d;
41
42 hwnd = GetDlgItem(pages[TAB_CONFIG], IDC_VMODE3D);
43 hwnd2d = GetDlgItem(pages[TAB_CONFIG], IDC_VMODE2D);
44 if (firstTime) {
45 getvalidmodes();
46 xdim = settings->xdim3d;
47 ydim = settings->ydim3d;
48 bpp = settings->bpp3d;
49 fullscreen = settings->fullscreen;
50
51 xdim2d = settings->xdim2d;
52 ydim2d = settings->ydim2d;
53 } else {
54 fullscreen = IsDlgButtonChecked(pages[TAB_CONFIG], IDC_FULLSCREEN) == BST_CHECKED;
55 i = ComboBox_GetCurSel(hwnd);
56 if (i != CB_ERR) i = ComboBox_GetItemData(hwnd, i);
57 if (i != CB_ERR) {
58 xdim = validmode[i].xdim;
59 ydim = validmode[i].ydim;
60 bpp = validmode[i].bpp;
61 }
62
63 i = ComboBox_GetCurSel(hwnd2d);
64 if (i != CB_ERR) i = ComboBox_GetItemData(hwnd2d, i);
65 if (i != CB_ERR) {
66 xdim2d = validmode[i].xdim;
67 ydim2d = validmode[i].ydim;
68 }
69 }
70
71 // Find an ideal match.
72 mode3d = checkvideomode(&xdim, &ydim, bpp, fullscreen, 1);
73 mode2d = checkvideomode(&xdim2d, &ydim2d, 8, fullscreen, 1);
74 if (mode2d < 0) {
75 mode2d = 0;
76 }
77 if (mode3d < 0) {
78 for (i=0; cd[i]; ) { if (cd[i] >= bpp) i++; else break; }
79 for ( ; cd[i]; i++) {
80 mode3d = checkvideomode(&xdim, &ydim, cd[i], fullscreen, 1);
81 if (mode3d < 0) continue;
82 break;
83 }
84 }
85
86 // Repopulate the lists.
87 ComboBox_ResetContent(hwnd);
88 ComboBox_ResetContent(hwnd2d);
89 for (i=0; i<validmodecnt; i++) {
90 if (validmode[i].fs != fullscreen) continue;
91
92 Bsprintf(modestr, "%d x %d %d-bpp", validmode[i].xdim, validmode[i].ydim, validmode[i].bpp);
93 j = ComboBox_AddString(hwnd, modestr);
94 ComboBox_SetItemData(hwnd, j, i);
95 if (i == mode3d) {
96 ComboBox_SetCurSel(hwnd, j);
97 }
98
99 if (validmode[i].bpp == 8 && validmode[i].xdim >= 640 && validmode[i].ydim >= 480) {
100 Bsprintf(modestr, "%d x %d", validmode[i].xdim, validmode[i].ydim);
101 j = ComboBox_AddString(hwnd2d, modestr);
102 ComboBox_SetItemData(hwnd2d, j, i);
103 if (i == mode2d) {
104 ComboBox_SetCurSel(hwnd2d, j);
105 }
106 }
107 }
108 }
109
set_settings(struct startwin_settings * thesettings)110 static void set_settings(struct startwin_settings *thesettings)
111 {
112 settings = thesettings;
113 }
114
set_page(int n)115 static void set_page(int n)
116 {
117 HWND tab = GetDlgItem(startupdlg, IDC_STARTWIN_TABCTL);
118 int cur = (int)SendMessage(tab, TCM_GETCURSEL,0,0);
119
120 ShowWindow(pages[cur], SW_HIDE);
121 SendMessage(tab, TCM_SETCURSEL, n, 0);
122 ShowWindow(pages[n], SW_SHOW);
123 mode = n;
124
125 SendMessage(startupdlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(startupdlg, IDC_STARTWIN_TABCTL), TRUE);
126 }
127
setup_config_mode(void)128 static void setup_config_mode(void)
129 {
130 set_page(TAB_CONFIG);
131
132 CheckDlgButton(startupdlg, IDC_ALWAYSSHOW, (settings->forcesetup ? BST_CHECKED : BST_UNCHECKED));
133 EnableWindow(GetDlgItem(startupdlg, IDC_ALWAYSSHOW), TRUE);
134
135 CheckDlgButton(pages[TAB_CONFIG], IDC_FULLSCREEN, (settings->fullscreen ? BST_CHECKED : BST_UNCHECKED));
136 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDC_FULLSCREEN), TRUE);
137
138 populate_video_modes(TRUE);
139 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDC_VMODE3D), TRUE);
140 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDC_VMODE2D), TRUE);
141
142 EnableWindow(GetDlgItem(startupdlg, IDCANCEL), TRUE);
143 EnableWindow(GetDlgItem(startupdlg, IDOK), TRUE);
144 }
145
setup_messages_mode(BOOL allowcancel)146 static void setup_messages_mode(BOOL allowcancel)
147 {
148 set_page(TAB_MESSAGES);
149
150 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDC_FULLSCREEN), FALSE);
151 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDC_VMODE3D), FALSE);
152 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDC_VMODE2D), FALSE);
153
154 EnableWindow(GetDlgItem(startupdlg, IDC_ALWAYSSHOW), FALSE);
155
156 EnableWindow(GetDlgItem(startupdlg, IDCANCEL), allowcancel);
157 EnableWindow(GetDlgItem(startupdlg, IDOK), FALSE);
158 }
159
fullscreen_clicked(void)160 static void fullscreen_clicked(void)
161 {
162 populate_video_modes(FALSE);
163 }
164
cancelbutton_clicked(void)165 static void cancelbutton_clicked(void)
166 {
167 retval = STARTWIN_CANCEL;
168 quitevent = quitevent || quiteventonclose;
169 }
170
startbutton_clicked(void)171 static void startbutton_clicked(void)
172 {
173 int i;
174 HWND hwnd;
175
176 hwnd = GetDlgItem(pages[TAB_CONFIG], IDC_VMODE3D);
177 i = ComboBox_GetCurSel(hwnd);
178 if (i != CB_ERR) i = ComboBox_GetItemData(hwnd, i);
179 if (i != CB_ERR) {
180 settings->xdim3d = validmode[i].xdim;
181 settings->ydim3d = validmode[i].ydim;
182 settings->bpp3d = validmode[i].bpp;
183 settings->fullscreen = validmode[i].fs;
184 }
185
186 hwnd = GetDlgItem(pages[TAB_CONFIG], IDC_VMODE2D);
187 i = ComboBox_GetCurSel(hwnd);
188 if (i != CB_ERR) i = ComboBox_GetItemData(hwnd, i);
189 if (i != CB_ERR) {
190 settings->xdim2d = validmode[i].xdim;
191 settings->ydim2d = validmode[i].ydim;
192 }
193
194 settings->forcesetup = IsDlgButtonChecked(startupdlg, IDC_ALWAYSSHOW) == BST_CHECKED;
195
196 retval = STARTWIN_RUN;
197 }
198
ConfigPageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)199 static INT_PTR CALLBACK ConfigPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
200 {
201 switch (uMsg) {
202 case WM_INITDIALOG: {
203 EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB);
204 return TRUE;
205 }
206
207 case WM_COMMAND:
208 switch (LOWORD(wParam)) {
209 case IDC_FULLSCREEN:
210 fullscreen_clicked();
211 return TRUE;
212 default: break;
213 }
214 break;
215 default: break;
216 }
217 return FALSE;
218 }
219
MessagesPageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)220 static INT_PTR CALLBACK MessagesPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
221 {
222 switch (uMsg) {
223 case WM_CTLCOLORSTATIC:
224 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_MESSAGES))
225 return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
226 break;
227 }
228 return FALSE;
229 }
230
startup_dlgproc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)231 static INT_PTR CALLBACK startup_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
232 {
233 switch (uMsg) {
234 case WM_INITDIALOG: {
235 HWND hwnd;
236 RECT r, rdlg, chrome, rtab, rcancel, rstart;
237 int xoffset = 0, yoffset = 0;
238
239 {
240 TCITEM tab;
241
242 hwnd = GetDlgItem(hwndDlg, IDC_STARTWIN_TABCTL);
243
244 // Add tabs to the tab control
245 ZeroMemory(&tab, sizeof(tab));
246 tab.mask = TCIF_TEXT;
247 tab.pszText = TEXT("Configuration");
248 TabCtrl_InsertItem(hwnd, 0, &tab);
249 tab.pszText = TEXT("Messages");
250 TabCtrl_InsertItem(hwnd, 1, &tab);
251
252 // Work out the position and size of the area inside the tab control for the pages.
253 ZeroMemory(&r, sizeof(r));
254 GetClientRect(hwnd, &r);
255 TabCtrl_AdjustRect(hwnd, FALSE, &r);
256
257 // Create the pages and position them in the tab control, but hide them.
258 pages[TAB_CONFIG] = CreateDialog((HINSTANCE)win_gethinstance(),
259 MAKEINTRESOURCE(IDD_PAGE_CONFIG), hwnd, ConfigPageProc);
260 SetWindowPos(pages[TAB_CONFIG], NULL, r.left,r.top,r.right,r.bottom, SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE);
261
262 pages[TAB_MESSAGES] = CreateDialog((HINSTANCE)win_gethinstance(),
263 MAKEINTRESOURCE(IDD_PAGE_MESSAGES), hwnd, MessagesPageProc);
264 SetWindowPos(pages[TAB_MESSAGES], NULL, r.left,r.top,r.right,r.bottom, SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE);
265
266 SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), TRUE);
267 }
268 return TRUE;
269 }
270
271 case WM_NOTIFY: {
272 LPNMHDR nmhdr = (LPNMHDR)lParam;
273 int cur;
274 if (nmhdr->idFrom != IDC_STARTWIN_TABCTL) break;
275 cur = (int)SendMessage(nmhdr->hwndFrom, TCM_GETCURSEL,0,0);
276 switch (nmhdr->code) {
277 case TCN_SELCHANGING: {
278 if (cur < 0 || !pages[cur]) break;
279 ShowWindow(pages[cur],SW_HIDE);
280 return TRUE;
281 }
282 case TCN_SELCHANGE: {
283 if (cur < 0 || !pages[cur]) break;
284 ShowWindow(pages[cur],SW_SHOW);
285 return TRUE;
286 }
287 }
288 break;
289 }
290
291 case WM_CLOSE:
292 cancelbutton_clicked();
293 return TRUE;
294
295 case WM_DESTROY:
296 if (pages[TAB_CONFIG]) {
297 DestroyWindow(pages[TAB_CONFIG]);
298 pages[TAB_CONFIG] = NULL;
299 }
300
301 if (pages[TAB_MESSAGES]) {
302 DestroyWindow(pages[TAB_MESSAGES]);
303 pages[TAB_MESSAGES] = NULL;
304 }
305
306 startupdlg = NULL;
307 return TRUE;
308
309 case WM_COMMAND:
310 switch (LOWORD(wParam)) {
311 case IDCANCEL:
312 cancelbutton_clicked();
313 return TRUE;
314 case IDOK: {
315 startbutton_clicked();
316 return TRUE;
317 }
318 }
319 break;
320
321 default: break;
322 }
323
324 return FALSE;
325 }
326
327
startwin_open(void)328 int startwin_open(void)
329 {
330 INITCOMMONCONTROLSEX icc;
331
332 if (startupdlg) return 1;
333
334 icc.dwSize = sizeof(icc);
335 icc.dwICC = ICC_TAB_CLASSES;
336 InitCommonControlsEx(&icc);
337 startupdlg = CreateDialog((HINSTANCE)win_gethinstance(), MAKEINTRESOURCE(IDD_STARTWIN), NULL, startup_dlgproc);
338 if (!startupdlg) {
339 return -1;
340 }
341
342 quiteventonclose = TRUE;
343 setup_messages_mode(FALSE);
344 return 0;
345 }
346
startwin_close(void)347 int startwin_close(void)
348 {
349 if (!startupdlg) return 1;
350
351 quiteventonclose = FALSE;
352 DestroyWindow(startupdlg);
353 startupdlg = NULL;
354
355 return 0;
356 }
357
startwin_puts(const char * buf)358 int startwin_puts(const char *buf)
359 {
360 const char *p = NULL, *q = NULL;
361 char workbuf[1024];
362 static int newline = 0;
363 int curlen, linesbefore, linesafter;
364 HWND edctl;
365 int vis;
366
367 if (!startupdlg) return 1;
368
369 edctl = GetDlgItem(pages[TAB_MESSAGES], IDC_MESSAGES);
370 if (!edctl) return -1;
371
372 vis = ((int)SendMessage(GetDlgItem(startupdlg, IDC_STARTWIN_TABCTL), TCM_GETCURSEL,0,0) == TAB_MESSAGES);
373
374 if (vis) SendMessage(edctl, WM_SETREDRAW, FALSE,0);
375 curlen = SendMessage(edctl, WM_GETTEXTLENGTH, 0,0);
376 SendMessage(edctl, EM_SETSEL, (WPARAM)curlen, (LPARAM)curlen);
377 linesbefore = SendMessage(edctl, EM_GETLINECOUNT, 0,0);
378 p = buf;
379 while (*p) {
380 if (newline) {
381 SendMessage(edctl, EM_REPLACESEL, 0, (LPARAM)"\r\n");
382 newline = 0;
383 }
384 q = p;
385 while (*q && *q != '\n') q++;
386 memcpy(workbuf, p, q-p);
387 if (*q == '\n') {
388 if (!q[1]) {
389 newline = 1;
390 workbuf[q-p] = 0;
391 } else {
392 workbuf[q-p] = '\r';
393 workbuf[q-p+1] = '\n';
394 workbuf[q-p+2] = 0;
395 }
396 p = q+1;
397 } else {
398 workbuf[q-p] = 0;
399 p = q;
400 }
401 SendMessage(edctl, EM_REPLACESEL, 0, (LPARAM)workbuf);
402 }
403 linesafter = SendMessage(edctl, EM_GETLINECOUNT, 0,0);
404 SendMessage(edctl, EM_LINESCROLL, 0, linesafter-linesbefore);
405 if (vis) SendMessage(edctl, WM_SETREDRAW, TRUE,0);
406 return 0;
407 }
408
startwin_settitle(const char * str)409 int startwin_settitle(const char *str)
410 {
411 if (startupdlg) {
412 SetWindowText(startupdlg, str);
413 }
414 return 0;
415 }
416
startwin_idle(void * v)417 int startwin_idle(void *v)
418 {
419 if (!startupdlg || !IsWindow(startupdlg)) return 0;
420 if (IsDialogMessage(startupdlg, (MSG*)v)) return 1;
421 return 0;
422 }
423
startwin_run(struct startwin_settings * settings)424 int startwin_run(struct startwin_settings *settings)
425 {
426 MSG msg;
427
428 if (!startupdlg) return 1;
429
430 set_settings(settings);
431 setup_config_mode();
432
433 while (retval < 0) {
434 switch (GetMessage(&msg, NULL, 0,0)) {
435 case 0: retval = STARTWIN_CANCEL; break; //WM_QUIT
436 case -1: return -1; // error
437 default:
438 if (IsWindow(startupdlg) && IsDialogMessage(startupdlg, &msg)) break;
439 TranslateMessage(&msg);
440 DispatchMessage(&msg);
441 break;
442 }
443 }
444
445 setup_messages_mode(FALSE);
446 set_settings(NULL);
447
448 return retval;
449 }
450
451