diff --git a/Files b/Files index 9ee2e74a9..01a61dd52 100644 --- a/Files +++ b/Files @@ -252,9 +252,10 @@ mhfont.h mhinput.c mhinput.h mhmain.c mhmain.h mhmap.c mhmap.h mhmenu.c mhmenu.h mhmsg.h mhmsgwnd.c mhmsgwnd.h mhrip.c mhrip.h mhstatus.c mhstatus.h mhtext.c mhtext.h mnsel.uu mnunsel.uu -mswproc.c nethack.dsw recover.dsp resource.h tile2bmp.c -tile2bmp.dsp tilemap.dsp tiles.dsp tiles.mak winhack.c -winhack.dsp winhack.h winhack.rc winMS.h winnt.dsw +mswproc.c nethack.dsw petmark.uu recover.dsp resource.h +tile2bmp.c tile2bmp.dsp tilemap.dsp tiles.dsp tiles.mak +winhack.c winhack.dsp winhack.h winhack.rc winMS.h +winnt.dsw diff --git a/include/ntconf.h b/include/ntconf.h index 31ca6a8eb..172bc790f 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -132,4 +132,6 @@ int _RTLENTRY _EXPFUNC open (const char _FAR *__path, int __access,... /*unsig #endif #endif +extern int FDECL(set_win32_option, (const char *, const char *)); + #endif /* NTCONF_H */ diff --git a/src/options.c b/src/options.c index 865b1a7ec..7304ac901 100644 --- a/src/options.c +++ b/src/options.c @@ -301,6 +301,11 @@ static struct Comp_Opt #endif #if 0 { "warnlevel", "minimum monster level to trigger warning", 4, SET_IN_GAME }, +#endif +#ifdef MSWIN_GRAPHICS + { "win32_map_mode", "map display mode under Windows", 20, SET_IN_FILE }, + { "win32_align_status", "status window alignment", 20, SET_IN_FILE }, + { "win32_align_message", "message window alignment", 20, SET_IN_FILE }, #endif { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME }, { (char *)0, (char *)0, 0, 0 } @@ -1689,6 +1694,52 @@ goodfruit: } #endif /* MSDOS */ +#ifdef MSWIN_GRAPHICS + /* win32_map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12|ascii8x12|ascii15x12 + |ascii12x16|ascii10x18|fit_to_screen] */ + fullname = "win32_map_mode"; + if (match_optname(opts, fullname, sizeof("win32_map_mode")-1, TRUE)) { + if (negated) { + bad_negation(fullname, FALSE); + return; + } + else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { + return; + } + if (!set_win32_option(fullname, opts)) + badoption(opts); + return; + } + + /* win32_align_status:[left|top|right|bottom] */ + fullname = "win32_align_status"; + if (match_optname(opts, fullname, sizeof("win32_align_status")-1, TRUE)) { + if (negated) { + bad_negation(fullname, FALSE); + return; + } + else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { + return; + } + if (!set_win32_option(fullname, opts)) + badoption(opts); + return; + } + /* win32_align_message:[left|top|right|bottom] */ + fullname = "win32_align_message"; + if (match_optname(opts, fullname, sizeof("win32_align_message")-1, TRUE)) { + if (negated) { + bad_negation(fullname, FALSE); + return; + } + else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { + return; + } + if (!set_win32_option(fullname, opts)) + badoption(opts); + return; + } +#endif /* MSWIN_GRAPHICS */ fullname = "windowtype"; if (match_optname(opts, fullname, 3, TRUE)) { diff --git a/sys/winnt/nhsetup.bat b/sys/winnt/nhsetup.bat index 68736f355..f1f2d8b2f 100755 --- a/sys/winnt/nhsetup.bat +++ b/sys/winnt/nhsetup.bat @@ -1,4 +1,4 @@ -@REM SCCS Id: @(#)nhsetup.bat 2002/01/13 +@REM SCCS Id: @(#)nhsetup.bat 2002/01/21 @REM Copyright (c) NetHack PC Development Team 1993, 1996, 2002 @REM NetHack may be freely redistributed. See license for details. @REM Win32 setup batch file, see Install.nt for details @@ -96,6 +96,18 @@ copy .\mnunsel.bmp ..\..\win\win32 :hasmnuns2 if NOT exist ..\..\win\win32\mnunsel.bmp set err_nouu=Y +if exist ..\..\win\win32\petmark.bmp goto haspm2 +if exist .\petmark.bmp goto haspm1 +if exist ..\..\win\win32\petmark.uu uudecode ..\..\win\win32\petmark.uu >nul +if exist .\petmark.bmp goto haspm1 +echo Error - No UUDECODE utility to decode ..\..\win\win32\petmark.uu +goto haspm2 +:haspm1 +echo copy .\petmark.bmp ..\..\win\win32 +copy .\petmark.bmp ..\..\win\win32 +:haspm2 +if NOT exist ..\..\win\win32\petmark.bmp set err_nouu=Y + echo "Decoding/Copying ICONS" if exist ..\..\win\win32\nethack.ico goto hasicon2 if exist .\nethack.ico goto hasicon1 diff --git a/win/win32/mhinput.h b/win/win32/mhinput.h index 294bc9b22..f8037190b 100644 --- a/win/win32/mhinput.h +++ b/win/win32/mhinput.h @@ -17,13 +17,14 @@ typedef struct mswin_event { } kbd; struct { + int mod; int x, y; } ms; }; } MSNHEvent, *PMSNHEvent; #define NHEVENT_KBD(c) { MSNHEvent e; e.type=NHEVENT_CHAR; e.kbd.ch=(c); mswin_input_push(&e); } -#define NHEVENT_MS(_x, _y) { MSNHEvent e; e.type=NHEVENT_MOUSE; e.ms.x=(_x); e.ms.y=(_y); mswin_input_push(&e); } +#define NHEVENT_MS(_mod, _x, _y) { MSNHEvent e; e.type=NHEVENT_MOUSE; e.ms.mod = (_mod); e.ms.x=(_x); e.ms.y=(_y); mswin_input_push(&e); } void mswin_nh_input_init(); int mswin_have_input(); diff --git a/win/win32/mhmain.c b/win/win32/mhmain.c index 2d2891927..d76ef74e6 100644 --- a/win/win32/mhmain.c +++ b/win/win32/mhmain.c @@ -175,7 +175,7 @@ LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar /* exit gracefully */ switch(MessageBox(hWnd, TEXT("Save?"), TEXT("WinHack"), MB_YESNOCANCEL | MB_ICONQUESTION)) { case IDYES: NHEVENT_KBD('y'); dosave(); break; - case IDNO: NHEVENT_KBD('y'); done2(); break; + case IDNO: NHEVENT_KBD('q'); done(QUIT); break; case IDCANCEL: break; } } return 0; @@ -235,10 +235,14 @@ void mswin_layout_main_window(HWND changed_child) { winid i; POINT pt; - RECT client_rt; + RECT client_rt, wnd_rect; SIZE menu_size; + POINT status_org; SIZE status_size; + POINT msg_org; SIZE msg_size; + POINT map_org; + SIZE map_size; HWND wnd_status, wnd_msg; PNHMainWindow data; @@ -257,36 +261,109 @@ void mswin_layout_main_window(HWND changed_child) if( IsWindow(wnd_msg) ) { mswin_message_window_size(wnd_msg, &msg_size); } else { - status_size.cx = status_size.cy = 0; + msg_size.cx = msg_size.cy = 0; } + /* set window positions */ + SetRect(&wnd_rect, client_rt.left, client_rt.top, client_rt.right, client_rt.bottom); + switch(GetNHApp()->winStatusAlign) { + case NHWND_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 NHWND_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 NHWND_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 NHWND_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(GetNHApp()->winMessageAlign) { + case NHWND_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 NHWND_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 NHWND_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 NHWND_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_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; + /* go through the windows list and adjust sizes */ for( i=0; iwindowlist[i].win && !GetNHApp()->windowlist[i].dead) { switch( GetNHApp()->windowlist[i].type ) { case NHW_STATUS: MoveWindow(GetNHApp()->windowlist[i].win, - client_rt.left, - client_rt.top, - client_rt.right-client_rt.left, + status_org.x, + status_org.y, + status_size.cx, status_size.cy, TRUE ); break; case NHW_MAP: MoveWindow(GetNHApp()->windowlist[i].win, - client_rt.left, - client_rt.top+status_size.cy, - client_rt.right-client_rt.left, - client_rt.bottom-client_rt.top-msg_size.cy-status_size.cy, + map_org.x, + map_org.y, + map_size.cx, + map_size.cy, TRUE ); break; case NHW_MESSAGE: MoveWindow(GetNHApp()->windowlist[i].win, - client_rt.left, - client_rt.bottom-msg_size.cy, - client_rt.right-client_rt.left, + msg_org.x, + msg_org.y, + msg_size.cx, msg_size.cy, TRUE ); break; @@ -295,14 +372,14 @@ void mswin_layout_main_window(HWND changed_child) mswin_menu_window_size(GetNHApp()->windowlist[i].win, &menu_size); menu_size.cx = min(menu_size.cx, (client_rt.right-client_rt.left)); - pt.x = max(0, (int)(client_rt.right-menu_size.cx)); - pt.y = client_rt.top+status_size.cy; + pt.x = map_org.x + max(0, (int)(map_size.cx-menu_size.cx)); + pt.y = map_org.y; ClientToScreen(GetNHApp()->hMainWnd, &pt); MoveWindow(GetNHApp()->windowlist[i].win, pt.x, pt.y, - min(menu_size.cx, client_rt.right), - client_rt.bottom-client_rt.top-msg_size.cy-status_size.cy, + min(menu_size.cx, map_size.cx), + map_size.cy, TRUE ); break; } diff --git a/win/win32/mhmain.h b/win/win32/mhmain.h index 4e4eac21a..5b07a7065 100644 --- a/win/win32/mhmain.h +++ b/win/win32/mhmain.h @@ -8,6 +8,11 @@ #include "winMS.h" +#define NHWND_ALIGN_LEFT 0 +#define NHWND_ALIGN_RIGHT 1 +#define NHWND_ALIGN_TOP 2 +#define NHWND_ALIGN_BOTTOM 3 + HWND mswin_init_main_window (); void mswin_layout_main_window(HWND changed_child); diff --git a/win/win32/mhmap.c b/win/win32/mhmap.c index 3d2f6a447..456a0f287 100644 --- a/win/win32/mhmap.c +++ b/win/win32/mhmap.c @@ -9,6 +9,7 @@ #define NHMAP_FONT_NAME TEXT("Terminal") #define MAXWINDOWTEXT 255 +#define CLIPAROUND_MARGIN 5 extern short glyph2tile[]; @@ -262,7 +263,7 @@ void register_map_window_class() ZeroMemory( &wcex, sizeof(wcex)); /* window class */ - wcex.style = CS_NOCLOSE; + wcex.style = CS_NOCLOSE | CS_DBLCLKS; wcex.lpfnWndProc = (WNDPROC)MapWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; @@ -329,10 +330,19 @@ LRESULT CALLBACK MapWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPara case WM_LBUTTONDOWN: NHEVENT_MS( + CLICK_1, max(0, min(COLNO, data->xPos + (LOWORD(lParam)-data->map_orig.x)/data->xScrTile)), max(0, min(ROWNO, data->yPos + (HIWORD(lParam)-data->map_orig.y)/data->yScrTile)) ); - break; + return 0; + + case WM_LBUTTONDBLCLK : + NHEVENT_MS( + CLICK_2, + max(0, min(COLNO, data->xPos + (LOWORD(lParam)-data->map_orig.x)/data->xScrTile)), + max(0, min(ROWNO, data->yPos + (HIWORD(lParam)-data->map_orig.y)/data->yScrTile)) + ); + return 0; case WM_DESTROY: if( data->hMapFont ) DeleteObject(data->hMapFont); @@ -369,16 +379,39 @@ void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) { PMSNHMsgClipAround msg_data = (PMSNHMsgClipAround)lParam; int x, y; + BOOL scroll_x, scroll_y; - /* get page size and center horizontally on x-position*/ - if( !GetNHApp()->bNoHScroll ) { - x = max(0, min(COLNO, msg_data->x - data->xPageSize/2)); + /* calculate if you should clip around */ + scroll_x = + !GetNHApp()->bNoHScroll && + ( msg_data->x<(data->xPos+CLIPAROUND_MARGIN) || + msg_data->x>(data->xPos+data->xPageSize-CLIPAROUND_MARGIN) ); + scroll_y = + !GetNHApp()->bNoVScroll && + ( msg_data->y<(data->yPos+CLIPAROUND_MARGIN) || + msg_data->y>(data->yPos+data->yPageSize-CLIPAROUND_MARGIN) ); + + /* get page size and center horizontally on x-position */ + if( scroll_x ) { + if( data->xPageSize<=2*CLIPAROUND_MARGIN ) { + x = max(0, min(COLNO, msg_data->x - data->xPageSize/2)); + } else if( msg_data->x < data->xPos+data->xPageSize/2 ) { + x = max(0, min(COLNO, msg_data->x - CLIPAROUND_MARGIN)); + } else { + x = max(0, min(COLNO, msg_data->x - data->xPageSize + CLIPAROUND_MARGIN)); + } SendMessage( hWnd, WM_HSCROLL, (WPARAM)MAKELONG(SB_THUMBTRACK, x), (LPARAM)NULL ); } - /* get page size and center vertically on y-position*/ - if( !GetNHApp()->bNoVScroll ) { - y = max(0, min(ROWNO, msg_data->y - data->yPageSize/2)); + /* get page size and center vertically on y-position */ + if( scroll_y ) { + if( data->yPageSize<=2*CLIPAROUND_MARGIN ) { + y = max(0, min(ROWNO, msg_data->y - data->yPageSize/2)); + } else if( msg_data->y < data->yPos+data->yPageSize/2 ) { + y = max(0, min(ROWNO, msg_data->y - CLIPAROUND_MARGIN)); + } else { + y = max(0, min(ROWNO, msg_data->y - data->yPageSize + CLIPAROUND_MARGIN)); + } SendMessage( hWnd, WM_VSCROLL, (WPARAM)MAKELONG(SB_THUMBTRACK, y), (LPARAM)NULL ); } } @@ -495,8 +528,7 @@ void onPaint(HWND hWnd) nhglyph2charcolor(data->map[i][j], &ch, &color); - if( color == NO_COLOR ) continue; - else SetTextColor( hDC, nhcolor_to_RGB(color) ); + SetTextColor( hDC, nhcolor_to_RGB(color) ); nhcoord2display(data, i, j, &glyph_rect); DrawText(hDC, @@ -539,6 +571,32 @@ void onPaint(HWND hWnd) TILE_Y, SRCCOPY ); + if( glyph_is_pet(data->map[i][j]) && iflags.hilite_pet ) { + /* apply pet mark transparently over + pet image */ + HDC hdcPetMark; + HBITMAP bmPetMarkOld; + + /* this is DC for petmark bitmap */ + hdcPetMark = CreateCompatibleDC(hDC); + bmPetMarkOld = SelectObject(hdcPetMark, GetNHApp()->bmpPetMark); + + nhapply_image_transparent( + hDC, + glyph_rect.left, + glyph_rect.top, + data->xScrTile, + data->yScrTile, + hdcPetMark, + 0, + 0, + TILE_X, + TILE_Y, + TILE_BK_COLOR + ); + SelectObject(hdcPetMark, bmPetMarkOld); + DeleteDC(hdcPetMark); + } } SelectObject(tileDC, saveBmp); DeleteDC(tileDC); @@ -752,7 +810,7 @@ COLORREF nhcolor_to_RGB(int c) case CLR_MAGENTA: return RGB(255, 0, 255); case CLR_CYAN: return RGB( 0, 255, 255); case CLR_GRAY: return RGB(192, 192, 192); - case NO_COLOR: return RGB( 0, 0, 0); + case NO_COLOR: return RGB(255, 255, 255); case CLR_ORANGE: return RGB(255, 165, 0); case CLR_BRIGHT_GREEN: return RGB( 0, 255, 0); case CLR_YELLOW: return RGB(255, 255, 0); @@ -763,3 +821,87 @@ COLORREF nhcolor_to_RGB(int c) default: return RGB( 0, 0, 0); /* black */ } } + +/* apply bitmap pointed by sourceDc transparently over + bitmap pointed by hDC */ +void 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, + COLORREF cTransparent +) +{ + 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, s_width, s_height); + + /* Monochrome DC */ + bmAndBack = CreateBitmap(s_width, s_height, 1, 1, NULL); + bmAndObject = CreateBitmap(s_width, s_height, 1, 1, NULL); + + /* resulting bitmap */ + bmAndMem = CreateCompatibleBitmap(hDC, s_width, s_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 */ + BitBlt(hdcSave, 0, 0, s_width, s_height, sourceDC, s_x, s_y, 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, s_width, s_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, s_width, s_height, hdcObject, 0, 0, NOTSRCCOPY); + + /* Copy background to the resulting image */ + StretchBlt(hdcMem, 0, 0, s_width, s_height, hDC, x, y, width, height, SRCCOPY); + + /* Mask out the places where the source image will be placed. */ + BitBlt(hdcMem, 0, 0, s_width, s_height, hdcObject, 0, 0, SRCAND); + + /* Mask out the transparent colored pixels on the source image. */ + BitBlt(hdcSave, 0, 0, s_width, s_height, hdcBack, 0, 0, SRCAND); + + /* XOR the source image with the beckground. */ + BitBlt(hdcMem, 0, 0, s_width, s_height, hdcSave, 0, 0, SRCPAINT); + + /* blt resulting image to the screen */ + StretchBlt( + hDC, + x, y, width, height, hdcMem, + 0, 0, s_width, s_height, 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); +} \ No newline at end of file diff --git a/win/win32/mhmenu.c b/win/win32/mhmenu.c index 79e2a8ef3..3cc880535 100644 --- a/win/win32/mhmenu.c +++ b/win/win32/mhmenu.c @@ -3,7 +3,6 @@ #include "winMS.h" #include -#include #include "resource.h" #include "mhmenu.h" #include "mhmain.h" @@ -35,8 +34,7 @@ typedef struct mswin_nethack_menu_window { } menu; struct menu_text { - int size; - char* text; + TCHAR* text; } text; }; int result; @@ -54,17 +52,12 @@ LRESULT CALLBACK MenuWndProc(HWND, UINT, WPARAM, LPARAM); static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam); static LRESULT onMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam); static LRESULT onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam); +static LRESULT onListChar(HWND hWnd, HWND hwndList, WORD ch); static void LayoutMenu(HWND hwnd); static void SetMenuType(HWND hwnd, int type); static void SetMenuListType(HWND hwnd, int now); static HWND GetMenuControl(HWND hwnd); -DWORD CALLBACK NHTextStreamCallback( - DWORD dwCookie, // application-defined value - LPBYTE pbBuff, // data buffer - LONG cb, // number of bytes to read or write - LONG *pcb // number of bytes transferred -); - +static int GetListPageSize( HWND hwndList ); HWND mswin_init_menu_window (int type) { HWND ret; @@ -256,6 +249,7 @@ LRESULT CALLBACK MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar case WM_SIZE: LayoutMenu(hWnd); + break; return FALSE; case WM_COMMAND: @@ -293,7 +287,6 @@ LRESULT CALLBACK MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar } } break; - } } break; @@ -309,7 +302,7 @@ LRESULT CALLBACK MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar case WM_DRAWITEM: return onDrawItem(hWnd, wParam, lParam); - case WM_VKEYTOITEM: + case WM_VKEYTOITEM: { WORD c[4]; BYTE kbd_state[256]; @@ -319,29 +312,16 @@ LRESULT CALLBACK MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar GetKeyboardState(kbd_state); if( ToAscii( LOWORD(wParam), 0, kbd_state, c, 0)==1 ) { - int i = 0; - for(i=0; imenu.size; i++ ) { - if( data->menu.items[i].accelerator == c[0] ) { - if( data->how == PICK_ANY ) { - SendMessage((HWND)lParam, - LB_SETSEL, - (WPARAM)!SendMessage((HWND)lParam, LB_GETSEL, (WPARAM)i, (LPARAM)0), - (LPARAM)i); - return -2; - } else if( data->how == PICK_ONE ) { - SendMessage((HWND)lParam, LB_SETCURSEL, (WPARAM)i, (LPARAM)0); - data->result = 0; - data->done = 1; - return -2; - } - } - } + return onListChar(hWnd, (HWND)lParam, c[0]); } } return -1; case WM_DESTROY: DeleteObject(data->bmpChecked); DeleteObject(data->bmpNotChecked); + if( data->type == MENU_TYPE_TEXT ) { + if( data->text.text ) free(data->text.text); + } free(data); SetWindowLong(hWnd, GWL_USERDATA, (LONG)0); return TRUE; @@ -359,37 +339,28 @@ void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) { PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr)lParam; HWND text_view; - EDITSTREAM txt_edit; - CHARFORMAT txt_format; + TCHAR wbuf[BUFSZ]; + size_t text_size; if( data->type!=MENU_TYPE_TEXT ) SetMenuType(hWnd, MENU_TYPE_TEXT); + if( !data->text.text ) { + text_size = strlen(msg_data->text) + 4; + data->text.text = (TCHAR*)malloc(text_size*sizeof(data->text.text[0])); + ZeroMemory(data->text.text, text_size*sizeof(data->text.text[0])); + } else { + text_size = _tcslen(data->text.text) + strlen(msg_data->text) + 4; + data->text.text = (TCHAR*)realloc(data->text.text, text_size*sizeof(data->text.text[0])); + } + if( !data->text.text ) break; + + _tcscat(data->text.text, NH_A2W(msg_data->text, wbuf, BUFSZ)); + _tcscat(data->text.text, TEXT("\r\n")); + text_view = GetDlgItem(hWnd, IDC_MENU_TEXT); if( !text_view ) panic("cannot get text view window"); - - /* apply text format to the selection */ - ZeroMemory(&txt_format, sizeof(txt_format)); - txt_format.cbSize = sizeof(txt_format); - txt_format.dwMask = CFM_BOLD | CFM_ITALIC | CFM_STRIKEOUT; - txt_format.dwEffects = - ((msg_data->attr==ATR_BOLD || msg_data->attr==ATR_INVERSE)? CFE_BOLD : 0) | - ((msg_data->attr==ATR_BLINK)? CFE_ITALIC : 0) | - ((msg_data->attr==ATR_ULINE)? CFE_STRIKEOUT : 0) - ; - /* txt_format.yHeight; */ - /* txt_format.yOffset; */ - /* txt_format.crTextColor; */ - /* txt_format.bCharSet; */ - /* txt_format.bPitchAndFamily = FIXED_PITCH; */ - /* txt_format.szFaceName[LF_FACESIZE]; */ - SendMessage(text_view, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&txt_format); - - /* inject text into control (see NHTextStreamCallback) */ - ZeroMemory(&txt_edit, sizeof(txt_edit)); - txt_edit.dwCookie = (DWORD)msg_data->text; - txt_edit.pfnCallback = NHTextStreamCallback; - SendMessage(text_view, EM_STREAMIN, SF_TEXT | SFF_SELECTION, (LPARAM)&txt_edit); + SetWindowText(text_view, data->text.text); } break; case MSNH_MSG_STARTMENU: @@ -433,8 +404,6 @@ void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) void LayoutMenu(HWND hWnd) { PNHMenuWindow data; -// HWND menu_list; -// HWND menu_text; HWND menu_ok; HWND menu_cancel; RECT clrt, rt; @@ -442,8 +411,6 @@ void LayoutMenu(HWND hWnd) SIZE sz_elem, sz_ok, sz_cancel; data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); -// menu_list = GetDlgItem(hWnd, IDC_MENU_LIST); -// menu_text = GetDlgItem(hWnd, IDC_MENU_TEXT); menu_ok = GetDlgItem(hWnd, IDOK); menu_cancel = GetDlgItem(hWnd, IDCANCEL); @@ -479,7 +446,6 @@ void SetMenuType(HWND hWnd, int type) HWND list, text; data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); -// if( type == data->type ) return; data->type = type; @@ -525,13 +491,14 @@ void SetMenuListType(HWND hWnd, int how) case PICK_ONE: dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD | WS_VSCROLL | WS_HSCROLL | LBS_WANTKEYBOARDINPUT - | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | LBS_OWNERDRAWFIXED; + | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | LBS_OWNERDRAWFIXED + | LBS_HASSTRINGS; break; case PICK_ANY: dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD | WS_VSCROLL | WS_HSCROLL | LBS_WANTKEYBOARDINPUT | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | LBS_MULTIPLESEL - | LBS_OWNERDRAWFIXED; + | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS; break; default: panic("how should be one of PICK_NONE, PICK_ONE or PICK_ANY"); }; @@ -617,7 +584,6 @@ LRESULT onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) PNHMenuItem item; PNHMenuWindow data; TEXTMETRIC tm; - HGDIOBJ saveBmp; HGDIOBJ saveFont; HGDIOBJ savePen; HPEN pen; @@ -630,7 +596,7 @@ LRESULT onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) lpdis = (LPDRAWITEMSTRUCT) lParam; /* If there are no list box items, skip this message. */ - if (lpdis->itemID == -1) return FALSE; + if ( (int)(lpdis->itemID) < 0) return FALSE; data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); switch (lpdis->itemAction) @@ -647,6 +613,7 @@ LRESULT onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) /* print check mark */ if( NHMENU_IS_SELECTABLE(*item) ) { + HGDIOBJ saveBmp; char buf[2]; saveBmp = SelectObject(tileDC, @@ -664,16 +631,25 @@ LRESULT onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) TextOut(lpdis->hDC, x, y, NH_A2W(buf, wbuf, sizeof(wbuf)), 1); } x += tm.tmAveCharWidth + 5; + SelectObject(tileDC, saveBmp); } - - SelectObject(tileDC, GetNHApp()->bmpTiles); - ntile = glyph2tile[ item->glyph ]; - t_x = (ntile % TILES_PER_LINE)*TILE_X; - t_y = (ntile / TILES_PER_LINE)*TILE_Y; - y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2; + /* print glyph if present */ + if( item->glyph != NO_GLYPH ) { + HGDIOBJ saveBmp; - BitBlt(lpdis->hDC, x, y, TILE_X, TILE_Y, tileDC, t_x, t_y, SRCCOPY ); + saveBmp = SelectObject(tileDC, GetNHApp()->bmpTiles); + ntile = glyph2tile[ item->glyph ]; + t_x = (ntile % TILES_PER_LINE)*TILE_X; + t_y = (ntile / TILES_PER_LINE)*TILE_Y; + + y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2; + + nhapply_image_transparent( + lpdis->hDC, x, y, TILE_X, TILE_Y, + tileDC, t_x, t_y, TILE_X, TILE_Y, TILE_BK_COLOR ); + SelectObject(tileDC, saveBmp); + } x += TILE_X + 5; y = (lpdis->rcItem.bottom + lpdis->rcItem.top - @@ -686,8 +662,8 @@ LRESULT onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) strlen(item->str)); mswin_destroy_font(SelectObject(lpdis->hDC, saveFont)); - SelectObject(tileDC, saveBmp); DeleteDC(tileDC); + break; case ODA_FOCUS: @@ -712,6 +688,168 @@ LRESULT onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) return TRUE; } +LRESULT onListChar(HWND hWnd, HWND hwndList, WORD ch) +{ + int i = 0; + PNHMenuWindow data; + int topIndex, pageSize; + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + + switch( ch ) { + case MENU_FIRST_PAGE: + SendMessage(hwndList, LB_SETTOPINDEX, 0, 0); + return -2; + + case MENU_LAST_PAGE: + SendMessage(hwndList, + LB_SETTOPINDEX, + (WPARAM)max(0, data->menu.size-1), + (LPARAM)0); + return -2; + + case MENU_NEXT_PAGE: + topIndex = (int)SendMessage( hwndList, LB_GETTOPINDEX, 0, 0 ); + pageSize = GetListPageSize( hwndList ); + SendMessage(hwndList, + LB_SETTOPINDEX, + (WPARAM)min(topIndex+pageSize, data->menu.size-1), + (LPARAM)0); + return -2; + + case MENU_PREVIOUS_PAGE: + topIndex = (int)SendMessage( hwndList, LB_GETTOPINDEX, 0, 0 ); + pageSize = GetListPageSize( hwndList ); + SendMessage(hwndList, + LB_SETTOPINDEX, + (WPARAM)max(topIndex-pageSize, 0), + (LPARAM)0); + break; + + case MENU_SELECT_ALL: + if( data->how == PICK_ANY ) { + for(i=0; imenu.size; i++ ) { + SendMessage(hwndList, LB_SETSEL, (WPARAM)TRUE, (LPARAM)i); + } + return -2; + } + break; + + case MENU_UNSELECT_ALL: + if( data->how == PICK_ANY ) { + for(i=0; imenu.size; i++ ) { + SendMessage(hwndList, LB_SETSEL, (WPARAM)FALSE, (LPARAM)i); + } + return -2; + } + break; + + case MENU_INVERT_ALL: + if( data->how == PICK_ANY ) { + for(i=0; imenu.size; i++ ) { + SendMessage(hwndList, + LB_SETSEL, + (WPARAM)!SendMessage(hwndList, LB_GETSEL, (WPARAM)i, (LPARAM)0), + (LPARAM)i); + } + return -2; + } + break; + + case MENU_SELECT_PAGE: + if( data->how == PICK_ANY ) { + topIndex = (int)SendMessage( hwndList, LB_GETTOPINDEX, 0, 0 ); + pageSize = GetListPageSize( hwndList ); + for(i=0; ihow == PICK_ANY ) { + topIndex = (int)SendMessage( hwndList, LB_GETTOPINDEX, 0, 0 ); + pageSize = GetListPageSize( hwndList ); + for(i=0; ihow == PICK_ANY ) { + topIndex = (int)SendMessage( hwndList, LB_GETTOPINDEX, 0, 0 ); + pageSize = GetListPageSize( hwndList ); + for(i=0; ihow==PICK_ANY || data->how==PICK_ONE ) { + char buf[BUFSZ]; + mswin_getlin("Search for:", buf); + if (!*buf || *buf == '\033') return -2; + for(i=0; imenu.size; i++ ) { + if( NHMENU_IS_SELECTABLE(data->menu.items[i]) + && strstr(data->menu.items[i].str, buf) ) { + if (data->how == PICK_ANY) { + SendMessage(hwndList, + LB_SETSEL, + (WPARAM)!SendMessage(hwndList, LB_GETSEL, (WPARAM)i, (LPARAM)0), + (LPARAM)i); + } else if( data->how == PICK_ONE ) { + SendMessage(hwndList, LB_SETCURSEL, (WPARAM)i, (LPARAM)0); + break; + } + } + } + } else { + mswin_nhbell(); + } + return -2; + + case ' ': + if( data->how==PICK_ONE || data->how==PICK_NONE ) { + data->done = 1; + data->result = 0; + return -2; + } + break; + + default: + if( (ch>='a' && ch<='z') || + (ch>='A' && ch<='Z') ) { + for(i=0; imenu.size; i++ ) { + if( data->menu.items[i].accelerator == ch ) { + if( data->how == PICK_ANY ) { + SendMessage(hwndList, + LB_SETSEL, + (WPARAM)!SendMessage(hwndList, LB_GETSEL, (WPARAM)i, (LPARAM)0), + (LPARAM)i); + return -2; + } else if( data->how == PICK_ONE ) { + SendMessage(hwndList, LB_SETCURSEL, (WPARAM)i, (LPARAM)0); + data->result = 0; + data->done = 1; + return -2; + } + } + } + } + break; + } + + return -1; +} + void mswin_menu_window_size (HWND hWnd, LPSIZE sz) { TEXTMETRIC tm; @@ -726,7 +864,7 @@ void mswin_menu_window_size (HWND hWnd, LPSIZE sz) sz->cy = rt.bottom - rt.top; data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); - if(data) { + if(data && data->type==MENU_TYPE_MENU ) { hdc = GetDC(GetMenuControl(hWnd)); saveFont = SelectObject(hdc, mswin_create_font(NHW_MENU, ATR_INVERSE, hdc)); GetTextMetrics(hdc, &tm); @@ -742,43 +880,16 @@ void mswin_menu_window_size (HWND hWnd, LPSIZE sz) } } -DWORD CALLBACK NHTextStreamCallback( - DWORD dwCookie, // application-defined value - LPBYTE pbBuff, // data buffer - LONG cb, // number of bytes to read or write - LONG *pcb // number of bytes transferred -) +int GetListPageSize( HWND hwndList ) { - static int st = 0; - static char* _text_buf = 0; - size_t to_copy; + int ntop, nRectheight, nVisibleItems; + RECT rc, itemrect; - switch(st) { - case 0: - _text_buf = (char*)dwCookie; - st = 1; - /* fall through */ + ntop = SendMessage(hwndList, LB_GETTOPINDEX, 0, 0); /* Top item index. */ + GetClientRect(hwndList, &rc); /* Get list box rectangle. */ + nRectheight = rc.bottom - rc.top; /* Compute list box height. */ - case 1: - to_copy = min((size_t)cb, strlen(_text_buf)); - if( *pcb>0 ) { - strncpy((char*)pbBuff, _text_buf, to_copy); - _text_buf += to_copy; - *pcb = (LONG)to_copy; - } - if( !_text_buf[0] ) st = 3; - break; - - case 3: - *pcb = 2; - strncpy( (char*)pbBuff, "\r\n", *pcb); - st = 4; - break; - - case 4: - *pcb = 0; - st = 0; - break; - } - return 0; -} \ No newline at end of file + SendMessage(hwndList, LB_GETITEMRECT, ntop, (DWORD)(&itemrect)); /* Get current line's rectangle. */ + nVisibleItems = nRectheight/(itemrect.bottom - itemrect.top); + return max(1, nVisibleItems); +} diff --git a/win/win32/mhtext.c b/win/win32/mhtext.c index e9a64234f..ec74ad090 100644 --- a/win/win32/mhtext.c +++ b/win/win32/mhtext.c @@ -7,20 +7,31 @@ #include "mhmsg.h" #include "mhfont.h" +typedef struct mswin_nethack_text_window { + TCHAR* window_text; +} NHTextWindow, *PNHTextWindow; + LRESULT CALLBACK TextWndProc(HWND, UINT, WPARAM, LPARAM); static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam); static void LayoutText(HWND hwnd); HWND mswin_init_text_window () { HWND ret; + PNHTextWindow data; ret = CreateDialog( GetNHApp()->hApp, - MAKEINTRESOURCE(IDD_TEXT), + MAKEINTRESOURCE(IDD_NHTEXT), GetNHApp()->hMainWnd, TextWndProc ); if( !ret ) panic("Cannot create text window"); + + data = (PNHTextWindow)malloc(sizeof(NHTextWindow)); + if( !data ) panic("out of memory"); + + ZeroMemory(data, sizeof(NHTextWindow)); + SetWindowLong(ret, GWL_USERDATA, (LONG)data); return ret; } @@ -28,12 +39,21 @@ void mswin_display_text_window (HWND hWnd) { MSG msg; RECT rt; - HWND map_wnd; + PNHTextWindow data; + HWND mapWnd; + + data = (PNHTextWindow)GetWindowLong(hWnd, GWL_USERDATA); + if( data && data->window_text ) { + HWND control; + control = GetDlgItem(hWnd, IDC_TEXT_CONTROL); + SendMessage(control, EM_FMTLINES, 1, 0 ); + SetWindowText(GetDlgItem(hWnd, IDC_TEXT_CONTROL), data->window_text); + } GetNHApp()->hMenuWnd = hWnd; - map_wnd = mswin_hwnd_from_winid(WIN_MAP); - if( !IsWindow(map_wnd) ) map_wnd = GetNHApp()->hMainWnd; - GetWindowRect(map_wnd, &rt); + mapWnd = mswin_hwnd_from_winid(WIN_MAP); + if( !IsWindow(mapWnd) ) mapWnd = GetNHApp()->hMainWnd; + GetWindowRect(mapWnd, &rt); MoveWindow(hWnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE); ShowWindow(hWnd, SW_SHOW); SetFocus(hWnd); @@ -55,17 +75,22 @@ LRESULT CALLBACK TextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar { HWND control; HDC hdc; - + PNHTextWindow data; + + data = (PNHTextWindow)GetWindowLong(hWnd, GWL_USERDATA); switch (message) { - case WM_INITDIALOG: /* set text control font */ - control = GetDlgItem(hWnd, IDC_TEXT_VIEW); + control = GetDlgItem(hWnd, IDC_TEXT_CONTROL); + if( !control ) { + panic("cannot get text view window"); + } + hdc = GetDC(control); SendMessage(control, WM_SETFONT, (WPARAM)mswin_create_font(NHW_TEXT, ATR_NONE, hdc), 0); ReleaseDC(control, hdc); - + SetFocus(control); return FALSE; @@ -89,34 +114,43 @@ LRESULT CALLBACK TextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar SetFocus(GetNHApp()->hMainWnd); return TRUE; } + break; + + case WM_DESTROY: + if( data ) { + if( data->window_text ) free(data->window_text); + free(data); + SetWindowLong(hWnd, GWL_USERDATA, (LONG)0); + } + break; + } return FALSE; } void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) { + PNHTextWindow data; + + data = (PNHTextWindow)GetWindowLong(hWnd, GWL_USERDATA); switch( wParam ) { case MSNH_MSG_PUTSTR: { PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr)lParam; - HWND text_view; - TCHAR* text; TCHAR wbuf[BUFSZ]; size_t text_size; - text_view = GetDlgItem(hWnd, IDC_TEXT_VIEW); - if( !text_view ) panic("cannot get text view window"); + if( !data->window_text ) { + text_size = strlen(msg_data->text) + 4; + data->window_text = (TCHAR*)malloc(text_size*sizeof(data->window_text[0])); + ZeroMemory(data->window_text, text_size*sizeof(data->window_text[0])); + } else { + text_size = _tcslen(data->window_text) + strlen(msg_data->text) + 4; + data->window_text = (TCHAR*)realloc(data->window_text, text_size*sizeof(data->window_text[0])); + } + if( !data->window_text ) break; - text_size = GetWindowTextLength(text_view) + strlen(msg_data->text) + 3; - text = (TCHAR*)malloc(text_size*sizeof(text[0])); - if( !text ) break; - ZeroMemory(text, text_size*sizeof(text[0])); - - GetWindowText(text_view, text, GetWindowTextLength(text_view)); - _tcscat(text, NH_A2W(msg_data->text, wbuf, sizeof(wbuf))); - _tcscat(text, TEXT("\n")); - SetWindowText(text_view, text); - - free(text); + _tcscat(data->window_text, NH_A2W(msg_data->text, wbuf, BUFSZ)); + _tcscat(data->window_text, TEXT("\r\n")); break; } } @@ -130,7 +164,7 @@ void LayoutText(HWND hWnd) POINT pt_elem, pt_ok; SIZE sz_elem, sz_ok; - text = GetDlgItem(hWnd, IDC_TEXT_VIEW); + text = GetDlgItem(hWnd, IDC_TEXT_CONTROL); btn_ok = GetDlgItem(hWnd, IDOK); /* get window coordinates */ diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index a09f98a65..19ec2d73c 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -471,7 +471,6 @@ void mswin_display_file(const char *filename,BOOLEAN_P must_exist) } else { HWND hwnd; char line[LLEN]; - RECT rt; hwnd = mswin_init_text_window(); @@ -487,10 +486,7 @@ void mswin_display_file(const char *filename,BOOLEAN_P must_exist) } (void) dlb_fclose(f); - GetNHApp()->hMenuWnd = hwnd; - GetWindowRect(mswin_hwnd_from_winid(WIN_MAP), &rt); - MoveWindow(hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE); - ShowWindow(hwnd, SW_SHOW); + mswin_display_text_window(hwnd); } } @@ -788,7 +784,7 @@ int mswin_nh_poskey(int *x, int *y, int *mod) while( (event = mswin_input_pop())==NULL ) mswin_main_loop(); if( event->type==NHEVENT_MOUSE ) { - *mod = CLICK_1; + *mod = event->ms.mod; *x = event->ms.x; *y = event->ms.y; key = 0; diff --git a/win/win32/resource.h b/win/win32/resource.h index 48cca55b3..dd5ad49a9 100644 --- a/win/win32/resource.h +++ b/win/win32/resource.h @@ -14,6 +14,7 @@ #define IDR_MAINFRAME 128 #define IDB_TILES 129 #define IDD_TEXT 130 +#define IDD_NHTEXT 130 #define IDD_MENU 132 #define IDB_MENU_SEL 133 #define IDB_MENU_UNSEL 134 @@ -21,7 +22,9 @@ #define IDD_GETLIN 138 #define IDD_EXTCMD 139 #define IDD_PLAYER_SELECTOR 141 +#define IDB_PETMARK 143 #define IDC_TEXT_VIEW 1000 +#define IDC_TEXT_CONTROL 1000 #define IDC_CMD_MOVE_NW 1001 #define IDC_CMD_MOVE_N 1002 #define IDC_MENU_LIST 1003 @@ -130,9 +133,9 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 143 +#define _APS_NEXT_RESOURCE_VALUE 144 #define _APS_NEXT_COMMAND_VALUE 32793 -#define _APS_NEXT_CONTROL_VALUE 1329 +#define _APS_NEXT_CONTROL_VALUE 1331 #define _APS_NEXT_SYMED_VALUE 110 #endif #endif diff --git a/win/win32/winMS.h b/win/win32/winMS.h index 3b5e9cbfb..805c2f204 100644 --- a/win/win32/winMS.h +++ b/win/win32/winMS.h @@ -25,6 +25,9 @@ #define TILES_PER_LINE 40 +/* tile background color */ +#define TILE_BK_COLOR RGB(71, 108, 108) + typedef struct mswin_nhwindow_data { HWND win; int type; @@ -40,12 +43,16 @@ typedef struct mswin_nhwindow_app { MSNHWinData windowlist[MAXWINDOWS]; HBITMAP bmpTiles; + HBITMAP bmpPetMark; boolean bNoHScroll; /* disable cliparound for horizontal grid (map) */ boolean bNoVScroll; /* disable cliparound for vertical grid (map) */ int mapDisplayMode; /* regular map display mode */ int mapDisplayModeSave; /* saved map display mode */ + + int winStatusAlign; /* alignment of the status window */ + int winMessageAlign; /* alignment of the status window */ } NHWinApp, *PNHWinApp; extern PNHWinApp GetNHApp(); @@ -105,6 +112,11 @@ winid mswin_winid_from_type(int type); winid mswin_winid_from_handle(HWND hWnd); void mswin_window_mark_dead(winid wid); void bail(const char *mesg); +void 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, + COLORREF cTransparent +); /* unicode stuff */ #ifdef UNICODE diff --git a/win/win32/winhack.c b/win/win32/winhack.c index afdf05a5a..fa1563fec 100644 --- a/win/win32/winhack.c +++ b/win/win32/winhack.c @@ -51,13 +51,15 @@ int APIENTRY WinMain(HINSTANCE hInstance, _nethack_app.hMenuWnd = 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.bNoHScroll = FALSE; _nethack_app.bNoVScroll = FALSE; _nethack_app.mapDisplayMode = NHMAP_VIEW_TILES; + _nethack_app.winStatusAlign = NHWND_ALIGN_BOTTOM; + _nethack_app.winMessageAlign = NHWND_ALIGN_TOP; // init controls - LoadLibrary( TEXT("RICHED32.DLL") ); - ZeroMemory(&InitCtrls, sizeof(InitCtrls)); InitCtrls.dwSize = sizeof(InitCtrls); InitCtrls.dwICC = ICC_LISTVIEW_CLASSES; @@ -129,3 +131,63 @@ PNHWinApp GetNHApp() return &_nethack_app; } +/* options */ +struct t_win32_opt_int { + const char* val; + int opt; +}; +static struct t_win32_opt_int _win32_map_mode[] = +{ + { "tiles", NHMAP_VIEW_TILES }, + { "ascii4x6", NHMAP_VIEW_ASCII4x6 }, + { "ascii6x8", NHMAP_VIEW_ASCII6x8 }, + { "ascii8x8", NHMAP_VIEW_ASCII8x8 }, + { "ascii16x8", NHMAP_VIEW_ASCII16x8 }, + { "ascii7x12", NHMAP_VIEW_ASCII7x12 }, + { "ascii8x12", NHMAP_VIEW_ASCII8x12 }, + { "ascii16x12", NHMAP_VIEW_ASCII16x12 }, + { "ascii12x16", NHMAP_VIEW_ASCII12x16 }, + { "ascii10x18", NHMAP_VIEW_ASCII10x18 }, + { "fit_to_screen", NHMAP_VIEW_FIT_TO_SCREEN }, + { NULL, -1 } +}; + +static struct t_win32_opt_int _win32_align[] = +{ + { "left", NHWND_ALIGN_LEFT }, + { "right", NHWND_ALIGN_RIGHT }, + { "top", NHWND_ALIGN_TOP }, + { "bottom", NHWND_ALIGN_BOTTOM }, + { NULL, -1 } +}; + +int set_win32_option( const char * name, const char * val) +{ + struct t_win32_opt_int* p; + if( _stricmp(name, "win32_map_mode")==0 ) { + for( p=_win32_map_mode; p->val; p++ ) { + if( _stricmp(p->val, val)==0 ){ + GetNHApp()->mapDisplayMode = p->opt; + return 1; + } + } + return 0; + } else if( _stricmp(name, "win32_align_status")==0 ) { + for( p=_win32_align; p->val; p++ ) { + if( _stricmp(p->val, val)==0 ) { + GetNHApp()->winStatusAlign = p->opt; + return 1; + } + } + return 0; + } else if( _stricmp(name, "win32_align_message")==0 ) { + for( p=_win32_align; p->val; p++ ) { + if( _stricmp(p->val, val)==0 ) { + GetNHApp()->winMessageAlign = p->opt; + return 1; + } + } + return 0; + } + return 0; +} \ No newline at end of file diff --git a/win/win32/winhack.rc b/win/win32/winhack.rc index 9365bd974..c857afdaa 100644 --- a/win/win32/winhack.rc +++ b/win/win32/winhack.rc @@ -103,31 +103,28 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP END -IDD_TEXT DIALOGEX 0, 0, 172, 178 +IDD_NHTEXT DIALOGEX 0, 0, 172, 178 STYLE DS_SETFOREGROUND | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME EXSTYLE WS_EX_STATICEDGE CAPTION "Text" -FONT 8, "MS Sans Serif", 0, 0, 0x1 +FONT 8, "MS Sans Serif" BEGIN DEFPUSHBUTTON "OK",IDOK,54,163,50,14 - CONTROL "",IDC_TEXT_VIEW,"RICHEDIT",ES_MULTILINE | ES_READONLY | - ES_WANTRETURN | WS_BORDER | WS_VSCROLL | WS_HSCROLL | - WS_TABSTOP,0,0,173,155 + EDITTEXT IDC_TEXT_CONTROL,0,0,170,160,ES_MULTILINE | + ES_OEMCONVERT | ES_READONLY | WS_VSCROLL | WS_HSCROLL END IDD_MENU DIALOGEX 0, 0, 187, 153 STYLE WS_POPUP | WS_CLIPSIBLINGS | WS_THICKFRAME EXSTYLE WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT | WS_EX_STATICEDGE -FONT 8, "MS Sans Serif", 0, 0, 0x1 +FONT 8, "MS Sans Serif" BEGIN DEFPUSHBUTTON "OK",IDOK,7,132,50,14,BS_FLAT PUSHBUTTON "Cancel",IDCANCEL,130,132,50,14,BS_FLAT - CONTROL "",IDC_MENU_TEXT,"RICHEDIT",ES_MULTILINE | ES_READONLY | - ES_WANTRETURN | WS_BORDER | WS_VSCROLL | WS_HSCROLL | - WS_TABSTOP,7,67,173,61 - LISTBOX IDC_MENU_LIST,10,10,170,55,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_MENU_LIST,10,10,170,55,LBS_SORT | WS_TABSTOP + EDITTEXT IDC_MENU_TEXT,10,70,170,60,ES_MULTILINE | ES_OEMCONVERT | + ES_READONLY | WS_VSCROLL | WS_HSCROLL END IDD_GETLIN DIALOG DISCARDABLE 0, 0, 131, 29 @@ -220,6 +217,7 @@ END IDB_TILES BITMAP DISCARDABLE "tiles.bmp" IDB_MENU_SEL BITMAP DISCARDABLE "mnsel.bmp" IDB_MENU_UNSEL BITMAP DISCARDABLE "mnunsel.bmp" +IDB_PETMARK BITMAP DISCARDABLE "petmark.bmp" ///////////////////////////////////////////////////////////////////////////// // @@ -229,7 +227,7 @@ IDB_MENU_UNSEL BITMAP DISCARDABLE "mnunsel.bmp" #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO DISCARDABLE BEGIN - IDD_TEXT, DIALOG + IDD_NHTEXT, DIALOG BEGIN BOTTOMMARGIN, 177 END