OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / win / win32 / winhack.c
1 /* NetHack 3.6    winhack.c    $NHDT-Date: 1449488876 2015/12/07 11:47:56 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.44 $ */
2 /* Copyright (C) 2001 by Alex Kompel      */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 // winhack.cpp : Defines the entry point for the application.
6 //
7
8 #include <process.h>
9 #include "winMS.h"
10 #include "hack.h"
11 #include "dlb.h"
12 #include "resource.h"
13 #include "mhmain.h"
14 #include "mhmap.h"
15
16 /* Borland and MinGW redefine "boolean" in shlwapi.h,
17    so just use the little bit we need */
18 typedef struct _DLLVERSIONINFO {
19     DWORD cbSize;
20     DWORD dwMajorVersion; // Major version
21     DWORD dwMinorVersion; // Minor version
22     DWORD dwBuildNumber;  // Build number
23     DWORD dwPlatformID;   // DLLVER_PLATFORM_*
24 } DLLVERSIONINFO;
25
26 //
27 // The caller should always GetProcAddress("DllGetVersion"), not
28 // implicitly link to it.
29 //
30
31 typedef HRESULT(CALLBACK *DLLGETVERSIONPROC)(DLLVERSIONINFO *);
32
33 /* end of shlwapi.h */
34
35 /* Minimal common control library version
36 Version     _WIN_32IE   Platform/IE
37 =======     =========   ===========
38 4.00        0x0200      Microsoft(r) Windows 95/Windows NT 4.0
39 4.70        0x0300      Microsoft(r) Internet Explorer 3.x
40 4.71        0x0400      Microsoft(r) Internet Explorer 4.0
41 4.72        0x0401      Microsoft(r) Internet Explorer 4.01
42 ...and probably going on infinitely...
43 */
44 #define MIN_COMCTLMAJOR 4
45 #define MIN_COMCTLMINOR 71
46 #define INSTALL_NOTES "http://www.nethack.org/v340/ports/download-win.html#cc"
47 /*#define COMCTL_URL
48  * "http://www.microsoft.com/msdownload/ieplatform/ie/comctrlx86.asp"*/
49
50 extern void FDECL(nethack_exit, (int));
51 static TCHAR *_get_cmd_arg(TCHAR *pCmdLine);
52 static HRESULT GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor);
53 BOOL WINAPI
54 _nhapply_image_transparent(HDC hDC, int x, int y, int width, int height,
55                            HDC sourceDC, int s_x, int s_y, int s_width,
56                            int s_height, UINT cTransparent);
57
58 // Global Variables:
59 NHWinApp _nethack_app;
60
61 #ifdef __BORLANDC__
62 #define _stricmp(s1, s2) stricmp(s1, s2)
63 #define _strdup(s1) strdup(s1)
64 #endif
65
66 // Foward declarations of functions included in this code module:
67 extern boolean FDECL(pcmain, (int, char **));
68 static void __cdecl mswin_moveloop(void *);
69
70 #define MAX_CMDLINE_PARAM 255
71
72 int APIENTRY
73 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
74         int nCmdShow)
75 {
76     INITCOMMONCONTROLSEX InitCtrls;
77     int argc;
78     char *argv[MAX_CMDLINE_PARAM];
79     size_t len;
80     TCHAR *p;
81     TCHAR wbuf[BUFSZ];
82     char buf[BUFSZ];
83     DWORD major, minor;
84     boolean resuming;
85     /* OSVERSIONINFO osvi; */
86
87     UNREFERENCED_PARAMETER(hPrevInstance);
88     UNREFERENCED_PARAMETER(lpCmdLine);
89     UNREFERENCED_PARAMETER(nCmdShow);
90
91     sys_early_init();
92
93     /* ensure that we don't access violate on a panic() */
94     windowprocs.win_raw_print = mswin_raw_print;
95     windowprocs.win_raw_print_bold = mswin_raw_print_bold;
96
97     /* init applicatio structure */
98     _nethack_app.hApp = hInstance;
99     _nethack_app.hAccelTable =
100         LoadAccelerators(hInstance, (LPCTSTR) IDC_NETHACKW);
101     _nethack_app.hMainWnd = NULL;
102     _nethack_app.hPopupWnd = NULL;
103     _nethack_app.bmpTiles = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TILES));
104     if (_nethack_app.bmpTiles == NULL)
105         panic("cannot load tiles bitmap");
106     _nethack_app.bmpPetMark =
107         LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_PETMARK));
108     if (_nethack_app.bmpPetMark == NULL)
109         panic("cannot load pet mark bitmap");
110 #ifdef USE_PILEMARK
111     _nethack_app.bmpPileMark =
112         LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_PILEMARK));
113     if (_nethack_app.bmpPileMark == NULL)
114         panic("cannot load pile mark bitmap");
115 #endif
116     _nethack_app.bmpRip = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_RIP));
117     if (_nethack_app.bmpRip == NULL)
118         panic("cannot load rip bitmap");
119     _nethack_app.bmpSplash =
120         LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_SPLASH));
121     if (_nethack_app.bmpSplash == NULL)
122         panic("cannot load splash bitmap");
123     _nethack_app.bmpMapTiles = _nethack_app.bmpTiles;
124     _nethack_app.mapTile_X = TILE_X;
125     _nethack_app.mapTile_Y = TILE_Y;
126     _nethack_app.mapTilesPerLine = TILES_PER_LINE;
127
128     _nethack_app.bNoHScroll = FALSE;
129     _nethack_app.bNoVScroll = FALSE;
130     _nethack_app.saved_text = strdup("");
131
132     _nethack_app.bAutoLayout = TRUE;
133     _nethack_app.bWindowsLocked = TRUE;
134
135     _nethack_app.bNoSounds = FALSE;
136
137 #if 0  /* GdiTransparentBlt does not render spash bitmap for whatever reason */
138     /* use system-provided TransparentBlt for Win2k+ */
139     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
140     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
141     GetVersionEx(&osvi);
142     if (osvi.dwMajorVersion >= 5)
143         _nethack_app.lpfnTransparentBlt = GdiTransparentBlt;
144     else
145 #endif
146         _nethack_app.lpfnTransparentBlt = _nhapply_image_transparent;
147
148     // init controls
149     if (FAILED(GetComCtlVersion(&major, &minor))) {
150         char buf[TBUFSZ];
151         Sprintf(buf, "Cannot load common control library.\n%s\n%s",
152                 "For further information, refer to the installation notes at",
153                 INSTALL_NOTES);
154         panic(buf);
155     }
156     if (major < MIN_COMCTLMAJOR
157         || (major == MIN_COMCTLMAJOR && minor < MIN_COMCTLMINOR)) {
158         char buf[TBUFSZ];
159         Sprintf(buf, "Common control library is outdated.\n%s %d.%d\n%s\n%s",
160                 "NetHack requires at least version ", MIN_COMCTLMAJOR,
161                 MIN_COMCTLMINOR,
162                 "For further information, refer to the installation notes at",
163                 INSTALL_NOTES);
164         panic(buf);
165     }
166     ZeroMemory(&InitCtrls, sizeof(InitCtrls));
167     InitCtrls.dwSize = sizeof(InitCtrls);
168     InitCtrls.dwICC = ICC_LISTVIEW_CLASSES;
169     InitCommonControlsEx(&InitCtrls);
170
171     /* get command line parameters */
172     p = _get_cmd_arg(GetCommandLine());
173     p = _get_cmd_arg(NULL); /* skip first paramter - command name */
174     for (argc = 1; p && argc < MAX_CMDLINE_PARAM; argc++) {
175         len = _tcslen(p);
176         if (len > 0) {
177             argv[argc] = _strdup(NH_W2A(p, buf, BUFSZ));
178         } else {
179             argv[argc] = "";
180         }
181         p = _get_cmd_arg(NULL);
182     }
183     GetModuleFileName(NULL, wbuf, BUFSZ);
184     argv[0] = _strdup(NH_W2A(wbuf, buf, BUFSZ));
185
186     if (argc == 2) {
187         TCHAR *savefile = strdup(argv[1]);
188         TCHAR *plname;
189         for (p = savefile; *p && *p != '-'; p++)
190             ;
191         if (*p) {
192             /* we found a '-' */
193             plname = p + 1;
194             for (p = plname; *p && *p != '.'; p++)
195                 ;
196             if (*p) {
197                 if (strcmp(p + 1, "NetHack-saved-game") == 0) {
198                     *p = '\0';
199                     argv[1] = "-u";
200                     argv[2] = _strdup(plname);
201                     argc = 3;
202                 }
203             }
204         }
205         free(savefile);
206     }
207     resuming = pcmain(argc, argv);
208
209     moveloop(resuming);
210
211     return 0;
212 }
213
214 PNHWinApp
215 GetNHApp()
216 {
217     return &_nethack_app;
218 }
219
220 TCHAR *
221 _get_cmd_arg(TCHAR *pCmdLine)
222 {
223     static TCHAR *pArgs = NULL;
224     TCHAR *pRetArg;
225     BOOL bQuoted;
226
227     if (!pCmdLine && !pArgs)
228         return NULL;
229     if (!pArgs)
230         pArgs = pCmdLine;
231
232     /* skip whitespace */
233     for (pRetArg = pArgs; *pRetArg && _istspace(*pRetArg);
234          pRetArg = CharNext(pRetArg))
235         ;
236     if (!*pRetArg) {
237         pArgs = NULL;
238         return NULL;
239     }
240
241     /* check for quote */
242     if (*pRetArg == TEXT('"')) {
243         bQuoted = TRUE;
244         pRetArg = CharNext(pRetArg);
245         pArgs = _tcschr(pRetArg, TEXT('"'));
246     } else {
247         /* skip to whitespace */
248         for (pArgs = pRetArg; *pArgs && !_istspace(*pArgs);
249              pArgs = CharNext(pArgs))
250             ;
251     }
252
253     if (pArgs && *pArgs) {
254         TCHAR *p;
255         p = pArgs;
256         pArgs = CharNext(pArgs);
257         *p = (TCHAR) 0;
258     } else {
259         pArgs = NULL;
260     }
261
262     return pRetArg;
263 }
264
265 /* Get the version of the Common Control library on this machine.
266    Copied from the Microsoft SDK
267  */
268 HRESULT
269 GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
270 {
271     HINSTANCE hComCtl;
272     HRESULT hr = S_OK;
273     DLLGETVERSIONPROC pDllGetVersion;
274
275     if (IsBadWritePtr(pdwMajor, sizeof(DWORD))
276         || IsBadWritePtr(pdwMinor, sizeof(DWORD)))
277         return E_INVALIDARG;
278     // load the DLL
279     hComCtl = LoadLibrary(TEXT("comctl32.dll"));
280     if (!hComCtl)
281         return E_FAIL;
282
283     /*
284     You must get this function explicitly because earlier versions of the DLL
285     don't implement this function. That makes the lack of implementation of
286     the
287     function a version marker in itself.
288     */
289     pDllGetVersion =
290         (DLLGETVERSIONPROC) GetProcAddress(hComCtl, TEXT("DllGetVersion"));
291     if (pDllGetVersion) {
292         DLLVERSIONINFO dvi;
293         ZeroMemory(&dvi, sizeof(dvi));
294         dvi.cbSize = sizeof(dvi);
295         hr = (*pDllGetVersion)(&dvi);
296         if (SUCCEEDED(hr)) {
297             *pdwMajor = dvi.dwMajorVersion;
298             *pdwMinor = dvi.dwMinorVersion;
299         } else {
300             hr = E_FAIL;
301         }
302     } else {
303         /*
304         If GetProcAddress failed, then the DLL is a version previous to the
305         one
306         shipped with IE 3.x.
307         */
308         *pdwMajor = 4;
309         *pdwMinor = 0;
310     }
311     FreeLibrary(hComCtl);
312     return hr;
313 }
314
315 /* apply bitmap pointed by sourceDc transparently over
316 bitmap pointed by hDC */
317 BOOL WINAPI
318 _nhapply_image_transparent(HDC hDC, int x, int y, int width, int height,
319                            HDC sourceDC, int s_x, int s_y, int s_width,
320                            int s_height, UINT cTransparent)
321 {
322     /* Don't use TransparentBlt; According to Microsoft, it contains a memory
323      * leak in Window 95/98. */
324     HDC hdcMem, hdcBack, hdcObject, hdcSave;
325     COLORREF cColor;
326     HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
327     HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
328
329     /* Create some DCs to hold temporary data. */
330     hdcBack = CreateCompatibleDC(hDC);
331     hdcObject = CreateCompatibleDC(hDC);
332     hdcMem = CreateCompatibleDC(hDC);
333     hdcSave = CreateCompatibleDC(hDC);
334
335     /* this is bitmap for our pet image */
336     bmSave = CreateCompatibleBitmap(hDC, width, height);
337
338     /* Monochrome DC */
339     bmAndBack = CreateBitmap(width, height, 1, 1, NULL);
340     bmAndObject = CreateBitmap(width, height, 1, 1, NULL);
341
342     /* resulting bitmap */
343     bmAndMem = CreateCompatibleBitmap(hDC, width, height);
344
345     /* Each DC must select a bitmap object to store pixel data. */
346     bmBackOld = SelectObject(hdcBack, bmAndBack);
347     bmObjectOld = SelectObject(hdcObject, bmAndObject);
348     bmMemOld = SelectObject(hdcMem, bmAndMem);
349     bmSaveOld = SelectObject(hdcSave, bmSave);
350
351     /* copy source image because it is going to be overwritten */
352     StretchBlt(hdcSave, 0, 0, width, height, sourceDC, s_x, s_y, s_width,
353         s_height, SRCCOPY);
354
355     /* Set the background color of the source DC to the color.
356     contained in the parts of the bitmap that should be transparent */
357     cColor = SetBkColor(hdcSave, cTransparent);
358
359     /* Create the object mask for the bitmap by performing a BitBlt
360     from the source bitmap to a monochrome bitmap. */
361     BitBlt(hdcObject, 0, 0, width, height, hdcSave, 0, 0, SRCCOPY);
362
363     /* Set the background color of the source DC back to the original
364     color. */
365     SetBkColor(hdcSave, cColor);
366
367     /* Create the inverse of the object mask. */
368     BitBlt(hdcBack, 0, 0, width, height, hdcObject, 0, 0, NOTSRCCOPY);
369
370     /* Copy background to the resulting image  */
371     BitBlt(hdcMem, 0, 0, width, height, hDC, x, y, SRCCOPY);
372
373     /* Mask out the places where the source image will be placed. */
374     BitBlt(hdcMem, 0, 0, width, height, hdcObject, 0, 0, SRCAND);
375
376     /* Mask out the transparent colored pixels on the source image. */
377     BitBlt(hdcSave, 0, 0, width, height, hdcBack, 0, 0, SRCAND);
378
379     /* XOR the source image with the beckground. */
380     BitBlt(hdcMem, 0, 0, width, height, hdcSave, 0, 0, SRCPAINT);
381
382     /* blt resulting image to the screen */
383     BitBlt(hDC, x, y, width, height, hdcMem, 0, 0, SRCCOPY);
384
385     /* cleanup */
386     DeleteObject(SelectObject(hdcBack, bmBackOld));
387     DeleteObject(SelectObject(hdcObject, bmObjectOld));
388     DeleteObject(SelectObject(hdcMem, bmMemOld));
389     DeleteObject(SelectObject(hdcSave, bmSaveOld));
390
391     DeleteDC(hdcMem);
392     DeleteDC(hdcBack);
393     DeleteDC(hdcObject);
394     DeleteDC(hdcSave);
395
396     return TRUE;
397 }