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