/* OCaml-Win32
 * win32_pager.c
 * Copyright (c) 2002-2004 by Harry Chomsky
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "win32.h"

/********************************************************************/
/* User Interface: Windows User Experience: Windows Shell: SDK: Windows Controls: Individual Control Information: Pager Controls */

/* Styles */

static DWORD pager_style_options[] = {
    PGS_AUTOSCROLL,
    PGS_DRAGNDROP,
    PGS_HORZ
};
Define_static_constants(pager_style_options);

CAMLprim value pager_style_of_option(value option)
{
    return copy_int64((int64)Constant_val(option, pager_style_options));
}

/* Messages */

CAMLprim value pack_pgm_forwardmouse(value forward)
{
    return pack_message(PGM_FORWARDMOUSE, Bool_val(forward), 0);
}

CAMLprim value unpack_pgm_getbkcolor(value result)
{
    return alloc_color((COLORREF)Int32_val(result));
}

CAMLprim value unpack_pgm_getborder(value result)
{
    return Val_int(Int32_val(result));
}

CAMLprim value unpack_pgm_getbuttonsize(value result)
{
    return Val_int(Int32_val(result));
}

static DWORD pager_buttons[] = {
    PGB_BOTTOMORRIGHT,
    PGB_TOPORLEFT
};
Define_static_constants(pager_buttons);

static DWORD pager_button_states[] = {
    PGF_DEPRESSED,
    PGF_GRAYED,
    PGF_HOT,
    PGF_INVISIBLE,
    PGF_NORMAL
};
Define_static_constants(pager_button_states);

CAMLprim value pack_pgm_getbuttonstate(value which)
{
    return pack_message(PGM_GETBUTTONSTATE, 0, Constant_val(which, pager_buttons));
}

CAMLprim value unpack_pgm_getbuttonstate(value result)
{
    return Val_constant(Int32_val(result), pager_button_states);
}

CAMLprim value unpack_pgm_getpos(value result)
{
    return Val_int(Int32_val(result));
}

CAMLprim value pack_pgm_setbkcolor(value color)
{
    return pack_message(PGM_SETBKCOLOR, 0, (LPARAM)color_val(color));
}

CAMLprim value unpack_pgm_setbkcolor(value result)
{
    return alloc_color((COLORREF)Int32_val(result));
}

CAMLprim value pack_pgm_setborder(value border)
{
    return pack_message(PGM_SETBORDER, 0, Int_val(border));
}

CAMLprim value unpack_pgm_setborder(value result)
{
    return Val_int(Int32_val(result));
}

CAMLprim value pack_pgm_setbuttonsize(value size)
{
    return pack_message(PGM_SETBUTTONSIZE, 0, Int_val(size));
}

CAMLprim value unpack_pgm_setbuttonsize(value result)
{
    return Val_int(Int32_val(result));
}

CAMLprim value pack_pgm_setchild(value child)
{
    return pack_message(PGM_SETCHILD, 0, (LPARAM)Handle_val(child));
}

CAMLprim value pack_pgm_setpos(value pos)
{
    return pack_message(PGM_SETPOS, 0, Int_val(pos));
}

/* Notifications */

static DWORD pager_modifier_keys[] = {
    PGK_CONTROL,
    PGK_MENU,
    PGK_SHIFT
};
Define_static_constants(pager_modifier_keys);

static DWORD pager_scroll_directions[] = {
    PGF_SCROLLDOWN,
    PGF_SCROLLLEFT,
    PGF_SCROLLRIGHT,
    PGF_SCROLLUP
};
Define_static_constants(pager_scroll_directions);

static DWORD pager_dimensions[] = {
    PGF_CALCHEIGHT,
    PGF_CALCWIDTH
};
Define_static_constants(pager_dimensions);

CAMLprim value on_pgn_calcsize(value handler, value wnd, value msg)
{
    CAMLparam3(handler, wnd, msg);
    NMHDR* nmh;
    NMPGCALCSIZE* nmpgcs;
    CAMLlocalN(args, 5);
    CAMLlocal3(result, val, ret);

    ret = Val_none;
    if (Int_val(Field(msg, 0)) == WM_NOTIFY) {
        nmh = (NMHDR*)Lparam(msg);
        if (nmh->code == PGN_CALCSIZE) {
            nmpgcs = (NMPGCALCSIZE*)nmh;
            args[0] = wnd;
            args[1] = msg;
            args[2] = Val_int(Wparam(msg));
            args[3] = alloc_nmhdr(nmh);
            args[4] = Constant_val(nmpgcs->dwFlag, pager_dimensions);
            result = callbackN(handler, 5, args);
            if (Is_block(result)) {
                if (Tag_val(result) == 0)
                    ret = alloc_some(Field(result, 0));
                else {
                    val = Field(result, 0);
                    if (nmpgcs->dwFlag == PGF_CALCHEIGHT)
                        nmpgcs->iHeight = Int_val(val);
                    else
                        nmpgcs->iWidth = Int_val(val);
                    ret = alloc_some(copy_int32(0));
                }
            }
        }
    }
    CAMLreturn(ret);
}

CAMLprim value on_pgn_scroll(value handler, value wnd, value msg)
{
    CAMLparam3(handler, wnd, msg);
    NMHDR* nmh;
    NMPGSCROLL* nmpgs;
    POINT pt;
    CAMLlocalN(args, 5);
    CAMLlocal4(result, val, v, ret);

    ret = Val_none;
    if (Int_val(Field(msg, 0)) == WM_NOTIFY) {
        nmh = (NMHDR*)Lparam(msg);
        if (nmh->code == PGN_SCROLL) {
            nmpgs = (NMPGSCROLL*)nmh;
            val = alloc_tuple(5);
            v = Alloc_flags(nmpgs->fwKeys, pager_modifier_keys);
            Store_field(val, 0, v);
            v = alloc_rect(&nmpgs->rcParent);
            Store_field(val, 1, v);
            Store_field(val, 2, Val_constant(nmpgs->iDir, pager_scroll_directions));
            pt.x = nmpgs->iXpos;
            pt.y = nmpgs->iYpos;
            v = alloc_point(pt);
            Store_field(val, 3, v);
            Store_field(val, 4, Val_int(nmpgs->iScroll));
            args[0] = wnd;
            args[1] = msg;
            args[2] = Val_int(Wparam(msg));
            args[3] = alloc_nmhdr(nmh);
            args[4] = val;
            result = callbackN(handler, 5, args);
            if (Is_block(result)) {
                if (Tag_val(result) == 0)
                    ret = alloc_some(Field(result, 0));
                else {
                    nmpgs->iScroll = Int_val(Field(result, 0));
                    ret = alloc_some(copy_int32(0));
                }
            }
        }
    }
    CAMLreturn(ret);
}
