Two things: 1. This patch causes the window placement of the main window to be written to the registry, and to be restored upon the next start of the program. I had to move the creation of the main window to init_nhwindows, as the registry is not read until then. 2. Implement support for wc_popup_dialog (or rather, support for not having popup windows.) It asks getlin questions and get_ext_cmd on the message window, much like the TTY port does it. The get_ext_cmd procedure is almost but not quite the same as the one for TTY, and I think it is better: It autocompletes the extended command you type, but if you keep on typing it doesn't add those letters after the completed command, but just keeps track of how many (correct) characters you typed. If you type a different character than the autocompleted command has, it shows you what you typed again. If you press backspace, it deletes the characters you typed, and if autocompletion is no longer possible, it removes the autocompleted part. The effect of this is that you can type as many letters as you want when typing an extended command, as long as it is enough to identify one command; and you only have to delete the characters you actually typed if you made a mistake. I think autocompletion is a lot less obtrusive this way. Some notes about the patch: - Both mswin_getlin and mswin_get_ext_cmd now have two versions, with and without a popup. - yn_question was changed so that it displays a caret, which is a lot nicer IMHO. - I had to implement a new NetHack Windows Message parameter, "MSNH_MSG_CARET", to make it possible to show and hide the caret in the message window. Normally the caret is created and destroyed by the window that owns it, but in NetHack the input focus is always on the main window, while the caret is in the message window, which happens to be the only one that knows how large the caret should be. - mswin_putstr_ex's last parameter changed from boolean to int; the semantics are enhanced so that a negative last parameter means "delete that many characters from the input line". The string to be deleted is passed in as well, although it is currently not used. - A rather large chunk of code finds out where the last string that was displayed on the message window ended. This is necessary to place the caret at the right spot. The caret is always positioned there, even if it is hidden or non-existing. - mswin_get_nh_event was changed to actually process and empty the message queue, and called from mswin_putstr_ex to make sure the message window is updated before the next step is done. Without this, the caret is positioned before the last message is painted, which makes its x-position after the last character of the previous line.
253 lines
7.0 KiB
C
253 lines
7.0 KiB
C
/* Copyright (C) 2001 by Alex Kompel <shurikk@pacbell.net> */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
// winhack.cpp : Defines the entry point for the application.
|
|
//
|
|
|
|
#include <process.h>
|
|
#include "winMS.h"
|
|
#include "hack.h"
|
|
#include "dlb.h"
|
|
#include "resource.h"
|
|
#include "mhmain.h"
|
|
#include "mhmap.h"
|
|
|
|
#ifndef __BORLANDC__
|
|
#include <shlwapi.h>
|
|
#else /* Borland redefines "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 *);
|
|
|
|
#endif
|
|
|
|
#ifdef OVL0
|
|
#define SHARED_DCL
|
|
#else
|
|
#define SHARED_DCL extern
|
|
#endif
|
|
|
|
/* 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"*/
|
|
|
|
extern void FDECL(nethack_exit,(int));
|
|
static TCHAR* _get_cmd_arg(TCHAR* pCmdLine);
|
|
static HRESULT GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor);
|
|
|
|
|
|
// Global Variables:
|
|
NHWinApp _nethack_app;
|
|
|
|
#ifdef __BORLANDC__
|
|
#define _stricmp(s1,s2) stricmp(s1,s2)
|
|
#define _strdup(s1) strdup(s1)
|
|
#endif
|
|
|
|
// Foward declarations of functions included in this code module:
|
|
extern void FDECL(pcmain, (int,char **));
|
|
static void __cdecl mswin_moveloop(void *);
|
|
|
|
#define MAX_CMDLINE_PARAM 255
|
|
|
|
int APIENTRY WinMain(HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
INITCOMMONCONTROLSEX InitCtrls;
|
|
int argc;
|
|
char* argv[MAX_CMDLINE_PARAM];
|
|
size_t len;
|
|
TCHAR *p;
|
|
TCHAR wbuf[BUFSZ];
|
|
char buf[BUFSZ];
|
|
DWORD major, minor;
|
|
|
|
|
|
/* ensure that we don't access violate on a panic() */
|
|
windowprocs.win_raw_print = mswin_raw_print;
|
|
windowprocs.win_raw_print_bold = mswin_raw_print_bold;
|
|
|
|
/* init applicatio 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");
|
|
_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;
|
|
_nethack_app.saved_text = strdup("");
|
|
|
|
// init controls
|
|
if (FAILED(GetComCtlVersion(&major, &minor)))
|
|
{
|
|
char buf[TBUFSZ];
|
|
Sprintf(buf, "Cannot load common control library.\n%s\n%s",
|
|
"For further information, refer to the installation notes at",
|
|
INSTALL_NOTES);
|
|
panic(buf);
|
|
}
|
|
if (major < MIN_COMCTLMAJOR
|
|
|| (major == MIN_COMCTLMAJOR && minor < MIN_COMCTLMINOR))
|
|
{
|
|
char buf[TBUFSZ];
|
|
Sprintf(buf, "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(buf);
|
|
}
|
|
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 paramter - 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] = "";
|
|
}
|
|
p = _get_cmd_arg(NULL);
|
|
}
|
|
GetModuleFileName(NULL, wbuf, BUFSZ);
|
|
argv[0] = _strdup(NH_W2A(wbuf, buf, BUFSZ));
|
|
|
|
pcmain(argc,argv);
|
|
|
|
moveloop();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
PNHWinApp GetNHApp()
|
|
{
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|