/*
 * w_base.c : Base window related routines
 *
 * 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"

/*
 * Base window property
 */
typedef struct tagWINBASEPROP{
    int x;  /* Horizontal window position */
    int y;  /* Vertical window position */
    int cx; /* Window width */
    int cy; /* Window height */
}WINBASEPROP;

/*
 * Local variables
 */
static WINBASEPROP property; 

const static struct {
    int menu_id;
    char cmd;
}menu_cmd[] = {
    { IDM_OPTION,       'O' },
    { IDM_AUTOPICKUP,   '@' },
    { IDM_ORIGINAL,     '`' },
    { IDM_DISCOVER,     'X' },
    { IDM_SAVEGAME,     'S' },
    { IDM_QUITGAME,     M('q') },
    { IDM_OPEN,         'o' },
    { IDM_CLOSE,        'c' },
    { IDM_FORCE,        M('f') },
    { IDM_LOOT,         M('l') },
    { IDM_KICK,         C('d') },
    { IDM_SEARCH,       's' },
    { IDM_ENGRAVE,      'E' },
    { IDM_SIT,          M('s') },
    { IDM_INV_ALL,      'i' },
    { IDM_VERSION,      'v' },
    { IDM_SYMBOL,       '/' },
    { IDM_UP,           '<' },
    { IDM_DOWN,         '>' },
    { IDM_REST,         '.' },
    { IDM_APPLY,        'a' },
    { IDM_TAKEOFF_SELECT,'A' },
    { IDM_TAKEOFF_ARMOR,'T' },
    { IDM_TAKEOFF_ACC,  'R' },
    { IDM_REDO,         C('A') },
    { IDM_MONNAME,      'C' },
    { IDM_DROP,         'd' },
    { IDM_DROP_SELECT,  'D' },
    { IDM_EAT,          'e' },
    { IDM_ENGRAVE,      'E' },
    { IDM_QUIVER,       'Q' },
/*
    { IDM_INV_GOLD,     '' } 
    { IDM_INV_UNPAID,   '' }
    { IDM_INV_USED,     '' }
*/
    { IDM_PAY,          'p' },
    { IDM_WEAR_RING,    'P' },
    { IDM_PREV,         C('p') },
    { IDM_QUAFF,        'q' },
    { IDM_READ,         'r' },
    { IDM_REDRAW,       C('r') },
    { IDM_THROW,        't' },
    { IDM_TELEPORT,     C('t') },
    { IDM_HISTORY,      'V' },
    { IDM_WEAR_WEAPON,   'w' },
    { IDM_TAKEOFF_WEAPON,'w' },
    { IDM_WEAR_ARMOR,   'W' },
    { IDM_SPELLLIST,    '+' },
    { IDM_ZAP,          'z' },
    { IDM_CASTSPELL,    'Z' },
    { IDM_FLOOR,        ';' },
    { IDM_PICKUP,       ',' },
    { IDM_AUTOPICKUP,   '@' },
    { IDM_CHECKTRAP,    '^' },
    { IDM_INV_WEAPON,   ')' },
    { IDM_INV_ARMOR,    '[' },
    { IDM_INV_RING,     '=' },
    { IDM_INV_AMULET,   '~' },
    { IDM_INV_TOOL,     '$' },
    { IDM_DISCOVERITEM, '\\' },
    { IDM_ADJUST,       M('a') },
    { IDM_CHAT,         M('c') },
    { IDM_DIP,          M('d') },
    { IDM_ENHANCE,      M('e') },
    { IDM_INVOKE,       M('i') },
    { IDM_JUMP,         M('j') },
    { IDM_MONSTER,      M('m') },
    { IDM_NAME,         M('n') },
    { IDM_OFFER,        M('o') },
    { IDM_PRAY,         M('p') },
    { IDM_RUB,          M('r') },
    { IDM_TURNUNDEAD,   M('t') },
    { IDM_UNTRAP,       M('u') },
    { IDM_COMPILEOPTION,M('v') },
    { IDM_WIPE,         M('w') },
    { IDM_NUMBER,       'n' },
    { IDM_HELP,         '?' },
    { IDM_CMD_CANCEL,   C('[') },
    { IDM_FIRE,         'f' },
    { 0, 0 }
};

/*
 * Local functions
 */
static void FDECL(BaseWnd_OnGetMinMaxInfo,(HWND,LPMINMAXINFO));
static void FDECL(BaseWnd_OnSize,(HWND,UINT,int,int));
static void FDECL(BaseWnd_OnMove,(HWND,int,int));
static void FDECL(BaseWnd_OnDestroy,(HWND));
static void FDECL(BaseWnd_OnClose,(HWND));
static void FDECL(BaseWnd_OnCommand,(HWND,int,HWND,UINT));
static void FDECL(BaseWnd_defaultProperty,(void *));
static void FDECL(BaseWnd_OnPaletteChanged,(HWND,HWND));
static BOOL FDECL(BaseWnd_OnQueryNewPalette,(HWND));
static void FDECL(BaseWnd_OnInitMenuPopup, (HWND,HMENU,UINT,BOOL));

/***************************************************************************************
 * main game window procedure
 ***************************************************************************************/
LRESULT CALLBACK BaseWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch (Msg) {
        HANDLE_MSG(hWnd, WM_KEYDOWN,         NHWnd_OnKey);
        HANDLE_MSG(hWnd, WM_CHAR,            NHWnd_OnChar);
        HANDLE_MSG(hWnd, WM_SYSKEYDOWN,      NHWnd_OnSysKey);
        HANDLE_MSG(hWnd, WM_GETMINMAXINFO,   BaseWnd_OnGetMinMaxInfo);
        HANDLE_MSG(hWnd, WM_SIZE,            BaseWnd_OnSize);
        HANDLE_MSG(hWnd, WM_DESTROY,         BaseWnd_OnDestroy);
        HANDLE_MSG(hWnd, WM_CLOSE,           BaseWnd_OnClose);
        HANDLE_MSG(hWnd, WM_COMMAND,         BaseWnd_OnCommand);
        HANDLE_MSG(hWnd, WM_PALETTECHANGED,  BaseWnd_OnPaletteChanged);
        HANDLE_MSG(hWnd, WM_QUERYNEWPALETTE, BaseWnd_OnQueryNewPalette);
        HANDLE_MSG(hWnd, WM_MOVE,            BaseWnd_OnMove);
        HANDLE_MSG(hWnd, WM_INITMENUPOPUP,   BaseWnd_OnInitMenuPopup);
    default:
        return DefWindowProc(hWnd,Msg,wParam,lParam);
    }
}

/***************************************************************************************
 * create base window
 ***************************************************************************************/
HWND BaseWnd_create()
{
    HWND hwnd;
    BOOL loaded;

    hwnd = CreateWindowEx(
        0,                                  /* Extra style          */
        "NHBASE",                           /* Class name           */
        NHWVersion,                         /* Window name          */
        WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,/* Window style         */
        0,                                  /* Horizontal position  */
        0,                                  /* Vertical position    */
        DEF_BASEMINWIDTH,                   /* Width                */
        DEF_BASEMINHEIGHT,                  /* Height               */
        NULL,                               /* Parent window        */
        (HMENU)0,                           /* Child-window id      */
        g_hInstance,                        /* Instance handle      */
        (LPVOID)0);                         /* CREATESTRUCT         */

    /* Restore window settings */
    loaded = NHWnd_loadProperty(
        "BaseWnd", &property, sizeof(WINBASEPROP), BaseWnd_defaultProperty);
    if (loaded) {
        SetWindowPos(
            hwnd,
            NULL,
            property.x,
            property.y,
            property.cx,
            property.cy,
            SWP_NOZORDER);
    } else {
        /* Default window size and position */
        NHWnd_moveCenter(hwnd, GetDesktopWindow());
    }
    ShowWindow(hwnd, SW_SHOW);

    return hwnd;
}

/*-------------------------------------------------------------------------------------
 * 
 *-------------------------------------------------------------------------------------*/
static void BaseWnd_handleCommand(int id)
{
    int i;

    for (i = 0; menu_cmd[i].menu_id != 0; i++) {
        if (menu_cmd[i].menu_id == id) {
            Key_put(menu_cmd[i].cmd);
            break;
        }
    }
}

/*-------------------------------------------------------------------------------------
 * WM_COMMAND
 *-------------------------------------------------------------------------------------*/
static void BaseWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
    switch (id) {
    case IDM_CONFIGMAP:
        MapWnd_cmdProperty((WINDESC*) WIN_MAP);
        break;
    case IDM_CONFIGMESSAGE:
        MesgWnd_cmdProperty((WINDESC*) WIN_MESSAGE);
        break;
    case IDM_CONFIGSTATUS:
        StatWnd_cmdProperty((WINDESC*) WIN_STATUS);
        break;
    case IDM_CONFIGMENU:
        MenuWnd_cmdProperty();
        break;
    case IDM_CONFIGSYS:
        break;
    case IDM_COPYMAPTEXT:
        MapWnd_copyText((WINDESC*) WIN_MAP);
        break;
    case IDM_COPYMESSAGE:
        MesgWnd_copyText((WINDESC*) WIN_MESSAGE);
        break;
    default:
        BaseWnd_handleCommand(id);
        break;
    }
}

/*-------------------------------------------------------------------------------------
 * WM_GETMINMAXINFO
 *-------------------------------------------------------------------------------------*/
static void BaseWnd_OnGetMinMaxInfo(HWND hwnd, LPMINMAXINFO lpMinMaxInfo)
{
    lpMinMaxInfo->ptMinTrackSize.x = DEF_BASEMINWIDTH;
    lpMinMaxInfo->ptMinTrackSize.y = DEF_BASEMINHEIGHT;
}

/*-------------------------------------------------------------------------------------
 * WM_MOVE
 *-------------------------------------------------------------------------------------*/
static void BaseWnd_OnMove(HWND hwnd, int x, int y)
{
    DWORD style, exstyle;
    RECT rc;

    GetClientRect(hwnd, &rc);
    OffsetRect(&rc, x, y);
    style = GetWindowLong(hwnd, GWL_STYLE);
    exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
    AdjustWindowRectEx(&rc, style, TRUE, exstyle);
    if (!IsZoomed(hwnd) && !IsIconic(hwnd)) {
        property.x = rc.left;
        property.y = rc.top;
        NHWnd_saveProperty("BaseWnd", &property, sizeof(WINBASEPROP));
    }
}

/*-------------------------------------------------------------------------------------
 * WM_SIZE
 *-------------------------------------------------------------------------------------*/
static void BaseWnd_OnSize(HWND hwnd, UINT state, int cx, int cy)
{
    DWORD style, exstyle;
    RECT rc;

    GetClientRect(hwnd, &rc);
    style = GetWindowLong(hwnd, GWL_STYLE);
    exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
    AdjustWindowRectEx(&rc, style, TRUE, exstyle);

    if (state != SIZE_MINIMIZED && state != SIZE_MAXIMIZED) {
        property.cx = rc.right - rc.left;
        property.cy = rc.bottom - rc.top;
        NHWnd_saveProperty("BaseWnd", &property, sizeof(WINBASEPROP));
    }
    NHWnd_newLayout();
}

/*-------------------------------------------------------------------------------------
 * WM_DETROY
 *-------------------------------------------------------------------------------------*/
static void BaseWnd_OnDestroy(HWND hwnd)
{
    /* finish */
    PostQuitMessage(0);
    exit(EXIT_SUCCESS);
}

/*-------------------------------------------------------------------------------------
 * WM_CLOSE
 *-------------------------------------------------------------------------------------*/
static void BaseWnd_OnClose(HWND hwnd)
{
    if (Key_getStatus() == KEYSTAT_WAITCOMMAND) {
        Key_put(M('q'));
    } else {
        /* warning */
    }
}

/*-------------------------------------------------------------------------------------
 * WM_PALETTECHANGED
 *-------------------------------------------------------------------------------------*/
static void BaseWnd_OnPaletteChanged(HWND hwnd, HWND hwndPaletteChange)
{
    if (hwndPaletteChange != hwnd) {
        BaseWnd_OnQueryNewPalette(hwnd);
    }
}

/*-------------------------------------------------------------------------------------
 * WM_QUERYNEWPALETTE
 *-------------------------------------------------------------------------------------*/
static BOOL BaseWnd_OnQueryNewPalette(HWND hwnd)
{
    HDC hdc;
    HPALETTE newPal, oldPal;

    newPal = disp_procs.getPalette();
    hdc = GetDC(hwnd);
    oldPal = SelectPalette(hdc, newPal, FALSE);
    RealizePalette(hdc);
    SelectPalette(hdc, oldPal, FALSE);
    ReleaseDC(hwnd, hdc);
    InvalidateRect(hwnd, NULL, FALSE);

    return TRUE;
}

/*-------------------------------------------------------------------------------------
 * WM_INITMENUPOPUP
 *-------------------------------------------------------------------------------------*/
static void BaseWnd_OnInitMenuPopup(HWND hwnd, HMENU hMenu, UINT item, BOOL fSystemMenu)
{
    UINT enable;
    int  i, count;

    if (!fSystemMenu) {
        count = GetMenuItemCount(hMenu);
        enable = (Key_getStatus() == KEYSTAT_WAITCOMMAND) ? MF_ENABLED : MF_GRAYED;
        for (i = 0; i < count; i++) {
            EnableMenuItem(hMenu, i, enable|MF_BYPOSITION);
        }
    }
}

/*-------------------------------------------------------------------------------------
 * Set default property
 *-------------------------------------------------------------------------------------*/
static void BaseWnd_defaultProperty(void *param)
{
    WINBASEPROP *property = (WINBASEPROP *)param;

    property->x  = 0;
    property->y  = 0;
    property->cx = DEF_BASEMINWIDTH;
    property->cy = DEF_BASEMINHEIGHT;
}


#endif /* NH2K_EXTENDS */
