/* 
   Copyright 2001-2003 Free Software Foundation, Inc.

   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., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222

**********************************************************************

DOCKMGR.C is the main code involved in dealing with dockable windows.
The windows get registered with this routine, and various messages
are sent to this to help it manage and relocate the dockable windows.
It also handles undocking and linking toolbars to parent MDI windows
when undocked.

**********************************************************************

*/
#include <windows.h>                           
#include <commctrl.h>
#include "winconst.h"
#include "lsctrl.h"

#define FRAMEWIDTH 8
#define GRIPWIDTH 15

#define MIN_WIDTH 30
#define DEFAULT_WIDTH 200
#define DEFAULT_HEIGHT 80
#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 ;

int dock(CCW_params *p, RECT *r) ;
CCD_params *FindParams(CCW_params *p, int *index) ;
void CalculateMoveableDocks(CCW_params *p,RECT *r) ;
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) ;

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)
{
   HDC dc = CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);
   RECT r3=*r1, r2 ;
   int i ;

   for (i=0; i < 4; i++) {
      DrawFocusRect(dc,&r3) ;
      r3.left++ ;
      r3.right-- ;
      r3.top++ ;
      r3.bottom-- ;
   }
   DeleteDC(dc) ;
   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_CYFRAME) ;

   r->bottom -= sbheight ;
}
void AllocContainer(CCW_params *p, RECT *r)
{
   if (p->type != LSTOOLBAR)
      return ;
         SendMessage(p->self,LCF_SETVERTICAL,0,0) ;
         if (containerCount >= containerMax)
            CreateContainerWindow(hwndClient,r) ;
         containers[containerCount]->u.gp.child = p->self ;
         SetParent(p->self,containers[containerCount]->self) ;
         p->parent = 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)+2*GetSystemMetrics(SM_CYFRAME),1) ;
         SendMessage(containers[containerCount]->self,WM_SETTEXT,0,(LPARAM)p->title) ;
         ShowWindow(containers[containerCount++]->self,SW_SHOW) ;
}
void FreeContainer(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 < 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)
{
   if (p->type != LSTOOLBAR)
      return ;
         SendMessage(p->self,LCF_SETVERTICAL,GRIPWIDTH,vertical) ;
         if (gripCount >= gripMax)
            CreateGripWindow(hwndClient,r) ;
         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) ;
         ShowWindow(grips[gripCount++]->self,SW_SHOW) ;
}
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 dmgrAddStatusBar(HWND sb)
{
   RECT r ;
   sbwnd = sb ;

   GetWindowRect(sb,&r) ;
   sbheight = r.bottom - r.top ;
}
void GetClientWindowRect(RECT *r)
{
   GetWindowRect(hwndClient,r) ;
//   r->top -= GetSystemMetrics(SM_CYDLGFRAME) ;
}
void dmgrInit(HINSTANCE hInstance, HWND frame, HWND client, int count) 
{
   hwndFrame = frame ;
   hwndClient = client ;
   cache = malloc(count * sizeof(CCW_params *)) ;
   if (cache) {
      docks = malloc(count * sizeof(CCD_params *)) ;
      if (!docks) {
         free(cache) ;
         cache = 0 ;
      }
   }
   if (cache)
      max = count ;
}
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 ;
      if (p->type == LSTOOLBAR) {
         memset(&r,0,sizeof(r)) ;
         AllocContainer(p,&r) ;
      }
   }
}
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) ;
//   if (movept.y < 0)
//      movept.y = 0 ; // hack for the toolbarcontainer which will select on a neg coord
   ClientToScreen(p->parent,&movept) ;

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

   if (d->flags & ~DOCK_PRESENT)  {
      moverect = d->oldsize ;
      OffsetRect(&moverect,d->position.left,d->position.top) ;
   } else {
      GetWindowRect(p->parent, &moverect) ;

   }


   moving = 1,drawnbound=0 ;
   lastSuggestedDock  = d->flags & ~ DOCK_PRESENT;
}
void dmgrMoveClient(CCW_params *p, LPARAM lParam)
{
   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) ;
   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) ;
   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) ;
      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) ;
}
int dmgrMoveGrip(CCW_params *p, LPARAM lParam)
{
   CCW_params *p1 = (CCW_params *) GetWindowLong(p->u.gp.child,0) ;
   dmgrMoveClient(p1,lParam) ;
}
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) ;
}
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 ;
}
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)
{
   int i;
   for (i=0; i < currentWindows; i++) {
      GetWindowRect(cache[i]->parent,&docks[i]->position) ;
   }
   CalculateLayout(-1,0) ;
}
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)
            CalculateHidden(d,index,state) ;
         ShowWindow(p->parent, state ? SW_HIDE : SW_SHOW) ;
         if (d->flags)
            CalculateLayout(-1,0) ;
      }
      SetFocus(p->parent) ;
   }
   return oldstate ;
}
void PutWindow(HWND hwnd, RECT *r)
{
   RECT r1, r2 = *r ;
   if (GetParent(hwnd) == hwndClient)
      GetClientWindowRect(&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) ;
}
int DoFit(CCW_params *p, RECT *r, CCD_params * d, RECT *dest)
{
   RECT dest1 ;
   IntersectRect(&dest1,r,&d->position) ;
//   if (dest1.bottom - dest1.top < 10)
//      return -1 ;
   *dest = dest1; 
   return dest1.right-dest1.left ;
   
}
#define HYSTER(x,y) ((x)-(y) < 10 && (x)-(y) > -10)
void CalculateMoveableDocks(CCW_params *p,RECT *r)
{
   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(r->left, r1.left)) {
      r->top = r1.top ;
      r->left = r1.left ;
      if (p->type == LSTOOLBAR) {
         r->bottom = r->top + p->u.tb.vsize.cy ;
         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(r->top, 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 ;
      } else {
         r->right = r3.right ;
         r->bottom = DEFAULT_HEIGHT+r->top ;
      }
      suggestedDock = DOCK_TOP ;
   } else if (HYSTER(r->right, r1.right)) {
      r->top = r1.top ;
      r->right = r1.right ;
      if (p->type == LSTOOLBAR) {
         r->bottom = r->top + p->u.tb.vsize.cy ;
         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(r->bottom, 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 ;
      } 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 &&
               cache[i] != p) {
            int z ;
            r2 = *r ;
            if (docks[i]->flags & DOCK_BOTTOM)
               r2.top = r2.bottom - TITLE_ALIAS ;
            else
               r2.bottom = r2.top + TITLE_ALIAS ;
            z = DoFit(p,&r2,docks[i],&dest) ;
            if (z > fitwidth) {
               fitwidth = z ;
               fit = i ;
            }
         }
      }
      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 ;
                  if (cache[fit]->type != LSTOOLBAR) {
                     r->top-- ;
                     r->bottom-- ;
                  }
               } else {
                  r->bottom = docks[fit]->position.bottom ;
                  r->top = r->bottom - p->u.tb.hsize.cy ;
                  if (cache[fit]->type != LSTOOLBAR) {
                     r->top++ ;
                     r->bottom++ ;
                  }
               }
               r->right = r->left + p->u.tb.hsize.cx ;
            } else {
               r->top = docks[fit]->position.top ;
               r->bottom = docks[fit]->position.bottom ;
               if (cache[fit]->type == LSTOOLBAR) {
                  r->top++ ;
                  r->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 ;
                  if (cache[fit]->type != LSTOOLBAR) {
                     r->left-- ;
                     r->right-- ;
                  }
               } else {
                  r->right = docks[fit]->position.right ;
                  r->left = r->right - p->u.tb.vsize.cx ;
                  if (cache[fit]->type != LSTOOLBAR) {
                     r->left++ ;
                     r->right++ ;
                  }
               }
               r->bottom = r->top + p->u.tb.vsize.cy ;
            } else {
               r->left = docks[fit]->position.left ;
               r->right = docks[fit]->position.right ;
               if (cache[fit]->type == LSTOOLBAR) {
                  r->left++ ;
                  r->right++ ;
               }
            }
         }
         suggestedDock = docks[fit]->flags ;
      }
   }
   lastSuggestedDock = suggestedDock ;
}
void NewParent(HWND hwnd, HWND owner)
{
      InvalidateRect(hwnd,0,0) ;
      SetParent(hwnd,owner) ;
}
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 ;
         } 
      } 
   }
   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 == -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 ;

      if (cache[windows[0]] -> type == LSTOOLBAR) {\
         docks[windows[0]]->position.left = 0 ;
         for (i=1; i <= wincount; i++)
            docks[windows[i]]->position.left = docks[windows[i-1]]->position.left + cache[windows[i-1]]->u.tb.hsize.cx ;
      }
      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 ;
         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) ;
         scale = unhiddenwidth / sizewidth ;
         totalwidth = totalwidth * 1000 / scale ;
         for (j=0; j < wincount; j++)
            docks[windows[j]]->hiddenwidth = docks[windows[j]]->hiddenwidth * 1000 / scale ;
      }
   }
}
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 ;
         } 
      } 
   }
   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 == -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 ;
      }
      windows[i] = index ;
      memmove(&windows[i+1],&windows[i], (wincount - i) *sizeof(int)) ;
      if (cache[windows[0]] -> type == LSTOOLBAR) {\
         docks[windows[0]]->position.top = 0 ;
         for (i=1; i <= wincount; i++)
            docks[windows[i]]->position.top = docks[windows[i-1]]->position.top + cache[windows[i-1]]->u.tb.hsize.cy ;
      }
      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 ;
         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) ;
         scale = unhiddenwidth / sizewidth ;
         totalwidth = totalwidth * 1000 / scale ;
         for (j=0; j < wincount; j++)
            docks[windows[j]]->hiddenwidth = docks[windows[j]]->hiddenwidth * 1000 / scale ;
      }
   }
}
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 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++) {
         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++) {
         docks[windows[i]]->position.top -= adj ;
         docks[windows[i]]->position.bottom -= adj ;
         if (cache[windows[0]]->type == LSTOOLBAR) {
            newright = currentleft + cache[windows[i]]->u.tb.hsize.cx+GRIPWIDTH ;
            if ( i < wincount-1)
               if (newright < docks[windows[i+1]]->position.left)
                  newright = docks[windows[i+1]]->position.left ;
            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 ;
         currentleft = newright ;
         if (cache[windows[0]]->type != LSTOOLBAR)
            currentleft += FRAMEWIDTH ;
      }
      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) ;
         }
      }
}
void SizeUpDown(int *windows, int wincount, int adj, RECT *client)
{
   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++) {
         docks[windows[i]]->position.left -= adj ;
         docks[windows[i]]->position.right -= adj ;
         if (cache[windows[0]]->type == LSTOOLBAR) {
            newbottom = currenttop + cache[windows[i]]->u.tb.vsize.cy +GRIPWIDTH;
            if ( i < wincount-1)
               if (newbottom < docks[windows[i+1]]->position.top)
                  newbottom = docks[windows[i+1]]->position.top ;
            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 ;
         currenttop = newbottom ;
         if (cache[windows[0]]->type != LSTOOLBAR)
            currenttop += FRAMEWIDTH ;
      }
      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) ;
         }
      }
}
void ShowFrames(void)
{
  int i ;
   for (i = 0; i < frameCount ; i++)
      SetWindowPos(frames[i]->self,HWND_TOP,frames[i]->position.left,
               frames[i]->position.top, frames[i]->position.right - frames[i]->position.left,
               frames[i]->position.bottom - frames[i]->position.top, SWP_SHOWWINDOW) ;
//      ShowWindow(frames[i]->self,SW_SHOW) ;

   for (i = frameCount ; i < frameMax; i++)
      ShowWindow(frames[i]->self,SW_HIDE) ;
}
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 ;
   GetClientWindowRect(&r1) ;
   GetFrameWindowRect(&r2) ;
   client = r2 ;

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

   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 ;
         if (index >= 0 && !docks[i]->hidden && 
               docks[i]->position.top == docks[index]->position.top) {
            docks[index]->rowindex = docks[i]->rowindex ;
         }
      }
   if (index >=0 && (docks[index]->flags & DOCK_TOP) && docks[index]->rowindex < 0)
      docks[index]->rowindex = ++indexmax ;
   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 ;
      }
      SizeLeftRight(windows,wincount,min-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 ;
   }
   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 ;
         if (index >= 0 && !docks[i]->hidden && 
               docks[i]->position.top == docks[index]->position.top) {
            docks[index]->rowindex = docks[i]->rowindex ;
         }
      }
   if (index >=0 && (docks[index]->flags & DOCK_BOTTOM) && docks[index]->rowindex < 0)
      docks[index]->rowindex = ++indexmax ;
   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 ;
      }
      SizeLeftRight(windows,wincount,min-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 ;
   for (i=0,min=-1 ; i < currentWindows; i++)
      if (docks[i]->flags & DOCK_LEFT) {
         if (docks[i]->rowindex > indexmax)
            indexmax = docks[i]->rowindex ;
         if (index >= 0 && !docks[i]->hidden && 
               docks[i]->position.left == docks[index]->position.left) {
            docks[index]->rowindex = docks[i]->rowindex ;
         }
      }
   if (index >=0 && (docks[index]->flags & DOCK_LEFT) && docks[index]->rowindex < 0)
      docks[index]->rowindex = ++indexmax ;
   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_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 ;
      }
      SizeUpDown(windows,wincount,min - client.left,&client) ;
      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;
   }
   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 ;
         if (index >= 0 && !docks[i]->hidden && 
               docks[i]->position.left == docks[index]->position.left) {
            docks[index]->rowindex = docks[i]->rowindex ;
         }
      }
   if (index >=0 && (docks[index]->flags & DOCK_RIGHT) && docks[index]->rowindex < 0)
      docks[index]->rowindex = ++indexmax ;
   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 ;
      }
      SizeUpDown(windows,wincount,min-client.right,&client) ;
      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) ;
      ShowWindow(hwndSourceTab,SW_SHOW) ;
   } else {
      ShowWindow(hwndSourceTab,SW_HIDE) ;
      PutWindow(hwndClient,&client) ;
   }
      

   ShowFrames() ;

   /* 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) ;
      }
}
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) ;
      NewParent(p->parent, hwndFrame) ;
      d->flexparams |= FLEX_UNREQ ;
   } else {
      if (d->flags & ~DOCK_PRESENT) {
         FreeGrip(p) ;
         p->vertical = FALSE ;
         NewParent(p->parent,hwndClient) ;
         d->flags = 0 ;
         d->flexparams = 0 ;
      } else
         FreeContainer(p) ;
      AllocContainer(p,&lastbound) ;
   } 
   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) {
      PutWindow(p->parent,&d->position) ;
      SendMessage(p->self,LCF_SETFLEX,0,0) ;
   }
}

void CalculateSizebarBounds(CFW_params *p, RECT *dest) 
{
   int i; 
   RECT r1 ;
   *dest = p->position ;
   GetFrameWindowRect(dest) ;
   dest->top += MIN_SIZE ;
   dest->left += MIN_SIZE ;
   dest->bottom -= MIN_SIZE ;
   dest->right -= MIN_SIZE ;
   GetWindowRect(hwndClient,&r1) ;
   for (i=0; i < frameCount; i++) {
      if (p != frames[i]) {
         if (frames[i]->vertical == p->vertical) {
            if (p->vertical && frames[i]->position.top == p->position.top) {
               if (frames[i]->position.left < p->position.left && frames[i]->position.left > dest->left && p->position.left < r1.left)
                  dest->left = frames[i]->position.right + MIN_SIZE ;
               else if (frames[i]->position.left > p->position.left && frames[i]->position.right < dest->right && p->position.right > r1.right)
                  dest->right = frames[i]->position.left - MIN_SIZE ;
            } else if (frames[i]->position.left == p->position.left || frames[i]->position.right == p->position.right) {
               if (frames[i]->position.top < p->position.top && frames[i]->position.top > dest->top && p->position.top < r1.top)
                  dest->top = frames[i]->position.bottom + MIN_SIZE ;
               else if (frames[i]->position.top > p->position.top && frames[i]->position.bottom < dest->bottom && p->position.bottom > r1.bottom)
                  dest->bottom = frames[i]->position.top -MIN_SIZE ;
            }
         }
      }
   }
   if (p->vertical) {
      if (dest->right > r1.right && p->position.left < r1.left)
         dest->right = r1.right - MIN_SIZE - (r1.left - p->position.right);
      else if (dest->left < r1.left && p->position.right > r1.right)
         dest->left = r1.left + MIN_SIZE + p->position.left - r1.right ;
   } else {
      if (dest->bottom > r1.bottom && p->position.top < r1.top)
         dest->bottom = r1.bottom - MIN_SIZE - ( r1.top - p->position.bottom);
      else if (dest->top < r1.top && p->position.bottom > r1.bottom)
         dest->top = r1.top + MIN_SIZE + p->position.top - r1.bottom ;
   }
}
void Resize(CFW_params *p, RECT *r)
{
   int i,j,changed ;
   RECT r1 ;
   GetWindowRect(hwndClient,&r1) ;
   for (i=0; i < currentWindows; i++) {
      changed = FALSE ;
      if (docks[i]->flags) {
         if (!p->vertical) {
            if (docks[i]->flags & (DOCK_TOP | DOCK_BOTTOM)) {
               if (p->position.top < r1.top) {
                  if (docks[i]->position.top < r1.top) {
                     if (docks[i]->position.bottom > p->position.top) {
                        docks[i]->position.top += r->top - p->position.top ;
                        docks[i]->position.bottom += r->top - p->position.top ;
                        changed = TRUE ;
                     } else if (docks[i]->position.bottom == p->position.top) {
                        docks[i]->position.bottom += r->top - p->position.top ;
                        changed = TRUE ;
                     }
                  }
               } else {
                  if (docks[i]->position.bottom > r1.bottom) {
                     if (docks[i]->position.top < p->position.bottom) {
                        docks[i]->position.top += r->top - p->position.top ;
                        docks[i]->position.bottom += r->top - p->position.top ;
                        changed = TRUE ;
                     } else if (docks[i]->position.top == p->position.bottom) {
                        docks[i]->position.top += r->top - p->position.top ;
                        changed = TRUE ;
                     }
                  }
               }
            } else {
               if (p->position.top == docks[i]->position.bottom) {
                  docks[i]->position.bottom += r->top - p->position.top ;
                  docks[i]->hiddenwidth += 1000 * (r->top - p->position.top) ;
                  changed = TRUE ;
               }
               if (p->position.bottom == docks[i]->position.top) {
                  docks[i]->position.top += r->top - p->position.top ;
                  docks[i]->hiddenwidth -= 1000 * (r->top - p->position.top) ;
                  changed = TRUE ;
               }
            }
         } else {
            if (docks[i]->flags & (DOCK_LEFT | DOCK_RIGHT)) {
               if (p->position.left < r1.left) {
                  if (docks[i]->position.left < r1.left) {
                     if (docks[i]->position.right > p->position.left) {
                        docks[i]->position.left += r->left - p->position.left ;
                        docks[i]->position.right += r->left - p->position.left ;
                        changed = TRUE ;
                     } else if (docks[i]->position.right == p->position.left) {
                        docks[i]->position.right += r->left - p->position.left ;
                        changed = TRUE ;
                     }
                  }
               } else {
                  if (docks[i]->position.right > r1.right) {
                     if (docks[i]->position.left < p->position.right) {
                        docks[i]->position.left += r->left - p->position.left ;
                        docks[i]->position.right += r->left - p->position.left ;
                        changed = TRUE ;
                     } else if (docks[i]->position.left == p->position.right) {
                        docks[i]->position.left += r->left - p->position.left ;
                        changed = TRUE ;
                     }
                  }
               }
            } else {
               if (p->position.left == docks[i]->position.right) {
                  docks[i]->position.right += r->left - p->position.left ;
                  docks[i]->hiddenwidth += 1000 * (r->left - p->position.left) ;
                  changed = TRUE ;
               }
               if (p->position.right == docks[i]->position.left) {
                  docks[i]->position.left += r->left - p->position.left ;
                  docks[i]->hiddenwidth -= 1000 *(r->left - p->position.left) ;
                  changed = TRUE ;
               }
                  
            }
         }
         if (changed)
           PutWindow(cache[i]->parent,&docks[i]->position) ;
      }
   }
   for (i=0; i < frameCount; i++) {
      changed = FALSE ;
         if (!p->vertical) {
            if (!frames[i]->vertical) {
               if (p->position.top < r1.top) {
                  if (frames[i]->position.top < r1.top) {
                     if (frames[i]->position.top > p->position.top) {
                        frames[i]->position.top += r->top - p->position.top ;
                        frames[i]->position.bottom += r->top - p->position.top ;
                       changed = TRUE ;
                     }
                  }
               } else {
                  if (frames[i]->position.bottom > r1.bottom) {
                     if (frames[i]->position.top < p->position.top) {
                        frames[i]->position.top += r->top - p->position.top ;
                        frames[i]->position.bottom += r->top - p->position.top ;
                        changed = TRUE ;
                     }
                  }
               }
            } else {
               if (p->position.top == frames[i]->position.bottom) {
                  frames[i]->position.bottom += r->top - p->position.top ;
                  changed = TRUE ;
               }
               if (p->position.bottom == frames[i]->position.top) {
                  frames[i]->position.top += r->top - p->position.top ;
                  changed = TRUE ;
               }
            }
         } else {
            if (frames[i]->vertical) {
               if (p->position.left < r1.left) {
                  if (frames[i]->position.left < r1.left) {
                     if (frames[i]->position.right > p->position.right) {
                        frames[i]->position.left += r->left - p->position.left ;
                        frames[i]->position.right += r->left - p->position.left ;
                        changed = TRUE ;
                     }
                  }
               } else {
                  if (frames[i]->position.right > r1.right) {
                     if (frames[i]->position.left < p->position.left) {
                        frames[i]->position.left += r->left - p->position.left ;
                        frames[i]->position.right += r->left - p->position.left ;
                        changed = TRUE ;
                     }
                  }
               }
            } else {
               if (p->position.left == frames[i]->position.right) {
                  frames[i]->position.right += r->left - p->position.left ;
                  changed = TRUE ;
               }
               if (p->position.right == frames[i]->position.left) {
                  frames[i]->position.left += r->left - p->position.left ;
                  changed = TRUE ;
               }
            }
         }
         if (changed)
           PutWindow(frames[i]->self,&frames[i]->position) ;
   }
   changed = FALSE ;
   if (!p->vertical) {
            if (p->position.top < r1.top) {
                  r1.top += r->top - p->position.top ;
                  changed = TRUE ;
            } else {
                  r1.bottom += r->top - p->position.top ;
                  changed = TRUE ;
            }
   } else {
            if (p->position.left < r1.left) {
                  r1.left += r->left - p->position.left ;
                  changed = TRUE ;
            } else {
                  r1.right += r->left - p->position.left ;
                  changed = TRUE ;
            }
   }
   if (changed)
      PutWindow(hwndClient,&r1) ;
   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 ;
   *p = cache ;
   *d = docks ;
   for (i=0; i < currentWindows; i++) {
      GetWindowRect(cache[i]->parent,&docks[i]->position) ;
   }
   return currentWindows ;
}
int dmgrSetInfo(int *ids, CCD_params *d, int size)
{
   int i,j ;
   int rv = 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 ;
            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) ;
               p->vertical = s->flags & (DOCK_TOP | DOCK_BOTTOM) ? 1 : 0 ;
               s->lastposition.right = s->lastposition.left + p->u.tb.hsize.cx ;
               s->position.right = s->position.left + p->u.tb.hsize.cx ;
               s->oldsize.right = s->oldsize.left + p->u.tb.hsize.cx ;
               s->lastposition.bottom = s->lastposition.top + 30 ;
               s->position.bottom = s->position.top + 30 ;
               s->oldsize.bottom = s->oldsize.top + p->u.tb.hsize.cy+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYFRAME) ;
               if (oldflags)
                  FreeGrip(p) ;
               else
                  FreeContainer(p) ;
               if (s->flags)
                  AllocGrip(p,&s->position,!p->vertical) ;
               else
                  AllocContainer(p,&s->position) ;
            } else {
               p->vertical = s->flags & (DOCK_TOP | DOCK_BOTTOM) ? 1 : 0 ;
            }
            if (s->flags)
               NewParent(p->parent, hwndFrame) ;
            else
               NewParent(p->parent, hwndClient) ;
            ShowWindow(p->parent, s->hidden ? SW_HIDE : SW_SHOW) ;
            break ;
         }
      if (i >= currentWindows)
         rv = 0 ;
      d++ ;
   }
   CalculateLayout(-1,1) ;
   return rv ;
}
void dmgrSetRundown(void)
{
   rundown = 1 ;
}
 
      