/* Unit tests for subclassed windows.
 *
 * Copyright 2004 Kevin Koltzau
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <assert.h>
#include <stdarg.h>

#define _WIN32_WINNT 0x0501 /* For SetWindowSubclass/etc */

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "commctrl.h"

#include "wine/test.h"

static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
static BOOL (WINAPI *pRemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
static LRESULT (WINAPI *pDefSubclassProc)(HWND, UINT, WPARAM, LPARAM);

#define SEND_NEST   0x01
#define DELETE_SELF 0x02
#define DELETE_PREV 0x04

struct message {
    int procnum;           /* WndProc id message is expected from */
    WPARAM wParam;         /* expected value of wParam */
};

static int sequence_cnt, sequence_size;
static struct message* sequence;

static const struct message Sub_BasicTest[] = {
    { 2, 1 },
    { 1, 1 },
    { 2, 2 },
    { 1, 2 },
    { 0 }
};

static const struct message Sub_DeletedTest[] = {
    { 2, 1 },
    { 1, 1 },
    { 0 }
};

static const struct message Sub_AfterDeletedTest[] = {
    { 1, 1 },
    { 0 }
};

static const struct message Sub_OldAfterNewTest[] = {
    { 3, 1 },
    { 2, 1 },
    { 1, 1 },
    { 3, 2 },
    { 2, 2 },
    { 1, 2 },
    { 0 }
};

static const struct message Sub_MixTest[] = {
    { 3, 1 },
    { 4, 1 },
    { 2, 1 },
    { 1, 1 },
    { 0 }
};

static const struct message Sub_MixAndNestTest[] = {
    { 3, 1 },
    { 4, 1 },
    { 3, 2 },
    { 4, 2 },
    { 2, 2 },
    { 1, 2 },
    { 2, 1 },
    { 1, 1 },
    { 0 }
};

static const struct message Sub_MixNestDelTest[] = {
    { 3, 1 },
    { 4, 1 },
    { 3, 2 },
    { 2, 2 },
    { 1, 2 },
    { 2, 1 },
    { 1, 1 },
    { 0 }
};

static const struct message Sub_MixDelPrevTest[] = {
    { 3, 1 },
    { 5, 1 },
    { 2, 1 },
    { 1, 1 },
    { 0 }
};

static void add_message(const struct message *msg)
{
    if (!sequence)
    {
        sequence_size = 10;
        sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
    }
    if (sequence_cnt == sequence_size)
    {
        sequence_size *= 2;
        sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
    }
    assert(sequence);

    sequence[sequence_cnt].wParam  = msg->wParam;
    sequence[sequence_cnt].procnum = msg->procnum;

    sequence_cnt++;
}

static void flush_sequence()
{
    HeapFree(GetProcessHeap(), 0, sequence);
    sequence = 0;
    sequence_cnt = sequence_size = 0;
}

static void ok_sequence(const struct message *expected, const char *context)
{
    static const struct message end_of_sequence = { 0, 0 };
    const struct message *actual;

    add_message(&end_of_sequence);

    actual = sequence;

    while(expected->procnum && actual->procnum)
    {
        ok(expected->procnum == actual->procnum,
            "%s: the procnum %d was expected, but got procnum %d instead\n",
            context, expected->procnum, actual->procnum);
        ok(expected->wParam == actual->wParam,
            "%s: in procnum %d expecting wParam 0x%x got 0x%x\n",
            context, expected->procnum, expected->wParam, actual->wParam);
        expected++;
        actual++;
    }
    ok(!expected->procnum, "Received fewer messages than expected\n");
    ok(!actual->procnum, "Received more messages than expected\n");
    flush_sequence();
}

static LRESULT WINAPI WndProc1(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    struct message msg;
    
    if(message == WM_USER) {
        msg.wParam = wParam;
        msg.procnum = 1;
        add_message(&msg);
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}


static WNDPROC origProc3;
static LRESULT WINAPI WndProc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    struct message msg;
    
    if(message == WM_USER) {
        msg.wParam = wParam;
        msg.procnum = 3;
        add_message(&msg);
    }
    return CallWindowProc(origProc3, hwnd, message, wParam, lParam);
}

static LRESULT WINAPI WndProcSub(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uldSubclass, DWORD_PTR dwRefData)
{
    struct message msg;
    
    if(message == WM_USER) {
        msg.wParam = wParam;
        msg.procnum = uldSubclass;
        add_message(&msg);
        
        if(lParam) {
            if(dwRefData & DELETE_SELF) {
                pRemoveWindowSubclass(hwnd, WndProcSub, uldSubclass);
                pRemoveWindowSubclass(hwnd, WndProcSub, uldSubclass);
            }
            if(dwRefData & DELETE_PREV)
                pRemoveWindowSubclass(hwnd, WndProcSub, uldSubclass-1);
            if(dwRefData & SEND_NEST)
                SendMessage(hwnd, WM_USER, wParam+1, 0);
        }
    }
    return pDefSubclassProc(hwnd, message, wParam, lParam);
}

static void test_subclass()
{
    HWND hwnd = CreateWindowExA(0, "TestSubclass", "Test subclass", WS_OVERLAPPEDWINDOW,
                           100, 100, 200, 200, 0, 0, 0, NULL);
    assert(hwnd);

    pSetWindowSubclass(hwnd, WndProcSub, 2, 0);
    SendMessage(hwnd, WM_USER, 1, 0);
    SendMessage(hwnd, WM_USER, 2, 0);
    ok_sequence(Sub_BasicTest, "Basic");

    pSetWindowSubclass(hwnd, WndProcSub, 2, DELETE_SELF);
    SendMessage(hwnd, WM_USER, 1, 1);
    ok_sequence(Sub_DeletedTest, "Deleted");

    SendMessage(hwnd, WM_USER, 1, 0);
    ok_sequence(Sub_AfterDeletedTest, "After Deleted");

    pSetWindowSubclass(hwnd, WndProcSub, 2, 0);
    origProc3 = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndProc3);
    SendMessage(hwnd, WM_USER, 1, 0);
    SendMessage(hwnd, WM_USER, 2, 0);
    ok_sequence(Sub_OldAfterNewTest, "Old after New");

    pSetWindowSubclass(hwnd, WndProcSub, 4, 0);
    SendMessage(hwnd, WM_USER, 1, 0);
    ok_sequence(Sub_MixTest, "Mix");

    /* Now the fun starts */
    pSetWindowSubclass(hwnd, WndProcSub, 4, SEND_NEST);
    SendMessage(hwnd, WM_USER, 1, 1);
    ok_sequence(Sub_MixAndNestTest, "Mix and nest");

    pSetWindowSubclass(hwnd, WndProcSub, 4, SEND_NEST | DELETE_SELF);
    SendMessage(hwnd, WM_USER, 1, 1);
    ok_sequence(Sub_MixNestDelTest, "Mix, nest, del");

    pSetWindowSubclass(hwnd, WndProcSub, 4, 0);
    pSetWindowSubclass(hwnd, WndProcSub, 5, DELETE_PREV);
    SendMessage(hwnd, WM_USER, 1, 1);
    ok_sequence(Sub_MixDelPrevTest, "Mix and del prev");

    DestroyWindow(hwnd);
}

static BOOL RegisterWindowClasses(void)
{
    WNDCLASSA cls;

    cls.style = 0;
    cls.lpfnWndProc = WndProc1;
    cls.cbClsExtra = 0;
    cls.cbWndExtra = 0;
    cls.hInstance = GetModuleHandleA(0);
    cls.hIcon = 0;
    cls.hCursor = NULL;
    cls.hbrBackground = NULL;
    cls.lpszMenuName = NULL;
    cls.lpszClassName = "TestSubclass";
    if(!RegisterClassA(&cls)) return FALSE;
    
    return TRUE;
}

START_TEST(subclass)
{
    HMODULE hdll;
    
    hdll = GetModuleHandleA("comctl32.dll");
    assert(hdll);
    pSetWindowSubclass = (void*)GetProcAddress(hdll, "SetWindowSubclass");
    pRemoveWindowSubclass = (void*)GetProcAddress(hdll, "RemoveWindowSubclass");
    pDefSubclassProc = (void*)GetProcAddress(hdll, "DefSubclassProc");
    
    if(!pSetWindowSubclass || !pRemoveWindowSubclass || !pDefSubclassProc)
        return;

    if(!RegisterWindowClasses()) assert(0);

    test_subclass();
}
