Files
nethack/win/win32/NetHackW.c
nhmall acb85b18cf Change Windows startup
remove the safeproc pseudo-windowport routines from
almost a decade ago.

A very early pass is made through the config file,
seeking out just the interface-related OPTIONS=windowport
and OPTIONS=soundlib and ignoring all other options in the
config file during that early pass, so the windowport
can be activated without the NetHack core initialization
in place that some of the other rcfile OPTIONS require.

Bundles the existing rcfile processing code into rcfile().

New functions to control which rcfile options will be
disregarded in the early config file pass, and which will be
processed:

    set_all_options_disregarded();
    set_all_options_heeded();
    disregard_this_option(opt_xx);
    heed_this_option(opt_xx);

Windows calls rcfile_interface_options(), which is
a bundling of a series of function calls to achieve
the desired result.

    void
    rcfile_interface_options(void)
    {
        allopt_array_init();
        set_all_options_disregarded();
        heed_this_option(opt_windowtype);
        heed_this_option(opt_soundlib);
        rcfile();
        set_all_options_heeded();
        disregard_this_option(opt_windowtype);
        disregard_this_option(opt_soundlib);
    }
2026-04-05 11:37:20 -04:00

432 lines
13 KiB
C

/* NetHack 3.7 NetHackW.c $NHDT-Date: 1693359674 2023/08/30 01:41:14 $ $NHDT-Branch: keni-crashweb2 $:$NHDT-Revision: 1.79 $ */
/* Copyright (C) 2001 by Alex Kompel */
/* NetHack may be freely redistributed. See license for details. */
// NetHackW.cpp : Defines the entry point for the application.
//
#include "win10.h"
#include <process.h>
#include "winMS.h"
#include "hack.h"
#include "dlb.h"
#include "resource.h"
#include "mhmain.h"
#include "mhmap.h"
/* Borland and MinGW redefine "boolean" in shlwapi.h,
so just use the little bit we need */
typedef struct _DLLVERSIONINFO {
DWORD cbSize;
DWORD dwMajorVersion; // Major version
DWORD dwMinorVersion; // Minor version
DWORD dwBuildNumber; // Build number
DWORD dwPlatformID; // DLLVER_PLATFORM_*
} DLLVERSIONINFO;
//
// The caller should always GetProcAddress("DllGetVersion"), not
// implicitly link to it.
//
typedef HRESULT(CALLBACK *DLLGETVERSIONPROC)(DLLVERSIONINFO *);
/* end of shlwapi.h */
/* Minimal common control library version
Version _WIN_32IE Platform/IE
======= ========= ===========
4.00 0x0200 Microsoft(r) Windows 95/Windows NT 4.0
4.70 0x0300 Microsoft(r) Internet Explorer 3.x
4.71 0x0400 Microsoft(r) Internet Explorer 4.0
4.72 0x0401 Microsoft(r) Internet Explorer 4.01
...and probably going on infinitely...
*/
#define MIN_COMCTLMAJOR 4
#define MIN_COMCTLMINOR 71
#define INSTALL_NOTES "http://www.nethack.org/v340/ports/download-win.html#cc"
/*#define COMCTL_URL
* "http://www.microsoft.com/msdownload/ieplatform/ie/comctrlx86.asp"*/
static TCHAR *_get_cmd_arg(TCHAR *pCmdLine);
static HRESULT GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor);
BOOL WINAPI
_nhapply_image_transparent(HDC hDC, int x, int y, int width, int height,
HDC sourceDC, int s_x, int s_y, int s_width,
int s_height, UINT cTransparent);
// Global Variables:
NHWinApp _nethack_app;
int GUILaunched = TRUE; /* We tell shared startup code in windmain.c
that the GUI was launched via this */
#ifdef __BORLANDC__
#define _stricmp(s1, s2) stricmp(s1, s2)
#define _strdup(s1) strdup(s1)
#endif
#define MAX_CMDLINE_PARAM 255
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable : 28251)
#endif
extern int nethackw_main(int argc, char *argv[]);
static char *argv[MAX_CMDLINE_PARAM];
int APIENTRY
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
INITCOMMONCONTROLSEX InitCtrls;
int argc;
size_t len;
TCHAR *p;
TCHAR wbuf[BUFSZ];
char buf[BUFSZ];
DWORD major, minor;
/* OSVERSIONINFO osvi; */
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
win10_init();
early_init(0, NULL); /* Change as needed to support CRASHREPORT */
/* init application structure */
_nethack_app.hApp = hInstance;
_nethack_app.hAccelTable =
LoadAccelerators(hInstance, (LPCTSTR) IDC_NETHACKW);
_nethack_app.hMainWnd = NULL;
_nethack_app.hPopupWnd = NULL;
_nethack_app.bmpTiles = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TILES));
if (_nethack_app.bmpTiles == NULL)
panic("cannot load tiles bitmap");
_nethack_app.bmpPetMark =
LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_PETMARK));
if (_nethack_app.bmpPetMark == NULL)
panic("cannot load pet mark bitmap");
#ifdef USE_PILEMARK
_nethack_app.bmpPileMark =
LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_PILEMARK));
if (_nethack_app.bmpPileMark == NULL)
panic("cannot load pile mark bitmap");
#endif
_nethack_app.bmpRip = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_RIP));
if (_nethack_app.bmpRip == NULL)
panic("cannot load rip bitmap");
_nethack_app.bmpSplash =
LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_SPLASH));
if (_nethack_app.bmpSplash == NULL)
panic("cannot load splash bitmap");
_nethack_app.bmpMapTiles = _nethack_app.bmpTiles;
_nethack_app.mapTile_X = TILE_X;
_nethack_app.mapTile_Y = TILE_Y;
_nethack_app.mapTilesPerLine = TILES_PER_LINE;
_nethack_app.bNoHScroll = FALSE;
_nethack_app.bNoVScroll = FALSE;
if (_nethack_app.saved_text)
free(_nethack_app.saved_text), _nethack_app.saved_text = 0;
_nethack_app.saved_text = strdup("");
_nethack_app.bAutoLayout = TRUE;
_nethack_app.bWindowsLocked = TRUE;
_nethack_app.bNoSounds = FALSE;
#if 0 /* GdiTransparentBlt does not render splash bitmap for whatever reason */
/* use system-provided TransparentBlt for Win2k+ */
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if (osvi.dwMajorVersion >= 5)
_nethack_app.lpfnTransparentBlt = GdiTransparentBlt;
else
#endif
_nethack_app.lpfnTransparentBlt = _nhapply_image_transparent;
// init controls
if (FAILED(GetComCtlVersion(&major, &minor))) {
char buf2[TBUFSZ];
Sprintf(buf2, "Cannot load common control library.\n%s\n%s",
"For further information, refer to the installation notes at",
INSTALL_NOTES);
panic("%s", buf2);
}
if (major < MIN_COMCTLMAJOR
|| (major == MIN_COMCTLMAJOR && minor < MIN_COMCTLMINOR)) {
char buf2[TBUFSZ];
Sprintf(buf2, "Common control library is outdated.\n%s %d.%d\n%s\n%s",
"NetHack requires at least version ", MIN_COMCTLMAJOR,
MIN_COMCTLMINOR,
"For further information, refer to the installation notes at",
INSTALL_NOTES);
panic("%s", buf2);
}
ZeroMemory(&InitCtrls, sizeof(InitCtrls));
InitCtrls.dwSize = sizeof(InitCtrls);
InitCtrls.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&InitCtrls);
/* get command line parameters */
p = _get_cmd_arg(GetCommandLine());
p = _get_cmd_arg(NULL); /* skip first parameter - command name */
for (argc = 1; p && argc < MAX_CMDLINE_PARAM; argc++) {
len = _tcslen(p);
if (len > 0) {
argv[argc] = strdup(NH_W2A(p, buf, BUFSZ));
} else {
argv[argc] = strdup("");
}
p = _get_cmd_arg(NULL);
}
GetModuleFileName(NULL, wbuf, BUFSZ);
argv[0] = strdup(NH_W2A(wbuf, buf, BUFSZ));
if (argc == 2) {
TCHAR *savefile = strdup(argv[1]);
TCHAR *name;
for (p = savefile; *p && *p != '-'; p++)
;
if (*p) {
/* we found a '-' */
name = p + 1;
for (p = name; *p && *p != '.'; p++)
;
if (*p) {
if (strcmp(p + 1, "NetHack-saved-game") == 0) {
*p = '\0';
argv[1] = strdup("-u");
argv[2] = strdup(name);
argc = 3;
}
}
}
free(savefile);
}
GUILaunched = 1;
/* let nethackw_main do the argument processing */
nethackw_main(argc, argv);
/* not reached */
return 0;
}
extern void free_menu_data(void);
void
free_winmain_stuff(void)
{
int cnt;
for (cnt = 0; cnt < MAX_CMDLINE_PARAM; ++cnt) {
if (argv[cnt])
free((genericptr_t) argv[cnt]), argv[cnt] = 0;
}
if (_nethack_app.saved_text)
free((genericptr_t) _nethack_app.saved_text),
_nethack_app.saved_text = 0;
for (cnt = 0; cnt < MAXWINDOWS; ++cnt) {
if (windowdata[cnt].address) {
if (!windowdata[cnt].isstatic)
free(windowdata[cnt].address);
windowdata[cnt].address = 0;
}
}
free_menu_data();
}
#ifdef _MSC_VER
#pragma warning( pop )
#endif
PNHWinApp
GetNHApp(void)
{
return &_nethack_app;
}
TCHAR *
_get_cmd_arg(TCHAR *pCmdLine)
{
static TCHAR *pArgs = NULL;
TCHAR *pRetArg;
BOOL bQuoted;
if (!pCmdLine && !pArgs)
return NULL;
if (!pArgs)
pArgs = pCmdLine;
/* skip whitespace */
for (pRetArg = pArgs; *pRetArg && _istspace(*pRetArg);
pRetArg = CharNext(pRetArg))
;
if (!*pRetArg) {
pArgs = NULL;
return NULL;
}
/* check for quote */
if (*pRetArg == TEXT('"')) {
bQuoted = TRUE;
pRetArg = CharNext(pRetArg);
pArgs = _tcschr(pRetArg, TEXT('"'));
} else {
/* skip to whitespace */
for (pArgs = pRetArg; *pArgs && !_istspace(*pArgs);
pArgs = CharNext(pArgs))
;
}
if (pArgs && *pArgs) {
TCHAR *p;
p = pArgs;
pArgs = CharNext(pArgs);
*p = (TCHAR) 0;
} else {
pArgs = NULL;
}
nhUse(bQuoted);
return pRetArg;
}
/* Get the version of the Common Control library on this machine.
Copied from the Microsoft SDK
*/
HRESULT
GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
{
HINSTANCE hComCtl;
HRESULT hr = S_OK;
DLLGETVERSIONPROC pDllGetVersion;
if (IsBadWritePtr(pdwMajor, sizeof(DWORD))
|| IsBadWritePtr(pdwMinor, sizeof(DWORD)))
return E_INVALIDARG;
// load the DLL
hComCtl = LoadLibrary(TEXT("comctl32.dll"));
if (!hComCtl)
return E_FAIL;
/*
You must get this function explicitly because earlier versions of the DLL
don't implement this function. That makes the lack of implementation of
the
function a version marker in itself.
*/
pDllGetVersion =
(DLLGETVERSIONPROC) GetProcAddress(hComCtl, TEXT("DllGetVersion"));
if (pDllGetVersion) {
DLLVERSIONINFO dvi;
ZeroMemory(&dvi, sizeof(dvi));
dvi.cbSize = sizeof(dvi);
hr = (*pDllGetVersion)(&dvi);
if (SUCCEEDED(hr)) {
*pdwMajor = dvi.dwMajorVersion;
*pdwMinor = dvi.dwMinorVersion;
} else {
hr = E_FAIL;
}
} else {
/*
If GetProcAddress failed, then the DLL is a version previous to the
one
shipped with IE 3.x.
*/
*pdwMajor = 4;
*pdwMinor = 0;
}
FreeLibrary(hComCtl);
return hr;
}
/* apply bitmap pointed by sourceDc transparently over
bitmap pointed by hDC */
BOOL WINAPI
_nhapply_image_transparent(HDC hDC, int x, int y, int width, int height,
HDC sourceDC, int s_x, int s_y, int s_width,
int s_height, UINT cTransparent)
{
/* Don't use TransparentBlt; According to Microsoft, it contains a memory
* leak in Window 95/98. */
HDC hdcMem, hdcBack, hdcObject, hdcSave;
COLORREF cColor;
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
/* Create some DCs to hold temporary data. */
hdcBack = CreateCompatibleDC(hDC);
hdcObject = CreateCompatibleDC(hDC);
hdcMem = CreateCompatibleDC(hDC);
hdcSave = CreateCompatibleDC(hDC);
/* this is bitmap for our pet image */
bmSave = CreateCompatibleBitmap(hDC, width, height);
/* Monochrome DC */
bmAndBack = CreateBitmap(width, height, 1, 1, NULL);
bmAndObject = CreateBitmap(width, height, 1, 1, NULL);
/* resulting bitmap */
bmAndMem = CreateCompatibleBitmap(hDC, width, height);
/* Each DC must select a bitmap object to store pixel data. */
bmBackOld = SelectObject(hdcBack, bmAndBack);
bmObjectOld = SelectObject(hdcObject, bmAndObject);
bmMemOld = SelectObject(hdcMem, bmAndMem);
bmSaveOld = SelectObject(hdcSave, bmSave);
/* copy source image because it is going to be overwritten */
StretchBlt(hdcSave, 0, 0, width, height, sourceDC, s_x, s_y, s_width,
s_height, SRCCOPY);
/* Set the background color of the source DC to the color.
contained in the parts of the bitmap that should be transparent */
cColor = SetBkColor(hdcSave, cTransparent);
/* Create the object mask for the bitmap by performing a BitBlt
from the source bitmap to a monochrome bitmap. */
BitBlt(hdcObject, 0, 0, width, height, hdcSave, 0, 0, SRCCOPY);
/* Set the background color of the source DC back to the original
color. */
SetBkColor(hdcSave, cColor);
/* Create the inverse of the object mask. */
BitBlt(hdcBack, 0, 0, width, height, hdcObject, 0, 0, NOTSRCCOPY);
/* Copy background to the resulting image */
BitBlt(hdcMem, 0, 0, width, height, hDC, x, y, SRCCOPY);
/* Mask out the places where the source image will be placed. */
BitBlt(hdcMem, 0, 0, width, height, hdcObject, 0, 0, SRCAND);
/* Mask out the transparent colored pixels on the source image. */
BitBlt(hdcSave, 0, 0, width, height, hdcBack, 0, 0, SRCAND);
/* XOR the source image with the background. */
BitBlt(hdcMem, 0, 0, width, height, hdcSave, 0, 0, SRCPAINT);
/* blt resulting image to the screen */
BitBlt(hDC, x, y, width, height, hdcMem, 0, 0, SRCCOPY);
/* cleanup */
DeleteObject(SelectObject(hdcBack, bmBackOld));
DeleteObject(SelectObject(hdcObject, bmObjectOld));
DeleteObject(SelectObject(hdcMem, bmMemOld));
DeleteObject(SelectObject(hdcSave, bmSaveOld));
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcSave);
return TRUE;
}