/*
 * w_stat.c : Status window related routines(NHW_STATUS)
 *
 * Copyright (c) Yukihiko Aoki 1999, 2005
 * NetHack may be freely redistributed.  See license for details.
 *
 */

#include "hack.h"

#ifdef NH2K_EXTENDS

#include "win32api.h"
#include "w_main.h"
#include "res/resource.h"
#include "w_dibtile.h"

/*
 * Display mode
 */
#define STAT_MODE_ORIGINAL      (0x00)
#define STAT_MODE_ADVANCED      (0x01)

/*
 * Status window property
 */
typedef struct tagWINSTATPROP {
    unsigned char mode;
    unsigned char show_top;
    unsigned char show_detail;
    unsigned char show_bar;
}WINSTATPROP;

/*
 * Status item
 */
typedef struct tagSTATITEM {
    char *name;                         /* Name */
    int value;                          /* Current value */
    int max;                            /* Max value (if exist) */
}STATITEM;

/*
 * Status window data
 */
typedef struct tagWINSTATINFO {
    char bot[2][BUFSZ];                 /* Original status line */
    char cname[BUFSZ];                  /* Advanced(?) status line */
    STATITEM hp;                        /* Hit point (current/max) */
    STATITEM pow;                       /* Magic power (current/max) */
    HWND icon_wnd;                      /* Icon window */
    HWND side_wnd;                      /* Side status window */
    OFFSCREEN   *ofb;                   /* Offscreen for icon_wnd */
    OFFSCREEN   *bgofb;
    FONTINFO    font;                   /* Font */
    WINSTATPROP property;               /* Property */
    BOOL init_flg;
}WINSTATINFO;

/*
 * External variables
 */
extern const char *hu_stat[];
extern const char *enc_stat[];
extern int g_childid;

/*
 * Local functions
 */
static void FDECL(StatWnd_setWindesc, (WINDESC *,int,void *));
static void FDECL(StatWnd_procCalcRect, (WINDESC *,RECT *,RECT *));
static void FDECL(StatWnd_procDestroy, (WINDESC *));
static void FDECL(StatWnd_procSetCursor, (WINDESC *,int,int));
static void FDECL(StatWnd_procPutStr, (WINDESC *,int,const char *));
static void FDECL(StatWnd_procDraw, (WINDESC *wd, HDC hdc));
static BOOL FDECL(StatWnd_OnCreate, (HWND, LPCREATESTRUCT));
static void FDECL(StatWnd_defaultProperty, (void *));
static int  FDECL(_drawGold, (int, int, int, OFFSCREEN *,TILELIST *));
static void FDECL(_drawIcons, (WINDESC *, HDC));
static void FDECL(_drawAbility, (WINDESC *, HDC));
static void FDECL(_updateSubWnd, (HWND, WINSTATINFO *));
static void FDECL(_drawBar, (HDC,FONTINFO*,RECT*,STATITEM*,COLORREF));

/***************************************************************************************/
/* Initialize
/***************************************************************************************/
BOOL StatWnd_init(WINDESC *wd, int type)
{
    WINSTATINFO *wsi;
    RECT rc;

    wsi = (WINSTATINFO*)calloc(1, sizeof(WINSTATINFO));
    if(wsi) {
        /* Load window settings */
        NHWnd_loadProperty(
            "StatWnd", &wsi->property, sizeof(WINSTATPROP), StatWnd_defaultProperty);

        /* Load font settings */
        Font_load(&wsi->font, g_propFile, "StatWnd");

        /* create offscreen for bottom_wnd */
        GetWindowRect(GetDesktopWindow(), &rc);
        wsi->ofb = Offscreen_create(
            rc.right - rc.left,
            g_resource->max_height,
            g_resource->gld_h->hpal);
        if (g_resource->wal_bmp) {
            wsi->bgofb = Offscreen_create(
                g_resource->wal_bmp->width,
                g_resource->wal_bmp->height,
                g_resource->wal_bmp->hpal);
            Offscreen_blt(
                    wsi->bgofb,
                    0,
                    0,
                    g_resource->wal_bmp->width,
                    g_resource->wal_bmp->height,
                    g_resource->wal_bmp->tiles,
                    0,
                    0,
                    BLTMODE_COPY);
        }
/*
        wsi->ofb = Offscreen_create(
            STB_GOLD_WIDTH * g_resource->gld_bmp->numtiles +
            STB_HUN_WIDTH +
            STB_ENC_WIDTH +
            STB_STAT_WIDTH * g_resource->stt_bmp->numtiles,
            STB_HEIGHT, g_resource->gld_bmp->hpal);
*/
        Offscreen_clear(wsi->ofb);

        StatWnd_setWindesc(wd, type, (void*)wsi);

        return TRUE;
    }
    return FALSE;
}

/*-------------------------------------------------------------------------------------
 * Fill WINDESC structure
 *-------------------------------------------------------------------------------------*/
static void StatWnd_setWindesc(WINDESC *wd, int type, void *pinfo)
{
    wd->exstyle        = 0;
    wd->style          = WS_CHILD|WS_CLIPSIBLINGS;
    wd->can_show       = TRUE;
    wd->create_at_init = TRUE;
    wd->draw_memory    = TRUE;
    wd->cname          = "NHSTAT";
    wd->wname          = NULL;
    wd->hwnd           = NULL;
    wd->type           = type;
    wd->cur.x          = -1;
    wd->cur.y          = -1;
    wd->more           = FALSE;
    wd->pinfo          = pinfo;

    wd->procCalcRect   = StatWnd_procCalcRect;
    wd->procDisplay    = NHWnd_display;
    wd->procPutStr     = StatWnd_procPutStr;
    wd->procDestroy    = StatWnd_procDestroy;
    wd->procClear      = NULL;
    wd->procSetCursor  = StatWnd_procSetCursor;
    wd->procDraw       = StatWnd_procDraw;
}

/***************************************************************************************/
/* status window procedure
/***************************************************************************************/
LRESULT CALLBACK StatWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg) {
        HANDLE_MSG(hWnd, WM_NCCREATE,   NHWnd_OnCreate);
        HANDLE_MSG(hWnd, WM_ERASEBKGND, NHWnd_OnEraseBkgnd);
        HANDLE_MSG(hWnd, WM_PAINT,      NHWnd_OnPaint);
        HANDLE_MSG(hWnd, WM_CREATE,     StatWnd_OnCreate);
    default:
        return DefWindowProc(hWnd,Msg,wParam,lParam);
    }
}

/*-------------------------------------------------------------------------------------
 * WM_CREATE
 *-------------------------------------------------------------------------------------*/
static BOOL StatWnd_OnCreate(HWND hwnd, LPCREATESTRUCT lpCS)
{
    WINDESC     *wd = GETWINDESC(hwnd);
    WINSTATINFO *wsi = (WINSTATINFO *)wd->pinfo;

    /* Create sub windows */
    wsi->icon_wnd = CreateWindowEx(
        0,"NHSUBSTAT","",WS_CHILD|WS_CLIPSIBLINGS,0,0,CW_USEDEFAULT,CW_USEDEFAULT,
        g_baseHwnd,(HMENU)2000,g_hInstance,(LPVOID)wsi);
    wsi->side_wnd = CreateWindowEx(
        0,"NHSUBSTAT","",WS_CHILD|WS_CLIPSIBLINGS,0,0,CW_USEDEFAULT,CW_USEDEFAULT,
        g_baseHwnd,(HMENU)2001,g_hInstance,(LPVOID)wsi);

    /* Show windows */
    if(wsi->property.mode == STAT_MODE_ADVANCED) {
        ShowWindow(wsi->icon_wnd, SW_SHOW);
        if(wsi->property.show_detail) {
            ShowWindow(wsi->side_wnd, SW_SHOW);
        }
    }

    return TRUE;
}

/*-------------------------------------------------------------------------------------
 * Update main status window
 *-------------------------------------------------------------------------------------*/
static void StatWnd_procDraw(WINDESC *wd, HDC hdc)
{
    WINSTATINFO *wsi = (WINSTATINFO*)wd->pinfo;
    RECT        rc;
    HFONT       oldFont;
    int         height;
    char        buf[BUFSZ];

    /* Fill background */
    GetClientRect(wd->hwnd, &rc);
    if (IsRectEmpty(&rc)) {
        return;
    }

    if (g_resource->wal_bmp) {
        NHWnd_drawWall2(hdc, &rc, wsi->bgofb->hbmp);
    }

    rc.left += 6;
    rc.right -= 6;

    if(!wsi->init_flg) {
        return;
    }

    /* Device context settings */
    oldFont = SelectObject(hdc, wsi->font.font_handle);

    height = Font_height(&wsi->font, hdc);
    if(wsi->property.mode == STAT_MODE_ORIGINAL) {
        rc.top += 3;

        /* First line */
        rc.bottom = rc.top + height;
        NHWnd_drawShadeText(hdc, &rc, wsi->bot[0], colormap[CLR_WHITE], 0);

        /* Second line */
        rc.top = rc.bottom;
        rc.bottom = rc.top + height;
        NHWnd_drawShadeText(hdc, &rc, wsi->bot[1], colormap[CLR_WHITE], 0);

    } else {

        /* Top line */
        rc.top += 3;
        rc.bottom = rc.top + height;
        NHWnd_drawShadeText(hdc, &rc, wsi->cname, colormap[CLR_WHITE], 0);

        sprintf(buf, "%s地下%d階", 
            jtrns_obj('d', dungeons[u.uz.dnum].dname), dunlev(&u.uz));
        NHWnd_drawShadeText(hdc, &rc, buf, colormap[CLR_WHITE], DT_RIGHT);

        if(wsi->property.show_bar == FLAG_ON) {
            rc.bottom += 3;

            /* Middle line */
            rc.top = rc.bottom;
            rc.bottom = rc.top + height;
            _drawBar(hdc, &wsi->font, &rc, &wsi->hp, colormap[CLR_BRIGHT_CYAN]);

            /* Bottom line */
            rc.top = rc.bottom;
            rc.bottom = rc.top + height;
            _drawBar(hdc, &wsi->font, &rc, &wsi->pow, colormap[CLR_BRIGHT_GREEN]);
        }

    }

    /* Restore settings */
    SelectObject(hdc, oldFont);
}

/*-------------------------------------------------------------------------------------
 * Caluculate window size
 *-------------------------------------------------------------------------------------*/
static void StatWnd_procCalcRect(WINDESC *wd, RECT *rcParent, RECT *rcChild)
{
    WINSTATINFO *wsi = (WINSTATINFO*)wd->pinfo;
    int height ,width;
    HDC hdc; /* for font size */

    /* Check main window height */
    hdc = GetDC(wd->hwnd);
    width = Font_width(&wsi->font, hdc);
    height = Font_height(&wsi->font, hdc);
    ReleaseDC(wd->hwnd, hdc);

    if(wsi->property.mode == STAT_MODE_ORIGINAL) {
        height = height * 2;
    }else if(wsi->property.show_bar) {
        height = height * 3 + 3;
    }
    height += 6;

    /* For icon window */
    if(wsi->property.mode == STAT_MODE_ADVANCED) {
        MoveWindow(wsi->icon_wnd, 
            rcParent->left,
            rcParent->bottom - g_resource->max_height,
            rcParent->right - rcParent->left,
            g_resource->max_height,
            TRUE);
        rcParent->bottom -= g_resource->max_height;
    }

    /* For main window */
    CopyRect(rcChild, rcParent);
    if(wsi->property.show_top) {
        rcChild->bottom = rcChild->top + height;
        rcParent->top += height;
    } else {
        rcChild->top = rcChild->bottom - height;
        rcParent->bottom -= height;
    }

    /* For side window */
    if(wsi->property.mode == STAT_MODE_ADVANCED
        && wsi->property.show_detail) {
        MoveWindow(wsi->side_wnd,
            rcParent->left,
            rcParent->top,
            width * 11 + 12,
            rcParent->bottom - rcParent->top, TRUE);
        rcParent->left += width * 11 + 12;
    }
}

/*-------------------------------------------------------------------------------------
 * this function will called after bot()
 *-------------------------------------------------------------------------------------*/
static void StatWnd_procPutStr(WINDESC *wd, int attr, const char *str)
{
    WINSTATINFO *wsi = (WINSTATINFO *)wd->pinfo;
    char buf[BUFSZ];
    int tmp1, tmp2;
    BOOL need_redraw = FALSE;

    wsi->init_flg = TRUE;

    if(str && strcmp(wsi->bot[wd->cur.y], str) != 0) {
        strcpy(wsi->bot[wd->cur.y], str);
        need_redraw = TRUE;
    }
    
    /* set new hit point */
    tmp1 = Upolyd ? u.mh : u.uhp;
    tmp2 = Upolyd ? u.mhmax : u.uhpmax;
    if(wsi->hp.value != tmp1 || wsi->hp.max != tmp2) {
        wsi->hp.name = "体力:";
        wsi->hp.value = tmp1;
        wsi->hp.max = tmp2;
    }
    /* set new power */
    if(wsi->pow.value != u.uen || wsi->pow.max != u.uenmax) {
        wsi->pow.name = "魔力:";
        wsi->pow.value = u.uen;
        wsi->pow.max = u.uenmax;
    }
    /* set player name */
    sprintf(buf, "%s-%s %s %s%u",
        plname, 
        Upolyd ? jtrns_mon_gen(mons[u.umonnum].mname, flags.female)
            : rank_of(u.ulevel, Role_switch, flags.female),
        align_str(u.ualign.type),
        Upolyd ? "HD:" : "Lev:",
        Upolyd ? mons[u.umonnum].mlevel : u.ulevel);
    if(flags.showexp) {
        sprintf(&buf[strlen(buf)], "/%-1ld", u.uexp);
    }
    if(!wsi->property.show_bar) {
        sprintf(&buf[strlen(buf)], " %s%d(%d) %s%d(%d)",
            wsi->hp.name, wsi->hp.value, wsi->hp.max,
            wsi->pow.name, wsi->pow.value, wsi->pow.max);
    }

    /* check player name */
    if(strcmp(buf, wsi->cname) != 0) {
        strcpy(wsi->cname, buf);
    }

    if(need_redraw) {
        InvalidateRect(wd->hwnd, NULL, FALSE);
        _updateSubWnd(wsi->icon_wnd, wsi);
        if(wsi->property.show_detail) {
            _updateSubWnd(wsi->side_wnd, wsi);
        }
    }
}

/*--------------------------------------------------------------------------------------
 * Destroy window
 *-------------------------------------------------------------------------------------*/
static void StatWnd_procDestroy(WINDESC* wd)
{
    WINSTATINFO *wsi = (WINSTATINFO *)wd->pinfo;

    if(wsi) {
        if(wsi->ofb) {
            Offscreen_free(wsi->ofb);
        }
        if(wsi->icon_wnd) {
            DestroyWindow(wsi->icon_wnd);
        }
        if(wsi->side_wnd) {
            DestroyWindow(wsi->side_wnd);
        }
        Font_delete(&wsi->font);
        free(wsi);
    }
}

/*-------------------------------------------------------------------------------------
 * Set Cursor position
 *-------------------------------------------------------------------------------------*/
static void StatWnd_procSetCursor(WINDESC *wd, int col, int row)
{
    wd->cur.x = col;
    wd->cur.y = row;
}

/*-------------------------------------------------------------------------------------
 * Draw bar graph
 *-------------------------------------------------------------------------------------*/
static void _drawBar(
    HDC hdc, FONTINFO *font, RECT *rc, STATITEM *item, COLORREF color)
{
    char        buf[BUFSZ];
    RECT        rcDraw;
    COLORREF    showColor;
    HBRUSH      oldBrs;
    HPEN        oldPen;
    HFONT       oldFont;
    int         cur;

    /* Device context settings */
    oldFont = SelectObject(hdc, font->font_handle);
    oldBrs = SelectObject(hdc, GetStockObject(WHITE_BRUSH));
    oldPen = SelectObject(hdc, GetStockObject(WHITE_PEN));

    /* Draw title */
    CopyRect(&rcDraw, rc);
    rcDraw.right = rcDraw.left + Font_width(font, hdc) * 15;
    NHWnd_drawShadeText(hdc, &rcDraw, item->name, colormap[CLR_WHITE], 0);

    /* Draw values */
    cur = (item->value >= 0) ? item->value : 0;
    showColor = (item->max / 5 > item->value) ? colormap[CLR_RED] : 
        (item->max / 3 > item->value) ? colormap[CLR_YELLOW] : color;
    sprintf(buf, "%d(%d)", cur, item->max);
    NHWnd_drawShadeText(hdc, &rcDraw, buf, showColor, DT_RIGHT);

    /* Fill frame */
    CopyRect(&rcDraw, rc);
    rcDraw.left = rcDraw.left + Font_width(font, hdc) * 16;
    RoundRect(hdc, 
        rcDraw.left,
        rcDraw.top + 2,
        rcDraw.left + item->max + 6,
        rcDraw.bottom - 2, 5, 5);

    /* Fill max value box */
    if(item->max > 0) {
        CopyRect(&rcDraw, rc);
        rcDraw.left   += Font_width(font, hdc) * 16 + 2;
        rcDraw.top    += 3;
        rcDraw.right  = rcDraw.left + item->max + 2;
        rcDraw.bottom -= 3;
        SetBkColor(hdc, colormap[CLR_BLACK]);
        ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, NULL);
    }

    /* Fill current value box */
    if(cur > 0) {
        CopyRect(&rcDraw, rc);
        rcDraw.left   += Font_width(font, hdc) * 16 + 3;
        rcDraw.top    += 4;
        rcDraw.right  = rcDraw.left + cur;
        rcDraw.bottom -= 4;
        SetBkColor(hdc, showColor);
        ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcDraw, NULL, 0, NULL);
    }

    /* Restore settings */
    SelectObject(hdc, oldBrs);
    SelectObject(hdc, oldPen);
    SelectObject(hdc, oldFont);
}
/*-------------------------------------------------------------------------------------
 * Draw gold count to offscreen buffer
 *-------------------------------------------------------------------------------------*/
static int _drawGold(int val, int offset, int y, OFFSCREEN *ofb, TILELIST *list)
{
    TILEDATA *tile;
    int pos;
    
    pos = offset;
    if((val / 10) > 0) {
        pos = _drawGold(val / 10, offset, y, ofb, list);
    }
    tile = &list->tiles[val % 10];
    Offscreen_blt(ofb, pos, y, tile->cx, tile->cy, tile, 0, 0, BLTMODE_MASK);

    return pos + list->width;
}

/*-------------------------------------------------------------------------------------
 * Update sub status window 
 *-------------------------------------------------------------------------------------*/
static void _drawIcons(WINDESC *wd, HDC hdc)
{
    WINSTATINFO *wsi = (WINSTATINFO *)wd->pinfo;
    int  i;
    int offset, x, ypos;
    BOOL ills[7];
    HDC dcMem;
    HBITMAP oldBmp;
    RECT rc;

    GetClientRect(wsi->icon_wnd, &rc);
    if (IsRectEmpty(&rc)) {
        return;
    }
/*
    if((rc.right - rc.left) > wsi->ofb->info->biWidth) {
        rc.left -= wsi->ofb->info->biWidth;
        FillRect(hdc, &rc, GetStockObject(BLACK_BRUSH));
    }
*/
    if(!wsi->init_flg) {
        return;
    }

    /* Check illness status */
    ills[0] = (Confusion);
    ills[1] = (Sick && (u.usick_type & SICK_VOMITABLE));
    ills[2] = (Sick && (u.usick_type & SICK_NONVOMITABLE));
    ills[3] = (Blind);
    ills[4] = (Stunned);
    ills[5] = (Hallucination);
    ills[6] = (Slimed);

    x = 6;
    Offscreen_clear(wsi->ofb);

    if (g_resource->wal_bmp != NULL) {
        NHWnd_drawWall(wsi->ofb, &rc, g_resource->wal_bmp->tiles);
    }

    /* Print gold symbol */
    ypos = ((rc.bottom - rc.top) - g_resource->gld_h->height) / 2;
    offset = g_resource->gld_h->width;
    Offscreen_blt(wsi->ofb, x, ypos, g_resource->gld_h->width, g_resource->gld_h->height,
        &g_resource->gld_h->tiles[0], 0, 0, BLTMODE_MASK);
    x += offset;

    /* Print gold value */
    x = _drawGold(u.ugold, x, ypos, wsi->ofb, g_resource->gld_n);

	if (g_resource->gld_f) {
		ypos = ((rc.bottom - rc.top) - g_resource->gld_f->height) / 2;
		offset = g_resource->gld_f->width;
		Offscreen_blt(wsi->ofb, x, ypos, g_resource->gld_f->width, g_resource->gld_f->height,
			&g_resource->gld_f->tiles[0], 0, 0, BLTMODE_MASK);
		x += offset;
	}

    /* Print hunger status */
    ypos = ((rc.bottom - rc.top) - g_resource->hun_bmp->height) / 2;
    Offscreen_blt(wsi->ofb, x, ypos, g_resource->hun_bmp->width, g_resource->hun_bmp->height,
        &g_resource->hun_bmp->tiles[u.uhs], 0, 0, BLTMODE_MASK);
    x += g_resource->hun_bmp->width;

    /* Print encumbered status */
    ypos = ((rc.bottom - rc.top) - g_resource->enc_bmp->height) / 2;
    Offscreen_blt(wsi->ofb, x, ypos, g_resource->enc_bmp->width, g_resource->enc_bmp->height,
        &g_resource->enc_bmp->tiles[near_capacity()], 0, 0, BLTMODE_MASK);
    x += g_resource->enc_bmp->width;

    /* Print special status */
    /*x = rc.right - rc.left;*/
    x += 6;
    offset = g_resource->stt_bmp->width;
    ypos = ((rc.bottom - rc.top) - g_resource->stt_bmp->height) / 2;
    for(i = 0; i < g_resource->stt_bmp->numtiles; i++) {
        if(ills[i]) {
            /*x -= offset;*/
            Offscreen_blt(
                wsi->ofb,
                x,
                ypos,
                g_resource->stt_bmp->width,
                g_resource->stt_bmp->height,
                &g_resource->stt_bmp->tiles[i],
                0,
                0,
                BLTMODE_MASK);
        }
        x += offset;
    }

    dcMem = CreateCompatibleDC(hdc);
    oldBmp = SelectObject(dcMem, wsi->ofb->hbmp);
    BitBlt(hdc, 0, 0, wsi->ofb->info->biWidth, wsi->ofb->info->biHeight, dcMem, 0, 0, SRCCOPY);
    SelectObject(dcMem, oldBmp);
    DeleteDC(dcMem);
}

/*-------------------------------------------------------------------------------------
 * Draw sub status window 
 *-------------------------------------------------------------------------------------*/
static void _drawAbility(WINDESC *wd, HDC hdc)
{
    WINSTATINFO *wsi = (WINSTATINFO *)wd->pinfo;
    char   buf[BUFSZ];
    char   str[20];
    RECT   rc;
    int    value;
    int    height, width;
    HFONT  oldFont;

    GetClientRect(wd->hwnd, &rc);
    if (IsRectEmpty(&rc)) {
        return;
    }

    if(!wsi->init_flg) {
        return;
    }

    if (g_resource->wal_bmp) {
        NHWnd_drawWall2(hdc, &rc, wsi->bgofb->hbmp);
    }

    oldFont = SelectObject(hdc, wsi->font.font_handle);
    width = Font_width(&wsi->font, hdc);
    height = Font_height(&wsi->font, hdc);

    value = ACURR(A_STR);
    if(value > 18) {
        if(value > 118) {
            sprintf(str, "%2d", value - 100);
        } else if(value < 118) {
            sprintf(str, "18/%02d", value - 18);
        } else {
            sprintf(str,"18/**");
        }
    } else {
        sprintf(str, "%-1d", value);
    }
    rc.left += 6;
    rc.right -= 6;
    sprintf(buf, "\n強さ:\n早さ:\n耐久:\n知力:\n賢さ:\n魅力:\n\n装備:");
#ifdef SCORE_ON_BOTL
    if(flags.showscore) {
        strcat(buf, "\n\n点:");
    }
#endif
    if(flags.time) {
        strcat(buf, "\n\n歩:");
    }
    NHWnd_drawShadeText(hdc, &rc, buf, colormap[CLR_WHITE], 0);

    sprintf(buf, "\n%s\n%d\n%d\n%d\n%d\n%d\n\n%d",
        str, ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS), ACURR(A_CHA), u.uac);
#ifdef SCORE_ON_BOTL
    if(flags.showscore) {
        sprintf(str, "\n\n%ld", botl_score());
        strcat(buf, str);
    }
#endif
    if(flags.time) {
        sprintf(str, "\n\n%d", moves);
        strcat(buf, str);
    }
    NHWnd_drawShadeText(hdc, &rc, buf, colormap[CLR_GRAY], DT_RIGHT);

    SelectObject(hdc, oldFont);
}

/*-------------------------------------------------------------------------------------
 * Update sub status window 
 *-------------------------------------------------------------------------------------*/
static void _updateSubWnd(HWND hwnd, WINSTATINFO *wsi)
{
    WINDESC wd;

    wd.hwnd = hwnd;
    wd.procDraw = (hwnd == wsi->side_wnd ? _drawAbility : _drawIcons);
    wd.pinfo = wsi;
    wd.more = FALSE;
    NHWnd_display(&wd);
}

/*-------------------------------------------------------------------------------------
 * status dialog window procedure
 *-------------------------------------------------------------------------------------*/
LRESULT CALLBACK SubStatProc(HWND hwnd, UINT mesg, UINT wParam, LONG lParam)
{
    switch(mesg) {
    case WM_CREATE:
        SetWindowLong(hwnd, GWL_USERDATA, (LONG)((LPCREATESTRUCT)lParam)->lpCreateParams);
        return 0;
    case WM_PAINT:
        ValidateRect(hwnd, NULL);
        _updateSubWnd(hwnd, (WINSTATINFO *)GetWindowLong(hwnd, GWL_USERDATA));
        return 0;
    case WM_ERASEBKGND:
        return FALSE;
    default:
        return DefWindowProc(hwnd,mesg,wParam,lParam);
    }
}

/*-------------------------------------------------------------------------------------
 * load settings from ini file 
 *-------------------------------------------------------------------------------------*/
static void StatWnd_defaultProperty(void *param)
{
    WINSTATPROP *property = (WINSTATPROP *)param;

    property->mode = STAT_MODE_ORIGINAL;
    property->show_top = FLAG_OFF;
    property->show_bar = FLAG_ON;
    property->show_detail = FLAG_ON;
}

/*-------------------------------------------------------------------------------------
 * Status window property dialog procedure
 *-------------------------------------------------------------------------------------*/
static BOOL CALLBACK StatPropProc(HWND hDlg, UINT mesg, UINT wParam, LONG lParam)
{
    static WINSTATPROP property;
    static FONTINFO    font;
    static WINSTATINFO *wsi;

    switch (mesg) {
    case WM_INITDIALOG:

        /* Set initial values */
        wsi = (WINSTATINFO *)lParam;
        CopyMemory(&property, &wsi->property, sizeof(WINSTATPROP));
        CopyMemory(&font, &wsi->font, sizeof(FONTINFO));
        CheckRadioButton(hDlg, RADIO_TOP, RADIO_BOTTOM, (property.show_top ? RADIO_TOP : RADIO_BOTTOM));
        CheckRadioButton(hDlg, RADIO_ORIGINAL, RADIO_ADVANCED, (property.mode == STAT_MODE_ORIGINAL ?
            RADIO_ORIGINAL : RADIO_ADVANCED));
        CheckDlgButton(hDlg, CHECK_DETAIL, (property.show_detail ? BST_CHECKED : BST_UNCHECKED));
        CheckDlgButton(hDlg, CHECK_BAR, (property.show_bar ? BST_CHECKED : BST_UNCHECKED));
        EnableWindow(GetDlgItem(hDlg, CHECK_DETAIL), (property.mode == STAT_MODE_ADVANCED));
        EnableWindow(GetDlgItem(hDlg, CHECK_BAR), (property.mode == STAT_MODE_ADVANCED));
        SendDlgItemMessage(hDlg, STATIC_FONT, WM_SETFONT, (WPARAM)font.font_handle, 0);
        break;

    case WM_CTLCOLORSTATIC:

        /* Set sample font color */
        if((HWND)lParam == GetDlgItem(hDlg, STATIC_FONT)) {
            SetTextColor((HDC)wParam, font.font_color);
            SetBkMode((HDC)wParam, TRANSPARENT);
            return (BOOL)GetStockObject(BLACK_BRUSH);
        } else {
            return DefWindowProc(hDlg, mesg, wParam, lParam);
        }
        break;

    case WM_COMMAND:
        switch (LOWORD(wParam)) {
        case IDOK:

            /* Save settings */
            property.mode = IsDlgButtonChecked(hDlg, RADIO_ORIGINAL) == BST_CHECKED 
                ? STAT_MODE_ORIGINAL : STAT_MODE_ADVANCED;
            property.show_top = IsDlgButtonChecked(hDlg, RADIO_TOP) == BST_CHECKED 
                ? FLAG_ON : FLAG_OFF;
            property.show_detail = IsDlgButtonChecked(hDlg, CHECK_DETAIL) == BST_CHECKED 
                ? FLAG_ON : FLAG_OFF;
            property.show_bar = IsDlgButtonChecked(hDlg, CHECK_BAR) == BST_CHECKED
                ? FLAG_ON : FLAG_OFF;
            CopyMemory(&wsi->property, &property, sizeof(WINSTATPROP));
            CopyMemory(&wsi->font, &font, sizeof(FONTINFO));
            EndDialog(hDlg, 1);
            break;

        case IDCANCEL:

            /* Dialog canceled */
            Font_delete(&font);
            Font_create(&wsi->font);
            EndDialog(hDlg, 0);
            break;

        case BUTTON_FONT:

            /* Show font dialog */
            Font_select(hDlg, &font, TRUE, FALSE, TRUE);
            SendDlgItemMessage(
                hDlg, STATIC_FONT, WM_SETFONT, (WPARAM)font.font_handle, MAKELPARAM(TRUE, 0));
            break;

        case BUTTON_RESET:

            /* Restore previous values */
            CopyMemory(&property, &wsi->property, sizeof(WINSTATPROP));

            Font_delete(&font);
            CopyMemory(&font, &wsi->font, sizeof(FONTINFO));
            Font_create(&font);
            CheckRadioButton(hDlg, RADIO_TOP, RADIO_BOTTOM, (property.show_top ? RADIO_TOP : RADIO_BOTTOM));
            CheckRadioButton(hDlg, RADIO_ORIGINAL, RADIO_ADVANCED, (property.mode == STAT_MODE_ORIGINAL ?
                RADIO_ORIGINAL : RADIO_ADVANCED));
            CheckDlgButton(hDlg, CHECK_DETAIL, (property.show_detail ? BST_CHECKED : BST_UNCHECKED));
            CheckDlgButton(hDlg, CHECK_BAR, (property.show_bar ? BST_CHECKED : BST_UNCHECKED));
            EnableWindow(GetDlgItem(hDlg, CHECK_DETAIL), (property.mode == STAT_MODE_ADVANCED));
            EnableWindow(GetDlgItem(hDlg, CHECK_BAR), (property.mode == STAT_MODE_ADVANCED));
            SendDlgItemMessage(
                hDlg, STATIC_FONT, WM_SETFONT, (WPARAM)font.font_handle, MAKELPARAM(TRUE, 0));
            break;

        case RADIO_ADVANCED:
        case RADIO_ORIGINAL:

            EnableWindow(GetDlgItem(hDlg, CHECK_DETAIL), IsDlgButtonChecked(hDlg, RADIO_ADVANCED));
            EnableWindow(GetDlgItem(hDlg, CHECK_BAR), IsDlgButtonChecked(hDlg, RADIO_ADVANCED));
            break;

        default:
            break;
        }
        break;
    default:
        return FALSE;
    }
    return TRUE;
}

/***************************************************************************************
 * Display property dialog
 ***************************************************************************************/
void StatWnd_cmdProperty(WINDESC *wd)
{
    WINSTATINFO *wsi;
    
    if(!NHWnd_isValid(wd)) {
        return;
    }
    
    wsi = (WINSTATINFO *)wd->pinfo;

    /* Property dialog open */
    if(DialogBoxParam(g_hInstance, "STAT_PROP", g_baseHwnd, StatPropProc, (LPARAM)wsi)) {

        /* "OK" button pressed */
        NHWnd_saveProperty("StatWnd", &wsi->property, sizeof(WINSTATPROP));
        Font_save(&wsi->font, g_propFile, "StatWnd");
        NHWnd_newLayout();
        StatWnd_procPutStr(wd,0,NULL);
        InvalidateRect(wd->hwnd, NULL, FALSE);
        if(wsi->property.mode == STAT_MODE_ADVANCED) {
            ShowWindow(wsi->icon_wnd, SW_SHOW); 
            if(wsi->property.show_detail) {
                ShowWindow(wsi->side_wnd, SW_SHOW); 
            }else {
                ShowWindow(wsi->side_wnd, SW_HIDE); 
            }
        }else {
            ShowWindow(wsi->icon_wnd, SW_HIDE);
            ShowWindow(wsi->side_wnd, SW_HIDE);
        }
        _updateSubWnd(wsi->icon_wnd, wsi);
        _updateSubWnd(wsi->side_wnd, wsi);
    }
}

/***************************************************************************************
 * Move Icon window to bottom
 * (I don't like this implement!)
 ***************************************************************************************/
void StatWnd_moveIconWindow(WINDESC *wd, RECT *rc)
{
    WINSTATINFO *wsi;
    
    if(!NHWnd_isValid(wd)) {
        return;
    }
    
    wsi = (WINSTATINFO *)wd->pinfo;

    if (wsi->property.mode == STAT_MODE_ADVANCED) {
        MoveWindow(
            wsi->icon_wnd,
            rc->left,
            rc->bottom - g_resource->max_height,
            rc->right - rc->left,
            g_resource->max_height,
            FALSE);
        rc->top -= g_resource->max_height;
        rc->bottom -= g_resource->max_height;
    }
}

#endif /* NH2K_EXTENDS */
