+static void about(frontend *fe)
+{
+ int i;
+ WNDCLASS wc;
+ MSG msg;
+ TEXTMETRIC tm;
+ HDC hdc;
+ HFONT oldfont;
+ SIZE size;
+ int gm, id;
+ int winwidth, winheight, y;
+ int height, width, maxwid;
+ const char *strings[16];
+ int lengths[16];
+ int nstrings = 0;
+ char titlebuf[512];
+
+ sprintf(titlebuf, "About %.250s", thegame.name);
+
+ strings[nstrings++] = thegame.name;
+ strings[nstrings++] = "from Simon Tatham's Portable Puzzle Collection";
+ strings[nstrings++] = ver;
+
+ wc.style = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW;
+ wc.lpfnWndProc = DefDlgProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = DLGWINDOWEXTRA + 8;
+ wc.hInstance = fe->inst;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND +1);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "GameAboutBox";
+ RegisterClass(&wc);
+
+ hdc = GetDC(fe->hwnd);
+ SetMapMode(hdc, MM_TEXT);
+
+ fe->dlg_done = FALSE;
+
+ fe->cfgfont = CreateFont(-MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),
+ 0, 0, 0, 0,
+ FALSE, FALSE, FALSE, DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ FF_SWISS,
+ "MS Shell Dlg");
+
+ oldfont = SelectObject(hdc, fe->cfgfont);
+ if (GetTextMetrics(hdc, &tm)) {
+ height = tm.tmAscent + tm.tmDescent;
+ width = tm.tmAveCharWidth;
+ } else {
+ height = width = 30;
+ }
+
+ /*
+ * Figure out the layout of the About box by measuring the
+ * length of each piece of text.
+ */
+ maxwid = 0;
+ winheight = height/2;
+
+ for (i = 0; i < nstrings; i++) {
+ if (GetTextExtentPoint32(hdc, strings[i], strlen(strings[i]), &size))
+ lengths[i] = size.cx;
+ else
+ lengths[i] = 0; /* *shrug* */
+ if (maxwid < lengths[i])
+ maxwid = lengths[i];
+ winheight += height * 3 / 2 + (height / 2);
+ }
+
+ winheight += height + height * 7 / 4; /* OK button */
+ winwidth = maxwid + 4*width;
+
+ SelectObject(hdc, oldfont);
+ ReleaseDC(fe->hwnd, hdc);
+
+ /*
+ * Create the dialog, now that we know its size.
+ */
+ {
+ RECT r, r2;
+
+ r.left = r.top = 0;
+ r.right = winwidth;
+ r.bottom = winheight;
+
+ AdjustWindowRectEx(&r, (WS_OVERLAPPEDWINDOW /*|
+ DS_MODALFRAME | WS_POPUP | WS_VISIBLE |
+ WS_CAPTION | WS_SYSMENU*/) &~
+ (WS_MAXIMIZEBOX | WS_OVERLAPPED),
+ FALSE, 0);
+
+ /*
+ * Centre the dialog on its parent window.
+ */
+ r.right -= r.left;
+ r.bottom -= r.top;
+ GetWindowRect(fe->hwnd, &r2);
+ r.left = (r2.left + r2.right - r.right) / 2;
+ r.top = (r2.top + r2.bottom - r.bottom) / 2;
+ r.right += r.left;
+ r.bottom += r.top;
+
+ fe->cfgbox = CreateWindowEx(0, wc.lpszClassName, titlebuf,
+ DS_MODALFRAME | WS_POPUP | WS_VISIBLE |
+ WS_CAPTION | WS_SYSMENU,
+ r.left, r.top,
+ r.right-r.left, r.bottom-r.top,
+ fe->hwnd, NULL, fe->inst, NULL);
+ }
+
+ SendMessage(fe->cfgbox, WM_SETFONT, (WPARAM)fe->cfgfont, FALSE);
+
+ SetWindowLong(fe->cfgbox, GWL_USERDATA, (LONG)fe);
+ SetWindowLong(fe->cfgbox, DWL_DLGPROC, (LONG)AboutDlgProc);
+
+ id = 1000;
+ y = height/2;
+ for (i = 0; i < nstrings; i++) {
+ int border = width*2 + (maxwid - lengths[i]) / 2;
+ mkctrl(fe, border, border+lengths[i], y+height*1/8, y+height*9/8,
+ "Static", 0, 0, strings[i], id++);
+ y += height*3/2;
+
+ assert(y < winheight);
+ y += height/2;
+ }
+
+ y += height/2; /* extra space before OK */
+ mkctrl(fe, width*2, maxwid+width*2, y, y+height*7/4, "BUTTON",
+ BS_PUSHBUTTON | BS_NOTIFY | WS_TABSTOP | BS_DEFPUSHBUTTON, 0,
+ "OK", IDOK);
+
+ SendMessage(fe->cfgbox, WM_INITDIALOG, 0, 0);
+
+ EnableWindow(fe->hwnd, FALSE);
+ ShowWindow(fe->cfgbox, SW_NORMAL);
+ while ((gm=GetMessage(&msg, NULL, 0, 0)) > 0) {
+ if (!IsDialogMessage(fe->cfgbox, &msg))
+ DispatchMessage(&msg);
+ if (fe->dlg_done)
+ break;
+ }
+ EnableWindow(fe->hwnd, TRUE);
+ SetForegroundWindow(fe->hwnd);
+ DestroyWindow(fe->cfgbox);
+ DeleteObject(fe->cfgfont);
+}
+
+static int get_config(frontend *fe, int which)