/* 
CCIDE
Copyright 2001-2011 David Lindauer.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

You may contact the author at:
	mailto::camille@bluegrass.net
 */
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "lsctrl.h"

#define TITLEWIDTH 15
#define EDGEWIDTH 1
#define TITLETOP 4
#define BARLEFT 2
#define BARRIGHT 2
#define BARTOP 0
#define BUTTONCORNER 1
#define BUTTONWIDTH 12

extern HWND hwndClient;
static char *szGripWindClassName = "ladSoftGripWindow";
static char *szTBContainerClassName = "ladSoftTBContainerWindow";
static char *szBlankWindowClassName = "ladSoftBlankWindow";

static HCURSOR mcurs;

static void DrawBorder(HWND hwnd, HDC dc)
{
    RECT r;
    GetClientRect(hwnd, &r);
    r.right += GetSystemMetrics(SM_CXBORDER) *2;
    r.bottom += GetSystemMetrics(SM_CYBORDER) *2;
    DrawEdge(dc, &r, EDGE_RAISED, BF_RECT | BF_FLAT);
}

//-------------------------------------------------------------------------

static void DrawTitle(HDC dc, RECT *r, int vertical)
{
    HPEN pen1, pen2, pen3, oldpen;
    pen1 = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DLIGHT));
    pen2 = CreatePen(PS_SOLID, 2, GetSysColor(COLOR_3DHILIGHT));
    pen3 = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
    if (vertical)
    {
        r->top = TITLETOP;
        r->left += EDGEWIDTH;
        r->right -= EDGEWIDTH;
        oldpen = SelectObject(dc, pen1);
        SelectObject(dc, pen1);
        MoveToEx(dc, r->left + BARLEFT, r->top + BARTOP, 0);
        LineTo(dc, r->right - BARRIGHT + 1, r->top + BARTOP);
        SelectObject(dc, pen2);
        MoveToEx(dc, r->left + BARLEFT - 1, r->top + BARTOP + 1, 0);
        LineTo(dc, r->right - BARRIGHT, r->top + BARTOP + 1);
        SelectObject(dc, pen3);
        MoveToEx(dc, r->left + BARLEFT, r->top + BARTOP + 3, 0);
        LineTo(dc, r->right - BARRIGHT + 1, r->top + BARTOP + 3);
        SelectObject(dc, pen2);
        MoveToEx(dc, r->left + BARLEFT - 1, r->top + BARTOP + 5, 0);
        LineTo(dc, r->right - BARRIGHT, r->top + BARTOP + 5);
        SelectObject(dc, pen3);
        MoveToEx(dc, r->left + BARLEFT, r->top + BARTOP + 7, 0);
        LineTo(dc, r->right - BARRIGHT + 1, r->top + BARTOP + 7);
    }
    else
    {
        r->left = TITLETOP;
        r->top += EDGEWIDTH;
        r->bottom -= EDGEWIDTH;
        oldpen = SelectObject(dc, pen1);
        MoveToEx(dc, r->left + BARTOP, r->top + BARRIGHT - 1, 0);
        LineTo(dc, r->left + BARTOP, r->bottom - BARLEFT);
        SelectObject(dc, pen2);
        MoveToEx(dc, r->left + BARTOP + 1, r->top + BARRIGHT, 0);
        LineTo(dc, r->left + BARTOP + 1, r->bottom - BARLEFT + 1);
        SelectObject(dc, pen3);
        MoveToEx(dc, r->left + BARTOP + 3, r->top + BARRIGHT - 1, 0);
        LineTo(dc, r->left + BARTOP + 3, r->bottom - BARLEFT);
        SelectObject(dc, pen2);
        MoveToEx(dc, r->left + BARTOP + 5, r->top + BARRIGHT, 0);
        LineTo(dc, r->left + BARTOP + 5, r->bottom - BARLEFT + 1);
        SelectObject(dc, pen3);
        MoveToEx(dc, r->left + BARTOP + 7, r->top + BARRIGHT - 1, 0);
        LineTo(dc, r->left + BARTOP + 7, r->bottom - BARLEFT);
    }
    SelectObject(dc, oldpen);
    DeleteObject(pen1);
    DeleteObject(pen2);
    DeleteObject(pen3);
}

//-------------------------------------------------------------------------

static LRESULT CALLBACK _export GripWindWndProc(HWND hwnd, UINT iMessage,
    WPARAM wParam, LPARAM lParam)
{
    RECT r,  *pr;
    PAINTSTRUCT ps;
    HDC dc;
    CCW_params *ptr;
    static int skip;
    static int dragging, oncursor, sizing;
    static HCURSOR oldCursor;
    POINT temppt;
    int temp;
    HBRUSH brush;
    int cx, cy;
    switch (iMessage)
    {
        case WM_SETTEXT:
            break;
        case WM_NOTIFY:
            break;
        case WM_COMMAND:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            break;
        case WM_NCPAINT:
            {
                HDC hdc;
                hdc = GetWindowDC(hwnd);
                DrawBorder(hwnd, hdc);
                ReleaseDC(hwnd, hdc);
            }
            return 0;
            break;
        case WM_LBUTTONDOWN:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            temppt.x = (long)(short)LOWORD(lParam);
            temppt.y = (long)(short)HIWORD(lParam);
            if ((ptr->vertical && temppt.y < 17) || (!ptr->vertical && temppt.x
                < 17))
            {
                dmgrStartMoveGrip(ptr, lParam);
                oldCursor = SetCursor(mcurs);
                SetCapture(hwnd);
                dragging = TRUE;
            }
            break;
        case WM_LBUTTONUP:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            if (dragging)
            {
                SetCursor(oldCursor);
                oldCursor = 0;
            }
            if (dragging)
                ReleaseCapture();
            dragging = FALSE;
            sizing = FALSE;
            dmgrEndMoveGrip(ptr);
            break;
        case WM_MOUSEMOVE:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            if (dragging)
            {
                dmgrMoveGrip(ptr, lParam);
            }
            break;
        case WM_PAINT:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            dc = BeginPaint(hwnd, &ps);
            GetClientRect(hwnd, &r);

            DrawTitle(dc, &r, ptr->vertical);
            EndPaint(hwnd, &ps);
            break;
        case WM_CREATE:
            ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof
                (CCW_params));
            SetWindowLong(hwnd, 0, (DWORD)ptr);
            *ptr = *(CCW_params*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
            ptr->self = hwnd;
            ptr->type = LSGRIP;
            dmgrAddGrip(ptr);
            GetClientRect(hwnd, &r);
            return 0;
        case WM_DESTROY:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            HeapFree(GetProcessHeap(), 0, ptr);
            break;
        case WM_CLOSE:
            return 0;
        case LCF_SETVERTICAL:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            ptr->vertical = (int)lParam;
            InvalidateRect(hwnd, 0, 0);
            return 0;
        case WM_SIZE:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            cx = 0; // GetSystemMetrics(SM_CXFRAME) ;
            cy = 0; // GetSystemMetrics(SM_CYFRAME) ;
            if (ptr->vertical)
                MoveWindow(ptr->u.gp.child, cx + 2, TITLEWIDTH + cy, LOWORD(lParam)
                    - cx, HIWORD(lParam) - TITLEWIDTH - cy, TRUE);
            else
                MoveWindow(ptr->u.gp.child, TITLEWIDTH + cx, cy + 2, LOWORD(lParam)
                    - TITLEWIDTH - cx, HIWORD(lParam) - cy, TRUE);
            return 0;
    }
    return DefWindowProc(hwnd, iMessage, wParam, lParam);
}

//-------------------------------------------------------------------------

LRESULT CALLBACK _export TBContainerProc(HWND hwnd, UINT iMessage, WPARAM
    wParam, LPARAM lParam)
{
    CCW_params *ptr,  *ptr1;
    int rv;
    static int selected, sizingbottom;
    RECT r,  *pr;
    TC_ITEM tie;
    NMHDR *h;
    DRAWITEMSTRUCT *dr;
    HFONT font;
    HBITMAP hbmp;
    HDC hMemDC;
    HDWP deferstruct;
    HDC dc;
    PAINTSTRUCT ps;
    static int dragging, oncursor, sizing;
    static HCURSOR oldCursor;
    POINT temppt;
    switch (iMessage)
    {
        case WM_SETTEXT:
            break;
        case WM_MDIACTIVATE:
            //            if (lParam == (LPARAM)hwnd)
            //                SendMessage(hwndSourceTab,WM_SETACTIVETAB,0,(LPARAM)hwnd) ;
            break;
        case WM_NCHITTEST:
            rv = DefMDIChildProc(hwnd, iMessage, wParam, lParam);
            if (rv == HTCAPTION)
                return HTCLIENT;
            return rv;
        case WM_SYSCOMMAND:
            if (wParam == SC_CLOSE)
            {
                PostMessage(hwnd, WM_CLOSE, 0, 0);
            }
            break;
        case WM_LBUTTONDOWN:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            temppt.x = (long)(short)LOWORD(lParam);
            temppt.y = (long)(short)HIWORD(lParam);
            if (temppt.y < GetSystemMetrics(SM_CYCAPTION))
            {
                //            ScreenToClient(hwnd,&temppt) ;
                //            SendMessage(hwndClient,WM_MDIACTIVATE,(WPARAM)hwnd,0) ;
                //            temppt.y += GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
                //            temppt.x += GetSystemMetrics(SM_CXFRAME) ;
                //            lParam = MAKELRESULT(temppt.x,temppt.y) ;
                ptr1 = (CCW_params*)GetWindowLong(ptr->u.gp.child, 0);
                if (ptr1->type == LSTOOLBAR)
                    dmgrStartMoveGrip(ptr, lParam);
                else
                    dmgrStartMoveClient(ptr1, lParam);
                oldCursor = SetCursor(mcurs);
                SetCapture(hwnd);
                dragging = TRUE;
                return 0;
            }
            break;
        case WM_LBUTTONUP:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            //         if (wParam == HTCAPTION) {
            if (dragging)
            {
                SetCursor(oldCursor);
                oldCursor = 0;
            }
            if (dragging)
                ReleaseCapture();
            dragging = FALSE;
            sizing = FALSE;
            ptr1 = (CCW_params*)GetWindowLong(ptr->u.gp.child, 0);
            if (ptr1->type == LSTOOLBAR)
                dmgrEndMoveGrip(ptr);
            else
                dmgrEndMoveSizeClient(ptr1);
            return 0;
            //         }
            break;
        case WM_MOUSEMOVE:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            if (dragging)
            {
                ptr1 = (CCW_params*)GetWindowLong(ptr->u.gp.child, 0);
                if (ptr1->type == LSTOOLBAR)
                    dmgrMoveGrip(ptr, lParam);
                else
                    dmgrMoveClient(ptr1, lParam);
            }
            break;
        case WM_NOTIFY:
        case WM_COMMAND:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
			SendMessage(ptr->parent, iMessage, wParam, lParam);
            break;
        case WM_CREATE:
            ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof
                (CCW_params));
            SetWindowLong(hwnd, 0, (DWORD)ptr);
            //         *ptr = *(CCW_params *)(((LPMDICREATESTRUCT)lParam)->lParam) ;
            ptr->self = hwnd;
            ptr->type = LSTBCONT;
            dmgrAddContainer(ptr);
            return 0;
        case WM_PAINT:
            dc = BeginPaint(hwnd, &ps);
            GetClientRect(hwnd, &r);
            EndPaint(hwnd, &ps);
            break;
        case WM_DESTROY:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            HeapFree(GetProcessHeap(), 0, ptr);
            break;
        case WM_SIZE:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            GetClientRect(hwnd, &r);
            MoveWindow(ptr->u.gp.directchild, 0, 0, r.right, r.bottom, TRUE);
            InvalidateRect(ptr->u.gp.child,0,TRUE);
            return 0;
        case WM_CLOSE:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            ptr = (CCW_params*)GetWindowLong(ptr->u.gp.child, 0);
            dmgrHideWindow(ptr->id, TRUE);
            return 0;
        case WM_MOVE:
            break;
    }
    return DefMDIChildProc(hwnd, iMessage, wParam, lParam);
}

//-------------------------------------------------------------------------

static LRESULT CALLBACK _export BlankWindowWndProc(HWND hwnd, UINT iMessage,
    WPARAM wParam, LPARAM lParam)
{
    RECT r,  *pr;
    PAINTSTRUCT ps;
    HDC dc;
    CCW_params *ptr;
    static int skip;
    static int dragging, oncursor, sizing;
    static RECT moverect;
    static HCURSOR oldCursor;
    POINT temppt, movept;
    int temp;
    switch (iMessage)
    {
        case WM_NOTIFY:
            SendMessage(GetParent(hwnd), iMessage, wParam, lParam);
            break;
        case WM_COMMAND:
            SendMessage(GetParent(hwnd), iMessage, wParam, lParam);
            break;
        case WM_PAINT:
            ptr = (CFW_params*)GetWindowLong(hwnd, 0);
            dc = BeginPaint(hwnd, &ps);
            EndPaint(hwnd, &ps);
            break;
        case WM_CREATE:
            ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof
                (CCW_params));
            SetWindowLong(hwnd, 0, (DWORD)ptr);
            *ptr = *(CCW_params*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
            ptr->self = hwnd;
            ptr->type = LSBLANK;
            dmgrAddBlank(ptr);
            return 0;
        case WM_DESTROY:
            ptr = (CCW_params*)GetWindowLong(hwnd, 0);
            HeapFree(GetProcessHeap(), 0, ptr);
            break;
        case WM_CLOSE:
            return 0;
        case WM_SIZE:
            break;
        case WM_MOVE:
            break;
    }
    return DefWindowProc(hwnd, iMessage, wParam, lParam);
}

//-------------------------------------------------------------------------

void RegisterGripWindow(HINSTANCE hInstance)
{
    WNDCLASS wc;
    memset(&wc, 0, sizeof(wc));
    wc.style = CS_PARENTDC;
    wc.lpfnWndProc = &GripWindWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = sizeof(LPVOID);
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor = LoadCursor(0, IDC_ARROW);
    wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_INACTIVEBORDER));
    wc.lpszMenuName = 0;
    wc.lpszClassName = szGripWindClassName;
    RegisterClass(&wc);

    memset(&wc, 0, sizeof(wc));
    wc.style = 0;
    wc.lpfnWndProc = &TBContainerProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 4;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor = LoadCursor(0, IDC_ARROW);
    wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_INACTIVEBORDER));
    wc.lpszMenuName = 0;
    wc.lpszClassName = szTBContainerClassName;
    RegisterClass(&wc);

    memset(&wc, 0, sizeof(wc));
    wc.style = CS_PARENTDC;
    wc.lpfnWndProc = &BlankWindowWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = sizeof(LPVOID);
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor = NULL;
    wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
    wc.lpszMenuName = 0;
    wc.lpszClassName = szBlankWindowClassName;
    RegisterClass(&wc);

    mcurs = LoadCursor(hInstance, "ID_MOVECUR");

}

//-------------------------------------------------------------------------

HWND CreateContainerWindow(HWND parent, RECT *r)
{
    CCW_params p;
    HWND hwnd;
    hwnd = CreateMDIWindow(szTBContainerClassName, "", WS_CLIPCHILDREN |
        WS_CLIPSIBLINGS | WS_CHILD | WS_OVERLAPPEDWINDOW - WS_MINIMIZEBOX -
        WS_MAXIMIZEBOX, r->left, r->top, r->right - r->left, r->bottom - r->top,
        parent, (HINSTANCE)GetWindowLong(parent, GWL_HINSTANCE), (LPARAM) &p);

    return hwnd;
}

//-------------------------------------------------------------------------

HWND CreateBlankWindow(HWND parent, RECT *r)
{
    CCW_params p;
    HWND hwnd;
    hwnd = CreateWindow(szBlankWindowClassName, "", WS_CLIPCHILDREN | WS_CHILD,
        r->left, r->top, r->right - r->left, r->bottom - r->top, parent, (HMENU)
        0, (HINSTANCE)GetWindowLong(parent, GWL_HINSTANCE), &p);

    return hwnd;
}

//-------------------------------------------------------------------------

HWND CreateGripWindow(HWND parent, RECT *r, int vertical)
{
    CCW_params p;
    HWND hwnd;
    RECT r1, r2;
    p.vertical = vertical;
    hwnd = CreateWindow(szGripWindClassName, "", WS_CLIPSIBLINGS |
        WS_CLIPCHILDREN | WS_CHILD | WS_BORDER, r->left, r->top, r->right - r
        ->left, r->bottom - r->top, parent, (HMENU)0, (HINSTANCE)GetWindowLong
        (parent, GWL_HINSTANCE), &p);

    return hwnd;
}
