/* Unit test suite for window classes.
 *
 * Copyright 2002 Mike McCormack
 *
 * 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 <stdlib.h>
#include <stdio.h>

#include "wine/test.h"
#include "winbase.h"
#include "winreg.h"
#include "wingdi.h"
#include "winuser.h"

#define NUMCLASSWORDS 4

LRESULT WINAPI ClassTest_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProcW (hWnd, msg, wParam, lParam);
}

/***********************************************************************
 *
 *           WinMain
 */
BOOL ClassTest(HINSTANCE hInstance, BOOL global)
{
    WNDCLASSW cls, wc;
    WCHAR className[] = {'T','e','s','t','C','l','a','s','s',0};
    WCHAR winName[]   = {'W','i','n','C','l','a','s','s','T','e','s','t',0};
    HWND hTestWnd;
    DWORD i;
    WCHAR str[20];

    cls.style         = CS_HREDRAW | CS_VREDRAW | (global?CS_GLOBALCLASS:0);
    cls.lpfnWndProc   = ClassTest_WndProc;
    cls.cbClsExtra    = NUMCLASSWORDS*sizeof(DWORD);
    cls.cbWndExtra    = 12;
    cls.hInstance     = hInstance;
    cls.hIcon         = LoadIconW (0, (LPWSTR)IDI_APPLICATION);
    cls.hCursor       = LoadCursorW (0, (LPWSTR)IDC_ARROW);
    cls.hbrBackground = GetStockObject (WHITE_BRUSH);
    cls.lpszMenuName  = 0;
    cls.lpszClassName = className;

    ok(RegisterClassW (&cls) ,
        "failed to register class");

    ok(!RegisterClassW (&cls),
        "RegisterClass of the same class should fail for the second time");

#if 0
    /* these succeeds on Wine, but shouldn't cause any trouble ... */
    ok(!GlobalFindAtomW(className),
        "Found class as global atom");

    ok(!FindAtomW(className),
        "Found class as global atom");
#endif

    /* Setup windows */
    hTestWnd = CreateWindowW (className, winName,
       WS_OVERLAPPEDWINDOW + WS_HSCROLL + WS_VSCROLL,
       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0,
       0, hInstance, 0);

    ok(hTestWnd!=0, "Failed to create window");

    /* test initial values of valid classwords */
    for(i=0; i<NUMCLASSWORDS; i++)
    {
        SetLastError(0);
        ok(!GetClassLongW(hTestWnd,i*sizeof (DWORD)),
            "GetClassLongW initial value nonzero!");
        ok(!GetLastError(),
            "GetClassLongW failed!");
    }

#if 0
    /*
     *  GetClassLongW(hTestWnd, NUMCLASSWORDS*sizeof(DWORD))
     *  does not fail on Win 98, though MSDN says it should
     */
    SetLastError(0);
    GetClassLongW(hTestWnd, NUMCLASSWORDS*sizeof(DWORD));
    ok(GetLastError(),
        "GetClassLongW() with invalid offset did not fail");
#endif

    /* set values of valid class words */
    for(i=0; i<NUMCLASSWORDS; i++)
    {
        SetLastError(0);
        ok(!SetClassLongW(hTestWnd,i*sizeof(DWORD),i+1),
            "GetClassLongW(%ld) initial value nonzero!",i*sizeof(DWORD));
        ok(!GetLastError(),
            "SetClassLongW(%ld) failed!",i*sizeof(DWORD));
    }

    /* test values of valid classwords that we set */
    for(i=0; i<NUMCLASSWORDS; i++)
    {
        SetLastError(0);
        ok( (i+1) == GetClassLongW(hTestWnd,i*sizeof (DWORD)),
            "GetClassLongW value doesn't match what was set!");
        ok(!GetLastError(),
            "GetClassLongW failed!");
    }

    /* check GetClassName */
    i = GetClassNameW(hTestWnd, str, sizeof str);
    ok(i == lstrlenW(className),
        "GetClassName returned incorrect length");
    ok(!lstrcmpW(className,str),
        "GetClassName returned incorrect name for this window's class");

    /* check GetClassInfo with our hInstance */
    if(GetClassInfoW(hInstance, str, &wc))
    {
        ok(wc.cbClsExtra == cls.cbClsExtra,
            "cbClsExtra did not match");
        ok(wc.cbWndExtra == cls.cbWndExtra,
            "cbWndExtra did not match");
        ok(wc.hbrBackground == cls.hbrBackground,
            "hbrBackground did not match");
        ok(wc.hCursor== cls.hCursor,
            "hCursor did not match");
        ok(wc.hInstance== cls.hInstance,
            "hInstance did not match");
    }
    else
        ok(FALSE,"GetClassInfo (hinstance) failed!");

    /* check GetClassInfo with zero hInstance */
    if(global)
    {
        if(GetClassInfoW(0, str, &wc))
        {
            ok(wc.cbClsExtra == cls.cbClsExtra,
                "cbClsExtra did not match %x!=%x",wc.cbClsExtra,cls.cbClsExtra);
            ok(wc.cbWndExtra == cls.cbWndExtra,
                "cbWndExtra did not match %x!=%x",wc.cbWndExtra,cls.cbWndExtra);
            ok(wc.hbrBackground == cls.hbrBackground,
                "hbrBackground did not match %p!=%p",wc.hbrBackground,cls.hbrBackground);
            ok(wc.hCursor== cls.hCursor,
                "hCursor did not match %p!=%p",wc.hCursor,cls.hCursor);
            ok(!wc.hInstance,
                "hInstance not zero for global class %p",wc.hInstance);
        }
        else
            ok(FALSE,"GetClassInfo (0) failed for global class!");
    }
    else
    {
        ok(!GetClassInfoW(0, str, &wc),
            "GetClassInfo (0) succeeded for local class!");
    }

    ok(!UnregisterClassW(className, hInstance),
        "Unregister class succeeded with window existing");

    ok(DestroyWindow(hTestWnd),
        "DestroyWindow() failed!");

    ok(UnregisterClassW(className, hInstance),
        "UnregisterClass() failed");

    return TRUE;
}

START_TEST(class)
{
    HANDLE hInstance = GetModuleHandleA( NULL );

    ClassTest(hInstance,FALSE);
    ClassTest(hInstance,TRUE);
}
