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 "witchaven.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