Subversion Repositories eduke32

Rev

Rev 197 | Rev 219 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
194 terminx 1
#ifndef RENDERTYPEWIN
2
#error Only for Windows
3
#endif
4
 
5
#include "duke3d.h"
6
 
7
#include "build.h"
8
#include "winlayer.h"
9
#include "compat.h"
10
 
214 terminx 11
#include "startdlg.h"
12
 
194 terminx 13
#define WIN32_LEAN_AND_MEAN
14
#include <windows.h>
15
#include <windowsx.h>
16
#define _WIN32_IE 0x0300
17
#include <commctrl.h>
18
#include <stdio.h>
19
 
20
#include "startwin.game.h"
21
 
22
#define TAB_CONFIG 0
214 terminx 23
#define TAB_GAME 1
24
#define TAB_MESSAGES 2
194 terminx 25
 
26
static struct {
27
    int fullscreen;
28
    int xdim, ydim, bpp;
29
    int forcesetup;
30
    int usemouse, usejoy;
214 terminx 31
    char selectedgrp[BMAX_PATH+1];
194 terminx 32
} settings;
33
 
34
static HWND startupdlg = NULL;
214 terminx 35
static HWND pages[3] = { NULL, NULL, NULL };
197 terminx 36
static int done = -1, mode = TAB_CONFIG;
194 terminx 37
 
214 terminx 38
static void PopulateForm(int pgs)
194 terminx 39
{
40
    HWND hwnd;
214 terminx 41
    if (pgs & (1<<TAB_CONFIG)) {
42
        int i,j;
43
        char buf[64];
44
        int mode;
194 terminx 45
 
214 terminx 46
        hwnd = GetDlgItem(pages[TAB_CONFIG], IDCVMODE);
194 terminx 47
 
214 terminx 48
        mode = checkvideomode(&settings.xdim, &settings.ydim, settings.bpp, settings.fullscreen, 1);
49
        if (mode < 0) {
50
            int cd[] = { 32, 24, 16, 15, 8, 0 };
51
            for (i=0; cd[i]; ) { if (cd[i] >= settings.bpp) i++; else break; }
52
            for ( ; cd[i]; i++) {
53
                mode = checkvideomode(&settings.xdim, &settings.ydim, cd[i], settings.fullscreen, 1);
54
                if (mode < 0) continue;
55
                settings.bpp = cd[i];
56
                break;
57
            }
194 terminx 58
        }
214 terminx 59
 
60
        Button_SetCheck(GetDlgItem(pages[TAB_CONFIG], IDCFULLSCREEN), (settings.fullscreen ? BST_CHECKED : BST_UNCHECKED));
61
        Button_SetCheck(GetDlgItem(pages[TAB_CONFIG], IDCALWAYSSHOW), (settings.forcesetup ? BST_CHECKED : BST_UNCHECKED));
62
 
63
        ComboBox_ResetContent(hwnd);
64
        for (i=0; i<validmodecnt; i++) {
65
            if (validmode[i].fs != settings.fullscreen) continue;
66
 
67
            // all modes get added to the 3D mode list
68
            Bsprintf(buf, "%ld x %ld %dbpp", validmode[i].xdim, validmode[i].ydim, validmode[i].bpp);
69
            j = ComboBox_AddString(hwnd, buf);
70
            ComboBox_SetItemData(hwnd, j, i);
71
            if (i == mode) ComboBox_SetCurSel(hwnd, j);
72
        }
73
 
74
        Button_SetCheck(GetDlgItem(pages[TAB_CONFIG], IDCINPUTMOUSE), (settings.usemouse ? BST_CHECKED : BST_UNCHECKED));
75
        Button_SetCheck(GetDlgItem(pages[TAB_CONFIG], IDCINPUTJOY), (settings.usejoy ? BST_CHECKED : BST_UNCHECKED));
194 terminx 76
    }
77
 
214 terminx 78
    if (pgs & (1<<TAB_GAME)) {
79
        struct grpfile *fg;
80
        int i, j;
81
        char buf[128+BMAX_PATH];
194 terminx 82
 
214 terminx 83
        hwnd = GetDlgItem(pages[TAB_GAME], IDGDATA);
194 terminx 84
 
214 terminx 85
        for (fg = foundgrps; fg; fg=fg->next) {
86
            for (i = 0; i<numgrpfiles; i++)
87
                if (fg->crcval == grpfiles[i].crcval) break;
88
            if (i == numgrpfiles) continue;     // unrecognised grp file
89
 
90
            Bsprintf(buf, "%s\t%s", grpfiles[i].name, fg->name);
91
            j = ListBox_AddString(hwnd, buf);
92
            ListBox_SetItemData(hwnd, j, (LPARAM)fg);
93
            if (!Bstrcasecmp(fg->name, settings.selectedgrp)) ListBox_SetCurSel(hwnd, j);
94
        }
194 terminx 95
    }
96
}
97
 
98
static INT_PTR CALLBACK ConfigPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
99
{
100
    switch (uMsg) {
101
    case WM_COMMAND:
102
        switch (LOWORD(wParam)) {
103
        case IDCFULLSCREEN:
104
            settings.fullscreen = !settings.fullscreen;
214 terminx 105
            PopulateForm(1<<TAB_CONFIG);
194 terminx 106
            return TRUE;
107
        case IDCVMODE:
108
            if (HIWORD(wParam) == CBN_SELCHANGE) {
109
                int i;
110
                i = ComboBox_GetCurSel((HWND)lParam);
111
                if (i != CB_ERR) i = ComboBox_GetItemData((HWND)lParam, i);
112
                if (i != CB_ERR) {
113
                    settings.xdim = validmode[i].xdim;
114
                    settings.ydim = validmode[i].ydim;
115
                    settings.bpp  = validmode[i].bpp;
116
                }
117
            }
118
            return TRUE;
119
        case IDCALWAYSSHOW:
120
            settings.forcesetup = IsDlgButtonChecked(hwndDlg, IDCALWAYSSHOW) == BST_CHECKED;
121
            return TRUE;
122
        case IDCINPUTMOUSE:
123
            settings.usemouse = IsDlgButtonChecked(hwndDlg, IDCINPUTMOUSE) == BST_CHECKED;
124
            return TRUE;
125
        case IDCINPUTJOY:
126
            settings.usejoy = IsDlgButtonChecked(hwndDlg, IDCINPUTJOY) == BST_CHECKED;
127
            return TRUE;
128
        default: break;
129
        }
130
        break;
131
    default: break;
132
    }
133
    return FALSE;
134
}
135
 
214 terminx 136
static INT_PTR CALLBACK GamePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
137
{
138
    switch (uMsg) {
139
    case WM_COMMAND:
140
        switch (LOWORD(wParam)) {
141
        case IDGDATA: {
142
                int i;
143
                i = ListBox_GetCurSel((HWND)lParam);
144
                if (i != CB_ERR) i = ListBox_GetItemData((HWND)lParam, i);
145
                if (i != CB_ERR) strcpy(settings.selectedgrp, ((struct grpfile*)i)->name);
146
                return TRUE;
147
            }
148
        default: break;
149
        }
150
        break;
151
    default: break;
152
    }
153
    return FALSE;
154
}
194 terminx 155
 
156
 
214 terminx 157
 
194 terminx 158
static void SetPage(int n)
159
{
160
    HWND tab;
161
    int cur;
162
    tab = GetDlgItem(startupdlg, WIN_STARTWIN_TABCTL);
163
    cur = (int)SendMessage(tab, TCM_GETCURSEL,0,0);
164
    ShowWindow(pages[cur],SW_HIDE);
165
    SendMessage(tab, TCM_SETCURSEL, n, 0);
166
    ShowWindow(pages[n],SW_SHOW);
197 terminx 167
    mode = n;
196 terminx 168
 
169
    SetFocus(GetDlgItem(startupdlg, WIN_STARTWIN_TABCTL));
194 terminx 170
}
171
 
172
static void EnableConfig(int n)
173
{
197 terminx 174
    //EnableWindow(GetDlgItem(startupdlg, WIN_STARTWIN_CANCEL), n);
194 terminx 175
    EnableWindow(GetDlgItem(startupdlg, WIN_STARTWIN_START), n);
176
    EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDCFULLSCREEN), n);
177
    EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDCVMODE), n);
178
    EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDCINPUTMOUSE), n);
179
    EnableWindow(GetDlgItem(pages[TAB_CONFIG], IDCINPUTJOY), n);
214 terminx 180
 
181
    EnableWindow(GetDlgItem(pages[TAB_GAME], IDGDATA), n);
194 terminx 182
}
183
 
184
static INT_PTR CALLBACK startup_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
185
{
186
    static HBITMAP hbmp = NULL;
187
    HDC hdc;
188
 
189
    switch (uMsg) {
190
    case WM_INITDIALOG: {
191
            HWND hwnd;
192
            RECT r, rdlg, chrome, rtab, rcancel, rstart;
193
            int xoffset = 0, yoffset = 0;
194
 
195
            // Fetch the positions (in screen coordinates) of all the windows we need to tweak
196
            ZeroMemory(&chrome, sizeof(chrome));
197
            AdjustWindowRect(&chrome, GetWindowLong(hwndDlg, GWL_STYLE), FALSE);
198
            GetWindowRect(hwndDlg, &rdlg);
199
            GetWindowRect(GetDlgItem(hwndDlg, WIN_STARTWIN_TABCTL), &rtab);
200
            GetWindowRect(GetDlgItem(hwndDlg, WIN_STARTWIN_CANCEL), &rcancel);
201
            GetWindowRect(GetDlgItem(hwndDlg, WIN_STARTWIN_START), &rstart);
202
 
203
            // Knock off the non-client area of the main dialogue to give just the client area
204
            rdlg.left -= chrome.left; rdlg.top -= chrome.top;
205
            rdlg.right -= chrome.right; rdlg.bottom -= chrome.bottom;
206
 
207
            // Translate them to client-relative coordinates wrt the main dialogue window
208
            rtab.right -= rtab.left - 1; rtab.bottom -= rtab.top - 1;
209
            rtab.left  -= rdlg.left; rtab.top -= rdlg.top;
210
 
211
            rcancel.right -= rcancel.left - 1; rcancel.bottom -= rcancel.top - 1;
212
            rcancel.left -= rdlg.left; rcancel.top -= rdlg.top;
213
 
214
            rstart.right -= rstart.left - 1; rstart.bottom -= rstart.top - 1;
215
            rstart.left -= rdlg.left; rstart.top -= rdlg.top;
216
 
217
            // And then convert the main dialogue coordinates to just width/length
218
            rdlg.right -= rdlg.left - 1; rdlg.bottom -= rdlg.top - 1;
219
            rdlg.left = 0; rdlg.top = 0;
220
 
221
            // Load the bitmap into the bitmap control and fetch its dimensions
222
            hbmp = LoadBitmap((HINSTANCE)win_gethinstance(), MAKEINTRESOURCE(RSRC_BMP));
223
            hwnd = GetDlgItem(hwndDlg,WIN_STARTWIN_BITMAP);
224
            SendMessage(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp);
225
            GetClientRect(hwnd, &r);
226
            xoffset = r.right;
227
            yoffset = r.bottom - rdlg.bottom;
228
 
229
            // Shift and resize the controls that require it
230
            rtab.left += xoffset; rtab.bottom += yoffset;
231
            rcancel.left += xoffset; rcancel.top += yoffset;
232
            rstart.left += xoffset; rstart.top += yoffset;
233
            rdlg.right += xoffset;
234
            rdlg.bottom += yoffset;
235
 
236
            // Move the controls to their new positions
237
            MoveWindow(GetDlgItem(hwndDlg, WIN_STARTWIN_TABCTL), rtab.left, rtab.top, rtab.right, rtab.bottom, FALSE);
238
            MoveWindow(GetDlgItem(hwndDlg, WIN_STARTWIN_CANCEL), rcancel.left, rcancel.top, rcancel.right, rcancel.bottom, FALSE);
239
            MoveWindow(GetDlgItem(hwndDlg, WIN_STARTWIN_START), rstart.left, rstart.top, rstart.right, rstart.bottom, FALSE);
240
 
241
            // Move the main dialogue to the centre of the screen
242
            hdc = GetDC(NULL);
243
            rdlg.left = (GetDeviceCaps(hdc, HORZRES) - rdlg.right) / 2;
244
            rdlg.top = (GetDeviceCaps(hdc, VERTRES) - rdlg.bottom) / 2;
245
            ReleaseDC(NULL, hdc);
246
            MoveWindow(hwndDlg, rdlg.left + chrome.left, rdlg.top + chrome.left,
247
                       rdlg.right + (-chrome.left+chrome.right), rdlg.bottom + (-chrome.top+chrome.bottom), TRUE);
248
 
249
            // Add tabs to the tab control
250
            {
251
                TCITEM tab;
252
 
253
                hwnd = GetDlgItem(hwndDlg, WIN_STARTWIN_TABCTL);
254
 
255
                ZeroMemory(&tab, sizeof(tab));
256
                tab.mask = TCIF_TEXT;
257
                tab.pszText = TEXT("Configuration");
214 terminx 258
                SendMessage(hwnd, TCM_INSERTITEM, (WPARAM)TAB_CONFIG, (LPARAM)&tab);
194 terminx 259
                tab.mask = TCIF_TEXT;
214 terminx 260
                tab.pszText = TEXT("Game");
261
                SendMessage(hwnd, TCM_INSERTITEM, (WPARAM)TAB_GAME, (LPARAM)&tab);
262
                tab.mask = TCIF_TEXT;
194 terminx 263
                tab.pszText = TEXT("Messages");
214 terminx 264
                SendMessage(hwnd, TCM_INSERTITEM, (WPARAM)TAB_MESSAGES, (LPARAM)&tab);
194 terminx 265
 
266
                // Work out the position and size of the area inside the tab control for the pages
267
                ZeroMemory(&r, sizeof(r));
268
                GetClientRect(hwnd, &r);
269
                SendMessage(hwnd, TCM_ADJUSTRECT, FALSE, (LPARAM)&r);
270
                r.right -= r.left-1;
271
                r.bottom -= r.top-1;
272
                r.top += rtab.top;
273
                r.left += rtab.left;
274
 
275
                // Create the pages and position them in the tab control, but hide them
276
                pages[TAB_CONFIG] = CreateDialog((HINSTANCE)win_gethinstance(),
277
                                                 MAKEINTRESOURCE(WIN_STARTWINPAGE_CONFIG), hwndDlg, ConfigPageProc);
214 terminx 278
                pages[TAB_GAME] = CreateDialog((HINSTANCE)win_gethinstance(),
279
                                               MAKEINTRESOURCE(WIN_STARTWINPAGE_GAME), hwndDlg, GamePageProc);
194 terminx 280
                pages[TAB_MESSAGES] = GetDlgItem(hwndDlg, WIN_STARTWIN_MESSAGES);
281
                SetWindowPos(pages[TAB_CONFIG], hwnd,r.left,r.top,r.right,r.bottom,SWP_HIDEWINDOW);
214 terminx 282
                SetWindowPos(pages[TAB_GAME], hwnd,r.left,r.top,r.right,r.bottom,SWP_HIDEWINDOW);
194 terminx 283
                SetWindowPos(pages[TAB_MESSAGES], hwnd,r.left,r.top,r.right,r.bottom,SWP_HIDEWINDOW);
284
 
285
                // Tell the editfield acting as the console to exclude the width of the scrollbar
286
                GetClientRect(pages[TAB_MESSAGES],&r);
287
                r.right -= GetSystemMetrics(SM_CXVSCROLL)+4;
288
                r.left = r.top = 0;
289
                SendMessage(pages[TAB_MESSAGES], EM_SETRECTNP,0,(LPARAM)&r);
290
 
214 terminx 291
                // Set a tab stop in the game data listbox
292
                {
293
                    DWORD tabs[1] = { 150 };
294
                    ListBox_SetTabStops(GetDlgItem(pages[TAB_GAME], IDGDATA), 1, tabs);
295
                }
296
 
194 terminx 297
                SetFocus(GetDlgItem(hwndDlg, WIN_STARTWIN_START));
214 terminx 298
                SetWindowText(hwndDlg, apptitle);
194 terminx 299
            }
300
            return FALSE;
301
        }
302
 
303
    case WM_NOTIFY: {
304
            LPNMHDR nmhdr = (LPNMHDR)lParam;
305
            int cur;
306
            if (nmhdr->idFrom != WIN_STARTWIN_TABCTL) break;
307
            cur = (int)SendMessage(nmhdr->hwndFrom, TCM_GETCURSEL,0,0);
308
            switch (nmhdr->code) {
309
            case TCN_SELCHANGING: {
310
                    if (cur < 0 || !pages[cur]) break;
311
                    ShowWindow(pages[cur],SW_HIDE);
312
                    return TRUE;
313
                }
314
            case TCN_SELCHANGE: {
315
                    if (cur < 0 || !pages[cur]) break;
316
                    ShowWindow(pages[cur],SW_SHOW);
317
                    return TRUE;
318
                }
319
            }
320
            break;
321
        }
322
 
323
    case WM_CLOSE:
214 terminx 324
        if (mode == TAB_CONFIG) done = 0;
325
        else quitevent++;
194 terminx 326
        return TRUE;
327
 
328
    case WM_DESTROY:
329
        if (hbmp) {
330
            DeleteObject(hbmp);
331
            hbmp = NULL;
332
        }
333
 
214 terminx 334
        if (pages[TAB_GAME]) {
335
            DestroyWindow(pages[TAB_GAME]);
336
            pages[TAB_GAME] = NULL;
337
        }
338
 
194 terminx 339
        if (pages[TAB_CONFIG]) {
340
            DestroyWindow(pages[TAB_CONFIG]);
341
            pages[TAB_CONFIG] = NULL;
342
        }
343
 
344
        startupdlg = NULL;
345
        return TRUE;
346
 
347
    case WM_COMMAND:
348
        switch (LOWORD(wParam)) {
214 terminx 349
        case WIN_STARTWIN_CANCEL:
350
            if (mode == TAB_CONFIG) done = 0;
351
            else quitevent++;
352
            return TRUE;
194 terminx 353
        case WIN_STARTWIN_START: done = 1; return TRUE;
354
        }
355
        return FALSE;
356
 
357
    case WM_CTLCOLORSTATIC:
358
        if ((HWND)lParam == pages[TAB_MESSAGES])
359
            return (BOOL)GetSysColorBrush(COLOR_WINDOW);
360
        break;
361
 
362
    default: break;
363
    }
364
 
365
    return FALSE;
366
}
367
 
368
 
369
int startwin_open(void)
370
{
371
    INITCOMMONCONTROLSEX icc;
372
    if (startupdlg) return 1;
373
    icc.dwSize = sizeof(icc);
374
    icc.dwICC = ICC_TAB_CLASSES;
375
    InitCommonControlsEx(&icc);
376
    startupdlg = CreateDialog((HINSTANCE)win_gethinstance(), MAKEINTRESOURCE(WIN_STARTWIN), NULL, startup_dlgproc);
377
    if (startupdlg) {
378
        SetPage(TAB_MESSAGES);
379
        EnableConfig(0);
380
        return 0;
381
    }
382
    return -1;
383
}
384
 
385
int startwin_close(void)
386
{
387
    if (!startupdlg) return 1;
388
    DestroyWindow(startupdlg);
389
    startupdlg = NULL;
390
    return 0;
391
}
392
 
393
int startwin_puts(const char *buf)
394
{
395
    const char *p = NULL, *q = NULL;
396
    char workbuf[1024];
397
    static int newline = 0;
398
    int curlen, linesbefore, linesafter;
399
    HWND edctl;
400
    int vis;
401
 
402
    if (!startupdlg) return 1;
403
 
404
    edctl = pages[TAB_MESSAGES];
405
    if (!edctl) return -1;
406
 
407
    vis = ((int)SendMessage(GetDlgItem(startupdlg, WIN_STARTWIN_TABCTL), TCM_GETCURSEL,0,0) == TAB_MESSAGES);
408
 
409
    if (vis) SendMessage(edctl, WM_SETREDRAW, FALSE,0);
410
    curlen = SendMessage(edctl, WM_GETTEXTLENGTH, 0,0);
411
    SendMessage(edctl, EM_SETSEL, (WPARAM)curlen, (LPARAM)curlen);
412
    linesbefore = SendMessage(edctl, EM_GETLINECOUNT, 0,0);
413
    p = buf;
414
    while (*p) {
415
        if (newline) {
416
            SendMessage(edctl, EM_REPLACESEL, 0, (LPARAM)"\r\n");
417
            newline = 0;
418
        }
419
        q = p;
420
        while (*q && *q != '\n') q++;
421
        memcpy(workbuf, p, q-p);
422
        if (*q == '\n') {
423
            if (!q[1]) {
424
                newline = 1;
425
                workbuf[q-p] = 0;
426
            } else {
427
                workbuf[q-p] = '\r';
428
                workbuf[q-p+1] = '\n';
429
                workbuf[q-p+2] = 0;
430
            }
431
            p = q+1;
432
        } else {
433
            workbuf[q-p] = 0;
434
            p = q;
435
        }
436
        SendMessage(edctl, EM_REPLACESEL, 0, (LPARAM)workbuf);
437
    }
438
    linesafter = SendMessage(edctl, EM_GETLINECOUNT, 0,0);
439
    SendMessage(edctl, EM_LINESCROLL, 0, linesafter-linesbefore);
440
    if (vis) SendMessage(edctl, WM_SETREDRAW, TRUE,0);
441
    return 0;
442
}
443
 
444
int startwin_settitle(const char *str)
445
{
446
    if (!startupdlg) return 1;
447
    SetWindowText(startupdlg, str);
448
    return 0;
449
}
450
 
451
int startwin_idle(void *v)
452
{
453
    if (!startupdlg || !IsWindow(startupdlg)) return 0;
454
    if (IsDialogMessage(startupdlg, (MSG*)v)) return 1;
455
    return 0;
456
}
457
 
214 terminx 458
extern char *duke3dgrp;
459
 
194 terminx 460
int startwin_run(void)
461
{
462
    MSG msg;
463
    if (!startupdlg) return 1;
464
 
465
    done = -1;
466
 
214 terminx 467
    ScanGroups();
468
 
194 terminx 469
    SetPage(TAB_CONFIG);
470
    EnableConfig(1);
471
 
472
    settings.fullscreen = ScreenMode;
473
    settings.xdim = ScreenWidth;
474
    settings.ydim = ScreenHeight;
475
    settings.bpp = ScreenBPP;
476
    settings.forcesetup = ForceSetup;
477
    settings.usemouse = UseMouse;
478
    settings.usejoy = UseJoystick;
214 terminx 479
    strncpy(settings.selectedgrp, duke3dgrp, BMAX_PATH);
480
    PopulateForm(-1);
194 terminx 481
 
482
    while (done < 0) {
483
        switch (GetMessage(&msg, NULL, 0,0)) {
484
        case 0: done = 1; break;
485
        case -1: return -1;
486
        default:
487
            if (IsWindow(startupdlg) && IsDialogMessage(startupdlg, &msg)) break;
488
            TranslateMessage(&msg);
489
            DispatchMessage(&msg);
490
            break;
491
        }
492
    }
493
 
494
    SetPage(TAB_MESSAGES);
495
    EnableConfig(0);
496
    if (done) {
497
        ScreenMode = settings.fullscreen;
498
        ScreenWidth = settings.xdim;
499
        ScreenHeight = settings.ydim;
500
        ScreenBPP = settings.bpp;
501
        ForceSetup = settings.forcesetup;
502
        UseMouse = settings.usemouse;
503
        UseJoystick = settings.usejoy;
214 terminx 504
        duke3dgrp = settings.selectedgrp;
194 terminx 505
    }
506
 
507
    return done;
508
}
509