1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010 EDuke32 developers and contributors
4
5 This file is part of EDuke32.
6
7 EDuke32 is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21 //-------------------------------------------------------------------------
22
23 #ifndef _WIN32
24 #error Only for Windows
25 #endif
26
27 #include "renderlayer.h"
28
29 #ifdef STARTUP_SETUP_WINDOW
30
31 #define NEED_WINDOWSX_H
32 #define NEED_COMMCTRL_H
33 #define ONLY_USERDEFS
34
35 #include "_control.h"
36 #include "build.h"
37 #include "cache1d.h"
38 #include "compat.h"
39 #include "keyboard.h"
40 #include "control.h"
41 #include "exhumed.h"
42 #include "config.h"
43 #include "grpscan.h"
44 #include "startwin.game.h"
45 #include "windows_inc.h"
46
47 #define TAB_CONFIG 0
48 #define TAB_MESSAGES 1
49
50 static struct
51 {
52 struct grpfile_t const * grp;
53 char *gamedir;
54 ud_setup_t shared;
55 int polymer;
56 }
57 settings;
58
59 static HWND startupdlg;
60 static HWND pages[3];
61 static int done = -1;
62 static int mode = TAB_CONFIG;
63
64 static BUILDVFS_FIND_REC *finddirs;
65
clearfilenames(void)66 static inline void clearfilenames(void)
67 {
68 klistfree(finddirs);
69 finddirs = NULL;
70 }
71
getfilenames(char const * path)72 static inline void getfilenames(char const *path)
73 {
74 clearfilenames();
75 finddirs = klistpath(path,"*",BUILDVFS_FIND_DIR);
76 }
77
78 #define POPULATE_VIDEO 1
79 #define POPULATE_CONFIG 2
80 #define POPULATE_GAME 4
81 #define POPULATE_GAMEDIRS 8
82
83 #ifdef INPUT_MOUSE
84 #undef INPUT_MOUSE
85 #endif
86
87 #define INPUT_KB 0
88 #define INPUT_MOUSE 1
89 #define INPUT_JOYSTICK 2
90 #define INPUT_ALL 3
91
92 const char *controlstrings[] = { "Keyboard only", "Keyboard and mouse", "Keyboard and joystick", "All supported devices" };
93
PopulateForm(int32_t pgs)94 static void PopulateForm(int32_t pgs)
95 {
96 char buf[512];
97
98 if (pgs & POPULATE_GAMEDIRS)
99 {
100 HWND hwnd = GetDlgItem(pages[TAB_CONFIG], IDCGAMEDIR);
101
102 getfilenames("/");
103 (void)ComboBox_ResetContent(hwnd);
104 int const r = ComboBox_AddString(hwnd, "None");
105 (void)ComboBox_SetItemData(hwnd, r, 0);
106 (void)ComboBox_SetCurSel(hwnd, r);
107 auto dirs = finddirs;
108 for (int i=1, j=1; dirs != NULL; dirs=dirs->next)
109 {
110 if (Bstrcasecmp(dirs->name, "autoload") == 0)
111 {
112 j++;
113 continue;
114 }
115
116 (void)ComboBox_AddString(hwnd, dirs->name);
117 (void)ComboBox_SetItemData(hwnd, i, j);
118 if (Bstrcasecmp(dirs->name, settings.gamedir) == 0)
119 (void)ComboBox_SetCurSel(hwnd, i);
120
121 i++;
122 j++;
123 }
124 }
125
126 if (pgs & POPULATE_VIDEO)
127 {
128 HWND hwnd = GetDlgItem(pages[TAB_CONFIG], IDCVMODE);
129 int mode = videoCheckMode(&settings.shared.xdim, &settings.shared.ydim, settings.shared.bpp, settings.shared.fullscreen, 1);
130
131 if (mode < 0 || (settings.shared.bpp < 15 && (settings.polymer)))
132 {
133 int CONSTEXPR cd[] = { 32, 24, 16, 15, 8, 0 };
134 int i;
135
136 for (i=0; cd[i];)
137 {
138 if (cd[i] >= settings.shared.bpp) i++;
139 else break;
140 }
141 for (; cd[i]; i++)
142 {
143 mode = videoCheckMode(&settings.shared.xdim, &settings.shared.ydim, cd[i], settings.shared.fullscreen, 1);
144 if (mode < 0) continue;
145 settings.shared.bpp = cd[i];
146 break;
147 }
148 }
149
150 Button_SetCheck(GetDlgItem(pages[TAB_CONFIG], IDCFULLSCREEN), ((settings.shared.fullscreen) ? BST_CHECKED : BST_UNCHECKED));
151 Button_SetCheck(GetDlgItem(pages[TAB_CONFIG], IDCPOLYMER), ((settings.polymer) ? BST_CHECKED : BST_UNCHECKED));
152
153 (void)ComboBox_ResetContent(hwnd);
154
155 for (int i=0; i<validmodecnt; i++)
156 {
157 if (validmode[i].fs != (settings.shared.fullscreen)) continue;
158 if ((validmode[i].bpp < 15) && (settings.polymer)) continue;
159
160 // all modes get added to the 3D mode list
161 Bsprintf(buf, "%dx%d %s", validmode[i].xdim, validmode[i].ydim, validmode[i].bpp == 8 ? "software" : "OpenGL");
162 int const j = ComboBox_AddString(hwnd, buf);
163 (void)ComboBox_SetItemData(hwnd, j, i);
164 if (i == mode)(void)ComboBox_SetCurSel(hwnd, j);
165 }
166 }
167
168 if (pgs & POPULATE_CONFIG)
169 {
170 Button_SetCheck(GetDlgItem(pages[TAB_CONFIG], IDCALWAYSSHOW), (settings.shared.forcesetup ? BST_CHECKED : BST_UNCHECKED));
171 Button_SetCheck(GetDlgItem(pages[TAB_CONFIG], IDCAUTOLOAD), (!(settings.shared.noautoload) ? BST_CHECKED : BST_UNCHECKED));
172
173 HWND hwnd = GetDlgItem(pages[TAB_CONFIG], IDCINPUT);
174
175 (void)ComboBox_ResetContent(hwnd);
176 (void)ComboBox_SetCurSel(hwnd, 0);
177
178 int j = 4;
179
180 #ifdef RENDERTYPEWIN
181 if (di_disabled) j = 2;
182 #endif
183
184 for (int i=0; i<j; i++)
185 {
186 (void)ComboBox_InsertString(hwnd, i, controlstrings[i]);
187 (void)ComboBox_SetItemData(hwnd, i, i);
188
189 switch (i)
190 {
191 case INPUT_MOUSE:
192 if (settings.shared.usemouse && !settings.shared.usejoystick)(void)ComboBox_SetCurSel(hwnd, i);
193 break;
194 case INPUT_JOYSTICK:
195 if (!settings.shared.usemouse && settings.shared.usejoystick)(void)ComboBox_SetCurSel(hwnd, i);
196 break;
197 case INPUT_ALL:
198 if (settings.shared.usemouse && settings.shared.usejoystick)(void)ComboBox_SetCurSel(hwnd, i);
199 break;
200 }
201 }
202 }
203
204 if (pgs & POPULATE_GAME)
205 {
206 HWND hwnd = GetDlgItem(pages[TAB_CONFIG], IDCDATA);
207
208 for (auto fg = foundgrps; fg; fg=fg->next)
209 {
210 Bsprintf(buf, "%s\t%s", fg->type->name, fg->filename);
211 int const j = ListBox_AddString(hwnd, buf);
212 (void)ListBox_SetItemData(hwnd, j, (LPARAM)fg);
213 if (settings.grp == fg)
214 (void)ListBox_SetCurSel(hwnd, j);
215 }
216 }
217 }
218
ConfigPageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)219 static INT_PTR CALLBACK ConfigPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
220 {
221 switch (uMsg)
222 {
223 case WM_COMMAND:
224 switch (LOWORD(wParam))
225 {
226 case IDCFULLSCREEN:
227 settings.shared.fullscreen = !settings.shared.fullscreen;
228 PopulateForm(POPULATE_VIDEO);
229 return TRUE;
230 case IDCPOLYMER:
231 settings.polymer = !settings.polymer;
232 if (settings.shared.bpp == 8) settings.shared.bpp = 32;
233 PopulateForm(POPULATE_VIDEO);
234 return TRUE;
235 case IDCVMODE:
236 if (HIWORD(wParam) == CBN_SELCHANGE)
237 {
238 int i = ComboBox_GetCurSel((HWND)lParam);
239 if (i != CB_ERR) i = ComboBox_GetItemData((HWND)lParam, i);
240 if (i != CB_ERR)
241 {
242 settings.shared.xdim = validmode[i].xdim;
243 settings.shared.ydim = validmode[i].ydim;
244 settings.shared.bpp = validmode[i].bpp;
245 }
246 }
247 return TRUE;
248 case IDCALWAYSSHOW:
249 settings.shared.forcesetup = IsDlgButtonChecked(hwndDlg, IDCALWAYSSHOW) == BST_CHECKED;
250 return TRUE;
251 case IDCAUTOLOAD:
252 settings.shared.noautoload = (IsDlgButtonChecked(hwndDlg, IDCAUTOLOAD) != BST_CHECKED);
253 return TRUE;
254 case IDCINPUT:
255 if (HIWORD(wParam) == CBN_SELCHANGE)
256 {
257 int i = ComboBox_GetCurSel((HWND)lParam);
258 if (i != CB_ERR) i = ComboBox_GetItemData((HWND)lParam, i);
259 if (i != CB_ERR)
260 {
261 switch (i)
262 {
263 case INPUT_KB:
264 settings.shared.usemouse = settings.shared.usejoystick = 0;
265 break;
266 case INPUT_MOUSE:
267 settings.shared.usemouse = 1;
268 settings.shared.usejoystick = 0;
269 break;
270 case INPUT_JOYSTICK:
271 settings.shared.usemouse = 0;
272 settings.shared.usejoystick = 1;
273 break;
274 case INPUT_ALL:
275 settings.shared.usemouse = settings.shared.usejoystick = 1;
276 break;
277 }
278 }
279 }
280 return TRUE;
281
282 case IDCGAMEDIR:
283 if (HIWORD(wParam) == CBN_SELCHANGE)
284 {
285 int i = ComboBox_GetCurSel((HWND)lParam);
286 if (i != CB_ERR) i = ComboBox_GetItemData((HWND)lParam, i);
287 if (i != CB_ERR)
288 {
289 if (i==0)
290 settings.gamedir = NULL;
291 else
292 {
293 BUILDVFS_FIND_REC *dir = finddirs;
294 for (int j = 1; dir != NULL; dir = dir->next, j++)
295 {
296 if (j == i)
297 {
298 settings.gamedir = dir->name;
299 break;
300 }
301 }
302 }
303 }
304 }
305 return TRUE;
306 case IDCDATA:
307 {
308 if (HIWORD(wParam) != LBN_SELCHANGE) break;
309 intptr_t i = ListBox_GetCurSel((HWND)lParam);
310 if (i != CB_ERR) i = ListBox_GetItemData((HWND)lParam, i);
311 if (i != CB_ERR)
312 {
313 settings.grp = (grpfile_t const *)i;
314 }
315 return TRUE;
316 }
317 default:
318 break;
319 }
320 break;
321 default:
322 break;
323 }
324 return FALSE;
325 }
326
327
SetPage(int pageNum)328 static void SetPage(int pageNum)
329 {
330 HWND tab = GetDlgItem(startupdlg, WIN_STARTWIN_TABCTL);
331 auto const cur = SendMessage(tab, TCM_GETCURSEL, 0, 0);
332 ShowWindow(pages[cur], SW_HIDE);
333 SendMessage(tab, TCM_SETCURSEL, pageNum, 0);
334 ShowWindow(pages[pageNum], SW_SHOW);
335 mode = pageNum;
336
337 SetFocus(GetDlgItem(startupdlg, WIN_STARTWIN_TABCTL));
338 }
339
EnableConfig(bool n)340 static void EnableConfig(bool n)
341 {
342 //EnableWindow(GetDlgItem(startupdlg, WIN_STARTWIN_CANCEL), n);
343 EnableWindow(GetDlgItem(startupdlg, WIN_STARTWIN_START), n);
344 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDCDATA), n);
345 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDCFULLSCREEN), n);
346 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDCGAMEDIR), n);
347 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDCINPUT), n);
348 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDCPOLYMER), n);
349 EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDCVMODE), n);
350 }
351
startup_dlgproc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)352 static INT_PTR CALLBACK startup_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
353 {
354 static HBITMAP hbmp = NULL;
355
356 switch (uMsg)
357 {
358 case WM_INITDIALOG:
359 {
360 // Fetch the positions (in screen coordinates) of all the windows we need to tweak
361 RECT chrome = {};
362 AdjustWindowRect(&chrome, GetWindowLong(hwndDlg, GWL_STYLE), FALSE);
363 RECT rdlg;
364 GetWindowRect(hwndDlg, &rdlg);
365
366 // Knock off the non-client area of the main dialogue to give just the client area
367 rdlg.left -= chrome.left;
368 rdlg.top -= chrome.top;
369 rdlg.right -= chrome.right;
370 rdlg.bottom -= chrome.bottom;
371
372 RECT rtab;
373 GetWindowRect(GetDlgItem(hwndDlg, WIN_STARTWIN_TABCTL), &rtab);
374
375 // Translate them to client-relative coordinates wrt the main dialogue window
376 rtab.right -= rtab.left - 1;
377 rtab.bottom -= rtab.top - 1;
378 rtab.left -= rdlg.left;
379 rtab.top -= rdlg.top;
380
381 RECT rcancel;
382 GetWindowRect(GetDlgItem(hwndDlg, WIN_STARTWIN_CANCEL), &rcancel);
383
384 rcancel.right -= rcancel.left - 1;
385 rcancel.bottom -= rcancel.top - 1;
386 rcancel.left -= rdlg.left;
387 rcancel.top -= rdlg.top;
388
389 RECT rstart;
390 GetWindowRect(GetDlgItem(hwndDlg, WIN_STARTWIN_START), &rstart);
391
392 rstart.right -= rstart.left - 1;
393 rstart.bottom -= rstart.top - 1;
394 rstart.left -= rdlg.left;
395 rstart.top -= rdlg.top;
396
397 // And then convert the main dialogue coordinates to just width/length
398 rdlg.right -= rdlg.left - 1;
399 rdlg.bottom -= rdlg.top - 1;
400 rdlg.left = 0;
401 rdlg.top = 0;
402
403 // Load the bitmap into the bitmap control and fetch its dimensions
404 hbmp = LoadBitmap((HINSTANCE)win_gethinstance(), MAKEINTRESOURCE(RSRC_BMP));
405
406 HWND hwnd = GetDlgItem(hwndDlg, WIN_STARTWIN_BITMAP);
407 SendMessage(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp);
408
409 RECT r;
410 GetClientRect(hwnd, &r);
411
412 int const xoffset = r.right;
413 int const yoffset = r.bottom - rdlg.bottom;
414
415 // Shift and resize the controls that require it
416 rtab.left += xoffset;
417 rtab.bottom += yoffset;
418 rcancel.left += xoffset;
419 rcancel.top += yoffset;
420 rstart.left += xoffset;
421 rstart.top += yoffset;
422 rdlg.right += xoffset;
423 rdlg.bottom += yoffset;
424
425 // Move the controls to their new positions
426 MoveWindow(GetDlgItem(hwndDlg, WIN_STARTWIN_TABCTL), rtab.left, rtab.top, rtab.right, rtab.bottom, FALSE);
427 MoveWindow(GetDlgItem(hwndDlg, WIN_STARTWIN_CANCEL), rcancel.left, rcancel.top, rcancel.right, rcancel.bottom, FALSE);
428 MoveWindow(GetDlgItem(hwndDlg, WIN_STARTWIN_START), rstart.left, rstart.top, rstart.right, rstart.bottom, FALSE);
429
430 // Move the main dialogue to the centre of the screen
431 HDC hdc = GetDC(NULL);
432 rdlg.left = (GetDeviceCaps(hdc, HORZRES) - rdlg.right) / 2;
433 rdlg.top = (GetDeviceCaps(hdc, VERTRES) - rdlg.bottom) / 2;
434 ReleaseDC(NULL, hdc);
435 MoveWindow(hwndDlg, rdlg.left + chrome.left, rdlg.top + chrome.left,
436 rdlg.right + (-chrome.left+chrome.right), rdlg.bottom + (-chrome.top+chrome.bottom), TRUE);
437
438 // Add tabs to the tab control
439 {
440 static char textSetup[] = TEXT("Setup");
441 static char textMessageLog[] = TEXT("Message Log");
442
443 hwnd = GetDlgItem(hwndDlg, WIN_STARTWIN_TABCTL);
444
445 TCITEM tab = {};
446 tab.mask = TCIF_TEXT;
447 tab.pszText = textSetup;
448 SendMessage(hwnd, TCM_INSERTITEM, (WPARAM)TAB_CONFIG, (LPARAM)&tab);
449 tab.mask = TCIF_TEXT;
450 tab.pszText = textMessageLog;
451 SendMessage(hwnd, TCM_INSERTITEM, (WPARAM)TAB_MESSAGES, (LPARAM)&tab);
452
453 // Work out the position and size of the area inside the tab control for the pages
454 ZeroMemory(&r, sizeof(r));
455 GetClientRect(hwnd, &r);
456 SendMessage(hwnd, TCM_ADJUSTRECT, FALSE, (LPARAM)&r);
457 r.right -= r.left-1;
458 r.bottom -= r.top-1;
459 r.top += rtab.top;
460 r.left += rtab.left;
461
462 // Create the pages and position them in the tab control, but hide them
463 pages[TAB_CONFIG] = CreateDialog((HINSTANCE)win_gethinstance(), MAKEINTRESOURCE(WIN_STARTWINPAGE_CONFIG), hwndDlg, ConfigPageProc);
464 SetWindowPos(pages[TAB_CONFIG], hwnd, r.left, r.top, r.right, r.bottom, SWP_HIDEWINDOW);
465
466 pages[TAB_MESSAGES] = GetDlgItem(hwndDlg, WIN_STARTWIN_MESSAGES);
467 SetWindowPos(pages[TAB_MESSAGES], hwnd, r.left, r.top, r.right, r.bottom, SWP_HIDEWINDOW);
468
469 // Tell the editfield acting as the console to exclude the width of the scrollbar
470 GetClientRect(pages[TAB_MESSAGES], &r);
471 r.right -= GetSystemMetrics(SM_CXVSCROLL)+4;
472 r.left = r.top = 0;
473 SendMessage(pages[TAB_MESSAGES], EM_SETRECTNP,0,(LPARAM)&r);
474
475 // Set a tab stop in the game data listbox
476 {
477 DWORD tabs[1] = { 150 };
478 (void)ListBox_SetTabStops(GetDlgItem(pages[TAB_CONFIG], IDCDATA), 1, tabs);
479 }
480
481 SetFocus(GetDlgItem(hwndDlg, WIN_STARTWIN_START));
482 SetWindowText(hwndDlg, apptitle);
483 }
484 return FALSE;
485 }
486
487 case WM_NOTIFY:
488 {
489 auto nmhdr = (LPNMHDR)lParam;
490 if (nmhdr->idFrom != WIN_STARTWIN_TABCTL) break;
491 int const cur = SendMessage(nmhdr->hwndFrom, TCM_GETCURSEL,0,0);
492 switch (nmhdr->code)
493 {
494 case TCN_SELCHANGING:
495 case TCN_SELCHANGE:
496 if (cur < 0 || !pages[cur])
497 break;
498 ShowWindow(pages[cur], nmhdr->code == TCN_SELCHANGING ? SW_HIDE : SW_SHOW);
499 return TRUE;
500 }
501 break;
502 }
503
504 case WM_CLOSE:
505 if (mode == TAB_CONFIG) done = 0;
506 else quitevent++;
507 return TRUE;
508
509 case WM_DESTROY:
510 if (hbmp)
511 {
512 DeleteObject(hbmp);
513 hbmp = NULL;
514 }
515
516 if (pages[TAB_CONFIG])
517 {
518 DestroyWindow(pages[TAB_CONFIG]);
519 pages[TAB_CONFIG] = NULL;
520 }
521
522 startupdlg = NULL;
523 return TRUE;
524
525 case WM_COMMAND:
526 switch (LOWORD(wParam))
527 {
528 case WIN_STARTWIN_CANCEL:
529 if (mode == TAB_CONFIG) done = 0;
530 else quitevent++;
531 return TRUE;
532 case WIN_STARTWIN_START:
533 done = 1;
534 return TRUE;
535 }
536 return FALSE;
537
538 case WM_CTLCOLORSTATIC:
539 if ((HWND)lParam == pages[TAB_MESSAGES])
540 return (BOOL)(intptr_t)GetSysColorBrush(COLOR_WINDOW);
541 break;
542
543 default:
544 break;
545 }
546
547 return FALSE;
548 }
549
550
startwin_open(void)551 int32_t startwin_open(void)
552 {
553 if (startupdlg) return 1;
554 INITCOMMONCONTROLSEX icc = { sizeof(icc), ICC_TAB_CLASSES };
555 InitCommonControlsEx(&icc);
556 startupdlg = CreateDialog((HINSTANCE)win_gethinstance(), MAKEINTRESOURCE(WIN_STARTWIN), NULL, startup_dlgproc);
557 if (startupdlg)
558 {
559 SetPage(TAB_MESSAGES);
560 EnableConfig(0);
561 return 0;
562 }
563 return -1;
564 }
565
startwin_close(void)566 int32_t startwin_close(void)
567 {
568 if (!startupdlg) return 1;
569 DestroyWindow(startupdlg);
570 startupdlg = NULL;
571 return 0;
572 }
573
startwin_puts(const char * buf)574 int32_t startwin_puts(const char *buf)
575 {
576 if (!startupdlg) return 1;
577
578 const HWND edctl = pages[TAB_MESSAGES];
579
580 if (!edctl) return -1;
581
582 static HWND dactrl = NULL;
583 if (!dactrl) dactrl = GetDlgItem(startupdlg, WIN_STARTWIN_TABCTL);
584
585 int const vis = ((int)SendMessage(dactrl, TCM_GETCURSEL,0,0) == TAB_MESSAGES);
586
587 if (vis)
588 SendMessage(edctl, WM_SETREDRAW, FALSE, 0);
589
590 int const curlen = SendMessage(edctl, WM_GETTEXTLENGTH, 0,0);
591 SendMessage(edctl, EM_SETSEL, (WPARAM)curlen, (LPARAM)curlen);
592
593 int const numlines = SendMessage(edctl, EM_GETLINECOUNT, 0, 0);
594 static bool newline = false;
595 const char *p = buf;
596
597 while (*p)
598 {
599 if (newline)
600 {
601 SendMessage(edctl, EM_REPLACESEL, 0, (LPARAM)"\r\n");
602 newline = false;
603 }
604 const char *q = p;
605 while (*q && *q != '\n') q++;
606 static char workbuf[1024];
607 Bmemcpy(workbuf, p, q-p);
608 if (*q == '\n')
609 {
610 if (!q[1])
611 {
612 newline = true;
613 workbuf[q-p] = 0;
614 }
615 else
616 {
617 workbuf[q-p] = '\r';
618 workbuf[q-p+1] = '\n';
619 workbuf[q-p+2] = 0;
620 }
621 p = q+1;
622 }
623 else
624 {
625 workbuf[q-p] = 0;
626 p = q;
627 }
628 SendMessage(edctl, EM_REPLACESEL, 0, (LPARAM)workbuf);
629 }
630
631 int const newnumlines = SendMessage(edctl, EM_GETLINECOUNT, 0, 0);
632 SendMessage(edctl, EM_LINESCROLL, 0, newnumlines - numlines);
633
634 if (vis)
635 SendMessage(edctl, WM_SETREDRAW, TRUE, 0);
636
637 return 0;
638 }
639
startwin_settitle(const char * str)640 int32_t startwin_settitle(const char *str)
641 {
642 if (!startupdlg) return 1;
643 SetWindowText(startupdlg, str);
644 return 0;
645 }
646
startwin_idle(void * v)647 int32_t startwin_idle(void *v)
648 {
649 if (!startupdlg || !IsWindow(startupdlg)) return 0;
650 if (IsDialogMessage(startupdlg, (MSG *)v)) return 1;
651 return 0;
652 }
653
startwin_run(void)654 int32_t startwin_run(void)
655 {
656 if (!startupdlg) return 1;
657
658 done = -1;
659
660 SetPage(TAB_CONFIG);
661 EnableConfig(1);
662
663 #ifdef POLYMER
664 settings.polymer = (glrendmode == REND_POLYMER);
665 #else
666 settings.polymer = 0;
667 #endif
668
669 settings.shared = gSetup;
670 settings.grp = g_selectedGrp;
671 settings.gamedir = g_modDir;
672
673 PopulateForm(-1);
674
675 do
676 {
677 MSG msg;
678
679 switch (GetMessage(&msg, NULL, 0,0))
680 {
681 case 0:
682 done = 1;
683 break;
684 case -1:
685 return -1;
686 default:
687 if (IsWindow(startupdlg) && IsDialogMessage(startupdlg, &msg))
688 break;
689 TranslateMessage(&msg);
690 DispatchMessage(&msg);
691 break;
692 }
693 }
694 while (done < 0);
695
696 SetPage(TAB_MESSAGES);
697 EnableConfig(0);
698
699 if (done)
700 {
701 gSetup = settings.shared;
702 #ifdef USE_OPENGL
703 glrendmode = (settings.polymer) ? REND_POLYMER : REND_POLYMOST;
704 #endif
705 g_selectedGrp = settings.grp;
706 Bstrcpy(g_modDir, (g_noSetup == 0 && settings.gamedir != NULL) ? settings.gamedir : "/");
707 }
708
709 return done;
710 }
711
712 #endif // STARTUP_SETUP_WINDOW
713