OSDN Git Service

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