#include "winMS.h"
#include "resource.h"
-#include "mhstatus.h"
+#include "mhmap.h"
#include "mhmsg.h"
#include "mhinput.h"
#include "mhfont.h"
#define MAXWINDOWTEXT 255
+
extern short glyph2tile[];
/* map window data */
typedef struct mswin_nethack_map_window {
int map[COLNO][ROWNO]; /* glyph map */
- int xPos, yPos;
- int xPageSize, yPageSize;
- int xCur, yCur;
+ int mapMode; /* current map mode */
+ boolean bAsciiMode; /* switch ASCII/tiled mode */
+ int xPos, yPos; /* scroll position */
+ int xPageSize, yPageSize; /* scroll page size */
+ int xCur, yCur; /* position of the cursor */
+ int xScrTile, yScrTile; /* size of display tile */
+ POINT map_orig; /* map origin point */
+
+ HFONT hMapFont; /* font for ASCII mode */
} NHMapWindow, *PNHMapWindow;
static TCHAR szNHMapWindowClass[] = TEXT("MSNethackMapWndClass");
static void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam);
static void onPaint(HWND hWnd);
static void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
-#ifdef TEXTCOLOR
+static void nhcoord2display(PNHMapWindow data, int x, int y, LPRECT lpOut);
+static void nhglyph2charcolor(short glyph, uchar* ch, int* color);
static COLORREF nhcolor_to_RGB(int c);
-#endif
HWND mswin_init_map_window () {
static int run_once = 0;
return ret;
}
+void mswin_map_stretch(HWND hWnd, LPSIZE lpsz, BOOL redraw)
+{
+ PNHMapWindow data;
+ RECT client_rt;
+ SCROLLINFO si;
+ SIZE wnd_size;
+ LOGFONT lgfnt;
+
+ /* check arguments */
+ if( !IsWindow(hWnd) ||
+ !lpsz ||
+ lpsz->cx<=0 ||
+ lpsz->cy<=0 ) return;
+
+ /* calculate window size */
+ GetClientRect(hWnd, &client_rt);
+ wnd_size.cx = client_rt.right - client_rt.left;
+ wnd_size.cy = client_rt.bottom - client_rt.top;
+
+ /* set new screen tile size */
+ data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA);
+ data->xScrTile = ((data->mapMode==NHMAP_VIEW_FIT_TO_SCREEN)? wnd_size.cx : lpsz->cx) / COLNO;
+ data->yScrTile = ((data->mapMode==NHMAP_VIEW_FIT_TO_SCREEN)? wnd_size.cy : lpsz->cy) / ROWNO;
+
+ /* set map origin point */
+ data->map_orig.x = max(0, client_rt.left + (wnd_size.cx - data->xScrTile*COLNO)/2 );
+ data->map_orig.y = max(0, client_rt.top + (wnd_size.cy - data->yScrTile*ROWNO)/2 );
+
+ data->map_orig.x -= data->map_orig.x % data->xScrTile;
+ data->map_orig.y -= data->map_orig.y % data->yScrTile;
+
+ /* adjust horizontal scroll bar */
+ if( data->mapMode==NHMAP_VIEW_FIT_TO_SCREEN )
+ data->xPageSize = COLNO+1; /* disable scroll bar */
+ else
+ data->xPageSize = wnd_size.cx/data->xScrTile;
+ if( wnd_size.cx/data->xScrTile >= COLNO ) {
+ data->xPos = 0;
+ GetNHApp()->bNoHScroll = TRUE;
+ } else {
+ GetNHApp()->bNoHScroll = FALSE;
+ data->xPos = max(0, min(COLNO, u.ux - data->xPageSize/2));
+ }
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMin = 0;
+ si.nMax = COLNO;
+ si.nPage = data->xPageSize;
+ si.nPos = data->xPos;
+ SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
+
+ /* adjust vertical scroll bar */
+ if( data->mapMode==NHMAP_VIEW_FIT_TO_SCREEN )
+ data->yPageSize = ROWNO+1; /* disable scroll bar */
+ else
+ data->yPageSize = wnd_size.cy/data->yScrTile;
+
+ if( wnd_size.cy/data->yScrTile >= ROWNO ) {
+ data->yPos = 0;
+ GetNHApp()->bNoVScroll = TRUE;
+ } else {
+ GetNHApp()->bNoVScroll = FALSE;
+ data->yPos = max(0, min(ROWNO, u.uy - data->yPageSize/2));
+ }
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMin = 0;
+ si.nMax = ROWNO;
+ si.nPage = data->yPageSize;
+ si.nPos = data->yPos;
+ SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
+
+ /* create font */
+ if( data->hMapFont ) DeleteObject(data->hMapFont);
+ ZeroMemory(&lgfnt, sizeof(lgfnt));
+ lgfnt.lfHeight = -data->yScrTile; // height of font
+ lgfnt.lfWidth = -data->xScrTile; // average character width
+ lgfnt.lfEscapement = 0; // angle of escapement
+ lgfnt.lfOrientation = 0; // base-line orientation angle
+ lgfnt.lfWeight = FW_NORMAL; // font weight
+ lgfnt.lfItalic = FALSE; // italic attribute option
+ lgfnt.lfUnderline = FALSE; // underline attribute option
+ lgfnt.lfStrikeOut = FALSE; // strikeout attribute option
+ lgfnt.lfCharSet = OEM_CHARSET; // character set identifier
+ lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS; // output precision
+ lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
+ lgfnt.lfQuality = DEFAULT_QUALITY; // output quality
+ lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family
+ _tcscpy(lgfnt.lfFaceName, TEXT("Terminal"));
+ data->hMapFont = CreateFontIndirect(&lgfnt);
+
+ mswin_cliparound(data->xCur, data->yCur);
+
+ if(redraw) InvalidateRect(hWnd, NULL, TRUE);
+}
+
+/* set map mode */
+int mswin_map_mode(HWND hWnd, int mode)
+{
+ PNHMapWindow data;
+ int oldMode;
+ SIZE mapSize;
+
+ data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA);
+ if( mode == data->mapMode ) return mode;
+
+ oldMode = data->mapMode;
+ data->mapMode = mode;
+
+ switch( data->mapMode ) {
+
+ case NHMAP_VIEW_ASCII4x6:
+ data->bAsciiMode = TRUE;
+ mapSize.cx = 4*COLNO;
+ mapSize.cy = 6*ROWNO;
+ break;
+
+ case NHMAP_VIEW_ASCII6x8:
+ data->bAsciiMode = TRUE;
+ mapSize.cx = 6*COLNO;
+ mapSize.cy = 8*ROWNO;
+ break;
+
+ case NHMAP_VIEW_ASCII8x8:
+ data->bAsciiMode = TRUE;
+ mapSize.cx = 8*COLNO;
+ mapSize.cy = 8*ROWNO;
+ break;
+
+ case NHMAP_VIEW_ASCII16x8:
+ data->bAsciiMode = TRUE;
+ mapSize.cx = 16*COLNO;
+ mapSize.cy = 8*ROWNO;
+ break;
+
+ case NHMAP_VIEW_ASCII7x12:
+ data->bAsciiMode = TRUE;
+ mapSize.cx = 7*COLNO;
+ mapSize.cy = 12*ROWNO;
+ break;
+
+ case NHMAP_VIEW_ASCII8x12:
+ data->bAsciiMode = TRUE;
+ mapSize.cx = 8*COLNO;
+ mapSize.cy = 12*ROWNO;
+ break;
+
+ case NHMAP_VIEW_ASCII16x12:
+ data->bAsciiMode = TRUE;
+ mapSize.cx = 16*COLNO;
+ mapSize.cy = 12*ROWNO;
+ break;
+
+ case NHMAP_VIEW_ASCII12x16:
+ data->bAsciiMode = TRUE;
+ mapSize.cx = 12*COLNO;
+ mapSize.cy = 16*ROWNO;
+ break;
+
+ case NHMAP_VIEW_ASCII10x18:
+ data->bAsciiMode = TRUE;
+ mapSize.cx = 10*COLNO;
+ mapSize.cy = 18*ROWNO;
+ break;
+
+ case NHMAP_VIEW_FIT_TO_SCREEN: {
+ RECT client_rt;
+ GetClientRect(hWnd, &client_rt);
+ mapSize.cx = client_rt.right - client_rt.left;
+ mapSize.cy = client_rt.bottom - client_rt.top;
+
+ data->bAsciiMode = TRUE;
+ } break;
+
+ case NHMAP_VIEW_TILES:
+ default:
+ data->bAsciiMode = FALSE;
+ mapSize.cx = TILE_X*COLNO;
+ mapSize.cy = TILE_Y*ROWNO;
+ break;
+ }
+
+ mswin_map_stretch(hWnd, &mapSize, TRUE);
+
+ return oldMode;
+}
+
+/* register window class for map window */
void register_map_window_class()
{
WNDCLASS wcex;
}
}
-
+/* map window procedure */
LRESULT CALLBACK MapWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PNHMapWindow data;
case WM_SIZE:
{
- SCROLLINFO si;
- int xNewSize;
- int yNewSize;
-
- xNewSize = LOWORD(lParam);
- yNewSize = HIWORD(lParam);
+ SIZE size;
- /* adjust horizontal scroll bar */
- if( xNewSize/TILE_X >= COLNO ) {
- data->xPos = 0;
- GetNHApp()->bNoHScroll = TRUE;
+ if( data->mapMode == NHMAP_VIEW_FIT_TO_SCREEN ) {
+ size.cx = LOWORD(lParam);
+ size.cy = HIWORD(lParam);
} else {
- GetNHApp()->bNoHScroll = FALSE;
- data->xPos = max(0, min(COLNO, u.ux - xNewSize/TILE_X/2));
+ /* mapping factor is unchaged we just need to adjust scroll bars */
+ size.cx = data->xScrTile*COLNO;
+ size.cy = data->yScrTile*ROWNO;
}
-
- si.cbSize = sizeof(si);
- si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
- si.nMin = 0;
- si.nMax = COLNO;
- si.nPage = xNewSize/TILE_X;
- si.nPos = data->xPos;
- SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
-
- /* adjust vertical scroll bar */
- if( yNewSize/TILE_Y >= ROWNO ) {
- data->yPos = 0;
- GetNHApp()->bNoVScroll = TRUE;
- } else {
- GetNHApp()->bNoVScroll = FALSE;
- data->yPos = max(0, min(ROWNO, u.uy - yNewSize/TILE_Y/2));
- }
-
- si.cbSize = sizeof(si);
- si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
- si.nMin = 0;
- si.nMax = ROWNO;
- si.nPage = yNewSize/TILE_Y;
- si.nPos = data->yPos;
- SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
-
- /* erase window */
- InvalidateRect(hWnd, NULL, TRUE);
+ mswin_map_stretch(hWnd, &size, TRUE);
}
break;
case WM_LBUTTONDOWN:
NHEVENT_MS(
- min(COLNO, data->xPos + LOWORD(lParam)/TILE_X),
- min(ROWNO, data->yPos + HIWORD(lParam)/TILE_Y)
+ 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;
case WM_DESTROY:
+ if( data->hMapFont ) DeleteObject(data->hMapFont);
free(data);
SetWindowLong(hWnd, GWL_USERDATA, (LONG)0);
break;
return 0;
}
+/* on WM_COMMAND */
void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PNHMapWindow data;
data->map[msg_data->x][msg_data->y] = msg_data->glyph;
/* invalidate the update area */
- rt.left = msg_data->x*TILE_X - TILE_X*data->xPos;
- rt.top = msg_data->y*TILE_Y - TILE_Y*data->yPos;
- rt.right = rt.left + TILE_X;
- rt.bottom = rt.top + TILE_Y;
-
+ nhcoord2display(data, msg_data->x, msg_data->y, &rt);
InvalidateRect(hWnd, &rt, TRUE);
}
break;
case MSNH_MSG_CLIPAROUND:
{
PMSNHMsgClipAround msg_data = (PMSNHMsgClipAround)lParam;
- SCROLLINFO si;
- int xPage, yPage;
int x, y;
-
- /* get page size */
- if( !GetNHApp()->bNoHScroll ) {
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE;
- GetScrollInfo(hWnd, SB_HORZ, &si);
- xPage = si.nPage;
-
- x = max(0, min(COLNO, msg_data->x - xPage/2));
+ /* get page size and center horizontally on x-position*/
+ if( !GetNHApp()->bNoHScroll ) {
+ x = max(0, min(COLNO, msg_data->x - data->xPageSize/2));
SendMessage( hWnd, WM_HSCROLL, (WPARAM)MAKELONG(SB_THUMBTRACK, x), (LPARAM)NULL );
}
+ /* get page size and center vertically on y-position*/
if( !GetNHApp()->bNoVScroll ) {
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE;
- GetScrollInfo(hWnd, SB_VERT, &si);
- yPage = si.nPage;
-
- y = max(0, min(ROWNO, msg_data->y - yPage/2));
-
+ y = max(0, min(ROWNO, msg_data->y - data->yPageSize/2));
SendMessage( hWnd, WM_VSCROLL, (WPARAM)MAKELONG(SB_THUMBTRACK, y), (LPARAM)NULL );
}
}
/* move focus rectangle at the cursor postion */
hdc = GetDC(hWnd);
- rt.left = (data->xCur - data->xPos)*TILE_X;
- rt.top = (data->yCur - data->yPos)*TILE_Y;
- rt.right = rt.left + TILE_X;
- rt.bottom = rt.top + TILE_Y;
- DrawFocusRect(hdc, &rt);
+
+ nhcoord2display(data, data->xCur, data->yCur, &rt);
+ if( data->bAsciiMode ) {
+ PatBlt(hdc, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, DSTINVERT);
+ } else {
+ DrawFocusRect(hdc, &rt);
+ }
data->xCur = msg_data->x;
data->yCur = msg_data->y;
- rt.left = (data->xCur - data->xPos)*TILE_X;
- rt.top = (data->yCur - data->yPos)*TILE_Y;
- rt.right = rt.left + TILE_X;
- rt.bottom = rt.top + TILE_Y;
- DrawFocusRect(hdc, &rt);
+
+ nhcoord2display(data, data->xCur, data->yCur, &rt);
+ if( data->bAsciiMode ) {
+ PatBlt(hdc, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, DSTINVERT);
+ } else {
+ DrawFocusRect(hdc, &rt);
+ }
ReleaseDC(hWnd, hdc);
} break;
}
}
+/* on WM_CREATE */
void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PNHMapWindow data;
for(j=0; j<ROWNO; j++) {
data->map[i][j] = -1;
}
+
+ data->bAsciiMode = FALSE;
+
+ data->xScrTile = TILE_X;
+ data->yScrTile = TILE_Y;
+
SetWindowLong(hWnd, GWL_USERDATA, (LONG)data);
}
+/* on WM_PAINT */
void onPaint(HWND hWnd)
{
PNHMapWindow data;
/* calculate paint rectangle */
if( !IsRectEmpty(&ps.rcPaint) ) {
/* calculate paint rectangle */
- paint_rt.top = data->yPos + ps.rcPaint.top/TILE_X;
- paint_rt.left = data->xPos + ps.rcPaint.left/TILE_Y;
- paint_rt.bottom = min(data->yPos+ps.rcPaint.bottom/TILE_Y+1, ROWNO);
- paint_rt.right = min(data->xPos+ps.rcPaint.right/TILE_X+1, COLNO);
+ paint_rt.left = max(data->xPos + (ps.rcPaint.left - data->map_orig.x)/data->xScrTile, 0);
+ paint_rt.top = max(data->yPos + (ps.rcPaint.top - data->map_orig.y)/data->yScrTile, 0);
+ paint_rt.right = min(data->xPos + (ps.rcPaint.right - data->map_orig.x)/data->xScrTile+1, COLNO);
+ paint_rt.bottom = min(data->yPos + (ps.rcPaint.bottom - data->map_orig.y)/data->yScrTile+1, ROWNO);
+ if( data->bAsciiMode
#ifdef REINCARNATION
- if (Is_rogue_level(&u.uz)) {
+ || Is_rogue_level(&u.uz)
/* You enter a VERY primitive world! */
+#endif
+ ) {
HGDIOBJ oldFont;
- int offset;
- oldFont = SelectObject(hDC, mswin_create_font(NHW_MAP, ATR_NONE, hDC));
+ oldFont = SelectObject(hDC, data->hMapFont);
SetBkMode(hDC, TRANSPARENT);
/* draw the map */
uchar ch;
TCHAR wch;
RECT glyph_rect;
- unsigned short g=data->map[i][j];
+ int color;
+
+ nhglyph2charcolor(data->map[i][j], &ch, &color);
- /* (from wintty, naturally)
- *
- * Map the glyph back to a character.
- *
- * Warning: For speed, this makes an assumption on the order of
- * offsets. The order is set in display.h.
- */
-
-#ifdef TEXTCOLOR
- int color;
-
-#define zap_color(n) color = iflags.use_color ? zapcolors[n] : NO_COLOR
-#define cmap_color(n) color = iflags.use_color ? defsyms[n].color : NO_COLOR
-#define obj_color(n) color = iflags.use_color ? objects[n].oc_color : NO_COLOR
-#define mon_color(n) color = iflags.use_color ? mons[n].mcolor : NO_COLOR
-#define pet_color(n) color = iflags.use_color ? mons[n].mcolor : NO_COLOR
-#define warn_color(n) color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR
-
-# else /* no text color */
-
-#define zap_color(n)
-#define cmap_color(n)
-#define obj_color(n)
-#define mon_color(n)
-#define pet_color(c)
-#define warn_color(c)
- SetTextColor( hDC, nhcolor_to_RGB(CLR_WHITE) );
-#endif
-
- if ((offset = (g - GLYPH_WARNING_OFF)) >= 0) { /* a warning flash */
- ch = warnsyms[offset];
- warn_color(offset);
- } else if ((offset = (g - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */
- /* see swallow_to_glyph() in display.c */
- ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)];
- mon_color(offset >> 3);
- } else if ((offset = (g - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */
- /* see zapdir_to_glyph() in display.c */
- ch = showsyms[S_vbeam + (offset & 0x3)];
- zap_color((offset >> 2));
- } else if ((offset = (g - GLYPH_CMAP_OFF)) >= 0) { /* cmap */
- ch = showsyms[offset];
- cmap_color(offset);
- } else if ((offset = (g - GLYPH_OBJ_OFF)) >= 0) { /* object */
- ch = oc_syms[(int)objects[offset].oc_class];
- obj_color(offset);
- } else if ((offset = (g - GLYPH_BODY_OFF)) >= 0) { /* a corpse */
- ch = oc_syms[(int)objects[CORPSE].oc_class];
- mon_color(offset);
- } else if ((offset = (g - GLYPH_PET_OFF)) >= 0) { /* a pet */
- ch = monsyms[(int)mons[offset].mlet];
- pet_color(offset);
- } else { /* a monster */
- ch = monsyms[(int)mons[g].mlet];
- mon_color(g);
- }
- // end of wintty code
-
-#ifdef TEXTCOLOR
if( color == NO_COLOR ) continue;
else SetTextColor( hDC, nhcolor_to_RGB(color) );
-#endif
- glyph_rect.left = (i-data->xPos)*TILE_X;
- glyph_rect.top = (j-data->yPos)*TILE_Y;
- glyph_rect.right = glyph_rect.left + TILE_X;
- glyph_rect.bottom = glyph_rect.top + TILE_Y;
+
+ nhcoord2display(data, i, j, &glyph_rect);
DrawText(hDC,
NH_A2W(&ch, &wch, 1),
1,
DT_CENTER | DT_VCENTER | DT_NOPREFIX
);
}
- mswin_destroy_font( SelectObject(hDC, oldFont) );
- } else
-#endif
- {
+ SelectObject(hDC, oldFont);
+ } else {
/* prepare tiles DC for mapping */
tileDC = CreateCompatibleDC(hDC);
saveBmp = SelectObject(tileDC, GetNHApp()->bmpTiles);
if(data->map[i][j]>0) {
short ntile;
int t_x, t_y;
+ RECT glyph_rect;
ntile = glyph2tile[ data->map[i][j] ];
t_x = (ntile % TILES_PER_LINE)*TILE_X;
t_y = (ntile / TILES_PER_LINE)*TILE_Y;
-
- BitBlt(hDC, (i-data->xPos)*TILE_X, (j-data->yPos)*TILE_Y, TILE_X, TILE_Y, tileDC, t_x, t_y, SRCCOPY );
+
+ nhcoord2display(data, i, j, &glyph_rect);
+
+ StretchBlt(
+ hDC,
+ glyph_rect.left,
+ glyph_rect.top,
+ data->xScrTile,
+ data->yScrTile,
+ tileDC,
+ t_x,
+ t_y,
+ TILE_X,
+ TILE_Y,
+ SRCCOPY
+ );
}
SelectObject(tileDC, saveBmp);
DeleteDC(tileDC);
}
/* draw focus rect */
- paint_rt.left = (data->xCur - data->xPos)*TILE_X;
- paint_rt.top = (data->yCur - data->yPos)*TILE_Y;
- paint_rt.right = paint_rt.left + TILE_X;
- paint_rt.bottom = paint_rt.top + TILE_Y;
- DrawFocusRect(hDC, &paint_rt);
+ nhcoord2display(data, data->xCur, data->yCur, &paint_rt);
+ if( data->bAsciiMode ) {
+ PatBlt( hDC,
+ paint_rt.left, paint_rt.top,
+ paint_rt.right-paint_rt.left, paint_rt.bottom-paint_rt.top,
+ DSTINVERT );
+ } else {
+ DrawFocusRect(hDC, &paint_rt);
+ }
}
EndPaint(hWnd, &ps);
}
+/* on WM_VSCROLL */
void onMSNH_VScroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PNHMapWindow data;
- SCROLLINFO si;
+ SCROLLINFO si;
int yNewPos;
int yDelta;
/* get window data */
data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA);
-
- /* get page size */
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE;
- GetScrollInfo(hWnd, SB_VERT, &si);
switch(LOWORD (wParam))
{
/* User clicked shaft left of the scroll box. */
case SB_PAGEUP:
- yNewPos = data->yPos-si.nPage;
+ yNewPos = data->yPos-data->yPageSize;
break;
/* User clicked shaft right of the scroll box. */
case SB_PAGEDOWN:
- yNewPos = data->yPos+si.nPage;
+ yNewPos = data->yPos+data->yPageSize;
break;
/* User clicked the left arrow. */
}
yNewPos = max(0, yNewPos);
- yNewPos = min(ROWNO, yNewPos);
+ yNewPos = min(ROWNO-data->yPageSize+1, yNewPos);
if( yNewPos == data->yPos ) return;
yDelta = yNewPos - data->yPos;
data->yPos = yNewPos;
- ScrollWindowEx (hWnd, 0, -TILE_Y * yDelta,
+ ScrollWindowEx (hWnd, 0, -data->yScrTile * yDelta,
(CONST RECT *) NULL, (CONST RECT *) NULL,
(HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE | SW_ERASE);
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
}
+/* on WM_HSCROLL */
void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PNHMapWindow data;
- SCROLLINFO si;
+ SCROLLINFO si;
int xNewPos;
int xDelta;
/* get window data */
data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA);
- /* get page size */
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE;
- GetScrollInfo(hWnd, SB_HORZ, &si);
-
switch(LOWORD (wParam))
{
/* User clicked shaft left of the scroll box. */
case SB_PAGEUP:
- xNewPos = data->xPos-si.nPage;
+ xNewPos = data->xPos-data->xPageSize;
break;
/* User clicked shaft right of the scroll box. */
case SB_PAGEDOWN:
- xNewPos = data->xPos+si.nPage;
+ xNewPos = data->xPos+data->xPageSize;
break;
/* User clicked the left arrow. */
}
xNewPos = max(0, xNewPos);
- xNewPos = min(COLNO, xNewPos);
+ xNewPos = min(COLNO-data->xPageSize+1, xNewPos);
if( xNewPos == data->xPos ) return;
xDelta = xNewPos - data->xPos;
data->xPos = xNewPos;
- ScrollWindowEx (hWnd, -TILE_X * xDelta, 0,
+ ScrollWindowEx (hWnd, -data->xScrTile * xDelta, 0,
(CONST RECT *) NULL, (CONST RECT *) NULL,
(HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE | SW_ERASE);
SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
}
+/* map nethack map coordinates to the screen location */
+void nhcoord2display(PNHMapWindow data, int x, int y, LPRECT lpOut)
+{
+ lpOut->left = (x - data->xPos)*data->xScrTile + data->map_orig.x;
+ lpOut->top = (y - data->yPos)*data->yScrTile + data->map_orig.y;
+ lpOut->right = lpOut->left + data->xScrTile;
+ lpOut->bottom = lpOut->top + data->yScrTile;
+}
+
+/* map glyph to character/color combination */
+void nhglyph2charcolor(short g, uchar* ch, int* color)
+{
+ int offset;
#ifdef TEXTCOLOR
-static
+
+#define zap_color(n) *color = iflags.use_color ? zapcolors[n] : NO_COLOR
+#define cmap_color(n) *color = iflags.use_color ? defsyms[n].color : NO_COLOR
+#define obj_color(n) *color = iflags.use_color ? objects[n].oc_color : NO_COLOR
+#define mon_color(n) *color = iflags.use_color ? mons[n].mcolor : NO_COLOR
+#define pet_color(n) *color = iflags.use_color ? mons[n].mcolor : NO_COLOR
+#define warn_color(n) *color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR
+
+# else /* no text color */
+
+#define zap_color(n)
+#define cmap_color(n)
+#define obj_color(n)
+#define mon_color(n)
+#define pet_color(c)
+#define warn_color(c)
+ *color = CLR_WHITE;
+#endif
+
+ if ((offset = (g - GLYPH_WARNING_OFF)) >= 0) { /* a warning flash */
+ *ch = warnsyms[offset];
+ warn_color(offset);
+ } else if ((offset = (g - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */
+ /* see swallow_to_glyph() in display.c */
+ *ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)];
+ mon_color(offset >> 3);
+ } else if ((offset = (g - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */
+ /* see zapdir_to_glyph() in display.c */
+ *ch = showsyms[S_vbeam + (offset & 0x3)];
+ zap_color((offset >> 2));
+ } else if ((offset = (g - GLYPH_CMAP_OFF)) >= 0) { /* cmap */
+ *ch = showsyms[offset];
+ cmap_color(offset);
+ } else if ((offset = (g - GLYPH_OBJ_OFF)) >= 0) { /* object */
+ *ch = oc_syms[(int)objects[offset].oc_class];
+ obj_color(offset);
+ } else if ((offset = (g - GLYPH_BODY_OFF)) >= 0) { /* a corpse */
+ *ch = oc_syms[(int)objects[CORPSE].oc_class];
+ mon_color(offset);
+ } else if ((offset = (g - GLYPH_PET_OFF)) >= 0) { /* a pet */
+ *ch = monsyms[(int)mons[offset].mlet];
+ pet_color(offset);
+ } else { /* a monster */
+ *ch = monsyms[(int)mons[g].mlet];
+ mon_color(g);
+ }
+ // end of wintty code
+}
+
+/* map nethack color to RGB */
COLORREF nhcolor_to_RGB(int c)
{
switch(c) {
default: return RGB( 0, 0, 0); /* black */
}
}
-#endif
#include "mhmsg.h"
#include "mhfont.h"
+#define MSG_WRAP_TEXT
#define MSG_VISIBLE_LINES 4
#define MAX_MSG_LINES 32
int yPos; /* current vertical scrolling position */
int xMax; /* maximum horizontal scrolling position */
int yMax; /* maximum vertical scrolling position */
+ int xPage; /* page size of horizontal scroll bar */
} NHMessageWindow, *PNHMessageWindow;
static TCHAR szMessageWindowClass[] = TEXT("MSNHMessageWndClass");
-LRESULT CALLBACK MessageWndProc(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK NHMessageWndProc(HWND, UINT, WPARAM, LPARAM);
static void register_message_window_class();
static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
static void onMSNH_VScroll(HWND hWnd, WPARAM wParam, LPARAM lParam);
+#ifndef MSG_WRAP_TEXT
static void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam);
+#endif
static void onPaint(HWND hWnd);
static void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
static HDC prepareDC( HDC hdc );
HWND mswin_init_message_window () {
static int run_once = 0;
HWND ret;
+ DWORD style;
if( !run_once ) {
register_message_window_class( );
run_once = 1;
}
-
+
+#ifdef MSG_WRAP_TEXT
+ style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL;
+#else
+ style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL;
+#endif
+
ret = CreateWindow(
szMessageWindowClass, /* registered class name */
NULL, /* window name */
- WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL, /* window style */
+ style, /* window style */
0, /* horizontal position of window */
0, /* vertical position of window */
0, /* window width */
ZeroMemory( &wcex, sizeof(wcex));
wcex.style = CS_NOCLOSE;
- wcex.lpfnWndProc = (WNDPROC)MessageWndProc;
+ wcex.lpfnWndProc = (WNDPROC)NHMessageWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = GetNHApp()->hApp;
RegisterClass(&wcex);
}
-LRESULT CALLBACK MessageWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+LRESULT CALLBACK NHMessageWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
SetFocus(GetNHApp()->hMainWnd);
break;
+#ifndef MSG_WRAP_TEXT
case WM_HSCROLL:
onMSNH_HScroll(hWnd, wParam, lParam);
break;
+#endif
case WM_VSCROLL:
onMSNH_VScroll(hWnd, wParam, lParam);
xNewSize = LOWORD(lParam);
yNewSize = HIWORD(lParam);
- data->xMax = max(0, (int)(1 + data->max_text - xNewSize/data->xChar));
- data->xPos = min(data->xPos, data->xMax);
-
- si.cbSize = sizeof(si);
- si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
- si.nMin = 0;
- si.nMax = data->max_text;
- si.nPage = xNewSize/data->xChar;
- si.nPos = data->xPos;
- SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
+ if( xNewSize>0 || yNewSize>0 ) {
+
+#ifndef MSG_WRAP_TEXT
+ data->xPage = xNewSize/data->xChar;
+ data->xMax = max(0, (int)(1 + data->max_text - data->xPage));
+ data->xPos = min(data->xPos, data->xMax);
+
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMin = 0;
+ si.nMax = data->max_text;
+ si.nPage = data->xPage;
+ si.nPos = data->xPos;
+ SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
+#endif
- data->yMax = MSG_LINES - MSG_VISIBLE_LINES + 1;
- data->yPos = min(data->yPos, data->yMax);
-
- si.cbSize = sizeof(si);
- si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
- si.nMin = 0;
- si.nMax = MSG_LINES;
- si.nPage = MSG_VISIBLE_LINES;
- si.nPos = data->yPos;
- SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
+ data->yMax = MSG_LINES - MSG_VISIBLE_LINES - 1;
+ data->yPos = min(data->yPos, data->yMax);
+
+ ZeroMemory(&si, sizeof(si));
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMin = 0;
+ si.nMax = MSG_LINES;
+ si.nPage = MSG_VISIBLE_LINES;
+ si.nPos = data->yPos;
+ SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
+ }
}
break;
{
PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr)lParam;
SCROLLINFO si;
- int i;
+ /* append text to the end of the array */
memmove(&data->window_text[0],
&data->window_text[1],
(MSG_LINES-1)*sizeof(data->window_text[0]));
data->window_text[MSG_LINES-1].attr = msg_data->attr;
strncpy(data->window_text[MSG_LINES-1].text, msg_data->text, MAXWINDOWTEXT);
+ /* reset V-scroll position to display new text */
data->yPos = data->yMax;
+
+ ZeroMemory(&si, sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = data->yPos;
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
- data->max_text = 0;
- for( i=0; i<MSG_LINES; i++ )
- if( data->max_text < strlen(data->window_text[i].text) )
- data->max_text = strlen(data->window_text[i].text);
-
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE;
- GetScrollInfo(hWnd, SB_HORZ, &si);
-
- data->xMax = max(0, (int)(1 + data->max_text - si.nPage) );
- data->xPos = min(data->xPos, data->xMax);
- si.cbSize = sizeof(si);
- si.fMask = SIF_POS | SIF_RANGE;
- si.nMin = 0;
- si.nMax = data->max_text;
- si.nPos = data->xPos;
- SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
-
+ /* update window content */
InvalidateRect(hWnd, NULL, TRUE);
}
break;
case MSNH_MSG_CLEAR_WINDOW:
{
- // do nothing
+ InvalidateRect(hWnd, NULL, TRUE);
break;
}
}
/* get window data */
data = (PNHMessageWindow)GetWindowLong(hWnd, GWL_USERDATA);
+ ZeroMemory(&si, sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_POS;
GetScrollInfo(hWnd, SB_VERT, &si);
*/
InvalidateRect(hWnd, NULL, TRUE);
+ ZeroMemory(&si, sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = data->yPos;
}
}
+#ifndef MSG_WRAP_TEXT
void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PNHMessageWindow data;
/* get window data */
data = (PNHMessageWindow)GetWindowLong(hWnd, GWL_USERDATA);
+ ZeroMemory(&si, sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE;
GetScrollInfo(hWnd, SB_HORZ, &si);
ScrollWindowEx (hWnd, -data->xChar * xInc, 0,
(CONST RECT *) NULL, (CONST RECT *) NULL,
(HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE | SW_ERASE);
+
+ ZeroMemory(&si, sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = data->xPos;
UpdateWindow (hWnd);
}
}
+#endif // MSG_WRAP_TEXT
void onPaint(HWND hWnd)
{
int FirstLine, LastLine;
int i, x, y;
HGDIOBJ oldFont;
- char draw_buf[MAXWINDOWTEXT+2];
TCHAR wbuf[MAXWINDOWTEXT+2];
+ size_t wlen;
hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &client_rt);
- FirstLine = max (0, data->yPos + ps.rcPaint.top/data->yChar - 1);
- LastLine = min (MSG_LINES, data->yPos + ps.rcPaint.bottom/data->yChar);
- for (i=FirstLine; i<LastLine; i++) {
- if( i==MSG_LINES-1 ) {
- x = data->xChar * (-data->xPos);
-
- SetRect( &draw_rt,
- client_rt.left, client_rt.bottom - data->yChar - 4, client_rt.right, client_rt.bottom );
- DrawEdge(hdc, &draw_rt, EDGE_SUNKEN, BF_TOP | BF_ADJUST);
- DrawEdge(hdc, &draw_rt, EDGE_SUNKEN, BF_BOTTOM | BF_ADJUST);
-
- draw_rt.left = x;
- draw_rt.right = client_rt.right - x;
-
- strcpy( draw_buf, "> " );
- strcat( draw_buf, data->window_text[i].text );
- } else {
- y = client_rt.bottom - data->yChar * (LastLine - i) - 4;
- x = data->xChar * (4 - data->xPos);
-
- SetRect( &draw_rt,
- x, y, max(client_rt.right, client_rt.right-x), y+data->yChar );
-
- strcpy( draw_buf, data->window_text[i].text );
- }
-
- if( strlen(draw_buf)>0 ) {
- oldFont = SelectObject(hdc, mswin_create_font(NHW_MESSAGE, data->window_text[i].attr, hdc));
- DrawText(hdc, NH_A2W(draw_buf, wbuf, sizeof(wbuf)), strlen(draw_buf), &draw_rt, DT_VCENTER | DT_NOPREFIX);
- mswin_destroy_font(SelectObject(hdc, oldFont));
+ if( !IsRectEmpty(&ps.rcPaint) ) {
+ FirstLine = max (0, data->yPos + ps.rcPaint.top/data->yChar - 1);
+ LastLine = min (MSG_LINES-1, data->yPos + ps.rcPaint.bottom/data->yChar);
+ y = min( ps.rcPaint.bottom, client_rt.bottom - 2);
+ for (i=LastLine; i>=FirstLine; i--) {
+ if( i==MSG_LINES-1 ) {
+ x = data->xChar * (2 - data->xPos);
+ } else {
+ x = data->xChar * (4 - data->xPos);
+ }
+
+
+ if( strlen(data->window_text[i].text)>0 ) {
+ /* convert to UNICODE */
+ NH_A2W(data->window_text[i].text, wbuf, sizeof(wbuf));
+ wlen = _tcslen(wbuf);
+
+ /* calculate text height */
+ draw_rt.left = x;
+ draw_rt.right = client_rt.right;
+ draw_rt.top = y - data->yChar;
+ draw_rt.bottom = y;
+
+ oldFont = SelectObject(hdc, mswin_create_font(NHW_MESSAGE, data->window_text[i].attr, hdc));
+
+#ifdef MSG_WRAP_TEXT
+ DrawText(hdc, wbuf, wlen, &draw_rt, DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT);
+ draw_rt.top = y - (draw_rt.bottom - draw_rt.top);
+ draw_rt.bottom = y;
+ DrawText(hdc, wbuf, wlen, &draw_rt, DT_NOPREFIX | DT_WORDBREAK);
+#else
+ DrawText(hdc, wbuf, wlen, &draw_rt, DT_NOPREFIX );
+#endif
+ mswin_destroy_font(SelectObject(hdc, oldFont));
+
+ y -= draw_rt.bottom - draw_rt.top;
+ } else {
+ y -= data->yChar;
+ }
+
+ /* highligh the last line */
+ if( i==MSG_LINES-1 ) {
+ draw_rt.left = client_rt.left;
+ draw_rt.right = draw_rt.left + 2*data->xChar;
+ DrawText(hdc, TEXT("> "), 2, &draw_rt, DT_NOPREFIX );
+
+ y -= 2;
+ draw_rt.left = client_rt.left;
+ draw_rt.right = client_rt.right;
+ draw_rt.top -= 2;
+ draw_rt.bottom = client_rt.bottom;
+ DrawEdge(hdc, &draw_rt, EDGE_SUNKEN, BF_TOP | BF_ADJUST);
+ DrawEdge(hdc, &draw_rt, EDGE_SUNKEN, BF_BOTTOM | BF_ADJUST);
+ }
}
}
+
EndPaint(hWnd, &ps);
}
/* Get the handle to the client area's device context. */
hdc = prepareDC( GetDC(hWnd) );
- saveFont = SelectObject(hdc, mswin_create_font(NHW_STATUS, ATR_NONE, hdc));
+ saveFont = SelectObject(hdc, mswin_create_font(NHW_MESSAGE, ATR_NONE, hdc));
/* Extract font dimensions from the text metrics. */
GetTextMetrics (hdc, &tm);
data->xChar = tm.tmAveCharWidth;
data->xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * data->xChar/2;
data->yChar = tm.tmHeight + tm.tmExternalLeading;
+ data->xPage = 1;
/* Free the device context. */
mswin_destroy_font(SelectObject(hdc, saveFont));
void mswin_message_window_size (HWND hWnd, LPSIZE sz)
{
PNHMessageWindow data;
- RECT rt;
+ RECT rt, client_rt;
GetWindowRect(hWnd, &rt);
data = (PNHMessageWindow)GetWindowLong(hWnd, GWL_USERDATA);
if(data) {
- sz->cy = data->yChar * MSG_VISIBLE_LINES + 4;
+ /* set size to accomodate MSG_VISIBLE_LINES, highligh rectangle and
+ horizontal scroll bar (difference between window rect and client rect */
+ GetClientRect(hWnd, &client_rt);
+ sz->cy = sz->cy-(client_rt.bottom - client_rt.top) +
+ data->yChar * MSG_VISIBLE_LINES + 4;
}
}
\ No newline at end of file