Files
nethack/win/win32/mhmain.c
2003-09-30 03:42:01 +00:00

1068 lines
28 KiB
C

/* Copyright (C) 2001 by Alex Kompel <shurikk@pacbell.net> */
/* NetHack may be freely redistributed. See license for details. */
#include "winMS.h"
#include "patchlevel.h"
#include "resource.h"
#include "mhmsg.h"
#include "mhinput.h"
#include "mhmain.h"
#include "mhmenu.h"
#include "mhstatus.h"
#include "mhmsgwnd.h"
#include "mhmap.h"
typedef struct mswin_nethack_main_window {
int mapAcsiiModeSave;
} NHMainWindow, *PNHMainWindow;
static TCHAR szMainWindowClass[] = TEXT("MSNHMainWndClass");
static TCHAR szTitle[MAX_LOADSTRING];
extern void mswin_display_splash_window(BOOL);
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
static LRESULT onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
static void register_main_window_class(void);
static int menuid2mapmode(int menuid);
static int mapmode2menuid(int map_mode);
static void nhlock_windows( BOOL lock );
HWND mswin_init_main_window () {
static int run_once = 0;
HWND ret;
WINDOWPLACEMENT wp;
/* register window class */
if( !run_once ) {
LoadString(GetNHApp()->hApp, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
register_main_window_class( );
run_once = 1;
}
/* create the main window */
ret = CreateWindow(
szMainWindowClass, /* registered class name */
szTitle, /* window name */
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, /* window style */
CW_USEDEFAULT, /* horizontal position of window */
CW_USEDEFAULT, /* vertical position of window */
CW_USEDEFAULT, /* window width */
CW_USEDEFAULT, /* window height */
NULL, /* handle to parent or owner window */
NULL, /* menu handle or child identifier */
GetNHApp()->hApp, /* handle to application instance */
NULL /* window-creation data */
);
if( !ret ) panic("Cannot create main window");
if (GetNHApp()->regMainMinX != CW_USEDEFAULT)
{
wp.length = sizeof(wp);
wp.showCmd = GetNHApp()->regMainShowState;
wp.ptMinPosition.x = GetNHApp()->regMainMinX;
wp.ptMinPosition.y = GetNHApp()->regMainMinY;
wp.ptMaxPosition.x = GetNHApp()->regMainMaxX;
wp.ptMaxPosition.y = GetNHApp()->regMainMaxY;
wp.rcNormalPosition.left = GetNHApp()->regMainLeft;
wp.rcNormalPosition.top = GetNHApp()->regMainTop;
wp.rcNormalPosition.right = GetNHApp()->regMainRight;
wp.rcNormalPosition.bottom = GetNHApp()->regMainBottom;
SetWindowPlacement(ret, &wp);
}
else
ShowWindow(ret, SW_SHOWDEFAULT);
UpdateWindow(ret);
return ret;
}
void register_main_window_class()
{
WNDCLASS wcex;
ZeroMemory(&wcex, sizeof(wcex));
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)MainWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = GetNHApp()->hApp;
wcex.hIcon = LoadIcon(GetNHApp()->hApp, (LPCTSTR)IDI_NETHACKW);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (TCHAR*)IDC_NETHACKW;
wcex.lpszClassName = szMainWindowClass;
RegisterClass(&wcex);
}
/*
* Keypad keys are translated to the normal values below.
* Shifted keypad keys are translated to the
* shift values below.
*/
enum KEY_INDEXES {
KEY_NW, KEY_N, KEY_NE, KEY_MINUS,
KEY_W, KEY_GOINTERESTING, KEY_E, KEY_PLUS,
KEY_SW, KEY_S, KEY_SE,
KEY_INV, KEY_WAITLOOK,
KEY_LAST};
static const unsigned char
/* normal, shift, control */
keypad[KEY_LAST][3] = {
{'y', 'Y', C('y')}, /* 7 */
{'k', 'K', C('k')}, /* 8 */
{'u', 'U', C('u')}, /* 9 */
{'m', C('p'), C('p')}, /* - */
{'h', 'H', C('h')}, /* 4 */
{'g', 'G', 'g'}, /* 5 */
{'l', 'L', C('l')}, /* 6 */
{'+', 'P', C('p')}, /* + */
{'b', 'B', C('b')}, /* 1 */
{'j', 'J', C('j')}, /* 2 */
{'n', 'N', C('n')}, /* 3 */
{'i', 'I', C('i')}, /* Ins */
{'.', ':', ':'} /* Del */
},
numpad[KEY_LAST][3] = {
{'7', M('7'), '7'}, /* 7 */
{'8', M('8'), '8'}, /* 8 */
{'9', M('9'), '9'}, /* 9 */
{'m', C('p'), C('p')}, /* - */
{'4', M('4'), '4'}, /* 4 */
{'5', M('5'), '5'}, /* 5 */
{'6', M('6'), '6'}, /* 6 */
{'+', 'P', C('p')}, /* + */
{'1', M('1'), '1'}, /* 1 */
{'2', M('2'), '2'}, /* 2 */
{'3', M('3'), '3'}, /* 3 */
{'0', M('0'), '0'}, /* Ins */
{'.', ':', ':'} /* Del */
};
#define STATEON(x) ((GetKeyState(x) & 0xFFFE) != 0)
#define KEYTABLE_REGULAR(x) ((iflags.num_pad ? numpad : keypad)[x][0])
#define KEYTABLE_SHIFT(x) ((iflags.num_pad ? numpad : keypad)[x][1])
#define KEYTABLE(x) (STATEON(VK_SHIFT) ? KEYTABLE_SHIFT(x) : KEYTABLE_REGULAR(x))
/* map mode macros */
#define IS_MAP_FIT_TO_SCREEN(mode) ((mode)==MAP_MODE_ASCII_FIT_TO_SCREEN || \
(mode)==MAP_MODE_TILES_FIT_TO_SCREEN )
#define IS_MAP_ASCII(mode) ((mode)!=MAP_MODE_TILES && (mode)!=MAP_MODE_TILES_FIT_TO_SCREEN)
static const char *extendedlist = "acdefijlmnopqrstuvw?2";
#define SCANLO 0x02
static const char scanmap[] = { /* ... */
'1','2','3','4','5','6','7','8','9','0',0,0,0,0,
'q','w','e','r','t','y','u','i','o','p','[',']', '\n',
0, 'a','s','d','f','g','h','j','k','l',';','\'', '`',
0, '\\', 'z','x','c','v','b','n','m',',','.','?' /* ... */
};
/*
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.
*/
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PNHMainWindow data;
switch (message)
{
case WM_CREATE:
/* set window data */
data = (PNHMainWindow)malloc(sizeof(NHMainWindow));
if( !data ) panic("out of memory");
ZeroMemory(data, sizeof(NHMainWindow));
data->mapAcsiiModeSave = MAP_MODE_ASCII12x16;
SetWindowLong(hWnd, GWL_USERDATA, (LONG)data);
/* update menu items */
CheckMenuItem(
GetMenu(hWnd),
IDM_SETTING_LOCKWINDOWS,
MF_BYCOMMAND |
(GetNHApp()->bWindowsLocked? MF_CHECKED : MF_UNCHECKED)
);
CheckMenuItem(
GetMenu(hWnd),
IDM_SETTING_AUTOLAYOUT,
GetNHApp()->bAutoLayout? MF_CHECKED : MF_UNCHECKED
);
/* store handle to the mane menu in the application record */
GetNHApp()->hMainWnd = hWnd;
break;
case WM_MSNH_COMMAND:
onMSNHCommand(hWnd, wParam, lParam);
break;
case WM_KEYDOWN:
{
data = (PNHMainWindow)GetWindowLong(hWnd, GWL_USERDATA);
/* translate arrow keys into nethack commands */
switch (wParam)
{
case VK_LEFT:
if( STATEON(VK_CONTROL) ) {
/* scroll map window one line left */
SendMessage(
mswin_hwnd_from_winid(WIN_MAP),
WM_HSCROLL,
MAKEWPARAM(SB_LINEUP, 0),
(LPARAM)NULL
);
} else {
NHEVENT_KBD(KEYTABLE(KEY_W));
}
return 0;
case VK_RIGHT:
if( STATEON(VK_CONTROL) ) {
/* scroll map window one line right */
SendMessage(
mswin_hwnd_from_winid(WIN_MAP),
WM_HSCROLL,
MAKEWPARAM(SB_LINEDOWN, 0),
(LPARAM)NULL
);
} else {
NHEVENT_KBD(KEYTABLE(KEY_E));
}
return 0;
case VK_UP:
if( STATEON(VK_CONTROL) ) {
/* scroll map window one line up */
SendMessage(
mswin_hwnd_from_winid(WIN_MAP),
WM_VSCROLL,
MAKEWPARAM(SB_LINEUP, 0),
(LPARAM)NULL
);
} else {
NHEVENT_KBD(KEYTABLE(KEY_N));
}
return 0;
case VK_DOWN:
if( STATEON(VK_CONTROL) ) {
/* scroll map window one line down */
SendMessage(
mswin_hwnd_from_winid(WIN_MAP),
WM_VSCROLL,
MAKEWPARAM(SB_LINEDOWN, 0),
(LPARAM)NULL
);
} else {
NHEVENT_KBD(KEYTABLE(KEY_S));
}
return 0;
case VK_HOME:
if( STATEON(VK_CONTROL) ) {
/* scroll map window to upper left corner */
SendMessage(
mswin_hwnd_from_winid(WIN_MAP),
WM_VSCROLL,
MAKEWPARAM(SB_THUMBTRACK, 0),
(LPARAM)NULL
);
SendMessage(
mswin_hwnd_from_winid(WIN_MAP),
WM_HSCROLL,
MAKEWPARAM(SB_THUMBTRACK, 0),
(LPARAM)NULL
);
} else {
NHEVENT_KBD(KEYTABLE(KEY_NW));
}
return 0;
case VK_END:
if( STATEON(VK_CONTROL) ) {
/* scroll map window to lower right corner */
SendMessage(
mswin_hwnd_from_winid(WIN_MAP),
WM_VSCROLL,
MAKEWPARAM(SB_THUMBTRACK, ROWNO),
(LPARAM)NULL
);
SendMessage(
mswin_hwnd_from_winid(WIN_MAP),
WM_HSCROLL,
MAKEWPARAM(SB_THUMBTRACK, COLNO),
(LPARAM)NULL
);
} else {
NHEVENT_KBD(KEYTABLE(KEY_SW));
}
return 0;
case VK_PRIOR:
if( STATEON(VK_CONTROL) ) {
/* scroll map window one page up */
SendMessage(
mswin_hwnd_from_winid(WIN_MAP),
WM_VSCROLL,
MAKEWPARAM(SB_PAGEUP, 0),
(LPARAM)NULL
);
} else {
NHEVENT_KBD(KEYTABLE(KEY_NE));
}
return 0;
case VK_NEXT:
if( STATEON(VK_CONTROL) ) {
/* scroll map window one page down */
SendMessage(
mswin_hwnd_from_winid(WIN_MAP),
WM_VSCROLL,
MAKEWPARAM(SB_PAGEDOWN, 0),
(LPARAM)NULL
);
} else {
NHEVENT_KBD(KEYTABLE(KEY_SE));
}
return 0;
case VK_DECIMAL:
case VK_DELETE:
NHEVENT_KBD(KEYTABLE(KEY_WAITLOOK));
return 0;
case VK_INSERT:
NHEVENT_KBD(KEYTABLE(KEY_INV));
return 0;
case VK_SUBTRACT:
NHEVENT_KBD(KEYTABLE(KEY_MINUS));
return 0;
case VK_ADD:
NHEVENT_KBD(KEYTABLE(KEY_PLUS));
return 0;
case VK_CLEAR: /* This is the '5' key */
NHEVENT_KBD(KEYTABLE(KEY_GOINTERESTING));
return 0;
case VK_F4:
if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) {
mswin_select_map_mode(
IS_MAP_ASCII(iflags.wc_map_mode)?
data->mapAcsiiModeSave :
MAP_MODE_TILES
);
} else {
mswin_select_map_mode(
IS_MAP_ASCII(iflags.wc_map_mode)?
MAP_MODE_ASCII_FIT_TO_SCREEN :
MAP_MODE_TILES_FIT_TO_SCREEN
);
}
return 0;
case VK_F5:
if( IS_MAP_ASCII(iflags.wc_map_mode) ) {
if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) {
mswin_select_map_mode(MAP_MODE_TILES_FIT_TO_SCREEN);
} else {
mswin_select_map_mode(MAP_MODE_TILES);
}
} else {
if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) {
mswin_select_map_mode(MAP_MODE_ASCII_FIT_TO_SCREEN);
} else {
mswin_select_map_mode(data->mapAcsiiModeSave);
}
}
return 0;
default: {
WORD c;
BYTE kbd_state[256];
c = 0;
ZeroMemory(kbd_state, sizeof(kbd_state));
GetKeyboardState(kbd_state);
if( ToAscii( wParam, (lParam>>16)&0xFF, kbd_state, &c, 0) ) {
NHEVENT_KBD( c&0xFF );
return 0;
} else {
return 1;
}
}
} /* end switch */
} break;
case WM_SYSCHAR: /* Alt-char pressed */
{
/*
If not nethackmode, don't handle Alt-keys here.
If no Alt-key pressed it can never be an extended command
*/
if (GetNHApp()->regNetHackMode && ((lParam & 1<<29) != 0))
{
unsigned char c = (unsigned char)(wParam & 0xFF);
unsigned char scancode = (lParam >> 16) & 0xFF;
if (index(extendedlist, tolower(c)) != 0)
{
NHEVENT_KBD(M(tolower(c)));
} else if (scancode == (SCANLO + SIZE(scanmap)) - 1) {
NHEVENT_KBD(M('?'));
}
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_COMMAND:
/* process commands - menu commands mostly */
if( onWMCommand(hWnd, wParam, lParam) )
return DefWindowProc(hWnd, message, wParam, lParam);
else
return 0;
case WM_MOVE:
case WM_SIZE:
{
WINDOWPLACEMENT wp;
mswin_layout_main_window(NULL);
wp.length = sizeof(wp);
if (GetWindowPlacement(hWnd, &wp)) {
GetNHApp()->regMainShowState = (wp.showCmd == SW_SHOWMAXIMIZED
? SW_SHOWMAXIMIZED : SW_SHOWNORMAL);
GetNHApp()->regMainMinX = wp.ptMinPosition.x;
GetNHApp()->regMainMinY = wp.ptMinPosition.y;
GetNHApp()->regMainMaxX = wp.ptMaxPosition.x;
GetNHApp()->regMainMaxY = wp.ptMaxPosition.y;
GetNHApp()->regMainLeft = wp.rcNormalPosition.left;
GetNHApp()->regMainTop = wp.rcNormalPosition.top;
GetNHApp()->regMainRight = wp.rcNormalPosition.right;
GetNHApp()->regMainBottom = wp.rcNormalPosition.bottom;
}
break;
}
case WM_SETFOCUS:
/* if there is a menu window out there -
transfer input focus to it */
if( IsWindow( GetNHApp()->hPopupWnd ) ) {
SetFocus( GetNHApp()->hPopupWnd );
}
break;
case WM_CLOSE:
{
/* exit gracefully */
if (program_state.gameover)
{
/* assume the user really meant this, as the game is already over... */
/* to make sure we still save bones, just set stop printing flag */
program_state.stopprint++;
NHEVENT_KBD('\033'); /* and send keyboard input as if user pressed ESC */
/* additional code for this is done in menu and rip windows */
}
else if (!program_state.something_worth_saving)
{
/* User exited before the game started, e.g. during splash display */
/* Just get out. */
bail((char *)0);
}
else
{
/* prompt user for action */
switch (NHMessageBox(hWnd, TEXT("Save?"), MB_YESNOCANCEL | MB_ICONQUESTION)) {
case IDYES:
#ifdef SAFERHANGUP
/* destroy popup window - it has its own loop and we need to
return control to NetHack core at this point */
if( IsWindow( GetNHApp()->hPopupWnd ) )
SendMessage( GetNHApp()->hPopupWnd, WM_COMMAND, IDCANCEL, 0);
/* tell NetHack core that "hangup" is requested */
hangup(1);
#else
NHEVENT_KBD('y'); dosave();
#endif
break;
case IDNO: NHEVENT_KBD('q'); done(QUIT); break;
case IDCANCEL: break;
}
}
} return 0;
case WM_DESTROY:
/* apparently we never get here
TODO: work on exit routines - need to send
WM_QUIT somehow */
/* clean up */
free( (PNHMainWindow)GetWindowLong(hWnd, GWL_USERDATA) );
SetWindowLong(hWnd, GWL_USERDATA, (LONG)0);
// PostQuitMessage(0);
exit(1);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
switch(wParam) {
/* new window was just added */
case MSNH_MSG_ADDWND: {
PMSNHMsgAddWnd msg_param = (PMSNHMsgAddWnd)lParam;
HWND child;
if( GetNHApp()->windowlist[msg_param->wid].type == NHW_MAP )
mswin_select_map_mode(iflags.wc_map_mode);
child = GetNHApp()->windowlist[msg_param->wid].win;
} break;
}
}
/* adjust windows to fit main window layout
---------------------------
| Status |
+-------------------------+
| |
| |
| MAP |
| |
| |
+-------------------------+
| Messages |
---------------------------
*/
void mswin_layout_main_window(HWND changed_child)
{
winid i;
RECT client_rt, wnd_rect;
POINT status_org;
SIZE status_size;
POINT msg_org;
SIZE msg_size;
POINT map_org;
SIZE map_size;
SIZE menu_size;
HWND wnd_status, wnd_msg;
PNHMainWindow data;
if( GetNHApp()->bAutoLayout ) {
GetClientRect(GetNHApp()->hMainWnd, &client_rt);
data = (PNHMainWindow)GetWindowLong(GetNHApp()->hMainWnd, GWL_USERDATA);
/* get sizes of child windows */
wnd_status = mswin_hwnd_from_winid(WIN_STATUS);
if( IsWindow(wnd_status) ) {
mswin_status_window_size(wnd_status, &status_size);
} else {
status_size.cx = status_size.cy = 0;
}
wnd_msg = mswin_hwnd_from_winid(WIN_MESSAGE);
if( IsWindow(wnd_msg) ) {
mswin_message_window_size(wnd_msg, &msg_size);
} else {
msg_size.cx = msg_size.cy = 0;
}
/* find all menu windows and calculate the size */
menu_size.cx = menu_size.cy = 0;
for( i=0; i<MAXWINDOWS; i++ ) {
SIZE tmp_size;
if( GetNHApp()->windowlist[i].win
&& !GetNHApp()->windowlist[i].dead
&& GetNHApp()->windowlist[i].type == NHW_MENU ) {
mswin_menu_window_size(GetNHApp()->windowlist[i].win , &tmp_size);
menu_size.cx = max(menu_size.cx, tmp_size.cx);
menu_size.cy = max(menu_size.cy, tmp_size.cy);
}
}
/* set window positions */
SetRect(&wnd_rect, client_rt.left, client_rt.top, client_rt.right, client_rt.bottom);
switch(iflags.wc_align_status) {
case ALIGN_LEFT:
status_size.cx = (wnd_rect.right-wnd_rect.left)/4;
status_size.cy = (wnd_rect.bottom-wnd_rect.top); // that won't look good
status_org.x = wnd_rect.left;
status_org.y = wnd_rect.top;
wnd_rect.left += status_size.cx;
break;
case ALIGN_RIGHT:
status_size.cx = (wnd_rect.right-wnd_rect.left)/4;
status_size.cy = (wnd_rect.bottom-wnd_rect.top); // that won't look good
status_org.x = wnd_rect.right - status_size.cx;
status_org.y = wnd_rect.top;
wnd_rect.right -= status_size.cx;
break;
case ALIGN_TOP:
status_size.cx = (wnd_rect.right-wnd_rect.left);
status_org.x = wnd_rect.left;
status_org.y = wnd_rect.top;
wnd_rect.top += status_size.cy;
break;
case ALIGN_BOTTOM:
default:
status_size.cx = (wnd_rect.right-wnd_rect.left);
status_org.x = wnd_rect.left;
status_org.y = wnd_rect.bottom - status_size.cy;
wnd_rect.bottom -= status_size.cy;
break;
}
switch(iflags.wc_align_message) {
case ALIGN_LEFT:
msg_size.cx = (wnd_rect.right-wnd_rect.left)/4;
msg_size.cy = (wnd_rect.bottom-wnd_rect.top);
msg_org.x = wnd_rect.left;
msg_org.y = wnd_rect.top;
wnd_rect.left += msg_size.cx;
break;
case ALIGN_RIGHT:
msg_size.cx = (wnd_rect.right-wnd_rect.left)/4;
msg_size.cy = (wnd_rect.bottom-wnd_rect.top);
msg_org.x = wnd_rect.right - msg_size.cx;
msg_org.y = wnd_rect.top;
wnd_rect.right -= msg_size.cx;
break;
case ALIGN_TOP:
msg_size.cx = (wnd_rect.right-wnd_rect.left);
msg_org.x = wnd_rect.left;
msg_org.y = wnd_rect.top;
wnd_rect.top += msg_size.cy;
break;
case ALIGN_BOTTOM:
default:
msg_size.cx = (wnd_rect.right-wnd_rect.left);
msg_org.x = wnd_rect.left;
msg_org.y = wnd_rect.bottom - msg_size.cy;
wnd_rect.bottom -= msg_size.cy;
break;
}
/* map window */
map_org.x = wnd_rect.left;
map_org.y = wnd_rect.top;
map_size.cx = wnd_rect.right - wnd_rect.left;
map_size.cy = wnd_rect.bottom - wnd_rect.top;
GetNHApp()->rtStatusWindow.left = status_org.x;
GetNHApp()->rtStatusWindow.top = status_org.y;
GetNHApp()->rtStatusWindow.right = status_org.x + status_size.cx;
GetNHApp()->rtStatusWindow.bottom= status_org.y + status_size.cy;
GetNHApp()->rtTextWindow.left = map_org.x;
GetNHApp()->rtTextWindow.top = map_org.y;
GetNHApp()->rtTextWindow.right = map_org.x + (wnd_rect.right - wnd_rect.left);
GetNHApp()->rtTextWindow.bottom = map_org.y + map_size.cy;
GetNHApp()->rtMapWindow.left = map_org.x;
GetNHApp()->rtMapWindow.top = map_org.y;
GetNHApp()->rtMapWindow.right = map_org.x + map_size.cx;
GetNHApp()->rtMapWindow.bottom = map_org.y + map_size.cy;
GetNHApp()->rtMsgWindow.left = msg_org.x;
GetNHApp()->rtMsgWindow.top = msg_org.y;
GetNHApp()->rtMsgWindow.right = msg_org.x + msg_size.cx;
GetNHApp()->rtMsgWindow.bottom = msg_org.y + msg_size.cy;
/* map_width/4 < menu_width < map_width*2/3 */
GetNHApp()->rtMenuWindow.left = GetNHApp()->rtMapWindow.right - min(map_size.cx*2/3, max(map_size.cx/4, menu_size.cx));
GetNHApp()->rtMenuWindow.top = GetNHApp()->rtMapWindow.top;
GetNHApp()->rtMenuWindow.right = GetNHApp()->rtMapWindow.right;
GetNHApp()->rtMenuWindow.bottom = GetNHApp()->rtMapWindow.bottom;
GetNHApp()->rtInvenWindow.left = GetNHApp()->rtMenuWindow.left;
GetNHApp()->rtInvenWindow.top = GetNHApp()->rtMenuWindow.top;
GetNHApp()->rtInvenWindow.right = GetNHApp()->rtMenuWindow.right;
GetNHApp()->rtInvenWindow.bottom = GetNHApp()->rtMenuWindow.bottom;
/* adjust map window size only if perm_invent is set */
if( flags.perm_invent )
GetNHApp()->rtMapWindow.right = GetNHApp()->rtMenuWindow.left;
}
/* go through the windows list and adjust sizes */
for( i=0; i<MAXWINDOWS; i++ ) {
if(GetNHApp()->windowlist[i].win && !GetNHApp()->windowlist[i].dead) {
RECT rt;
/* kludge - inventory window should have its own type (same as menu-text
as a matter of fact) */
if( flags.perm_invent && i==WIN_INVEN )
mswin_get_window_placement(NHW_INVEN, &rt);
else
mswin_get_window_placement(GetNHApp()->windowlist[i].type, &rt);
MoveWindow(GetNHApp()->windowlist[i].win,
rt.left,
rt.top,
rt.right - rt.left,
rt.bottom - rt.top,
TRUE
);
}
}
if( IsWindow(changed_child) )
SetForegroundWindow(changed_child);
}
LRESULT onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PNHMainWindow data;
data = (PNHMainWindow)GetWindowLong(hWnd, GWL_USERDATA);
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
mswin_display_splash_window(TRUE);
break;
case IDM_EXIT:
done2();
break;
case IDM_SAVE:
if (!program_state.gameover && !program_state.done_hup) dosave();
else MessageBeep(0);
break;
case IDM_MAP_TILES:
case IDM_MAP_ASCII4X6:
case IDM_MAP_ASCII6X8:
case IDM_MAP_ASCII8X8:
case IDM_MAP_ASCII16X8:
case IDM_MAP_ASCII7X12:
case IDM_MAP_ASCII8X12:
case IDM_MAP_ASCII12X16:
case IDM_MAP_ASCII16X12:
case IDM_MAP_ASCII10X18:
mswin_select_map_mode(menuid2mapmode(wmId));
break;
case IDM_MAP_FIT_TO_SCREEN:
if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) {
mswin_select_map_mode(
IS_MAP_ASCII(iflags.wc_map_mode)?
data->mapAcsiiModeSave :
MAP_MODE_TILES
);
} else {
mswin_select_map_mode(
IS_MAP_ASCII(iflags.wc_map_mode)?
MAP_MODE_ASCII_FIT_TO_SCREEN :
MAP_MODE_TILES_FIT_TO_SCREEN
);
}
break;
case IDM_NHMODE:
{
GetNHApp()->regNetHackMode = GetNHApp()->regNetHackMode ? 0 : 1;
mswin_menu_check_intf_mode();
break;
}
case IDM_CLEARSETTINGS:
{
mswin_destroy_reg();
/* Notify the user that windows settings will not be saved this time. */
NHMessageBox(GetNHApp()->hMainWnd,
"Your Windows Settings will not be stored when you exit this time.",
MB_OK | MB_ICONINFORMATION);
break;
}
case IDM_SETTING_AUTOLAYOUT:
GetNHApp()->bAutoLayout = !GetNHApp()->bAutoLayout;
mswin_layout_main_window(NULL);
/* Update menu item check-mark */
CheckMenuItem(
GetMenu(GetNHApp()->hMainWnd),
IDM_SETTING_AUTOLAYOUT,
GetNHApp()->bAutoLayout? MF_CHECKED : MF_UNCHECKED
);
break;
case IDM_SETTING_LOCKWINDOWS:
nhlock_windows( !GetNHApp()->bWindowsLocked );
break;
case IDM_HELP_LONG:
display_file(HELP, TRUE);
break;
case IDM_HELP_COMMANDS:
display_file(SHELP, TRUE);
break;
case IDM_HELP_HISTORY:
(void) dohistory();
break;
case IDM_HELP_INFO_CHAR:
(void) dowhatis();
break;
case IDM_HELP_INFO_KEY:
(void) dowhatdoes();
break;
case IDM_HELP_OPTIONS:
option_help();
break;
case IDM_HELP_OPTIONS_LONG:
display_file(OPTIONFILE, TRUE);
break;
case IDM_HELP_EXTCMD:
(void) doextlist();
break;
case IDM_HELP_LICENSE:
display_file(LICENSE, TRUE);
break;
case IDM_HELP_PORTHELP:
display_file(PORT_HELP, TRUE);
break;
default:
return 1;
}
return 0;
}
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
char buf[BUFSZ];
TCHAR wbuf[BUFSZ];
RECT main_rt, dlg_rt;
SIZE dlg_sz;
switch (message)
{
case WM_INITDIALOG:
getversionstring(buf);
SetDlgItemText(hDlg, IDC_ABOUT_VERSION, NH_A2W(buf, wbuf, sizeof(wbuf)));
SetDlgItemText(hDlg, IDC_ABOUT_COPYRIGHT,
NH_A2W(
COPYRIGHT_BANNER_A "\n"
COPYRIGHT_BANNER_B "\n"
COPYRIGHT_BANNER_C,
wbuf,
BUFSZ
) );
/* center dialog in the main window */
GetWindowRect(GetNHApp()->hMainWnd, &main_rt);
GetWindowRect(hDlg, &dlg_rt);
dlg_sz.cx = dlg_rt.right - dlg_rt.left;
dlg_sz.cy = dlg_rt.bottom - dlg_rt.top;
dlg_rt.left = (main_rt.left+main_rt.right-dlg_sz.cx)/2;
dlg_rt.right = dlg_rt.left + dlg_sz.cx;
dlg_rt.top = (main_rt.top+main_rt.bottom-dlg_sz.cy)/2;
dlg_rt.bottom = dlg_rt.top + dlg_sz.cy;
MoveWindow( hDlg,
(main_rt.left+main_rt.right-dlg_sz.cx)/2,
(main_rt.top+main_rt.bottom-dlg_sz.cy)/2,
dlg_sz.cx,
dlg_sz.cy,
TRUE );
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
void mswin_menu_check_intf_mode()
{
HMENU hMenu = GetMenu(GetNHApp()->hMainWnd);
if (GetNHApp()->regNetHackMode)
CheckMenuItem(hMenu, IDM_NHMODE, MF_CHECKED);
else
CheckMenuItem(hMenu, IDM_NHMODE, MF_UNCHECKED);
}
void mswin_select_map_mode(int mode)
{
PNHMainWindow data;
winid map_id;
map_id = WIN_MAP;
data = (PNHMainWindow)GetWindowLong(GetNHApp()->hMainWnd, GWL_USERDATA);
/* override for Rogue level */
#ifdef REINCARNATION
if( Is_rogue_level(&u.uz) && !IS_MAP_ASCII(mode) ) return;
#endif
/* set map mode menu mark */
if( IS_MAP_ASCII(mode) ) {
CheckMenuRadioItem(
GetMenu(GetNHApp()->hMainWnd),
IDM_MAP_TILES,
IDM_MAP_ASCII10X18,
mapmode2menuid( IS_MAP_FIT_TO_SCREEN(mode)? data->mapAcsiiModeSave : mode ),
MF_BYCOMMAND);
} else {
CheckMenuRadioItem(
GetMenu(GetNHApp()->hMainWnd),
IDM_MAP_TILES,
IDM_MAP_ASCII10X18,
mapmode2menuid( MAP_MODE_TILES ),
MF_BYCOMMAND);
}
/* set fit-to-screen mode mark */
CheckMenuItem(
GetMenu(GetNHApp()->hMainWnd),
IDM_MAP_FIT_TO_SCREEN,
MF_BYCOMMAND |
(IS_MAP_FIT_TO_SCREEN(mode)? MF_CHECKED : MF_UNCHECKED)
);
if( IS_MAP_ASCII(iflags.wc_map_mode) && !IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) {
data->mapAcsiiModeSave = iflags.wc_map_mode;
}
iflags.wc_map_mode = mode;
/*
** first, check if WIN_MAP has been inialized.
** If not - attempt to retrieve it by type, then check it again
*/
if( map_id==WIN_ERR )
map_id = mswin_winid_from_type(NHW_MAP);
if( map_id!=WIN_ERR )
mswin_map_mode(mswin_hwnd_from_winid(map_id), mode);
}
static struct t_menu2mapmode {
int menuID;
int mapMode;
} _menu2mapmode[] =
{
{ IDM_MAP_TILES, MAP_MODE_TILES },
{ IDM_MAP_ASCII4X6, MAP_MODE_ASCII4x6 },
{ IDM_MAP_ASCII6X8, MAP_MODE_ASCII6x8 },
{ IDM_MAP_ASCII8X8, MAP_MODE_ASCII8x8 },
{ IDM_MAP_ASCII16X8, MAP_MODE_ASCII16x8 },
{ IDM_MAP_ASCII7X12, MAP_MODE_ASCII7x12 },
{ IDM_MAP_ASCII8X12, MAP_MODE_ASCII8x12 },
{ IDM_MAP_ASCII12X16, MAP_MODE_ASCII12x16 },
{ IDM_MAP_ASCII16X12, MAP_MODE_ASCII16x12 },
{ IDM_MAP_ASCII10X18, MAP_MODE_ASCII10x18 },
{ IDM_MAP_FIT_TO_SCREEN, MAP_MODE_ASCII_FIT_TO_SCREEN },
{ -1, -1 }
};
int menuid2mapmode(int menuid)
{
struct t_menu2mapmode* p;
for( p = _menu2mapmode; p->mapMode!=-1; p++ )
if(p->menuID==menuid ) return p->mapMode;
return -1;
}
int mapmode2menuid(int map_mode)
{
struct t_menu2mapmode* p;
for( p = _menu2mapmode; p->mapMode!=-1; p++ )
if(p->mapMode==map_mode ) return p->menuID;
return -1;
}
void nhlock_windows( BOOL lock )
{
int i;
/* go through the windows list and adjust sizes */
for( i=0; i<MAXWINDOWS; i++ ) {
if( IsWindow(GetNHApp()->windowlist[i].win) && !GetNHApp()->windowlist[i].dead) {
DWORD style;
style = GetWindowLong(GetNHApp()->windowlist[i].win, GWL_STYLE);
if( lock ) style &= ~WS_CAPTION;
else style |= WS_CAPTION;
SetWindowLong(GetNHApp()->windowlist[i].win, GWL_STYLE, style);
SetWindowPos(
GetNHApp()->windowlist[i].win,
NULL,
0,
0,
0,
0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED
);
}
}
/* update menu */
GetNHApp()->bWindowsLocked = lock;
CheckMenuItem(
GetMenu(GetNHApp()->hMainWnd),
IDM_SETTING_LOCKWINDOWS,
MF_BYCOMMAND |
(lock? MF_CHECKED : MF_UNCHECKED)
);
}