+/*
+ * Given the current window size, make sure it's sane for the
+ * current puzzle and resize if necessary.
+ */
+
+static void check_window_size(frontend *fe, int *px, int *py)
+{
+ RECT r;
+ int wx, wy, cx, cy;
+
+ GetClientRect(fe->hwnd, &r);
+ cx = r.right - r.left;
+ cy = r.bottom - r.top;
+
+ if (check_window_resize(fe, cx, cy, px, py, &wx, &wy, FALSE)) {
+#ifdef _WIN32_WCE
+ SetWindowPos(fe->hwnd, NULL, 0, 0, wx, wy,
+ SWP_NOMOVE | SWP_NOZORDER);
+#endif
+ ;
+ }
+
+ GetClientRect(fe->hwnd, &r);
+ adjust_statusbar(fe, &r);
+}
+
+static void get_max_puzzle_size(frontend *fe, int *x, int *y)
+{
+ RECT r, sr;
+
+ if (SystemParametersInfo(SPI_GETWORKAREA, 0, &sr, FALSE)) {
+ *x = sr.right - sr.left;
+ *y = sr.bottom - sr.top;
+ r.left = 100;
+ r.right = 200;
+ r.top = 100;
+ r.bottom = 200;
+ AdjustWindowRectEx(&r, WINFLAGS, TRUE, 0);
+ *x -= r.right - r.left - 100;
+ *y -= r.bottom - r.top - 100;
+ } else {
+ *x = *y = INT_MAX;
+ }
+
+ if (fe->statusbar != NULL) {
+ GetWindowRect(fe->statusbar, &sr);
+ *y -= sr.bottom - sr.top;
+ }
+}
+
+#ifdef _WIN32_WCE
+/* Toolbar buttons on the numeric pad */
+static TBBUTTON tbNumpadButtons[] =
+{
+ {0, IDM_KEYEMUL + '1', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1},
+ {1, IDM_KEYEMUL + '2', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1},
+ {2, IDM_KEYEMUL + '3', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1},
+ {3, IDM_KEYEMUL + '4', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1},
+ {4, IDM_KEYEMUL + '5', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1},
+ {5, IDM_KEYEMUL + '6', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1},
+ {6, IDM_KEYEMUL + '7', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1},
+ {7, IDM_KEYEMUL + '8', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1},
+ {8, IDM_KEYEMUL + '9', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1},
+ {9, IDM_KEYEMUL + ' ', TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, -1}
+};
+#endif
+
+static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
+{
+ frontend *fe;
+ int x, y;
+ RECT r;
+
+ fe = snew(frontend);
+
+ fe->me = midend_new(fe, &thegame, &win_drawing, fe);
+
+ if (game_id) {
+ *error = midend_game_id(fe->me, game_id);
+ if (*error) {
+ midend_free(fe->me);
+ sfree(fe);
+ return NULL;
+ }
+ }
+
+ fe->inst = inst;
+
+ fe->timer = 0;
+ fe->hwnd = NULL;
+
+ fe->help_running = FALSE;
+
+ fe->drawstatus = NOTHING;
+ fe->dr = NULL;
+ fe->fontstart = 0;
+
+ midend_new_game(fe->me);
+
+ fe->fonts = NULL;
+ fe->nfonts = fe->fontsize = 0;
+
+ {
+ int i, ncolours;
+ float *colours;
+
+ colours = midend_colours(fe->me, &ncolours);
+
+ fe->colours = snewn(ncolours, COLORREF);
+ fe->brushes = snewn(ncolours, HBRUSH);
+ fe->pens = snewn(ncolours, HPEN);
+
+ for (i = 0; i < ncolours; i++) {
+ fe->colours[i] = RGB(255 * colours[i*3+0],
+ 255 * colours[i*3+1],
+ 255 * colours[i*3+2]);
+ fe->brushes[i] = CreateSolidBrush(fe->colours[i]);
+ fe->pens[i] = CreatePen(PS_SOLID, 1, fe->colours[i]);
+ }
+ sfree(colours);
+ }
+
+ if (midend_wants_statusbar(fe->me)) {
+ fe->statusbar = CreateWindowEx(0, STATUSCLASSNAME, TEXT("ooh"),
+ WS_CHILD | WS_VISIBLE,
+ 0, 0, 0, 0, /* status bar does these */
+ NULL, NULL, inst, NULL);
+ } else
+ fe->statusbar = NULL;
+
+ get_max_puzzle_size(fe, &x, &y);
+ midend_size(fe->me, &x, &y, FALSE);
+
+ r.left = r.top = 0;
+ r.right = x;
+ r.bottom = y;
+ AdjustWindowRectEx(&r, WINFLAGS, TRUE, 0);
+
+#ifdef _WIN32_WCE
+ fe->hwnd = CreateWindowEx(0, wGameName, wGameName,
+ WS_VISIBLE,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, inst, NULL);
+
+ {
+ SHMENUBARINFO mbi;
+ RECT rc, rcBar, rcTB, rcClient;
+
+ memset (&mbi, 0, sizeof(SHMENUBARINFO));
+ mbi.cbSize = sizeof(SHMENUBARINFO);
+ mbi.hwndParent = fe->hwnd;
+ mbi.nToolBarId = IDR_MENUBAR1;
+ mbi.hInstRes = inst;
+
+ SHCreateMenuBar(&mbi);
+
+ GetWindowRect(fe->hwnd, &rc);
+ GetWindowRect(mbi.hwndMB, &rcBar);
+ rc.bottom -= rcBar.bottom - rcBar.top;
+ MoveWindow(fe->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE);
+
+ if (thegame.flags & REQUIRE_NUMPAD)
+ {
+ fe->numpad = CreateToolbarEx (fe->hwnd,
+ WS_VISIBLE | WS_CHILD | CCS_NOPARENTALIGN | TBSTYLE_FLAT,
+ 0, 10, inst, IDR_PADTOOLBAR,
+ tbNumpadButtons, sizeof (tbNumpadButtons) / sizeof (TBBUTTON),
+ 0, 0, 14, 15, sizeof (TBBUTTON));
+ GetWindowRect(fe->numpad, &rcTB);
+ GetClientRect(fe->hwnd, &rcClient);
+ MoveWindow(fe->numpad,
+ 0,
+ rcClient.bottom - (rcTB.bottom - rcTB.top) - 1,
+ rcClient.right,
+ rcTB.bottom - rcTB.top,
+ FALSE);
+ SendMessage(fe->numpad, TB_SETINDENT, (rcClient.right - (10 * 21)) / 2, 0);
+ }
+ else
+ fe->numpad = NULL;
+ }
+#else
+ fe->hwnd = CreateWindowEx(0, thegame.name, thegame.name,
+ WS_OVERLAPPEDWINDOW &~
+ (WS_MAXIMIZEBOX),
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ r.right - r.left, r.bottom - r.top,
+ NULL, NULL, inst, NULL);
+#endif
+
+ if (midend_wants_statusbar(fe->me)) {
+ RECT sr;
+ DestroyWindow(fe->statusbar);
+ fe->statusbar = CreateWindowEx(0, STATUSCLASSNAME, TEXT("ooh"),
+ WS_CHILD | WS_VISIBLE,
+ 0, 0, 0, 0, /* status bar does these */
+ fe->hwnd, NULL, inst, NULL);
+#ifdef _WIN32_WCE
+ /* Flat status bar looks better on the Pocket PC */
+ SendMessage(fe->statusbar, SB_SIMPLE, (WPARAM) TRUE, 0);
+ SendMessage(fe->statusbar, SB_SETTEXT,
+ (WPARAM) 255 | SBT_NOBORDERS,
+ (LPARAM) L"");
+#endif
+
+ /*
+ * Now resize the window to take account of the status bar.
+ */
+ GetWindowRect(fe->statusbar, &sr);
+ GetWindowRect(fe->hwnd, &r);
+#ifndef _WIN32_WCE
+ SetWindowPos(fe->hwnd, NULL, 0, 0, r.right - r.left,
+ r.bottom - r.top + sr.bottom - sr.top,
+ SWP_NOMOVE | SWP_NOZORDER);
+#endif
+ } else {
+ fe->statusbar = NULL;
+ }
+
+ {
+#ifndef _WIN32_WCE
+ HMENU bar = CreateMenu();
+ HMENU menu = CreateMenu();
+ RECT menusize;
+
+ AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)menu, "&Game");
+#else
+ HMENU menu = SHGetSubMenu(SHFindMenuBar(fe->hwnd), ID_GAME);
+ DeleteMenu(menu, 0, MF_BYPOSITION);
+#endif
+ AppendMenu(menu, MF_ENABLED, IDM_NEW, TEXT("&New"));
+ AppendMenu(menu, MF_ENABLED, IDM_RESTART, TEXT("&Restart"));
+#ifndef _WIN32_WCE
+ /* ...here I run out of sensible accelerator characters. */
+ AppendMenu(menu, MF_ENABLED, IDM_DESC, TEXT("Speci&fic..."));
+ AppendMenu(menu, MF_ENABLED, IDM_SEED, TEXT("Rando&m Seed..."));
+#endif
+
+ if ((fe->npresets = midend_num_presets(fe->me)) > 0 ||
+ thegame.can_configure) {
+ int i;
+#ifndef _WIN32_WCE
+ HMENU sub = CreateMenu();
+
+ AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)sub, "&Type");
+#else
+ HMENU sub = SHGetSubMenu(SHFindMenuBar(fe->hwnd), ID_TYPE);
+ DeleteMenu(sub, 0, MF_BYPOSITION);
+#endif