/* 
CCIDE
Copyright 2001-2006 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 "header.h"
#include "winconst.h"

#define FRAMEWIDTH 6

#define MIN_WIDTH 30
#define DEFAULT_WIDTH 200
#define DEFAULT_HEIGHT 160
#define TITLE_ALIAS 25

#define MIN_SIZE (21)

extern HWND hwndSourceTab;

static CCW_params **cache;
static CCD_params **docks;
static int max, currentWindows;
static HWND hwndFrame, hwndClient;
static RECT moverect;
static POINT movept;
static int curstype;
static int moving = 0;
static int sizing = 0;
static RECT lastbound;
static int drawnbound;
static int suggestedDock, lastSuggestedDock;
static int frameCount, frameMax;
static int blankCount, blankMax;
static int gripCount, gripMax;
static int containerCount, containerMax;
static CFW_params *frames[30];
static CCW_params *blanks[30],  *grips[30],  *containers[30];
static HWND sbwnd;
static int sbheight;
static int rundown;
static HBITMAP hFocusBitmap;
int dock(CCW_params *p, RECT *r);
CCD_params *FindParams(CCW_params *p, int *index);
void CalculateMoveableDocks(CCW_params *p, RECT *r, POINT *pt);
void DoDocks(CCW_params *p);
void CalculateLayout(int index, int recalhidden);
void CalculateSizebarBounds(CFW_params *p, RECT *dest);
void Resize(CFW_params *p, RECT *new);
void PutWindow(HWND hwnd, RECT *r);
void CalculateHidden(CCD_params *d, int index, int state);
void InsertVertFrame(int index, int left, RECT *fullframe);
void InsertHorizFrame(int index, int top, int fullframe);

CCD_params *FindParams(CCW_params *p, int *index)
{
    int i;
    for (i = 0; i < currentWindows; i++)
    if (cache[i] == p)
    {
        if (index)
            *index = i;
        return docks[i];
    }

    return NULL;
}

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

void DrawBoundingRect(RECT *r1)
{
    static int drawn;
    static HDC hdcMem, dc;
    static HBITMAP bm;
    HBRUSH brush, oldbrush;

    RECT r3 =  *r1, r2;
    int i;
    if (!drawn)
    {
        dc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
        hdcMem = CreateCompatibleDC(dc);
        bm = CreateCompatibleBitmap(dc, r1->right - r1->left, r1->bottom - r1
            ->top);
        SelectObject(hdcMem, bm);
        BitBlt(hdcMem, 0, 0, r1->right - r1->left, r1->bottom - r1->top, dc, r1
            ->left, r1->top, SRCCOPY);
        brush = CreatePatternBrush(hFocusBitmap);
        oldbrush = SelectObject(dc, brush);
        for (i = 0; i < 4; i++)
        {
            FrameRect(dc, &r3, brush);
            r3.left++;
            r3.right--;
            r3.top++;
            r3.bottom--;
        }
        SelectObject(dc, oldbrush);
        DeleteObject(brush);
    }
    else
    {
        BitBlt(dc, r1->left, r1->top, r1->right - r1->left, r1->bottom - r1
            ->top, hdcMem, 0, 0, SRCCOPY);
        DeleteDC(hdcMem);
        DeleteDC(dc);
        DeleteObject(bm);
    }
    drawn = !drawn;
    #ifdef XXXXX
        for (i = 0; i < 4; i++)
        {
            DrawFocusRect(dc, &r3);
            r3.left++;
            r3.right--;
            r3.top++;
            r3.bottom--;
        }
    #endif 
    lastbound =  *r1;
    drawnbound = TRUE;
}

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

void GetRelativeRect(HWND parent, HWND self, RECT *r)
{
    POINT pt;
    GetWindowRect(self, r);
    pt.x = r->left;
    pt.y = r->top;
    ScreenToClient(parent, &pt);
    r->bottom = r->bottom - r->top + pt.y;
    r->right = r->right - r->left + pt.x;
    r->left = pt.x;
    r->top = pt.y;
}

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

void GetFrameWindowRect(RECT *r)
{
    GetWindowRect(hwndFrame, r);
    r->top += GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYMENU) +
        GetSystemMetrics(SM_CYFRAME);
    r->bottom -= GetSystemMetrics(SM_CYFRAME);
    r->left += GetSystemMetrics(SM_CXFRAME);
    r->right -= GetSystemMetrics(SM_CXFRAME);

    r->bottom -= sbheight;
}

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

void AllocContainer(CCW_params *p, RECT *r, int reshow)
{
    SendMessage(p->self, LCF_SETVERTICAL, 0, 0);
    if (containerCount >= containerMax)
        CreateContainerWindow(hwndClient, r);
    containers[containerCount]->parent = p->parent;
    containers[containerCount]->u.gp.child = p->self;
    if (p->type != LSTOOLBAR)
    {
        // relies on the next higher window being the top...
        containers[containerCount]->u.gp.directchild = p->parent;
        SendMessage(p->self, LCF_CONTAINER, 0, 1);
        SetParent(p->parent, containers[containerCount]->self);
        MoveWindow(containers[containerCount]->self, r->left, r->top, r->right 
            - r->left + 2 * GetSystemMetrics(SM_CXFRAME), r->bottom - r->top +
            GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME), 1);
        ShowWindow(p->parent, SW_SHOW);
    }
    else
    {
        containers[containerCount]->u.gp.directchild = p->self;
        SetParent(p->self, containers[containerCount]->self);
        MoveWindow(containers[containerCount]->self, r->left, r->top, p
            ->u.tb.hsize.cx + 2 * GetSystemMetrics(SM_CXFRAME), p
            ->u.tb.hsize.cy + GetSystemMetrics(SM_CYCAPTION), 1);
    }
    p->parent = containers[containerCount]->self; 
        // parent is the frame here, not the real parent
    SendMessage(containers[containerCount]->self, WM_SETTEXT, 0, (LPARAM)p
        ->title);
    if (reshow)
        ShowWindow(containers[containerCount]->self, SW_SHOW);
    containerCount++;
}

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

void FreeContainer(CCW_params *ps)
{
    int i;
    CCW_params *p = (CCW_params*)GetWindowLong(ps->parent, 0);
    if (!p) // || ps->type != LSTOOLBAR || p->type != LSTBCONT)
        return ;
    ShowWindow(ps->parent, SW_HIDE);
    ps->parent = p->parent; 
        // TBCONT parent field was munged to hold original parent
    if (ps->type != LSTOOLBAR)
    {
        SendMessage(ps->self, LCF_CONTAINER, 0, 0);
    }
    for (i = 0; i < containerMax; i++)
        if (p == containers[i])
            break;
    memcpy(containers + i, containers + i + 1, (containerMax - i - 1) *sizeof
        (CCW_params*));
    containers[containerMax - 1] = p;
    containerCount--;
}

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

void AllocGrip(CCW_params *p, RECT *r, int vertical, int reshow)
{
    if (p->type != LSTOOLBAR)
        return ;
    SendMessage(p->self, LCF_SETVERTICAL, GRIPWIDTH, vertical);
    if (gripCount >= gripMax)
        CreateGripWindow(hwndClient, r, vertical);
    SendMessage(grips[gripCount]->self, LCF_SETVERTICAL, 0, vertical);
    grips[gripCount]->u.gp.child = p->self;
    SetParent(p->self, grips[gripCount]->self);
    p->parent = grips[gripCount]->self;
    if (vertical)
        MoveWindow(grips[gripCount]->self, r->left, r->top, p->u.tb.vsize.cx, p
            ->u.tb.vsize.cy + GRIPWIDTH, 1);
    else
        MoveWindow(grips[gripCount]->self, r->left, r->top, p->u.tb.hsize.cx +
            GRIPWIDTH, p->u.tb.hsize.cy, 1);
    if (reshow)
        ShowWindow(grips[gripCount]->self, SW_SHOW);
    gripCount++;
}

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

void FreeGrip(CCW_params *ps)
{
    int i;
    CCW_params *p;
    if (ps->type != LSTOOLBAR)
        return ;
    p = (CCW_params*)GetWindowLong(ps->parent, 0);
    ShowWindow(ps->parent, SW_HIDE);
    for (i = 0; i < gripMax; i++)
        if (p == grips[i])
            break;
    memcpy(grips + i, grips + i + 1, (gripMax - i - 1) *sizeof(CCW_params*));
    grips[gripMax - 1] = p;
    gripCount--;
}

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

void AllocBlank(RECT *r, CCD_params *d, int vertical)
{
    if (blankCount >= blankMax)
        CreateBlankWindow(hwndFrame, r);
    blanks[blankCount]->u.bw.position =  *r;
    blanks[blankCount]->u.bw.representative_dock = d;
	blankCount++;
//    MoveWindow(blanks[blankCount++]->self, r->left, r->top, r->right - r->left,
//        r->bottom - r->top, 1);
}

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

void dmgrAddStatusBar(HWND sb)
{
    RECT r;
    sbwnd = sb;

    GetWindowRect(sb, &r);
    sbheight = r.bottom - r.top;
}

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

void GetClientWindowRect(RECT *r)
{
    GetWindowRect(hwndClient, r);
    r->top -= SendMessage(hwndSourceTab, WM_GETHEIGHT, 0, 0);
}

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

void dmgrInit(HINSTANCE hInstance, HWND frame, HWND client, int count)
{
	RECT r;
	int i;
	
    hFocusBitmap = LoadBitmap(hInstance, "ID_BRFOCUS");

    hwndFrame = frame;
    hwndClient = client;
    cache = calloc(1, count *sizeof(CCW_params*));
    if (cache)
    {
        docks = calloc(1, count *sizeof(CCD_params*));
        if (!docks)
        {
            free(cache);
            cache = 0;
        }
    }
    if (cache)
        max = count;
		
	memset(&r, 0, sizeof(r));
	for (i=0; i < 30; i++)
		CreateFrameWindow(hwndFrame, &r, FALSE);
}

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

void dmgrAddClient(CCW_params *p)
{
    RECT r;
    if (currentWindows < max)
    {
        int style = GetWindowLong(p->parent, GWL_STYLE);
        CCD_params *s = calloc(sizeof(CCD_params), 1);
        if (!s)
            return ;
        s->hidden = !(style &WS_VISIBLE);
        cache[currentWindows] = p;
        docks[currentWindows++] = s;
        GetWindowRect(p->parent, &s->position);
        s->lastposition = s->position;
        s->lastposition.right -= s->lastposition.left;
        s->lastposition.bottom -= s->lastposition.top;
        s->lastposition.left = s->lastposition.top = 0;
        s->oldsize = s->lastposition;
        if (p->type == LSTOOLBAR)
        {
            memset(&r, 0, sizeof(r));
            AllocContainer(p, &r, FALSE);
            ShowWindow(p->parent, SW_HIDE);
        }
    }
}

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

int dmgrRemoveClient(CCW_params *p)
{
    int i;
    CCD_params *d;
    for (i = 0; i < currentWindows; i++)
    {
        GetWindowRect(cache[i]->parent, &docks[i]->position);
    }
    d = FindParams(p, &i);
    if (d)
    {
        free(d);
        memmove(&docks[i], &docks[i + 1], sizeof(CCD_params*) * currentWindows 
            - i - 1);
        memmove(&cache[i], &cache[i + 1], sizeof(CCW_params*) * currentWindows 
            - i - 1);
        currentWindows--;
        CalculateLayout( - 1, 0);
    }
}

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

void dmgrAddFrame(CFW_params *p)
{
    frames[frameMax++] = p;
}

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

void dmgrAddBlank(CCW_params *p)
{
    blanks[blankMax++] = p;
}

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

void dmgrAddGrip(CCW_params *p)
{
    grips[gripMax++] = p;
}

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

void dmgrAddContainer(CCW_params *p)
{
    containers[containerMax++] = p;
}

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

void dmgrStartMoveClient(CCW_params *p, LPARAM lParam)
{
    RECT r;
    int i;
    CCD_params *d = FindParams(p, 0);
    GetFrameWindowRect(&r);
    ClipCursor(&r);

    movept.x = (long)(short)LOWORD(lParam);
    movept.y = (long)(short)HIWORD(lParam);
    ClientToScreen(p->parent, &movept);

    for (i = 0; i < currentWindows; i++)
    {
        GetWindowRect(cache[i]->parent, &docks[i]->position);
        if (!docks[i]->flags)
            docks[i]->oldsize = docks[i]->position;
    }

    moverect = d->oldsize;
    OffsetRect(&moverect,  - moverect.left,  - moverect.top);
    OffsetRect(&moverect, d->position.left, d->position.top);

    moving = 1, drawnbound = 1;
    DrawBoundingRect(&moverect);
    lastSuggestedDock = d->flags &~DOCK_PRESENT;
}

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

void dmgrMoveClient(CCW_params *p, LPARAM lParam, int grip)
{
    RECT r = moverect;
    POINT temppt;
    RECT r1;
    POINT adjust;
    int adj;
    int newcurs = 0;
    temppt.x = (long)(short)LOWORD(lParam);
    temppt.y = (long)(short)HIWORD(lParam);
    if (grip)
        ClientToScreen(p->parent, &temppt);
    else
        ClientToScreen(p->self, &temppt);
    OffsetRect(&r, temppt.x - movept.x, temppt.y - movept.y);
    adjust.x = adjust.y = 0;
    GetFrameWindowRect(&r1);

    if (r1.right < r.right)
    {
        adj = r1.right - r.right;
        r.left += adj;
        r.right += adj;
        adjust.x += adj;
        newcurs++;
    }
    else if (r1.left > r.left)
    {
        adj = r1.left - r.left;
        r.left += adj;
        r.right += adj;
        adjust.x += adj;
        newcurs++;
    }
    if (r1.bottom < r.bottom)
    {
        adj = r1.bottom - r.bottom;
        r.top += adj;
        r.bottom += adj;
        adjust.y += adj;
        newcurs++;
    }
    else if (r1.top > r.top)
    {
        adj = r1.top - r.top;
        r.top += adj;
        r.bottom += adj;
        adjust.y += adj;
        newcurs++;
    }

    CalculateMoveableDocks(p, &r, &temppt);
    if (drawnbound)
        DrawBoundingRect(&lastbound);
    DrawBoundingRect(&r);

}

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

void dmgrStartSizeClient(CCW_params *p, int oncursor, LPARAM lParam)
{
    RECT r;
    GetClientWindowRect(&r);
    ClipCursor(&r);
    movept.x = (long)(short)LOWORD(lParam);
    movept.y = (long)(short)HIWORD(lParam);
    ClientToScreen(p->parent, &movept);
    curstype = oncursor;
    GetWindowRect(p->parent, &moverect);

    sizing = 1, drawnbound = 0;
}

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

void dmgrSizeClient(CCW_params *p, LPARAM lParam)
{
    POINT temppt;
    RECT r = moverect;
    temppt.x = (long)(short)LOWORD(lParam);
    temppt.y = (long)(short)HIWORD(lParam);
    ClientToScreen(p->self, &temppt);
    switch (curstype)
    {
        case HTRIGHT:
            r.right += temppt.x - movept.x;
            if (r.right - r.left < MIN_WIDTH)
                r.right = r.left + MIN_WIDTH;
            break;
        case HTLEFT:
            r.left += temppt.x - movept.x;
            if (r.right - r.left < MIN_WIDTH)
                r.left = r.right - MIN_WIDTH;
            break;
        case HTTOP:
            r.top += temppt.y - movept.y;
            if (r.bottom - r.top < MIN_WIDTH)
                r.top = r.bottom - MIN_WIDTH;
            break;
        case HTBOTTOM:
            r.bottom += temppt.y - movept.y;
            if (r.bottom - r.top < MIN_WIDTH)
                r.bottom = r.top + MIN_WIDTH;
            break;
        case HTTOPRIGHT:
            r.top += temppt.y - movept.y;
            if (r.bottom - r.top < MIN_WIDTH)
                r.top = r.bottom - MIN_WIDTH;
            r.right += temppt.x - movept.x;
            if (r.right - r.left < MIN_WIDTH)
                r.right = r.left + MIN_WIDTH;
            break;
        case HTTOPLEFT:
            r.top += temppt.y - movept.y;
            if (r.bottom - r.top < MIN_WIDTH)
                r.bottom = r.top + MIN_WIDTH;
            r.left += temppt.x - movept.x;
            if (r.right - r.left < MIN_WIDTH)
                r.left = r.right - MIN_WIDTH;
            break;
        case HTBOTTOMRIGHT:
            r.bottom += temppt.y - movept.y;
            if (r.bottom - r.top < MIN_WIDTH)
                r.top = r.bottom - MIN_WIDTH;
            r.right += temppt.x - movept.x;
            if (r.right - r.left < MIN_WIDTH)
                r.right = r.left + MIN_WIDTH;
            break;
        case HTBOTTOMLEFT:
            r.bottom += temppt.y - movept.y;
            if (r.bottom - r.top < MIN_WIDTH)
                r.bottom = r.top + MIN_WIDTH;
            r.left += temppt.x - movept.x;
            if (r.right - r.left < MIN_WIDTH)
                r.left = r.right - MIN_WIDTH;
            break;
    }

    if (drawnbound)
        DrawBoundingRect(&lastbound);
    DrawBoundingRect(&r);
}

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

void dmgrEndMoveSizeClient(CCW_params *p, LPARAM lParam)
{
    int i;
    if (sizing == 0 && moving == 0)
        return ;
    if (drawnbound)
    {
        DrawBoundingRect(&lastbound);
        if (moving)
        {
            DoDocks(p);
            PostMessage(hwndSourceTab, WM_RESETTABS, 0, 0);
        }
        else
            PutWindow(p->parent, &lastbound);
    }
    moving = sizing = 0;
    ClipCursor(0);
}

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

int dmgrStartMoveGrip(CCW_params *p, LPARAM lParam)
{
    CCW_params *p1 = (CCW_params*)GetWindowLong(p->u.gp.child, 0);
    dmgrStartMoveClient(p1, lParam);
    dmgrMoveClient(p1, lParam, TRUE);
}

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

int dmgrMoveGrip(CCW_params *p, LPARAM lParam)
{
    CCW_params *p1 = (CCW_params*)GetWindowLong(p->u.gp.child, 0);
    dmgrMoveClient(p1, lParam, TRUE);
}

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

int dmgrEndMoveGrip(CCW_params *p, LPARAM lParam)
{
    CCW_params *p1 = (CCW_params*)GetWindowLong(p->u.gp.child, 0);
    dmgrEndMoveSizeClient(p1, lParam);
}

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

int dmgrDocked(CCW_params *p)
{
    CCD_params *d = FindParams(p, 0);
    if (d)
    {
        return !!(d->flags &DOCK_PRESENT);
    }
    return FALSE;
}

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

int dmgrSizeBarStartMove(CFW_params *p, LPARAM lParam)
{
    int i;
    RECT r;
    GetWindowRect(p->self, &moverect);
    movept.x = (long)(short)LOWORD(lParam);
    movept.y = (long)(short)HIWORD(lParam);
    ClientToScreen(p->self, &movept);
    drawnbound = FALSE;
    for (i = 0; i < frameCount; i++)
    {
        GetWindowRect(frames[i]->self, &frames[i]->position);
    }
    for (i = 0; i < currentWindows; i++)
    {
        GetWindowRect(cache[i]->parent, &docks[i]->position);
    }
    CalculateSizebarBounds(p, &r);
    ClipCursor(&r);
    drawnbound = 1;
    DrawBoundingRect(&p->position);
}

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

int dmgrSizeBarMove(CFW_params *p, LPARAM lParam)
{
    POINT temp;
    RECT r = moverect;
    temp.x = (long)(short)LOWORD(lParam);
    temp.y = (long)(short)HIWORD(lParam);
    ClientToScreen(p->self, &temp);

    if (!p->vertical)
        OffsetRect(&r, 0, temp.y - movept.y);
    else
        OffsetRect(&r, temp.x - movept.x, 0);
    if (drawnbound)
        DrawBoundingRect(&lastbound);
    DrawBoundingRect(&r);
}

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

int dmgrSizeBarEndMove(CFW_params *p)
{
    ClipCursor(0);

    Resize(p, &lastbound);
    if (drawnbound)
        DrawBoundingRect(&lastbound);
    drawnbound = 0;
    PostMessage(hwndSourceTab, WM_RESETTABS, 0, 0);
}

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

int dmgrFlex(CCW_params *p)
{
    int index;
    CCD_params *d;
    d = FindParams(p, &index);
    d->flexparams |= p->u.cw.flexed ? FLEX_UNREQ : FLEX_REQ;
    CalculateLayout( - 1, 0);
}

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

int dmgrSizeFrame(void)
{
#ifdef XXXXX
    for (i = 0; i < currentWindows; i++)
    {
        GetWindowRect(cache[i]->parent, &docks[i]->position);
    }
#endif
    CalculateLayout( - 1, 0);
}

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

int dmgrGetHiddenState(int id)
{
    int i;
    for (i = 0; i < currentWindows; i++)
        if (cache[i]->id == id)
            return docks[i]->hidden;
    return FALSE;
}

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

int dmgrHideWindow(int id, int state)
{

    int oldstate = 0;
    CCW_params *p = 0;
    CCD_params *d = 0;
    int i, index;
    for (i = 0; i < currentWindows; i++)
    {
        if (cache[i]->id == id)
        {
            p = cache[i];
            d = docks[i];
            index = i;
            break;
        }
    }
    if (p)
    {
        oldstate = !d->hidden;
        if (state != d->hidden)
        {
            d->hidden = state;
            if (d->flags && p->type != LSTOOLBAR)
                CalculateHidden(d, index, state);
            ShowWindow(p->parent, state ? SW_HIDE : SW_SHOW);
            if (d->flags)
                CalculateLayout( - 1, 0);
            SendMessage(hwndSourceTab, WM_RESETTABS, 0, 0);
	        if (!state)
    	        SetFocus(p->parent);
        }
    }
    return oldstate;
}

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

void PutWindow(HWND hwnd, RECT *r)
{
    RECT r1, r2 =  *r;
    if (GetParent(hwnd) == hwndClient)
        GetWindowRect(hwndClient, &r1);
    else
        GetFrameWindowRect(&r1);
    OffsetRect(&r2,  - r1.left,  - r1.top);
    InvalidateRect(hwnd, 0, 0);
    MoveWindow(hwnd, r2.left, r2.top, r2.right - r2.left, r2.bottom - r2.top, 1)
        ;
}

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

#define HYSTER(x,y) ((x)-(y) < 10 && (x)-(y) > -10)
void CalculateMoveableDocks(CCW_params *p, RECT *r, POINT *cursor)
{
    int i, fit =  - 1, fitwidth = 0, index, j;
    CCD_params *d = FindParams(p, &index);
    RECT r1, r2, r3;
    GetFrameWindowRect(&r3);
    GetClientWindowRect(&r1);
    suggestedDock = 0;

    if (HYSTER(cursor->x, r1.left))
    {
        r->top = r1.top;
        r->left = r1.left;
        if (p->type == LSTOOLBAR)
        {
            r->bottom = r->top + p->u.tb.vsize.cy + GRIPWIDTH;
            r->right = r->left + p->u.tb.vsize.cx;
        }
        else
        {
            r->bottom = r1.bottom;
            r->right = DEFAULT_WIDTH + r->left;
        }
        suggestedDock = DOCK_LEFT;
    }
    else if (HYSTER(cursor->y, r1.top))
    {
        r->left = r3.left;
        r->top = r1.top;
        if (p->type == LSTOOLBAR)
        {
            r->bottom = r->top + p->u.tb.hsize.cy;
            r->right = r->left + p->u.tb.hsize.cx + GRIPWIDTH;
        }
        else
        {
            r->right = r3.right;
            r->bottom = DEFAULT_HEIGHT + r->top;
        }
        suggestedDock = DOCK_TOP;
    }
    else if (HYSTER(cursor->x, r1.right))
    {
        r->top = r1.top;
        r->right = r1.right;
        if (p->type == LSTOOLBAR)
        {
            r->bottom = r->top + p->u.tb.vsize.cy + GRIPWIDTH;
            r->left = r->right - p->u.tb.vsize.cx;
        }
        else
        {
            r->bottom = r1.bottom;
            r->left = r->right - DEFAULT_WIDTH;
        }
        suggestedDock = DOCK_RIGHT;
    }
    else if (HYSTER(cursor->y, r1.bottom))
    {
        r->left = r3.left;
        r->bottom = r1.bottom;
        if (p->type == LSTOOLBAR)
        {
            r->top = r->bottom - p->u.tb.hsize.cy;
            r->right = r->left + p->u.tb.hsize.cx + GRIPWIDTH;
        }
        else
        {
            r->right = r3.right;
            r->top = r->bottom - DEFAULT_HEIGHT;
        }
        suggestedDock = DOCK_BOTTOM;
    }
    else
    {
        RECT dest;
        for (i = 0; i < currentWindows; i++)
        {
            if ((docks[i]->flags &DOCK_PRESENT) && !docks[i]->hidden)
            {
                if (PtInRect(&docks[i]->position,  *cursor))
                {
                    fit = i;
                    break;
                }
            }
        }
        if (fit !=  - 1)
        {

            int insert = 0, width;
            if (docks[fit]->flags &(DOCK_BOTTOM | DOCK_TOP))
            {
                if (p->type == LSTOOLBAR)
                {
                    if (docks[fit]->flags &DOCK_TOP)
                    {
                        r->top = docks[fit]->position.top;
                        r->bottom = r->top + p->u.tb.hsize.cy;
                    }
                    else
                    {
                        r->bottom = docks[fit]->position.bottom;
                        r->top = r->bottom - p->u.tb.hsize.cy;
                    }
                    r->right = r->left + p->u.tb.hsize.cx + GRIPWIDTH;
                }
                else
                {
                    r->top = docks[fit]->position.top;
                    r->bottom = docks[fit]->position.bottom;
                }
            }
            else
            {
                if (p->type == LSTOOLBAR)
                {
                    if (docks[fit]->flags &DOCK_LEFT)
                    {
                        r->left = docks[fit]->position.left;
                        r->right = r->left + p->u.tb.vsize.cx;
                    }
                    else
                    {
                        r->right = docks[fit]->position.right;
                        r->left = r->right - p->u.tb.vsize.cx;
                    }
                    r->bottom = r->top + p->u.tb.vsize.cy + GRIPWIDTH;
                }
                else
                {
                    r->left = docks[fit]->position.left;
                    r->right = docks[fit]->position.right;
                }
            }
            suggestedDock = docks[fit]->flags;
        }
        else
        {
            if (p->type == LSTOOLBAR)
            {
                for (i = 0; i < blankCount; i++)
                {
                    if (PtInRect(&blanks[i]->u.bw.position,  *cursor))
                    {
                        fit = i;
                        break;
                    }
                }
                if (fit !=  - 1)
                {
                    if (blanks[fit]->u.bw.representative_dock->flags &
                        (DOCK_LEFT | DOCK_RIGHT))
                    {
                        r->left = blanks[fit]->u.bw.representative_dock
                            ->position.left;
                        r->right = blanks[fit]->u.bw.representative_dock
                            ->position.right;
                        r->bottom = r->top + p->u.tb.vsize.cy + GRIPWIDTH;
                    }
                    else
                    {
                        r->top = blanks[fit]->u.bw.representative_dock
                            ->position.top;
                        r->bottom = blanks[fit]->u.bw.representative_dock
                            ->position.bottom;
                        r->right = r->left + p->u.tb.hsize.cx + GRIPWIDTH;
                    }
                    suggestedDock = blanks[fit]->u.bw.representative_dock
                        ->flags;
                }
            }
        }
    }
    lastSuggestedDock = suggestedDock;
}

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

void NewParent(HWND hwnd, HWND owner)
{
    InvalidateRect(hwnd, 0, 0);
    SetParent(hwnd, owner);
}

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

int InsertRow(int index, int dflag)
{
    int maxindex = 0, i;
    RECT dest;
    if (index >= 0)
    {
        docks[index]->rowindex =  - 1;
        for (i = 0; i < currentWindows; i++)
        {
            if (i == index)
                continue;
            if (docks[i]->rowindex > maxindex)
                maxindex = docks[i]->rowindex;
            if (docks[i]->flags &dflag)
            {
                if (cache[i]->type == cache[index]->type)
                {
                    if (docks[index]->position.top == docks[i]->position.top &&
                        docks[index]->position.bottom == docks[i]
                        ->position.bottom)
                        return docks[index]->rowindex = docks[i]->rowindex;
                }
                else
                {
                    if (dflag &DOCK_TOP)
                    {
                        if (docks[index]->position.top == docks[i]
                            ->position.top)
                        {
                            docks[index]->rowindex = docks[i]->rowindex;
                            break;
                        }
                    }
                    else
                    {
                        if (docks[index]->position.bottom == docks[i]
                            ->position.bottom)
                        {
                            docks[index]->rowindex = docks[i]->rowindex;
                            break;
                        }
                    }
                }
            }
        }
        if (docks[index]->rowindex ==  - 1)
        {
            docks[index]->rowindex = maxindex + 1;
        }
        else
        {
            for (i = 0; i < currentWindows; i++)
                if (i != index && (docks[i]->flags &dflag) && docks[i]
                    ->rowindex >= docks[index]->rowindex)
                    docks[i]->rowindex++;

        }
        return docks[index]->rowindex;
    }
    return 0;
}

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

void OrderLeftRight(int *windows, int wincount, int byposition)
{
    int i, j;
    if (byposition)
        for (i = 0; i < wincount - 1; i++)
    for (j = i + 1; j < wincount; j++)
    {
        CCD_params *d1 = docks[windows[j]],  *d2 = docks[windows[i]];
        if (d1->position.left < d2->position.left || (d1->position.left == d2
            ->position.left && d2->position.right > d1->position.right))
        {
            int val = windows[j];
            windows[j] = windows[i];
            windows[i] = val;
        }
    }
    else
        for (i = 0; i < wincount - 1; i++)
    for (j = i + 1; j < wincount; j++)
    {
        CCD_params *d1 = docks[windows[j]],  *d2 = docks[windows[i]];
        if (d1->colindex < d2->colindex)
        {
            int val = windows[j];
            windows[j] = windows[i];
            windows[i] = val;
        }
    }
}

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

int IndexLeftRight(int *windows, int wincount, int index)
{
    int j;
    RECT dest;
    int maxindex =  - 1, max = 0;
    if (docks[index]->oldflags == docks[index]->flags && docks[index]
        ->position.top == docks[index]->lastposition.top)
    if (IntersectRect(&dest, &docks[index]->position, &docks[index]
        ->lastposition))
    {
        if (dest.right - dest.left > max)
        {
            max = dest.right - dest.left;
            maxindex =  - 2;
        }
    }
    for (j = 0; j < wincount; j++)
    {
        if (IntersectRect(&dest, &docks[index]->position, &docks[windows[j]]
            ->position))
        {
            if (dest.right - dest.left > max)
            {
                max = dest.right - dest.left;
                maxindex = j;
            }
        }
    }
    if (maxindex ==  - 1)
    {
        for (maxindex = wincount; maxindex > 0; maxindex--)
        if (docks[index]->position.left > docks[windows[maxindex - 1]]
            ->position.left)
        {
            break;
        }
    }

    return maxindex;
}

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

int InsertLeftRight(int *windows, int wincount, int index, RECT *frame, int min)
{
    int i;
    for (i = 0; i < wincount; i++)
        if (index == windows[i])
            return 0;
    //      if (wincount && cache[windows[0]]->type == LSTOOLBAR || !wincount && cache[index]->type == LSTOOLBAR) {
    //         i = wincount ;
    //      } else 
    {

        i = IndexLeftRight(windows, wincount, index);
        if (i < wincount)
        {
            if (i ==  - 2)
            {
                for (i = 0; i < wincount && docks[windows[i]]->position.left <
                    docks[index]->position.left; i++)
                    ;
            }
            else if (i !=  - 1)
            {
                int val1 = (docks[windows[i]]->position.right +
                    docks[windows[i]]->position.left) / 2;
                if (docks[index]->position.left > val1)
                {
                    i++;
                }
                else if (docks[index]->position.right > val1)
                {
                    if (val1 - docks[index]->position.left < docks[index]
                        ->position.right - val1)
                        i++;
                }
            }
            else
                i = 0;
        }
        if (docks[index]->oldflags != docks[index]->flags || docks[index]
            ->lastposition.top != min)
            docks[index]->position.right = docks[index]->position.left + (frame
                ->right - frame->left) / (wincount ? wincount : 1);
        else
            docks[index]->position.right = docks[index]->position.left +
                docks[index]->lastposition.right - docks[index]
                ->lastposition.left;
    }

    memmove(&windows[i + 1], &windows[i], (wincount - i) *sizeof(int));
    windows[i] = index;
    wincount++;

    if (cache[windows[0]]->type == LSTOOLBAR)
    {
        for (i = 1; i < wincount; i++)
        if (docks[windows[i]]->position.left < docks[windows[i - 1]]
            ->position.left + cache[windows[i - 1]]->u.tb.hsize.cx + GRIPWIDTH)
        {
            docks[windows[i]]->position.left = docks[windows[i - 1]]
                ->position.left + cache[windows[i - 1]]->u.tb.hsize.cx +
                GRIPWIDTH;
            docks[windows[i]]->position.right = docks[windows[i]]
                ->position.left + cache[windows[i]]->u.tb.hsize.cx + GRIPWIDTH;
        }
    }
    return 1;
}

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

void HideAdjLeftRight(int *windows, int wincount, int index)
{
    if (cache[index]->type == LSTOOLBAR)
    {
        return ;
    }
    if (wincount <= 1)
        docks[index]->hiddenwidth = 1000 *(docks[index]->position.right -
            docks[index]->position.left);
    else
    {
        int j, unhiddenwidth = 0, totalwidth = 0;
        RECT r;
        int sizewidth, scale;
        OrderLeftRight(windows, wincount, TRUE);
        GetFrameWindowRect(&r);
        sizewidth = r.right - r.left;
        docks[index]->hiddenwidth = 0;
        for (j = 0; j < wincount; j++)
        {
            docks[windows[j]]->colindex = j;
            if (windows[j] != index)
            {
                totalwidth += docks[windows[j]]->hiddenwidth;
                if (!docks[windows[j]]->hidden)
                    unhiddenwidth += docks[windows[j]]->hiddenwidth;
            }
        }
        if (!unhiddenwidth)
        {
            // if there is a bug and unhiddenwith is zero, resync
            for (j = 0; j < wincount; j++)
                docks[windows[j]]->hiddenwidth = 1000 *(r.right - r.left) /
                    wincount;
        }
        else
        {
            docks[index]->hiddenwidth = totalwidth / (wincount - 1);
            if (!docks[index]->hidden)
                unhiddenwidth += docks[index]->hiddenwidth;
            scale = unhiddenwidth / sizewidth;
            for (j = 0; j < wincount; j++)
                docks[windows[j]]->hiddenwidth = docks[windows[j]]->hiddenwidth
                    *1000 / scale;
        }
    }
}

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

void SizeLeftRight(int *windows, int wincount, int adj, RECT *r2)
{
    int i, j, multiply = 1000;
    int framesize = r2->right - r2->left;
    int actualsize = 0, currentleft = r2->left, newright;
    if (cache[windows[0]]->type != LSTOOLBAR)
        framesize -= (wincount - 1) *FRAMEWIDTH;
    for (i = 0; i < wincount; i++)
    {
        int v = windows[i];
        actualsize += docks[windows[i]]->position.right - docks[windows[i]]
            ->position.left;
        if (docks[windows[i]]->flexparams &(FLEX_LARGE | FLEX_SMALL))
            docks[windows[i]]->position = docks[windows[i]]->flexposition;
    }
    if (actualsize != framesize && actualsize)
    {
        multiply = 1000 * framesize / actualsize;
    }
    for (i = 0; i < wincount; i++)
    {
		if (docks[windows[0]]->flags & DOCK_TOP) 
		{
	        docks[windows[i]]->position.bottom = adj
					+ docks[windows[0]]->position.bottom 
					- docks[windows[0]]->position.top ;
	        docks[windows[i]]->position.top = adj;
		} 
		else
		{
	        docks[windows[i]]->position.top = adj
					- docks[windows[0]]->position.bottom 
					+ docks[windows[0]]->position.top ;
	        docks[windows[i]]->position.bottom = adj;
		}
        if (cache[windows[0]]->type == LSTOOLBAR)
        {
//            currentleft = docks[windows[i]]->position.left;
            if (currentleft < r2->left || currentleft >= r2->right - GRIPWIDTH)
                if (i == 0)
                    currentleft = r2->left;
                else
                    currentleft = docks[windows[i - 1]]->position.right;
            if (i > 0 && currentleft < docks[windows[i - 1]]->position.right)
                currentleft = docks[windows[i - 1]]->position.right;
            newright = currentleft + cache[windows[i]]->u.tb.hsize.cx +
                GRIPWIDTH;
            docks[windows[i]]->position.right = newright;
        }
        else
        {
            newright = docks[windows[i]]->position.right = currentleft + 
                (docks[windows[i]]->position.right - docks[windows[i]]
                ->position.left) *multiply / 1000;
        }
        docks[windows[i]]->position.left = currentleft;
		docks[windows[i]]->position.right = newright ;
        currentleft = newright;
        if (cache[windows[0]]->type != LSTOOLBAR) {
            currentleft += FRAMEWIDTH;
		}
    }
    if (cache[windows[0]]->type != LSTOOLBAR)
        docks[windows[wincount - 1]]->position.right = r2->right;
    if (wincount == 1)
    {
        SendMessage(cache[windows[0]]->self, LCF_SETFLEX, 0, wincount != 1);
    }
    else
    {
        for (i = 0; i < wincount; i++)
        {
            if (docks[windows[i]]->flexparams &FLEX_UNREQ)
            {
                for (j = 0; j < wincount; j++)
                    docks[windows[j]]->flexparams = 0;
                break;
            }
            else if (docks[windows[i]]->flexparams &FLEX_REQ)
            {
                for (j = 0; j < wincount; j++)
                    docks[windows[j]]->flexparams = FLEX_SMALL;
                docks[windows[i]]->flexparams = FLEX_LARGE;
                break;
            }
            docks[windows[i]]->flexparams &= ~(FLEX_UNREQ | FLEX_REQ);
        }
        if (docks[windows[0]]->flexparams &(FLEX_SMALL | FLEX_LARGE))
        {
            framesize -= (wincount - 1) *MIN_SIZE;
            currentleft = r2->left;

            for (i = 0; i < wincount; i++)
                if (docks[windows[i]]->flexparams &FLEX_LARGE)
                    break;

            if (i < wincount)
            for (i = 0; i < wincount; i++)
            {
                docks[windows[i]]->flexposition = docks[windows[i]]->position;
                docks[windows[i]]->position.left = currentleft;
                if (docks[windows[i]]->flexparams &FLEX_LARGE)
                    currentleft = docks[windows[i]]->position.right =
                        currentleft + framesize;
                else
                    currentleft = docks[windows[i]]->position.right =
                        currentleft + MIN_SIZE;
                currentleft += FRAMEWIDTH;
            }
            else
                for (i = 0; i < wincount; i++)
                    docks[windows[i]]->flexparams = 0;
        }
        for (i = 0; i < wincount; i++)
        {
            SendMessage(cache[windows[i]]->self, LCF_SETFLEX, docks[windows[i]]
                ->flexparams &FLEX_LARGE ? 1 : 0, wincount != 1);
            if (i != wincount - 1 && cache[windows[i]]->type != LSTOOLBAR)
                InsertVertFrame(windows[i], 0, 0);
        }
    }
    if (cache[windows[0]]->type == LSTOOLBAR)
    {
        int left = r2->left;
        RECT r = docks[windows[0]]->position;
        for (i = 0; i < wincount; i++)
        {
            if (left < docks[windows[i]]->position.left)
            {
                r.left = left;
                r.right = docks[windows[i]]->position.left;
                AllocBlank(&r, docks[windows[0]], FALSE);
            }
            left = docks[windows[i]]->position.right;
        }
        if (left < r2->right)
        {
            r. left = left;
            r.right = r2->right;
            AllocBlank(&r, docks[windows[0]], FALSE);
        }
    }
}

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

int InsertColumn(int index, int dflag)
{
    int maxindex = 0, i;
    RECT dest;
    if (index >= 0)
    {
        docks[index]->rowindex =  - 1;
        for (i = 0; i < currentWindows; i++)
        {
            if (i == index)
                continue;
            if (docks[i]->rowindex > maxindex)
                maxindex = docks[i]->rowindex;
            if (docks[i]->flags &dflag)
            {
                if (cache[i]->type == cache[index]->type)
                {
                    if (docks[index]->position.left == docks[i]->position.left
                        && docks[index]->position.right == docks[i]
                        ->position.right)
                        return docks[index]->rowindex = docks[i]->rowindex;
                }
                else
                {
                    if (dflag &DOCK_LEFT)
                    {
                        if (docks[index]->position.left == docks[i]
                            ->position.left)
                        {
                            docks[index]->rowindex = docks[i]->rowindex;
                            break;
                        }
                    }
                    else
                    {
                        if (docks[index]->position.right == docks[i]
                            ->position.right)
                        {
                            docks[index]->rowindex = docks[i]->rowindex;
                            break;
                        }
                    }
                }
            }
        }
        if (docks[index]->rowindex ==  - 1)
        {
            docks[index]->rowindex = maxindex + 1;
        }
        else
        {
            for (i = 0; i < currentWindows; i++)
                if (i != index && (docks[i]->flags &dflag) && docks[i]
                    ->rowindex >= docks[index]->rowindex)
                    docks[i]->rowindex++;

        }
        return docks[index]->rowindex;
    }
    return 0;
}

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

void OrderTopBottom(int *windows, int wincount, int byposition)
{
    int i, j;
    if (byposition)
        for (i = 0; i < wincount - 1; i++)
    for (j = i + 1; j < wincount; j++)
    {
        CCD_params *d1 = docks[windows[j]],  *d2 = docks[windows[i]];
        if (d1->position.top < d2->position.top || (d1->position.top == d2
            ->position.top && d2->position.bottom > d1->position.bottom))
        {
            int val = windows[j];
            windows[j] = windows[i];
            windows[i] = val;
        }
    }
    else
        for (i = 0; i < wincount - 1; i++)
    for (j = i + 1; j < wincount; j++)
    {
        CCD_params *d1 = docks[windows[j]],  *d2 = docks[windows[i]];
        if (d1->colindex < d2->colindex)
        {
            int val = windows[j];
            windows[j] = windows[i];
            windows[i] = val;
        }
    }
}

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

int IndexTopBottom(int *windows, int wincount, int index)
{
    int j;
    RECT dest;
    int maxindex =  - 1, max = 0;
    if (docks[index]->oldflags == docks[index]->flags && docks[index]
        ->position.left == docks[index]->lastposition.left)
    if (IntersectRect(&dest, &docks[index]->position, &docks[index]
        ->lastposition))
    {
        if (dest.bottom - dest.top > max)
        {
            max = dest.bottom - dest.top;
            maxindex =  - 2;
        }
    }
    for (j = 0; j < wincount; j++)
    {
        if (IntersectRect(&dest, &docks[index]->position, &docks[windows[j]]
            ->position))
        {
            if (dest.bottom - dest.top > max)
            {
                max = dest.bottom - dest.top;
                maxindex = j;
            }
        }
    }
    if (maxindex ==  - 1)
    {
        for (maxindex = wincount; maxindex > 0; maxindex--)
        if (docks[index]->position.top > docks[windows[maxindex - 1]]
            ->position.top)
        {
            break;
        }
    }
    return maxindex;
}

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

int InsertTopBottom(int *windows, int wincount, int index, RECT *frame, int min)
{
    int i;
    for (i = 0; i < wincount; i++)
        if (index == windows[i])
            return 0;
    //      if (wincount && cache[windows[0]]->type == LSTOOLBAR || !wincount && cache[index]->type == LSTOOLBAR)
    //         i = wincount ;
    //      else 
    {
        i = IndexTopBottom(windows, wincount, index);
        if (i < wincount)
        {
            if (i ==  - 2)
            {
                for (i = 0; i < wincount && docks[windows[i]]->position.top <
                    docks[index]->position.top; i++)
                    ;
            }
            else if (i !=  - 1)
            {
                int val1 = (docks[windows[i]]->position.bottom +
                    docks[windows[i]]->position.top) / 2;
                if (docks[index]->position.top > val1)
                {
                    i++;
                }
                else if (docks[index]->position.bottom > val1)
                {
                    if (val1 - docks[index]->position.top < docks[index]
                        ->position.bottom - val1)
                        i++;
                }
            }
            else
                i = 0;
        }
        if (docks[index]->oldflags != docks[index]->flags || docks[index]
            ->lastposition.left != min)
            docks[index]->position.bottom = docks[index]->position.top + (frame
                ->bottom - frame->top) / (wincount ? wincount : 1);
        else
            docks[index]->position.bottom = docks[index]->position.top +
                docks[index]->lastposition.bottom - docks[index]
                ->lastposition.top;
    }
    memmove(&windows[i + 1], &windows[i], (wincount - i) *sizeof(int));
    windows[i] = index;
    wincount++;
    if (cache[windows[0]]->type == LSTOOLBAR)
    {
        for (i = 1; i < wincount; i++)
        if (docks[windows[i]]->position.top < docks[windows[i - 1]]
            ->position.top + cache[windows[i - 1]]->u.tb.vsize.cy + GRIPWIDTH)
        {
            docks[windows[i]]->position.top = docks[windows[i - 1]]
                ->position.top + cache[windows[i - 1]]->u.tb.vsize.cy +
                GRIPWIDTH;
            docks[windows[i]]->position.bottom = docks[windows[i]]
                ->position.top + cache[windows[i]]->u.tb.vsize.cy + GRIPWIDTH;
        }
    }
    return 1;
}

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

void HideAdjTopBottom(int *windows, int wincount, int index)
{
    if (cache[index]->type == LSTOOLBAR)
    {
        return ;
    }
    if (wincount <= 1)
        docks[index]->hiddenwidth = 1000 *(docks[index]->position.bottom -
            docks[index]->position.top);
    else
    {
        int j, unhiddenwidth = 0, totalwidth = 0;
        RECT r;
        int sizewidth, scale;
        OrderTopBottom(windows, wincount, TRUE);
        GetWindowRect(hwndClient, &r);
        sizewidth = r.bottom - r.top;
        docks[index]->hiddenwidth = 0;
        for (j = 0; j < wincount; j++)
        {
            docks[windows[j]]->colindex = j;
            if (windows[j] != index)
            {
                totalwidth += docks[windows[j]]->hiddenwidth;
                if (!docks[windows[j]]->hidden)
                    unhiddenwidth += docks[windows[j]]->hiddenwidth;
            }
        }
        if (!unhiddenwidth)
        {
            // if there is a bug and unhiddenwith is zero, resync
            for (j = 0; j < wincount; j++)
                docks[windows[j]]->hiddenwidth = 1000 *(r.bottom - r.top) /
                    wincount;
        }
        else
        {
            docks[index]->hiddenwidth = totalwidth / (wincount - 1);
            if (!docks[index]->hidden)
                unhiddenwidth += docks[index]->hiddenwidth;
            scale = unhiddenwidth / sizewidth;
            totalwidth = totalwidth * 1000 / scale;
            for (j = 0; j < wincount; j++)
                docks[windows[j]]->hiddenwidth = docks[windows[j]]->hiddenwidth
                    *1000 / scale;
        }
    }
}

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

void SizeTopBottom(int *windows, int wincount, int adj, RECT *client, RECT
    *oldclient)
{
    int i, j, multiply = 1000;
    int framesize = client->bottom - client->top;
    int actualsize = 0, currenttop = client->top, newbottom;
    if (cache[windows[0]]->type != LSTOOLBAR)
        framesize -= (wincount - 1) *FRAMEWIDTH;
    for (i = 0; i < wincount; i++)
    {
        actualsize += docks[windows[i]]->position.bottom - docks[windows[i]]
            ->position.top;
        if (docks[windows[i]]->flexparams &(FLEX_LARGE | FLEX_SMALL))
            docks[windows[i]]->position = docks[windows[i]]->flexposition;
    }
    if (actualsize != framesize && actualsize)
    {
        multiply = 1000 * framesize / actualsize;
    }
    for (i = 0; i < wincount; i++)
    {
		if (docks[windows[0]]->flags & DOCK_LEFT) 
		{
	        docks[windows[i]]->position.right = adj
					+ docks[windows[0]]->position.right
					- docks[windows[0]]->position.left ;
	        docks[windows[i]]->position.left = adj;
		}
		else
		{
	        docks[windows[i]]->position.left = adj
					- docks[windows[0]]->position.right
					+ docks[windows[0]]->position.left ;
	        docks[windows[i]]->position.right = adj;
		}
        if (cache[windows[0]]->type == LSTOOLBAR)
        {
//            currenttop = docks[windows[i]]->position.top - oldclient->top +
//                client->top;
            if (currenttop < client->top || currenttop >= client->bottom -
                GRIPWIDTH)
                if (i = 0)
                    currenttop = client->top;
                else
                    currenttop = docks[windows[i - 1]]->position.bottom;
            if (i > 0 && currenttop < docks[windows[i - 1]]->position.bottom)
                currenttop = docks[windows[i - 1]]->position.bottom;
            newbottom = currenttop + cache[windows[i]]->u.tb.vsize.cy +
                GRIPWIDTH;
            docks[windows[i]]->position.bottom = newbottom;
        }
        else
        {
            newbottom = docks[windows[i]]->position.bottom = currenttop + 
                (docks[windows[i]]->position.bottom - docks[windows[i]]
                ->position.top) *multiply / 1000;
        }
        docks[windows[i]]->position.top = currenttop;
		docks[windows[i]]->position.bottom = newbottom ;
        currenttop = newbottom;
        if (cache[windows[0]]->type != LSTOOLBAR) {
            currenttop += FRAMEWIDTH;
		}
    }
    if (cache[windows[0]]->type != LSTOOLBAR)
        docks[windows[wincount - 1]]->position.bottom = client->bottom;
    if (wincount == 1)
    {
        SendMessage(cache[windows[0]]->self, LCF_SETFLEX, 0, wincount != 1);
    }
    else
    {
        for (i = 0; i < wincount; i++)
        {
            if (docks[windows[i]]->flexparams &FLEX_UNREQ)
            {
                for (j = 0; j < wincount; j++)
                    docks[windows[j]]->flexparams = 0;
                break;
            }
            else if (docks[windows[i]]->flexparams &FLEX_REQ)
            {
                for (j = 0; j < wincount; j++)
                    docks[windows[j]]->flexparams = FLEX_SMALL;
                docks[windows[i]]->flexparams = FLEX_LARGE;
                break;
            }
            docks[windows[i]]->flexparams &= ~(FLEX_UNREQ | FLEX_REQ);
        }
        if (docks[windows[0]]->flexparams &(FLEX_SMALL | FLEX_LARGE))
        {
            framesize -= (wincount - 1) *MIN_SIZE;
            currenttop = client->top;

            for (i = 0; i < wincount; i++)
                if (docks[windows[i]]->flexparams &FLEX_LARGE)
                    break;
            if (i < wincount)
            for (i = 0; i < wincount; i++)
            {
                docks[windows[i]]->flexposition = docks[windows[i]]->position;
                docks[windows[i]]->position.top = currenttop;
                if (docks[windows[i]]->flexparams &FLEX_LARGE)
                    currenttop = docks[windows[i]]->position.bottom =
                        currenttop + framesize;
                else
                    currenttop = docks[windows[i]]->position.bottom =
                        currenttop + MIN_SIZE;
                currenttop += FRAMEWIDTH;
            }
            else
                for (i = 0; i < wincount; i++)
                    docks[windows[i]]->flexparams = 0;
        }
        for (i = 0; i < wincount; i++)
        {
            SendMessage(cache[windows[i]]->self, LCF_SETFLEX, docks[windows[i]]
                ->flexparams &FLEX_LARGE ? 1 : 0, wincount != 1);
            if (i != wincount - 1 && cache[windows[i]]->type != LSTOOLBAR)
                InsertHorizFrame(windows[i], 0, 0);
        }
    }
    if (cache[windows[0]]->type == LSTOOLBAR)
    {
        int top = client->top;
        RECT r = docks[windows[0]]->position;
        for (i = 0; i < wincount; i++)
        {
            if (top < docks[windows[i]]->position.top)
            {
                r.top = top;
                r.bottom = docks[windows[i]]->position.top;
                AllocBlank(&r, docks[windows[0]], FALSE);
            }
            top = docks[windows[i]]->position.bottom;
        }
        if (top < client->bottom)
        {
            r.top = top;
            r.bottom = client->bottom;
            AllocBlank(&r, docks[windows[0]], FALSE);
        }
    }
}

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

void InsertVertFrame(int index, int left, RECT *fullframe)
{
    RECT r, r1;
    CCD_params *d = docks[index];
    GetFrameWindowRect(&r1);
    if (left)
    {
        r.right = d->position.left;
        r.left = d->position.left - FRAMEWIDTH;
    }
    else
    {
        r.left = d->position.right;
        r.right = d->position.right + FRAMEWIDTH;
    }
    if (fullframe)
    {
        r.top = fullframe->top;
        r.bottom = fullframe->bottom;
    }
    else
    {
        r.top = d->position.top;
        r.bottom = d->position.bottom;
    }
    OffsetRect(&r,  - r1.left,  - r1.top);
    if (frameCount >= frameMax)
    {
        CreateFrameWindow(hwndFrame, &r, TRUE);
        frameCount++;
    }
    else
    {
        frames[frameCount]->vertical = TRUE;
        frames[frameCount]->position = r;
        InvalidateRect(frames[frameCount]->self, 0, 0);
        MoveWindow(frames[frameCount++]->self, r.left, r.top, r.right - r.left,
            r.bottom - r.top, 1);
    }
}

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

void InsertHorizFrame(int index, int top, int fullframe)
{
    RECT r, r1;
    CCD_params *d = docks[index];
    GetFrameWindowRect(&r1);
    if (top)
    {
        r.top = d->position.top - FRAMEWIDTH;
        r.bottom = d->position.top;
    }
    else
    {
        r.top = d->position.bottom;
        r.bottom = d->position.bottom + FRAMEWIDTH;
    }
    if (fullframe)
    {
        r.left = r1.left;
        r.right = r1.right;
    }
    else
    {
        r.left = d->position.left;
        r.right = d->position.right;
    }
    OffsetRect(&r,  - r1.left,  - r1.top);
    if (frameCount >= frameMax)
    {
        CreateFrameWindow(hwndFrame, &r, FALSE);
        frameCount++;
    }
    else
    {
        frames[frameCount]->vertical = FALSE;
        frames[frameCount]->position = r;
        InvalidateRect(frames[frameCount]->self, 0, 0);
        MoveWindow(frames[frameCount++]->self, r.left, r.top, r.right - r.left,
            r.bottom - r.top, 1);
    }
}

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

void CalculateLayout(int index, int recalhidden)
{
    int i, j, pos, indexmax, min, adj2, found, hidden, totalsize;
    int windows[30], wincount, hwindows[30], hwincount;
    int srctabheight;
    RECT r1, r2, temp, client, oldclient;
    GetWindowRect(hwndClient, &r1);
    GetFrameWindowRect(&r2);
    client = r2;
    oldclient = r1;
    oldclient.top -= SendMessage(hwndSourceTab, WM_GETHEIGHT, 0, 0);
    if (rundown)
        return ;

    blankCount = 0;
    frameCount = 0;
    if (index >= 0)
        docks[index]->rowindex =  - 1;

    if (index >= 0 && (docks[index]->flags &DOCK_TOP))
        InsertRow(index, DOCK_TOP);
    indexmax =  - 1;
    for (i = 0, min =  - 1; i < currentWindows; i++)
    if (docks[i]->flags &DOCK_TOP)
    {
        if (docks[i]->rowindex > indexmax)
            indexmax = docks[i]->rowindex;
    }
    adj2 = 0;
    for (i = 0; i <= indexmax; i++)
    {
        found = FALSE, hidden = FALSE;
        hwincount = 0;
        wincount = 0;
        for (j = 0; j < currentWindows; j++)
        if ((docks[j]->flags &DOCK_TOP) && docks[j]->rowindex == i)
        {
            docks[j]->rowindex -= adj2;
            if (!docks[j]->hidden)
            {
                found = TRUE;
                min = docks[j]->position.top;
                if (j != index)
                    windows[wincount++] = j;
            }
            else
                hidden = TRUE;
            hwindows[hwincount++] = j;
        }
        if (!found)
        {
            if (!hidden)
                adj2++;
            continue;
        }
        OrderLeftRight(windows, wincount, FALSE);
        if (index >= 0 && docks[index]->rowindex == i - adj2 && (docks[index]
            ->flags &DOCK_TOP) && !docks[index]->hidden)
        {
            wincount += InsertLeftRight(windows, wincount, index, &r2, min);
            HideAdjLeftRight(hwindows, hwincount, index);
            index =  - 1;
        }
        for (j = 0; j < wincount; j++) {
            docks[windows[j]]->colindex = j;
		}
        SizeLeftRight(windows, wincount, client.top, &r2);
        if (recalhidden)
        {
            totalsize = 0;
            for (j = 0; j < wincount; j++)
            {
                totalsize += docks[j]->hiddenwidth = (docks[j]->position.right 
                    - docks[j]->position.left) *1000;
            }
            for (j = 0; j < hwincount; j++)
            {
                if (docks[j]->hidden)
                {
                    docks[j]->hiddenwidth = totalsize / wincount;
                }
            }
        }
        if (cache[windows[0]]->type != LSTOOLBAR)
        {
            InsertHorizFrame(windows[0], 0, 1);
            client.top = FRAMEWIDTH;
        }
        else
            client.top = 0;
        client.top += docks[windows[0]]->position.bottom;
    }
    if (index >= 0 && (docks[index]->flags &DOCK_BOTTOM))
        InsertRow(index, DOCK_BOTTOM);
    indexmax =  - 1;
    for (i = 0, min =  - 1; i < currentWindows; i++)
    if (docks[i]->flags &DOCK_BOTTOM)
    {
        if (docks[i]->rowindex > indexmax)
            indexmax = docks[i]->rowindex;
    }
    adj2 = 0;
    for (i = 0; i <= indexmax; i++)
    {
        found = FALSE, hidden = FALSE;
        hwincount = 0;
        wincount = 0;
        for (j = 0; j < currentWindows; j++)
        if ((docks[j]->flags &DOCK_BOTTOM) && docks[j]->rowindex == i)
        {
            docks[j]->rowindex -= adj2;
            if (!docks[j]->hidden)
            {
                found = TRUE;
                min = docks[j]->position.bottom;
                if (j != index)
                    windows[wincount++] = j;
            }
            else
                hidden = TRUE;
            hwindows[hwincount++] = j;
        }
        if (!found)
        {
            if (!hidden)
                adj2++;
            continue;
        }
        OrderLeftRight(windows, wincount, FALSE);
        if (index >= 0 && docks[index]->rowindex == i - adj2 && (docks[index]
            ->flags &DOCK_BOTTOM) && !docks[index]->hidden)
        {
            wincount += InsertLeftRight(windows, wincount, index, &r2, min);
            HideAdjLeftRight(hwindows, hwincount, index);
            index =  - 1;
        }
        for (j = 0; j < wincount; j++) {
            docks[windows[j]]->colindex = j;
		}
        SizeLeftRight(windows, wincount, client.bottom, &r2);
        if (recalhidden)
        {
            totalsize = 0;
            for (j = 0; j < wincount; j++)
            {
                totalsize += docks[j]->hiddenwidth = (docks[j]->position.right 
                    - docks[j]->position.left) *1000;
            }
            for (j = 0; j < hwincount; j++)
            {
                if (docks[j]->hidden)
                {
                    docks[j]->hiddenwidth = totalsize / wincount;
                }
            }
        }
        if (cache[windows[0]]->type != LSTOOLBAR)
        {
            InsertHorizFrame(windows[0], 1, 1);
            client.bottom =  - FRAMEWIDTH;
        }
        else
            client.bottom = 0;
        client.bottom += docks[windows[0]]->position.top;
    }
    indexmax =  - 1;
    if (index >= 0 && (docks[index]->flags &DOCK_LEFT))
        InsertColumn(index, DOCK_LEFT);
    for (i = 0, min =  - 1; i < currentWindows; i++)
    if (docks[i]->flags &DOCK_LEFT)
    {
        if (docks[i]->rowindex > indexmax)
            indexmax = docks[i]->rowindex;
    }
    adj2 = 0;
    if (index ==  - 2)
        oldclient = client;
    for (i = 0; i <= indexmax; i++)
    {
        found = FALSE, hidden = FALSE;
        hwincount = 0;
        wincount = 0;
        for (j = 0; j < currentWindows; j++)
        if ((docks[j]->flags &DOCK_LEFT) && docks[j]->rowindex == i)
        {
            docks[j]->rowindex -= adj2;
            if (!docks[j]->hidden)
            {
                found = TRUE;
                min = docks[j]->position.left;
                if (j != index)
                    windows[wincount++] = j;
            }
            else
                hidden = TRUE;
            hwindows[hwincount++] = j;
        }
        if (!found)
        {
            if (!hidden)
                adj2++;
            continue;
        }
        OrderTopBottom(windows, wincount, FALSE);
        if (index >= 0 && docks[index]->rowindex == i - adj2 && (docks[index]
            ->flags &DOCK_LEFT) && !docks[index]->hidden)
        {
            wincount += InsertTopBottom(windows, wincount, index, &client, min);
            HideAdjTopBottom(hwindows, hwincount, index);
            index =  - 1;
        }
        for (j = 0; j < wincount; j++) {
            docks[windows[j]]->colindex = j;
		}
        SizeTopBottom(windows, wincount, client.left, &client, &oldclient)
            ;
        if (recalhidden)
        {
            totalsize = 0;
            for (j = 0; j < wincount; j++)
            {
                totalsize += docks[j]->hiddenwidth = (docks[j]->position.bottom
                    - docks[j]->position.top) *1000;
            }
            for (j = 0; j < hwincount; j++)
            {
                if (docks[j]->hidden)
                {
                    docks[j]->hiddenwidth = totalsize / wincount;
                }
            }
        }
        if (cache[windows[0]]->type != LSTOOLBAR)
        {
            InsertVertFrame(windows[0], 0, &client);
            client.left = FRAMEWIDTH;
        }
        else
            client.left = 0;
        client.left += docks[windows[0]]->position.right;
    }
    if (index >= 0 && (docks[index]->flags &DOCK_RIGHT))
        InsertColumn(index, DOCK_RIGHT);
    indexmax =  - 1;
    for (i = 0, min =  - 1; i < currentWindows; i++)
    if (docks[i]->flags &DOCK_RIGHT)
    {
        if (docks[i]->rowindex > indexmax)
            indexmax = docks[i]->rowindex;
    }
    adj2 = 0;
    for (i = 0; i <= indexmax; i++)
    {
        found = FALSE, hidden = FALSE;
        hwincount = 0;
        wincount = 0;
        for (j = 0; j < currentWindows; j++)
        if ((docks[j]->flags &DOCK_RIGHT) && docks[j]->rowindex == i)
        {
            docks[j]->rowindex -= adj2;
            if (!docks[j]->hidden)
            {
                found = TRUE;
                min = docks[j]->position.right;
                if (j != index)
                    windows[wincount++] = j;
            }
            else
                hidden = TRUE;
            hwindows[hwincount++] = j;
        }
        if (!found)
        {
            if (!hidden)
                adj2++;
            continue;
        }
        OrderTopBottom(windows, wincount, FALSE);
        if (index >= 0 && docks[index]->rowindex == i - adj2 && (docks[index]
            ->flags &DOCK_RIGHT) && !docks[index]->hidden)
        {
            wincount += InsertTopBottom(windows, wincount, index, &client, min);
            HideAdjTopBottom(hwindows, hwincount, index);
            index =  - 1;
        }
        for (j = 0; j < wincount; j++) {
            docks[windows[j]]->colindex = j;
		}
        SizeTopBottom(windows, wincount, client.right, &client,
            &oldclient);
        if (recalhidden)
        {
            totalsize = 0;
            for (j = 0; j < wincount; j++)
            {
                totalsize += docks[j]->hiddenwidth = (docks[j]->position.bottom
                    - docks[j]->position.top) *1000;
            }
            for (j = 0; j < hwincount; j++)
            {
                if (docks[j]->hidden)
                {
                    docks[j]->hiddenwidth = totalsize / wincount;
                }
            }
        }
        if (cache[windows[0]]->type != LSTOOLBAR)
        {
            InsertVertFrame(windows[0], 1, &client);
            client.right =  - FRAMEWIDTH;
        }
        else
            client.right = 0;
        client.right += docks[windows[0]]->position.left;
    }
    srctabheight = SendMessage(hwndSourceTab, WM_GETHEIGHT, 0, 0);
    if (srctabheight)
    {
        client.top += srctabheight;
        PutWindow(hwndClient, &client);
        client.bottom = client.top;
        client.top -= srctabheight;
        PutWindow(hwndSourceTab, &client);
		if (!IsWindowVisible(hwndSourceTab))
	        ShowWindow(hwndSourceTab, SW_SHOW);
    }
    else
    {
		if (IsWindowVisible(hwndSourceTab))
	        ShowWindow(hwndSourceTab, SW_HIDE);
        PutWindow(hwndClient, &client);
    }

    for (i = 0; i < frameCount; i++)
    {
	    ShowWindow(frames[i]->self, SW_SHOW) ;
        InvalidateRect(frames[i]->self, 0, 1);	
    }

    for ( ; i < frameMax; i++)
        ShowWindow(frames[i]->self, SW_HIDE);

    for (i = blankCount; i < blankMax; i++)
        ShowWindow(blanks[i]->self, SW_HIDE);
    /* put out docked windows, and self if just undocked */
    for (i = 0; i < currentWindows; i++)
    if (docks[i]->flags)
    {
        //         if (docks[i]->flags & (DOCK_LEFT | DOCK_RIGHT)) {
        //            docks[i]->position.top = r2.top ;
        //            docks[i]->position.bottom = r2.bottom ;
        //         }
        PutWindow(cache[i]->parent, &docks[i]->position);
    }
    for (i = 0; i < blankCount; i++)
    {
        PutWindow(blanks[i]->self, &blanks[i]->u.bw.position);
        ShowWindow(blanks[i]->self, SW_SHOW);
    }
}

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

void DoDocks(CCW_params *p)
{
    int index;
    CCD_params *d = FindParams(p, &index);
    RECT r;
    GetFrameWindowRect(&r);
    d->oldflags = d->flags;

    /*now do docking */
    if (suggestedDock)
    {
        if (d->flags &DOCK_PRESENT)
        {
            FreeGrip(p);
            moverect = d->oldsize;
        }
        else
            FreeContainer(p);

        d->flags = suggestedDock | DOCK_PRESENT;
        switch (suggestedDock &~DOCK_PRESENT)
        {
            case DOCK_LEFT:
            case DOCK_RIGHT:
                p->vertical = FALSE;
                break;
            case DOCK_TOP:
            case DOCK_BOTTOM:
                p->vertical = TRUE;
                break;

        }
        AllocGrip(p, &lastbound, !p->vertical, TRUE);
        NewParent(p->parent, hwndFrame);
        d->flexparams |= FLEX_UNREQ;
    }
    else
    {
        if (d->flags &~DOCK_PRESENT)
        {
            FreeGrip(p);
            p->vertical = FALSE;
            d->flags = 0;
            d->flexparams = 0;
        }
        else
            FreeContainer(p);
        AllocContainer(p, &lastbound, TRUE);
        NewParent(p->parent, hwndClient);
    }
    d->lastposition = d->position;
    d->position = lastbound;
    CalculateLayout(index, 0);
    if (d->flags &~DOCK_PRESENT)
    {
        OffsetRect(&moverect,  - moverect.left,  - moverect.top);
        d->oldsize = moverect;
    }
    if (!d->flags)
    {
        GetWindowRect(hwndClient, &r);
        // keep it out from under the source tab window
        if (d->position.top < r.top)
        {
            d->position.bottom += r.top - d->position.top;
            d->position.top += r.top - d->position.top;
        }
        PutWindow(p->parent, &d->position);
        SendMessage(p->self, LCF_SETFLEX, 0, 0);
    }
}

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

void CalculateSizebarBounds(CFW_params *p, RECT *dest)
{
    int i;
    RECT r1;
    int min1 = 100000, min2 = 100000;
    GetFrameWindowRect(dest);
    dest->right -= 3 * FRAMEWIDTH;
    dest->left += 3 * FRAMEWIDTH;
    dest->top += 3 * FRAMEWIDTH;
    dest->bottom -= 3 * FRAMEWIDTH;
    for (i = 0; i < frameCount; i++)
    {
        if (p != frames[i])
        {
            if (frames[i]->vertical == p->vertical)
            {
                if (p->vertical)
                {
                    #ifdef XXXXX
                        if (frames[i]->position.right > p->position.right)
                        {
                            if (min1 > frames[i]->position.left - p
                                ->position.right)
                                min1 = frames[i]->position.left - p
                                    ->position.right;
                        }
                        else
                        {
                            if (min2 > p->position.left - frames[i]
                                ->position.right)
                                min2 = p->position.left - frames[i]
                                    ->position.right;
                        }
                    #endif 
                }
                else
                {
                    if (frames[i]->position.bottom > p->position.bottom)
                    {
                        if (min1 > frames[i]->position.top - p->position.bottom)
                            min1 = frames[i]->position.top - p->position.bottom;
                    }
                    else
                    {
                        if (min2 > p->position.top - frames[i]->position.bottom)
                            min2 = p->position.top - frames[i]->position.bottom;
                    }
                }
            }
        }
    }
    if (p->vertical)
    {
        if (min1 != 100000)
            dest->right = p->position.right + min1 - FRAMEWIDTH * 3;
        if (min2 != 100000)
            dest->left = p->position.left - min2 + FRAMEWIDTH * 3;
    }
    else
    {
        if (min1 != 100000)
            dest->bottom = p->position.bottom + min1 - FRAMEWIDTH * 3;
        if (min2 != 100000)
            dest->top = p->position.top - min2 + FRAMEWIDTH * 3;
    }
}

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

void Resize(CFW_params *p, RECT *r)
{
    int i, j, changed, left =  - 1, right =  - 1, leftw, rightw, row;
    RECT r1;
    GetWindowRect(hwndClient, &r1);
    changed = FALSE;
    if (!p->vertical)
    {
        if (p->position.top == r1.bottom)
        {
            r1.bottom = r->top;
            changed = TRUE;
        }
        else if (p->position.bottom == r1.top)
        {
            r1.top = r->bottom;
            changed = TRUE;
        }
    }
    else
    {
        if (p->position.left == r1.right)
        {
            r1.right = r->left;
            changed = TRUE;
        }
        else if (p->position.right == r1.left)
        {
            r1.left = r->right;
            changed = TRUE;
        }
    }
    if (changed)
        PutWindow(hwndClient, &r1);

    // move windows
    for (i = 0; i < currentWindows; i++)
    {
        changed = FALSE;
        if (docks[i]->flags)
        {
            if (!p->vertical)
            {
                if (p->position.top == docks[i]->position.bottom)
                {
                    docks[i]->position.bottom = r->top;
                    left = i;
                    row = docks[i]->rowindex;
                    changed = TRUE;
                }
                else if (p->position.bottom == docks[i]->position.top)
                {
                    docks[i]->position.top = r->bottom;
                    right = i;
                    row = docks[i]->rowindex;
                    changed = TRUE;
                }
            }
            else
            {
                if (p->position.left == docks[i]->position.right)
                {
                    docks[i]->position.right = r->left;
                    left = i;
                    row = docks[i]->rowindex;
                    changed = TRUE;
                }
                else if (p->position.right == docks[i]->position.left)
                {
                    docks[i]->position.left = r->right;
                    right = i;
                    row = docks[i]->rowindex;
                    changed = TRUE;
                }
            }
            if (changed)
                PutWindow(cache[i]->parent, &docks[i]->position);
        }
    }
    // recalculate hidden widths for later
    if (left >= 0 && right >= 0)
    {
        leftw = docks[left]->position.right - docks[left]->position.left;
        rightw = docks[right]->position.right - docks[right]->position.left;
        i = docks[left]->hiddenwidth + docks[right]->hiddenwidth;
        docks[left]->hiddenwidth = i * leftw / (leftw + rightw);
        docks[right]->hiddenwidth = i * rightw / (leftw + rightw);
    }

    // move frames
    for (i = 0; i < frameCount; i++)
    {
        changed = FALSE;
        if (!p->vertical)
        {
            if (frames[i]->position.bottom == p->position.top)
            {
                frames[i]->position.bottom = r->top;
                changed = TRUE;
            }
            else if (frames[i]->position.top == p->position.bottom)
            {
                frames[i]->position.top = r->bottom;
                changed = TRUE;
            }
        }
        else
        {
            if (frames[i]->position.right == p->position.left)
            {
                frames[i]->position.right = r->left;
                changed = TRUE;
            }
            else if (frames[i]->position.left == p->position.right)
            {
                frames[i]->position.left = r->right;
                changed = TRUE;
            }
        }
        if (changed)
            PutWindow(frames[i]->self, &frames[i]->position);
    }
    PutWindow(p->self, r);
}

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

void CalculateHidden(CCD_params *d, int index, int state)
{
    int j, unhiddenwidth = 0, totalwidth = 0;
    int windows[30], wincount = 0;
    RECT r;
    int sizewidth, scale;
    d->flexparams |= FLEX_UNREQ;
    if (d->flags &(DOCK_TOP | DOCK_BOTTOM))
    {
        GetFrameWindowRect(&r);
        sizewidth = r.right - r.left;
    }
    else
    {
        GetWindowRect(hwndClient, &r);
        sizewidth = r.bottom - r.top;
    }
    for (j = 0; j < currentWindows; j++)
    if ((docks[j]->flags == d->flags) && docks[j]->rowindex == d->rowindex)
    {
        windows[wincount++] = j;
        totalwidth += docks[j]->hiddenwidth;
        if (!docks[j]->hidden)
            unhiddenwidth += docks[j]->hiddenwidth;
    }
    if (unhiddenwidth == 0)
        return ;
    //   if (d->flags & (DOCK_TOP | DOCK_BOTTOM))
    //      OrderLeftRight(windows,wincount,FALSE) ;
    //   else
    //      OrderTopBottom(windows,wincount,FALSE) ;
    scale = unhiddenwidth / sizewidth;
    totalwidth = totalwidth * 1000 / scale;
    for (j = 0; j < wincount; j++)
    {
        int x = docks[windows[j]]->hiddenwidth = docks[windows[j]]->hiddenwidth
            *1000 / scale;
        if (!docks[windows[j]]->hidden)
        if (docks[windows[j]]->flags &(DOCK_TOP | DOCK_BOTTOM))
        {
            docks[windows[j]]->position.right = docks[windows[j]]
                ->position.left + x * sizewidth / totalwidth;
        }
        else
        {
            docks[windows[j]]->position.bottom = docks[windows[j]]
                ->position.top + x * sizewidth / totalwidth;
        }
    }
}

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

int dmgrGetInfo(CCW_params *p, CCD_params *d)
{
    int i;
    RECT r;
    GetWindowRect(hwndClient, &r);
    for (i = 0; i < currentWindows; i++)
    {
        GetWindowRect(cache[i]->parent, &docks[i]->position);
        p[i] = *(cache[i]);
        d[i] = *(docks[i]);
        if (!docks[i]->flags)
        {
            OffsetRect(&d[i].position,  - r.left,  - r.top);
            OffsetRect(&d[i].lastposition,  - r.left,  - r.top);
        }
    }
    return currentWindows;
}

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

int dmgrSetInfo(int *ids, CCD_params *d, int size)
{
    int i, j;
    int rv = 1;
    RECT r;
    PostMessage(hwndSourceTab, WM_RESETTABS, 0, 1);
    for (j = 0; j < size; j++)
    {
        for (i = 0; i < currentWindows; i++)
        if (ids[j] == cache[i]->id)
        {
            CCD_params *s = docks[i];
            CCW_params *p = cache[i];
            int oldflags = s->flags;
            ShowWindow(p->parent, SW_HIDE); // hide it while recalculating
            s->flexparams = FLEX_UNREQ;
            s->rowindex = d->rowindex;
            s->colindex = d->colindex;
            s->hidden = d->hidden;
            s->hiddenwidth = d->hiddenwidth;
            s->oldsize = d->oldsize;
            s->position = d->position;
            s->lastposition = d->position;
            s->flags = s->oldflags = d->flags;
            if (s->flags)
            {
                s->flags |= DOCK_PRESENT;
                s->oldflags |= DOCK_PRESENT;
            }
            if (p->type == LSTOOLBAR)
            {
                CCW_params *parent = (CCW_params*)GetWindowLong(p->parent, 0);
                int vertical = s->flags &(DOCK_LEFT | DOCK_RIGHT) ? 1 : 0;
                if (s->flags)
                {
                    if (!vertical)
                    {
                        s->lastposition.right = s->lastposition.left + p
                            ->u.tb.hsize.cx + GRIPWIDTH;
                        s->position.right = s->position.left + p->u.tb.hsize.cx
                            + GRIPWIDTH;
                        s->oldsize.right = s->oldsize.left + p->u.tb.hsize.cx +
                            GRIPWIDTH;
                        s->lastposition.bottom = s->lastposition.top + p
                            ->u.tb.hsize.cy;
                        s->position.bottom = s->position.top + p->u.tb.hsize.cy;
                        s->oldsize.bottom = s->oldsize.top + p->u.tb.hsize.cy +
                            GetSystemMetrics(SM_CYCAPTION);
                    }
                    else
                    {
                        s->lastposition.bottom = s->lastposition.top + p
                            ->u.tb.vsize.cy + GRIPWIDTH;
                        s->position.bottom = s->position.top + p->u.tb.vsize.cy
                            + GRIPWIDTH;
                        s->oldsize.bottom = s->oldsize.top + p->u.tb.vsize.cx +
                            GRIPWIDTH;
                        s->lastposition.right = s->lastposition.left + p
                            ->u.tb.vsize.cx;
                        s->position.right = s->position.left + p->u.tb.vsize.cx;
                        s->oldsize.right = s->oldsize.left + p->u.tb.vsize.cx +
                            2 * GetSystemMetrics(SM_CXFRAME);
                    }
                }
                if (oldflags)
                    FreeGrip(p);
                else
                    FreeContainer(p);
                if (s->flags)
                    AllocGrip(p, &s->position, vertical, FALSE);
                else
                    AllocContainer(p, &s->position, FALSE);
            }
            else
            {
                p->vertical = s->flags &(DOCK_TOP | DOCK_BOTTOM) ? 1 : 0;
                if (!oldflags)
                    FreeContainer(p);
                if (!s->flags)
                    AllocContainer(p, &s->position, FALSE);
            }
            if (s->flags)
                NewParent(p->parent, hwndFrame);
            else
                NewParent(p->parent, hwndClient);
            break;
        }
        if (i >= currentWindows)
            rv = 0;
        d++;
    }
    CalculateLayout( - 2, 1);
    GetWindowRect(hwndClient, &r);
    for (j = 0; j < size; j++)
        for (i = 0; i < currentWindows; i++)
    if (ids[j] == cache[i]->id)
    {
        CCD_params *s = docks[i];
        CCW_params *p = cache[i];
        if (!s->flags)
        {
            OffsetRect(&s->position, r.left, r.top);
            OffsetRect(&s->lastposition, r.left, r.top);
            PutWindow(p->parent, &s->position);
        }
        UpdateWindow(p->parent);
        ShowWindow(p->parent, s->hidden ? SW_HIDE : SW_SHOW);
    }
    PostMessage(hwndSourceTab, WM_RESETTABS, 0, 2);
    return rv;
}

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

void dmgrSetRundown(void)
{
    rundown = 1;
}

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

int adjustforbadplacement(int id, CCD_params *d)
{
    RECT r;
    if (d->flags)
        return FALSE ;
    GetClientRect(hwndClient, &r);
    if (d->oldsize.left < 0 || d->oldsize.right - d->oldsize.left < 40 || d
        ->oldsize.bottom - d->oldsize.top < 80 || d->position.right - d
        ->position.left < 40 || d->position.bottom - d->position.top < 40 || d
        ->position.left < 0 || d->position.top < 0 || d->position.left >
        r.right - 64 || d->position.top > r.bottom - GetSystemMetrics
        (SM_CYCAPTION) || d->lastposition.right - d->lastposition.left < 40 ||
        d->lastposition.bottom - d->lastposition.top < 40 || d
        ->lastposition.left < 0 || d->lastposition.top < 0 || d
        ->lastposition.left > r.right - 64 || d->lastposition.top > r.bottom -
        GetSystemMetrics(SM_CYCAPTION))
    {
        d->oldsize.left = d->oldsize.right = 0;
        d->position.top = d->position.left = 0;
        switch (id)
        {
            case DID_TABWND:
                d->oldsize.right = 200;
                d->oldsize.bottom = 200;
                break;
            case DID_WATCHWND:
                d->oldsize.right = 200;
                d->oldsize.bottom = 200;
                break;
            case DID_ERRORWND:
                d->oldsize.right = 200;
                d->oldsize.bottom = 200;
                break;
            case DID_ASMWND:
                d->oldsize.right = 500;
                d->oldsize.bottom = 200;
                break;
            case DID_MEMWND:
                d->oldsize.right = 80 * 8;
                d->oldsize.bottom = 19 * 8+40;
                break;
            case DID_STACKWND:
                d->oldsize.right = 30 * 8;
                d->oldsize.bottom = 19 * 8;
                break;
            case DID_THREADWND:
                d->oldsize.right = 30 * 8;
                d->oldsize.bottom = 19 * 8;
                break;
            case DID_REGWND:
                d->oldsize.right = 200;
                d->oldsize.bottom = 400;
        }
        d->lastposition = d->oldsize;
        d->position.right = d->position.left + d->oldsize.right;
        d->position.bottom = d->position.top + d->oldsize.bottom;
    }
    return FALSE;
}

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

void SaveDocksToRegistry(void)
{
    int i;
    CCW_params p[20];
    CCD_params d[20];
    char regname[256];
    char iobuf[512];
    int len;
    WINDOWPLACEMENT wp;
	wp.length = sizeof(wp);
    GetWindowPlacement(hwndFrame, &wp);
    sprintf(iobuf, "%d %d %d %d %d %d %d %d %d %d", wp.flags, wp.showCmd,
        wp.ptMinPosition.x, wp.ptMinPosition.y, wp.ptMaxPosition.x,
        wp.ptMaxPosition.y, wp.rcNormalPosition.left, wp.rcNormalPosition.top,
        wp.rcNormalPosition.right, wp.rcNormalPosition.bottom);
    StringToProfile("Placement", iobuf);
#ifdef XXXXX
    len = dmgrGetInfo(&p[0], &d[0]);
    for (i = 0; i < len; i++)
    {
        sprintf(regname, "DOCK%d", i);
        sprintf(iobuf, 
            "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d>",
            p[i].id, d[i].flags, d[i].flexparams, d[i].rowindex, d[i].colindex,
            d[i].hidden, d[i].hiddenwidth, d[i].oldsize.left, d[i].oldsize.top,
            d[i].oldsize.right, d[i].oldsize.bottom, d[i].position.left,
            d[i].position.top, d[i].position.right, d[i].position.bottom,
            d[i].lastposition.left, d[i].lastposition.top,
            d[i].lastposition.right, d[i].lastposition.bottom);
        StringToProfile(regname, iobuf);
    }
#endif
}

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

int RestoreDocksFromRegistry(void)
{
#ifdef XXXXX
    char *buf, regname[256];
    CCD_params d[20];
    int ids[20];
    int count = 0;
    while (count < 20)
    {
        sprintf(regname, "DOCK%d", count);
        buf = ProfileToString(regname, "");
        if (!buf[0])
            break;
        sscanf(buf, 
            "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d>\n", 
            &ids[count],  &d[count].flags, &d[count].flexparams, 
            &d[count].rowindex, &d[count].colindex,  &d[count].hidden,
            &d[count].hiddenwidth,  &d[count].oldsize.left,
            &d[count].oldsize.top, &d[count].oldsize.right,
            &d[count].oldsize.bottom,  &d[count].position.left,
            &d[count].position.top, &d[count].position.right,
            &d[count].position.bottom,  &d[count].lastposition.left,
            &d[count].lastposition.top, &d[count].lastposition.right,
            &d[count].lastposition.bottom);
        adjustforbadplacement(ids[count], &d[count]);
        count++;
    }
    if (count)
        dmgrSetInfo(ids, &d[0], count);
#endif
    return 0;
}

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

int RestorePlacementFromRegistry(WINDOWPLACEMENT *wp)
{
    char *buf = ProfileToString("Placement", "");
    if (buf[0])
    {
        wp->length = sizeof(WINDOWPLACEMENT);
        sscanf(buf, "%d %d %d %d %d %d %d %d %d %d",  &wp->flags, &wp->showCmd,
            &wp->ptMinPosition.x, &wp->ptMinPosition.y,  &wp->ptMaxPosition.x,
            &wp->ptMaxPosition.y,  &wp->rcNormalPosition.left, &wp
            ->rcNormalPosition.top,  &wp->rcNormalPosition.right, &wp
            ->rcNormalPosition.bottom);
        return 1;
    }
    return 0;
}
