//------------------------------------------------------------------------- /* Copyright (C) 2010 EDuke32 developers and contributors This file is part of EDuke32. EDuke32 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //------------------------------------------------------------------------- #include "ns.h" // Must come before everything else! #ifndef _WIN32 #error Only for Windows #endif #include "renderlayer.h" #ifdef STARTUP_SETUP_WINDOW #define NEED_WINDOWSX_H #define NEED_COMMCTRL_H #define ONLY_USERDEFS #include "_control.h" #include "build.h" #include "cache1d.h" #include "compat.h" #include "control.h" #include "keyboard.h" #include "startwin.game.h" #include "windows_inc.h" #include "gamecontrol.h" #pragma warning(disable:4244) // There's just a bit too much of these in here... #define TAB_CONFIG 0 #define TAB_MESSAGES 1 typedef struct { int32_t fullscreen; int32_t xdim; int32_t ydim; int32_t bpp; } ud_setup_t; static struct { int grp; ud_setup_t shared; int polymer; } settings; static HWND startupdlg; static HWND pages[3]; static int done = -1; static int mode = TAB_CONFIG; static TArray *gamedata; static CACHE1D_FIND_REC *finddirs; static inline void clearfilenames(void) { klistfree(finddirs); finddirs = NULL; } static inline void getfilenames(char const *path) { clearfilenames(); finddirs = klistpath(path,"*",CACHE1D_FIND_DIR); } #define POPULATE_VIDEO 1 #define POPULATE_CONFIG 2 #define POPULATE_GAME 4 #define POPULATE_GAMEDIRS 8 #ifdef INPUT_MOUSE #undef INPUT_MOUSE #endif #define INPUT_KB 0 #define INPUT_MOUSE 1 #define INPUT_JOYSTICK 2 #define INPUT_ALL 3 // Thanks, Microsoft for not providing alternatives for the dialog control macros. :( #undef SNDMSG #define SNDMSG ::SendMessageA const char *controlstrings[] = { "Keyboard only", "Keyboard and mouse", "Keyboard and joystick", "All supported devices" }; static void PopulateForm(int32_t pgs) { char buf[512]; if (pgs & POPULATE_GAMEDIRS) { HWND hwnd = GetDlgItem(pages[TAB_CONFIG], IDCGAMEDIR); #if 0 // This doesn't currently work and in its current form is useless anyway. It should offer a real directory picker. getfilenames("/"); (void)ComboBox_ResetContent(hwnd); int const r = ComboBox_AddString(hwnd, "None"); (void)ComboBox_SetItemData(hwnd, r, 0); (void)ComboBox_SetCurSel(hwnd, r); auto dirs = finddirs; for (int i=1, j=1; dirs != NULL; dirs=dirs->next) { if (Bstrcasecmp(dirs->name, "autoload") == 0) { j++; continue; } (void)ComboBox_AddString(hwnd, dirs->name); (void)ComboBox_SetItemData(hwnd, i, j); i++; j++; } #endif } if (pgs & POPULATE_VIDEO) { HWND hwnd = GetDlgItem(pages[TAB_CONFIG], IDCVMODE); int mode = videoCheckMode(&settings.shared.xdim, &settings.shared.ydim, settings.shared.bpp, settings.shared.fullscreen, 1); if (mode < 0 || (settings.shared.bpp < 15)) { int CONSTEXPR cd[] = { 32, 24, 16, 15, 8, 0 }; int i; for (i=0; cd[i];) { if (cd[i] >= settings.shared.bpp) i++; else break; } for (; cd[i]; i++) { mode = videoCheckMode(&settings.shared.xdim, &settings.shared.ydim, cd[i], settings.shared.fullscreen, 1); if (mode < 0) continue; settings.shared.bpp = cd[i]; break; } } Button_SetCheck(GetDlgItem(pages[TAB_CONFIG], IDCFULLSCREEN), ((settings.shared.fullscreen) ? BST_CHECKED : BST_UNCHECKED)); //Button_SetCheck(GetDlgItem(pages[TAB_CONFIG], IDCPOLYMER), ((settings.polymer) ? BST_CHECKED : BST_UNCHECKED)); (void)ComboBox_ResetContent(hwnd); for (int i=0; iidFrom != WIN_STARTWIN_TABCTL) break; int const cur = SendMessageA(nmhdr->hwndFrom, TCM_GETCURSEL,0,0); switch (nmhdr->code) { case TCN_SELCHANGING: case TCN_SELCHANGE: if (cur < 0 || !pages[cur]) break; ShowWindow(pages[cur], nmhdr->code == TCN_SELCHANGING ? SW_HIDE : SW_SHOW); return TRUE; } break; } case WM_CLOSE: if (mode == TAB_CONFIG) done = 0; else quitevent++; return TRUE; case WM_DESTROY: if (hbmp) { DeleteObject(hbmp); hbmp = NULL; } if (pages[TAB_CONFIG]) { DestroyWindow(pages[TAB_CONFIG]); pages[TAB_CONFIG] = NULL; } startupdlg = NULL; return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case WIN_STARTWIN_CANCEL: if (mode == TAB_CONFIG) done = 0; else quitevent++; return TRUE; case WIN_STARTWIN_START: done = 1; return TRUE; } return FALSE; case WM_CTLCOLORSTATIC: if ((HWND)lParam == pages[TAB_MESSAGES]) return (BOOL)(intptr_t)GetSysColorBrush(COLOR_WINDOW); break; default: break; } return FALSE; } int32_t startwin_open(void) { if (startupdlg) return 1; INITCOMMONCONTROLSEX icc = { sizeof(icc), ICC_TAB_CLASSES }; InitCommonControlsEx(&icc); startupdlg = CreateDialog((HINSTANCE)win_gethinstance(), MAKEINTRESOURCE(WIN_STARTWIN), NULL, startup_dlgproc); if (startupdlg) { SetPage(TAB_MESSAGES); EnableConfig(0); return 0; } return -1; } int32_t startwin_close(void) { if (!startupdlg) return 1; DestroyWindow(startupdlg); startupdlg = NULL; return 0; } int32_t startwin_puts(const char *buf) { if (!startupdlg) return 1; const HWND edctl = pages[TAB_MESSAGES]; if (!edctl) return -1; static HWND dactrl = NULL; if (!dactrl) dactrl = GetDlgItem(startupdlg, WIN_STARTWIN_TABCTL); int const vis = ((int)SendMessageA(dactrl, TCM_GETCURSEL,0,0) == TAB_MESSAGES); if (vis) SendMessageA(edctl, WM_SETREDRAW, FALSE, 0); int const curlen = SendMessageA(edctl, WM_GETTEXTLENGTH, 0,0); SendMessageA(edctl, EM_SETSEL, (WPARAM)curlen, (LPARAM)curlen); int const numlines = SendMessageA(edctl, EM_GETLINECOUNT, 0, 0); static bool newline = false; const char *p = buf; while (*p) { if (newline) { SendMessageA(edctl, EM_REPLACESEL, 0, (LPARAM)"\r\n"); newline = false; } const char *q = p; while (*q && *q != '\n') q++; static char workbuf[1024]; Bmemcpy(workbuf, p, q-p); if (*q == '\n') { if (!q[1]) { newline = true; workbuf[q-p] = 0; } else { workbuf[q-p] = '\r'; workbuf[q-p+1] = '\n'; workbuf[q-p+2] = 0; } p = q+1; } else { workbuf[q-p] = 0; p = q; } SendMessageA(edctl, EM_REPLACESEL, 0, (LPARAM)workbuf); } int const newnumlines = SendMessageA(edctl, EM_GETLINECOUNT, 0, 0); SendMessageA(edctl, EM_LINESCROLL, 0, newnumlines - numlines); if (vis) SendMessageA(edctl, WM_SETREDRAW, TRUE, 0); return 0; } int32_t startwin_settitle(const char *str) { if (!startupdlg) return 1; SetWindowTextA(startupdlg, str); return 0; } int32_t startwin_idle(void *v) { if (!startupdlg || !IsWindow(startupdlg)) return 0; if (IsDialogMessage(startupdlg, (MSG *)v)) return 1; return 0; } int32_t startwin_run(void) { if (!startupdlg) return 1; done = -1; SetPage(TAB_CONFIG); EnableConfig(1); settings.shared = { ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP }; settings.grp = 0; PopulateForm(-1); do { MSG msg; switch (GetMessage(&msg, NULL, 0,0)) { case 0: done = 1; break; case -1: return -1; default: if (IsWindow(startupdlg) && IsDialogMessage(startupdlg, &msg)) break; TranslateMessage(&msg); DispatchMessage(&msg); break; } } while (done < 0); SetPage(TAB_MESSAGES); EnableConfig(0); if (done) { ScreenWidth = settings.shared.xdim; ScreenHeight = settings.shared.ydim; ScreenMode = settings.shared.fullscreen; ScreenBPP = settings.shared.bpp; } return done; } int ShowStartupWindow(TArray &groups) { gamedata = &groups; startwin_open(); startwin_settitle("Demolition"); if (1)//readSetup < 0 || (!g_noSetup && (displaysetup)) || g_commandSetup) { auto choice = startwin_run(); if (choice == 0) { Bexit(EXIT_SUCCESS); } } startwin_close(); return settings.grp; } #endif // STARTUP_SETUP_WINDOW