//********
//
// Win.c
//
//********

//******** Header files

//#include <intuition/screens.h>
#include <exec/memory.h>
#include <intuition/gadgetclass.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <intuition/classusr.h>
#include <clib/intuition_protos.h>
#include <pragmas/intuition_pragmas.h>
#include <clib/graphics_protos.h>
#include <pragmas/graphics_pragmas.h>
#include <clib/exec_protos.h>
#include <pragmas/exec_pragmas.h>

#include <string.h>

#include "Librarian.h"
#include "Prefs.h"
#include "win.h"
#include "VScreen.h"
#include "MPMGClass.h"
#include "TButClass.h"
#include "TDEBUG.H"

extern UBYTE VersTag[];

extern Class *MPMGClass;
extern Class *TBUTClass;


//******** Local Definitions

#define GAPX    4
#define GAPY    2
#define NUMWINGAD 16

//******** Local Storage

struct Window *OnGoWin=NULL;
struct Gadget **MyGadgets=NULL;
static struct Gadget *MyWGadget[NUMWINGAD]={NULL};
static ULONG NextGadget;
static ULONG NormalHeight;

struct Gadget DragGadget= {
  NULL, 0, 0, 20, 10,
  GFLG_GADGHNONE, GACT_IMMEDIATE, GTYP_SYSGADGET|GTYP_WDRAGGING,
  NULL, NULL, NULL, NULL, NULL, 200, NULL
};


ULONG LeftMost;
ULONG MapX;
ULONG MapY;
WORD ScrWidth, ScrHeight;
BOOL Hidden;


//******** Private functions

static struct Window *FindWBWin(struct Screen *WBScreen) {
  struct Window *WBWin;

  Forbid();
  WBWin = WBScreen->FirstWindow;
  while (WBWin && !((WBWin->Flags & WFLG_BACKDROP) && (WBWin->Flags & WFLG_WBENCHWINDOW)))
  {
    WBWin = WBWin->NextWindow;
  }
  Permit();
  return WBWin;
} // FindWBWin


static void ResizeWorkbench (ULONG oh) {
  struct Screen *WBScreen;
  struct Window *WBWin;
  struct Window *Backdrop;

  if (WBScreen = (struct Screen *)LockPubScreen("Workbench")) {
    WBWin=FindWBWin(WBScreen);
    if (WBWin) {
      ChangeWindowBox(WBWin,
		      WBWin->LeftEdge,
		      WBWin->TopEdge+(MyWinPos?-oh:0),
		      WBWin->Width,
		      WBWin->Height+oh);
//      WindowToBack(WBWin);

      Forbid();
      for (Backdrop = WBScreen->FirstWindow; Backdrop; Backdrop = Backdrop->NextWindow ) {
	if ((Backdrop->Flags & WFLG_BACKDROP) && !(Backdrop->Flags & WFLG_WBENCHWINDOW))
	  WindowToFront(Backdrop);
      } // while backdrop
      Permit();

    } // if wbwin
    UnlockPubScreen(NULL, WBScreen);
  } // if LockScreen WorkBench

} // ResizeWorkbench


static void RethinkWGadgets(void) {
  LONG totspace;
  LONG spaceea;
  LONG w;
  int i;

  SetAPen(OnGoWin->RPort,0);
  RectFill(OnGoWin->RPort,LeftMost,1,OnGoWin->Width-3,OnGoWin->Height-3);

  if (NextGadget) {
    if (DragSys==1) RemoveGadget(OnGoWin,&DragGadget);
    totspace=OnGoWin->Width-2-LeftMost;
    spaceea=(totspace/NextGadget)-GAPX;

    w=LeftMost;
    for (i=0; i<NextGadget; i++) {
      SetGadgetAttrs(MyWGadget[i],OnGoWin,NULL,
	GA_Left,w, GA_Width, spaceea, GA_Top, GAPY,
	TAG_END);
      w+=spaceea+GAPX;
    }
    if (DragSys==1)  AddGadget(OnGoWin, &DragGadget, -1);
    RefreshGList(MyWGadget[0], OnGoWin, NULL, -1);
  }
} // RethinkWGadgets


static void WedgeWB(void) {
  struct Screen *WBScreen;
  struct Window *WBWin;

  if (WBScreen = (struct Screen *)LockPubScreen("Workbench")) {
    Forbid();
    for ( WBWin = WBScreen->FirstWindow ; WBWin;
	  WBWin = WBWin->NextWindow ) {
      if (WBWin->Flags & WFLG_WBENCHWINDOW) ModifyIDCMP(WBWin,WBWin->IDCMPFlags & ~IDCMP_MOUSEBUTTONS);
    }
    Permit();
    UnlockPubScreen(NULL, WBScreen);
  }
} // WedgeWB


static void UnWedgeWB(void) {
  struct Screen *WBScreen;
  struct Window *WBWin;

  if (WBScreen = (struct Screen *)LockPubScreen("Workbench")) {
    Forbid();
    for ( WBWin = WBScreen->FirstWindow ; WBWin;
	  WBWin = WBWin->NextWindow ) {
      if (WBWin->Flags & WFLG_WBENCHWINDOW) ModifyIDCMP(WBWin,WBWin->IDCMPFlags | IDCMP_MOUSEBUTTONS);
    }
    Permit();
    UnlockPubScreen(NULL, WBScreen);
  }

} // UnWedgeWB


//******** Public functions

BOOL DoIconify(void) {
  BOOL done=FALSE;
  struct Gadget *g;
  char *s,*t;
  struct Node *n;

  if (NextGadget<NUMGADGETS) {
    if (n=Iconify()) {
      t = ((struct Window *)(n->ln_Name))->Title;
      if (NULL==t) t="Noname";
      s = strcpy(AllocVec(strlen(t)+1,MEMF_PUBLIC|MEMF_REVERSE),t);
      g = (struct Gadget *)NewObject(TBUTClass, NULL,
	GA_ID, 128, GA_Top, OnGoWin->Height+GAPY, GA_Left, LeftMost, GA_Height, MyGadgets[0]->Height,
	GA_Width, 50, GA_RelVerify, TRUE,
	TBUT_GadgetText,s,
      TAG_END);
      if (g) {
	g->UserData=n;
	MyWGadget[NextGadget]=g;
	NextGadget++;
	AddGadget(OnGoWin, g, -1);
	RethinkWGadgets();
	done=TRUE;
      } else {
	FreeVec(s);
	UnIconify(n);
      }
    }
  }
  return done;
} // DoIconify


void DoUnIconify(struct Gadget *gad) {
  UWORD GadId;
  int i;
  char *s;
  struct Node *n;

  if (gad) {
    for (i=0; i<NextGadget; i++)
      if (MyWGadget[i]==gad) break;
    GadId=i;
    RemoveGadget(OnGoWin,gad);
    GetAttr(TBUT_GadgetText,gad,(ULONG *)&s);
    FreeVec(s);
    n=gad->UserData;
    DisposeObject(gad);
    MyWGadget[GadId]=NULL;
    for (i=GadId; i<NextGadget-1; i++) {
      MyWGadget[i]=MyWGadget[i+1];
    }
    NextGadget--;
    MyWGadget[NextGadget]=NULL;

    RethinkWGadgets();
    UnIconify(n);
  }
} // DoUnIconify



//******** Public functions

void DrawBevelBorder(struct RastPort *rp, UBYTE Pen1, UBYTE Pen2,
     WORD ox, WORD oy, WORD ow, WORD oh) {
  SetAPen(rp,Pen1);
  Move(rp,ox+1,oy+1);
  Draw(rp,ox+1,oh-2);
  Draw(rp,ox  ,oh-1);
  Draw(rp,ox  ,oy  );
  Draw(rp,ow-2,oy  );
  SetAPen(rp,Pen2);
  Move(rp,ow-2,oh-2);
  Draw(rp,ow-2,oy+1);
  Draw(rp,ow-1,oy  );
  Draw(rp,ow-1,oh-1);
  Draw(rp,ox+1,oh-1);
} // DrawBevelBorder


void MyCloseWindow(void) {
  int i;

  if (MyGadgets) {
    for (i=0; i<NumVScreens+1; i++) {
      if (MyGadgets[i]) {
	RemoveGadget(OnGoWin,MyGadgets[i]);
	DisposeObject(MyGadgets[i]);
	MyGadgets[i]=NULL;
      } // if
    } // for
    FreeVec(MyGadgets);
    MyGadgets=NULL;
  }

  for (i=0; i<NextGadget; i++) {
    if (MyWGadget[i]) {
      DoUnIconify(MyWGadget[i]);
      MyWGadget[i]=NULL;
    } // if
  }

  if (OnGoWin) {
    CloseVScreen();
    if (1==ShrinkWorkbench) ResizeWorkbench(OnGoWin->Height);
    if (1==DragSys) RemoveGadget(OnGoWin,&DragGadget);
    if ((1==AutoHide) && (Hidden==FALSE)) UnWedgeWB();
    CloseWindow(OnGoWin);
    OnGoWin=NULL;
  }
} // MyCloseWindow


BOOL MyOpenWindow(ULONG MyMenus) {
  BOOL rc=FALSE;
  struct Screen *scr;
  struct DrawInfo *dri;
  UWORD ow,oh;
  int i;
  ULONG w,y;

  if (scr = LockPubScreen("Workbench")) {
    MapX=scr->Width-1;
    MapY=scr->Height-1;
    ScrWidth=scr->Width-2;
    ScrHeight=scr->Height-2;
    if (dri = GetScreenDrawInfo(scr) ) {

      oh=4+GAPY+GAPY+dri->dri_Font->tf_YSize;
      NormalHeight=oh;
      if (MyWinPos==1) {
	OnGoWin=FindWBWin(scr);
	if (OnGoWin) {
	  y=OnGoWin->TopEdge;
	} else {
	  // should not occur
	  y=0;
	}
      } else {
	y=scr->Height-oh;
      }

      if (OnGoWin = OpenWindowTags(NULL,
	WA_Left,       0,
	WA_Top,        y,
	WA_Width,      scr->Width,
	WA_Height,     oh,
	WA_Flags,      WFLG_SIMPLE_REFRESH,
	WA_IDCMP,      IDCMP_GADGETUP | IDCMP_VANILLAKEY |
	      IDCMP_REFRESHWINDOW | IDCMP_IDCMPUPDATE | IDCMP_INACTIVEWINDOW,
	WA_AutoAdjust, TRUE,
	WA_PubScreen,  scr,
	WA_ScreenTitle,&VersTag[7],
	WA_Borderless, TRUE,
	TAG_END))
      {
	DrawBevelBorder(OnGoWin->RPort,dri->dri_Pens[SHINEPEN],dri->dri_Pens[SHADOWPEN],
	    0,0,scr->Width,oh);
	w=2+GAPX;
	DragGadget.Width=OnGoWin->Width;
	DragGadget.Height=OnGoWin->Height;

	MyGadgets=(struct Gadget **)AllocVec( (1+NumVScreens)*sizeof(struct Gadget *),MEMF_PUBLIC|MEMF_REVERSE);

	for (i=0; i<NumVScreens+1; i++) {
	  ow=16+TextLength(&(scr->RastPort), GadgetText[i], strlen(GadgetText[i]) );
	  if (0==i)
	    MyGadgets[i] = (struct Gadget *)NewObject(MPMGClass, NULL,
	      GA_ID, i, GA_Top, GAPY, GA_Left, w, GA_Height, oh-GAPY-GAPY,
	      GA_Width, ow, GA_RelVerify,TRUE,
	      MPMG_GadgetText,GadgetText[i],
	      MPMG_Menus,     MyMenus,
	      MPMG_Look,      MyLook,
	      MPMG_MinWidth,  MinWinW,
	      MPMG_MenuOverLap,HangDist,
	      MPMG_MenuDelay, MenuDelay,
	      MPMG_Top,       MyWinPos,
	      ICA_TARGET,     ICTARGET_IDCMP,
	      TAG_END);
	  else
	    MyGadgets[i] = (struct Gadget *)NewObject(TBUTClass, NULL,
	      GA_ID, i, GA_Top, GAPY, GA_Left, w, GA_Height, oh-GAPY-GAPY,
	      GA_Width, ow, GA_RelVerify, TRUE,
	      TBUT_GadgetText,GadgetText[i],
	      GA_Selected, 1==i?1:0,
	      TAG_END);
	  w+=GAPX+ow;
	} // for
	LeftMost=w;

	if (MyGadgets[NumVScreens]) {
	  for (i=0; i<NumVScreens+1; i++)
	    AddGadget(OnGoWin, MyGadgets[i], -1);
	  if (DragSys==1) AddGadget(OnGoWin, &DragGadget, -1);
	  RefreshGList(MyGadgets[0], OnGoWin, NULL, -1);
	  if (1==ShrinkWorkbench) ResizeWorkbench ( -oh );
	  InitVScreen();
	  NextGadget=0;
	  Hidden=FALSE;
	  rc=TRUE;
	} // if
      } else {
	DPRINT("win: OpenWindow() failed\n",0);
      } // if OpenWindow
      FreeScreenDrawInfo( scr, dri );
    } else {
      DPRINT("win: GetScreenDrawInfo() failed\n",0);
    } // if GetScreenDrawInfo
    UnlockPubScreen( NULL, scr );
  } else {
    DPRINT("win: LockPubScreen() failed\n",0);
  } // if LockPubScreen

  if (FALSE==rc) MyCloseWindow();
  return rc;
} // MyOpenWindow


void HideWindow(void) {
  if (Hidden==FALSE) {
    UnWedgeWB();

    if (0==MyWinPos)
      ChangeWindowBox(OnGoWin,0,ScrHeight,OnGoWin->Width,2);
    else
      ChangeWindowBox(OnGoWin,0,OnGoWin->TopEdge,OnGoWin->Width,2);
    Hidden=TRUE;
  }
} // HideWindow


void UnHideWindow(void) {
  if (Hidden==TRUE) {
    WedgeWB();

    WindowToFront( OnGoWin );
    if (0==MyWinPos)
      ChangeWindowBox(OnGoWin,0,ScrHeight+2-NormalHeight,OnGoWin->Width,NormalHeight);
    else
      ChangeWindowBox(OnGoWin,0,OnGoWin->TopEdge,OnGoWin->Width,NormalHeight);
    ActivateWindow( OnGoWin );
    Hidden=FALSE;
  }
} // UnHideWindow

//******** End of file

