/*****************************************************************************
    MODULE
	GTB.c

    DESCRIPTION
	XDME Command Module to support GADTOOLBOX projects as
	additional parts of the GUI

    NOTES
	GADTOOLS or GTX (at least one of them) seem to rely on the
	order of creation so that menus must be created before gadgets,
	else we get E-hits and a wrong font when opening the window

    BUGS
	none known

    TODO
	we still need an XDME interface ...

    EXAMPLES

    SEE ALSO

    AUTHOR
	Bernd "0" Noll (b_noll@informatik.uni-kl.de)

    HISTORY
	16-09-94 b_noll created
	06-11-94 b_noll continued tests ... na endlich
	09-11-94 b_noll cleanup
	12-11-94 b_noll + ActivateGTBWindow
	24-11-94 b_noll fixed setgbtgadget
	27-11-94 b_noll first checks for non-gtbbased guis

******************************************************************************/


/**************************************
	      Includes
**************************************/

//#include "defs.h"

#define PREFS_PREFHDR_H 1


/* #include <intuition/intuitionbase.h> */


#ifndef   GADTOOLSBOX_FORMS_H
#include <gadtoolsbox/forms.h>
#endif /* GADTOOLSBOX_FORMS_H */

#ifndef   CLIB_ALIB_PROTOS_H
#include <clib/alib_protos.h>
#endif /* CLIB_ALIB_PROTOS_H */

#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/nofrag.h>
#include <proto/gtx.h>



#include <stdio.h>

#include "HL.h"
#include "xdme_base.h"

#include "lists.h"



/* ---- Interface ... */

//#define GTB_FindProject(x) ((struct GTB_Project *)FindName((struct List *)GTB_Projects, (x)))
//APTR GetHead (APTR);
//APTR GetSucc (APTR);
//#define DLL_Init(x)      NewList((struct List *)(x))
//#define DLL_AddTail(x,y) AddTail((struct List *)(x),(y))
//#define DLL_GetHead(x)   GetHead(x)
//#define DLL_GetSucc(x,y) GetSucc(y)
//extern  void DLL_Scan (struct MinList *l, void (*scan)(struct Node *, void *, int), void *ud);
//#define DISPOSE(x) free(x) // free((x), sizeof(x))
//#define NEW(x)     ((x) = malloc (sizeof (*(x))))

#define CloseWindowSafely closesharedwindow
#define HL_FindName(l,x) HL_Find((l), (void *)NodeStringComparison, (x))


/**************************************
	    Global Variables
**************************************/
struct GTXBase * GTXBase;


/**************************************
      Internal Defines & Structures
**************************************/

//#define GTB_NOPROJECTACTIVE -16
#define GTB_PROJECTACTIVE    -15
#define GTB_WINDOWOPEN	     -14
#define GTB_WINDOWCLOSE      -13
#define GTB_NOPORT	     -12
#define GTB_NOMEM	     -11
#define GTB_OK		      0

#define GTB_BUFFERSIZE 1000
#define GTB_DEFFMT	"%s-%s-%s '%s"
	      // Project-Window-Gadget 'Value

#define GTB_FixedDefWin 0

/**************************************
	   Internal Variables
**************************************/

Prototype struct TextAttr GTB_Font;
Prototype UBYTE 	 *GTB_Format;
Prototype ULONG 	  GTB_SigMask;

#ifdef LOCAL_MEM
#define 	  GTB_MemChain ((struct GTB_Project *)prj)->MemChain
#else
APTR		  GTB_MemChain = NULL;
#endif
struct MsgPort	 *GTB_Port     = NULL;
ULONG		  GTB_SigMask  = 0;
struct TextAttr   GTB_Font     = { (STRPTR)"topaz.font", 8, 0x00, 0x01 };
UBYTE		 *GTB_Format   = NULL;
UBYTE		 *GTB_Buffer   = NULL;
APTR		  GTBRoot      = NULL;
//struct DList	   *GTB_Projects = NULL;
static struct DList _GTB_Projects;

static struct Window *GTB_DefWindow = NULL;

/**************************************
	   Internal Prototypes
**************************************/

//extern int  HL_Connect    (APTR base, APTR partner, ULONG attr);
//extern void HL_Disconnect (APTR base, APTR partner);
extern APTR HL_LockNode   (UBYTE *name);

/**************************************
		 Macros
**************************************/


/**************************************
	     Implementation
**************************************/

struct GTB_Project {
    struct HNode	  Node;
    struct HLASubs	  AppliWindows;


    APTR		  VisualInfo;
    struct WindowList	  GuiWindows;
#ifdef LOCAL_MEM
    APTR		  MemChain;
#endif
    WORD		  OffsX, OffsY,
			  FactX, FactY,
			  DivX,  DivY,
			  FontX, FontY;
    GUIDATA		 *GuiData;
    struct Screen	 *IntuiScreen;
    struct TextAttr	  Font;
}; /* struct GTB_Project */

struct WinNode {
    struct HNode	  Node;
    struct HLASubs	  AppliGadgets;

    //struct GTB_Project   *Parent;
    struct Gadget	 *IntuiGadgets;
    struct Window	 *IntuiWindow;
    struct Menu 	 *IntuiMenus;
    struct DList	  AppliMenus;
    struct ProjectWindow *GuiWindow;
}; /* WinNode */


/* not yet used */
struct GadNode {
    struct HNode	  Node;
    //struct WinNode	   *Parent;

    struct Gadget	 *IntuiGadget;
    ULONG		  LastCode;
    APTR		  gdata;
    struct ExtNewGadget  *GuiGadget;
}; /* GadNode */

/* not yet used */
struct MenNode {
    struct HNode	  Node;
    struct HLASubs	  AppliSubs;

    struct ExtNewMenu	 *GuiMenu;
    struct MenuItem	 *IntuiMenu;
  //APTR		  gdata;
}; /* MenNode */


#define Div(w,x)  (((struct GTB_Project *)w->Node.Parent)->Div  ## x)
#define Fact(w,x) (((struct GTB_Project *)w->Node.Parent)->Fact ## x)
#define Offs(w,x) (((struct GTB_Project *)w->Node.Parent)->Offs ## x)


static int  GTB__ComputeWidX (struct WinNode *wn, int val) {
    return ((val * 2 * Fact(wn,X) + Fact(wn,X)) / (2 * Div(wn,X)));
} /* GTB__ComputeWidX */

static int  GTB__ComputeWidY (struct WinNode *wn, int val) {
    return ((val * 2 * Fact(wn,Y) + Fact(wn,Y)) / (2 * Div(wn,Y)));
} /* GTB__ComputeWidY */

static int  GTB__ComputePosX (struct WinNode *wn, int val) {
    return ((val * 2 * Fact(wn,X) + Fact(wn,X)) / (2 * Div(wn,X)));
} /* GTB__ComputePosX */

static int  GTB__ComputePosY (struct WinNode *wn, int val) {
    return ((val * 2 * Fact(wn,Y) + Fact(wn,Y)) / (2 * Div(wn,Y))) + Offs(wn,Y);
    //return val + wn->Parent->IntuiScreen->WBorTop + 1;
} /* GTB__ComputePosY */


/* ---------------------------------- */
/* ---- close one window in a project */
static int GTB_CloseWindow (struct WinNode *wn, struct GTB_Project *prj) {
//puts ("GTB_Closewin");
    if (wn->IntuiWindow) {
	CloseWindowSafely(wn->IntuiWindow);
	wn->IntuiWindow = NULL;
	return GTB_OK;
    } /* if */
    return GTB_WINDOWCLOSE;
} /* GTB_CloseWindow */


static int GTB_RedrawWindow (struct WinNode *wn, struct GTB_Project *prj) {
    struct ProjectWindow *pw;

    if (!wn->IntuiWindow)
	return GTB_WINDOWCLOSE;

    pw = wn->GuiWindow;

    /* ---- Draw all ITexts */
    {
	struct IntuiText *it, itt;

	for (it = pw->pw_WindowText; it; it = it->NextText) {
	    //it->ITextFont   = &prj->Font;
	    itt 	    = *it;
	    itt.ITextFont   = &prj->Font;
	    itt.NextText    = NULL;
	    itt.LeftEdge    = GTB__ComputePosX( wn, itt.LeftEdge );
	    itt.TopEdge     = GTB__ComputePosY( wn, itt.TopEdge  );
	    PrintIText (wn->IntuiWindow->RPort, &itt, 0, 0);
	} /* for */

	//PrintIText (wn->IntuiWindow->RPort, pw->pw_WindowText, 0, 0);
    }

    /* ---- Draw all Boxes */
    {
	struct BevelBox *bv;

	for (bv = GetHead(&pw->pw_Boxes); bv; bv = GetSucc (bv)) {
	    DrawBevelBox ( wn->IntuiWindow->RPort,
		GTB__ComputePosX( wn, bv->bb_Left   ),
		GTB__ComputePosY( wn, bv->bb_Top    ),
		GTB__ComputeWidX( wn, bv->bb_Width  ),
		GTB__ComputeWidY( wn, bv->bb_Height ),
		GTBB_Recessed, bv->bb_Flags & BBF_RECESSED,
		//GTBB_FrameType, bv->bb_Flags & BBF_DROPBOX,
		GT_VisualInfo, ((struct GTB_Project *)(wn->Node.Parent))->VisualInfo,
		TAG_DONE );
	} /* for */
    }
} /* GTB_RedrawWindow */


/* --------------------------------- */
/* ---- open one window in a project */
static int GTB_OpenWindow (struct WinNode *wn, struct GTB_Project *prj) {
    struct TagItem *tgs,
		   *tgh,
		   *tgw,
		   *tgi,
		   *tags,
		    tgadd[3] = { TAG_IGNORE, 0, TAG_IGNORE, 0, TAG_MORE };
    struct Window  *win;

//puts ("GTB_Openwin");
    if (wn->IntuiWindow)
	return GTB_WINDOWOPEN;

    tags = wn->GuiWindow->pw_Tags;
    tgadd[2].ti_Data = (ULONG)tags;

    /* ---- recalculate windimensions */

    if ((tgw = FindTagItem(WA_Width, tags))) {
	tgadd[0].ti_Tag  = WA_Width;
	tgadd[0].ti_Data = GTB__ComputePosX( wn, tgw->ti_Data );
	//tgw->ti_Tag	   = TAG_IGNORE;
    } /* if */

    if ((tgh = FindTagItem(WA_Height, tags))) {
	tgadd[1].ti_Tag  = WA_Height;
	tgadd[1].ti_Data = GTB__ComputePosY( wn, tgh->ti_Data );
	//tgh->ti_Tag	   = TAG_IGNORE;
    } /* if */

    /* ---- ignore customscreen & idcmp */
    if ((tgs = FindTagItem (WA_CustomScreen, tags))) {
	//tgs->ti_Tag = TAG_IGNORE;
	tgs->ti_Data = (ULONG)prj->IntuiScreen;
    } /* if customscreen */

    if ((tgi = FindTagItem (WA_IDCMP, tags))) {
	tgi->ti_Tag = TAG_IGNORE;
    } /* if needs idcmp */

    /* ---- Open the window */
    win = OpenWindowTags(NULL,
	    WA_Gadgets, wn->IntuiGadgets,
	    TAG_MORE,	tgadd);

    /* ---- reinstall customscreen & idcmp */
    if (tgi)
	tgi->ti_Tag   = WA_IDCMP;

    //if (tgs)
    //	  tgs->ti_Tag	= WA_CustomScreen;
    //if (tgw)
    //	  tgw->ti_Tag = WA_Width;
    //if (tgh)
    //	  tgh->ti_Tag = WA_Height;

    /* ---- connect */
    if (!(wn->IntuiWindow = win)) {
	return GTB_WINDOWCLOSE;
    } /* if */
    win->UserData = (char *)wn;

    /* ---- if necessary set the right idcmp */
    if (tgi && tgi->ti_Data) {
	win->UserPort = GTB_Port;
	ModifyIDCMP (win, tgi->ti_Data);
    } /* if needs idcmp */


    /* ---- install menu */
    if (wn->IntuiMenus) {
	SetMenuStrip(win, wn->IntuiMenus);
    } /* if ex menu */

    GT_RefreshWindow( win, NULL );
    GTB_RedrawWindow( wn, prj );

    return GTB_OK;
} /* GTB_OpenWindow */


/* ---- support function for _gtb_dropappliwindow */
static void _gtb_dropappligadget (struct GadNode *gd, struct GTB_Project *prj) {

    // IntuiGadget Deletion is performed in _gtb_dropappliwindow

//puts ("GTB_Dropgad");
    if (gd->gdata) {
	HL_Disconnect (gd->gdata, &gd->Node);
    }
    HL_Uninit(&gd->Node);

    //Remove	  (&gd->Node);
    DISPOSE (gd);
} /* _gtb_dropappligadget */


/* ---- support function for _gtb_dropappliwindow */
static void _gtb_dropapplimenu (struct MenNode *mn, struct GTB_Project *prj) {

    // IntuiMenu Deletion is performed in _gtb_dropappliwindow
//puts ("GTB_Dropmenu");

    HL_Scan	(&mn->Node, (void *)_gtb_dropapplimenu, prj);
    HL_Uninit	(&mn->Node);
    DISPOSE	(mn);
} /* _gtb_dropapplimenu */


/* ---- support function for GTB_CloseProject */
static void _gtb_dropappliwindow (struct WinNode *wn, struct GTB_Project *prj) {

//puts ("GTB_Dropwin");
    GTB_CloseWindow (wn, prj);

    HL_Scan  (&wn->Node,         (void *)_gtb_dropappligadget, prj);
    DLL_Scan (&wn->AppliMenus,   (void *)_gtb_dropapplimenu,   prj);

    if (wn->IntuiMenus) {
	FreeMenus   (wn->IntuiMenus);
	wn->IntuiMenus = NULL;
    } /* if */
    if (wn->IntuiGadgets) {
	FreeGadgets (wn->IntuiGadgets);
	wn->IntuiGadgets = NULL;
    } /* if */


    //Remove	     (&wn->Node);
    HL_Uninit	   (&wn->Node);
    DISPOSE	   (wn);
} /* _gtb_dropappliwindow */


/* ---------------------- */
/* ---- close one Project */
static int GTB_CloseProject (struct GTB_Project *prj) {

//puts ("GTB_Dropprj");
    /* ---- drop all windows */
    HL_Scan (&prj->Node, (void *)_gtb_dropappliwindow, prj);

    if (prj->VisualInfo) {
	FreeVisualInfo (prj->VisualInfo);
	prj->VisualInfo = NULL;
    } /* if */

    if (GTB_MemChain) {
	GTX_FreeWindows (GTB_MemChain, &prj->GuiWindows);
	FreeItem	(GTB_MemChain, prj->GuiData, sizeof (*prj->GuiData));
#ifdef LOCAL_MEM
	FreeMemoryChain (prj->MemChain, TRUE);
	prj->MemChain = NULL;
#endif
    } /* if */

    HL_Uninit(&prj->Node);
    //if (prj->Node.Name)
    //	  free (prj->Node.Name);
    //Remove  (&prj->Node);
    DISPOSE   (prj);
    return GTB_OK;
} /* GTB_CloseProject */


static int ok;
static int counter;

static void _gtb_countguimenus (struct ExtNewMenu *men) {
    ++ counter;
    if (((struct ExtNewMenu *)men)->em_Items)
	DLL_Scan ((struct DList *)men->em_Items, (void *)_gtb_countguimenus, 0);
} /* _gtb_countguimenus */

static void _gtb_copyguimenus (struct ExtNewMenu *men, void *x) {
    ((struct NewMenu *)x)[counter] = men->em_NewMenu;
    ((struct NewMenu *)x)[counter].nm_UserData = (APTR)men;
    ++ counter;
    if (men->em_Items)
	DLL_Scan ((struct DList *)men->em_Items, (void *)_gtb_copyguimenus, x);
} /* _gtb_copyguimenus */


/* ---- part of GTB_OpenProject */
static void _gtb_genappliwindow (struct ProjectWindow *pw, struct GTB_Project *prj) {
    struct WinNode	 *wn;
    struct TagItem	 *tg  = NULL;

    if (!ok)
	return;

    /* ---- create the AppliWindow */
    if (!NEW(wn)) {
	ok = FALSE;
	return;
    } /* if */
    bzero(wn, sizeof(*wn));
    wn->GuiWindow    = pw;
    //wn->IntuiMenus   = NULL;
    //wn->IntuiGadgets = NULL;

#if 0
{
struct BevelBox *bv;
struct IntuiText *it;
printf ("WINDOW l=%s x=%d y=%d w=%d h=%d\n",
    pw->pw_Name,
    FindTagItem(WA_Left,   pw->pw_Tags)->ti_Data,
    FindTagItem(WA_Top,    pw->pw_Tags)->ti_Data,
    FindTagItem(WA_Width,  pw->pw_Tags)->ti_Data,
    FindTagItem(WA_Height, pw->pw_Tags)->ti_Data,
    0);

for (it = pw->pw_WindowText; it; it = it->NextText)
    printf (" ITXT x=%d y=%d p=(%d %d) d=%d t='\n",
	it->LeftEdge,
	it->TopEdge,
	it->FrontPen,
	it->BackPen,
	it->DrawMode,
	it->IText,
	/* TextAttr it->ITextFont */
	0);

for (bv = GetHead(&pw->pw_Boxes); bv; bv = GetSucc (bv))
    printf(" BBOX x=%d y=%d w=%d h=%d f=%d\n",
	bv->bb_Left,
	bv->bb_Top,
	bv->bb_Width,
	bv->bb_Height,
	bv->bb_Flags,
	0);

}
#endif

    //wn->Parent       = prj;
    //wn->Node.ln_Name = pw->pw_Name;
    //DLL_Init	 (&wn->AppliGadgets);
    //DLL_AddTail(&prj->AppliWindows, &wn->Node);

    HL_Init(&wn->Node, pw->pw_Name, &prj->Node, HLF_SYSNODE|HLF_SUBCARRIER);

    DLL_Init   (&wn->AppliMenus);


    /* ---- Create the Menu structures */
    {
	int		    numnm;
	struct NewMenu	   *nmb;

	counter = 0;
	DLL_Scan ((struct DList *)&pw->pw_Menus, (void *)_gtb_countguimenus, 0);

	if (counter) {
	    numnm = counter + 1;

	    if (!(nmb = AllocMem (sizeof (struct NewMenu) * numnm, 0))) {
		ok = FALSE;
		return;
	    } /* if */

	    counter = 0;
	    DLL_Scan ((struct DList *)&pw->pw_Menus, (void *)_gtb_copyguimenus, nmb);
	    nmb[counter].nm_Type = NM_END;

	    wn->IntuiMenus = CreateMenus (nmb, TAG_DONE);
	    FreeMem (nmb, sizeof (struct NewMenu) * numnm);
	    if (!wn->IntuiMenus) {
		ok = FALSE;
		return;
	    } else {
		LayoutMenusA (wn->IntuiMenus, prj->VisualInfo, TAG_END);
	    } /* if */
	} /* if menues */
    }

//if (!GETF_DEBUG(Ep))
    /* ---- Create the Gadget structures */
    {
	struct ExtNewGadget *pg;
	struct Gadget	    *gad = NULL;
	struct NewGadget     ng;

	if (!(gad = CreateContext(&wn->IntuiGadgets))) {
	    ok = 0;
	} /* if */

	for (pg = GetHead(&pw->pw_Gadgets); ok && pg; pg = GetSucc(pg)) {
	    struct GadNode *gd;
//printf ("gad: %s\n", pg->en_GadgetLabel);
	    if (!NEW(gd)) {
		ok = FALSE;
		return;
	    } /* if */
	    gd->GuiGadget    = pg;
	    gd->LastCode     = 0;
	    //gd->Node.ln_Name = pg->en_GadgetLabel;
	    //gd->Parent       = wn;
	    //DLL_AddTail (&wn->AppliGadgets, &gd->Node);
	    HL_Init(&gd->Node, pg->en_GadgetLabel, &wn->Node, HLF_SYSNODE);

	    /* ---- Listviews w/ ShowSelected are preceeded by their partner */
	    if (pg->en_Kind == LISTVIEW_KIND) {
		tg = FindTagItem (GTLV_ShowSelected, pg->en_Tags);
		if (tg && tg->ti_Data) {
		    tg->ti_Data = (ULONG)gad;
		} /* if needs company */
#ifndef ONLY_V39
	    } else if (pg->en_Kind == CHECKBOX_KIND) {
		tg = FindTagItem (GTCB_Checked, pg->en_Tags);
		if (tg && tg->ti_Data) {
		    gd->LastCode = 1;
		} /* if is selected checkbox */
#endif
	    } /* if certain kind */

	    /* ---- GenericKind is not (yet) supported */
	    if (pg->en_Kind == GENERIC_KIND) {
		ok = 0;
		break;
	    } /* if is genkind */

	    ng	= pg->en_NewGadget;
	    ng.ng_VisualInfo = prj->VisualInfo;
	    ng.ng_TextAttr   = &prj->Font;
	    ng.ng_LeftEdge   = GTB__ComputePosX( wn, ng.ng_LeftEdge );
	    ng.ng_TopEdge    = GTB__ComputePosY( wn, ng.ng_TopEdge  );
	    ng.ng_Width      = GTB__ComputeWidX( wn, ng.ng_Width    );
	    ng.ng_Height     = GTB__ComputeWidY( wn, ng.ng_Height   );

	    gad = CreateGadgetA (pg->en_Kind, gad, &ng, pg->en_Tags);
	    if (!gad) {
		ok = 0;
		break;
	    } /* if */
	    gad->UserData    = gd;
	    gd->IntuiGadget  = gad;
	    gd->gdata	     = NULL;
//if (GETF_ABORTCOMMAND(Ep)) break;
	} /* for all gads */
    }
} /* _gtb_genappliwindow */


/* Include this one so I do not need to give the gtx.lib along */
LONG GTX_LoadGUI (struct MemoryChain * mch, UBYTE * filename, Tag tag,
			...)
{
    return GTX_LoadGUIA (mch, filename, (struct TagItem *)&tag);
} /* GTX_LoadGUI */


/* --------------------- */
/* ---- open one project */
int GTB_OpenProject (const char *filename, const char *label) {
    ULONG		valid = 0;
    int 		error = 0;
    struct GTB_Project *prj;

    /* ---- is the module correctly initialized ? */
    if (!GTB_Port) {
	return GTB_NOPORT;
    } /* if */

    /* ---- is a duplicate elimination necessary? */
    if (prj = (void *)HL_FindName (GTBRoot, label)) {
	return GTB_PROJECTACTIVE;
    } /* if */

    /* ---- init the project */
    {
	if (!NEW(prj)) {
	    return GTB_NOMEM;
	} /* if */
	bzero (prj, sizeof(*prj));

	/* ---- basics */
	DLL_Init      ((struct DList *)&prj->GuiWindows);
	//DLL_AddTail (GTB_Projects, &prj->Node); DLL_Init (&prj->AppliWindows);

	if (HL_Init(&prj->Node, label, GTBRoot, HLF_SYSNODE|HLF_SUBCARRIER) != HL_OK) {
	    GTB_CloseProject (prj);
	    return GTB_NOMEM;
	} /* if */

#ifdef LOCAL_MEM
	/* ---- local memory chain */
	if (!(prj->MemChain = GetMemoryChain(4096))) {
	    GTB_CloseProject (prj);
	    return GTB_NOMEM;
	} /* if */
#endif

	/* ---- node/name */
	if (!(prj->Node.Name = strdup (label))) {
	    GTB_CloseProject (prj);
	    return GTB_NOMEM;
	} /* if */

	/* ---- heap for .gui information */
	if (!(prj->GuiData = AllocItem(GTB_MemChain, sizeof (*prj->GuiData), MEMF_CLEAR))) {
	    GTB_CloseProject (prj);
	    return GTB_NOMEM;
	} /* if */
    }

    /* ---- Load the GuiWindows */
    error = (int)GTX_LoadGUI(GTB_MemChain, filename,
			    RG_WindowList, &prj->GuiWindows,
			    RG_GUI,	    prj->GuiData,
			    RG_Valid,	   &valid,
			    TAG_DONE );
//printf ("error %d valid %08lx (%08lx)\n", error, valid, VLF_WINDOWLIST|VLF_GUI);

    if (error) {
	GTB_CloseProject(prj);
	return -error;
    } /* if */

    if (valid != (VLF_GUI|VLF_WINDOWLIST)) {
	GTB_CloseProject(prj);
	return -ERROR_NOTGUIFILE;
//#define ERROR_NOMEM		      1
//#define ERROR_OPEN		      2
//#define ERROR_READ		      3
//#define ERROR_WRITE		      4
//#define ERROR_PARSE		      5
//#define ERROR_PACKER		      6
//#define ERROR_PPLIB		      7
//#define ERROR_NOTGUIFILE	      8
    } /* if */

    /* ---- Screen specifics */
    {
	struct Screen *screen;
// naja ... solange wir noch nicht am xdme kleben ...
//#define ___SCREEN___ IntuitionBase->ActiveScreen
#define   ___SCREEN___ active_window()->WScreen
	prj->IntuiScreen = ___SCREEN___;
	screen = prj->IntuiScreen;

	if (!(prj->VisualInfo = GetVisualInfo(screen, TAG_DONE))) {
	    GTB_CloseProject (prj);
	    return GTB_NOMEM;
	} /* if */

	//if ((prj->GuiData->gui_Font.ta_YSize == 8) && !stricmp(prj->GuiData->gui_Font.ta_Name, "topaz.font")) {
	//    prj->Font.ta_Name  = (STRPTR)screen->RastPort.Font->tf_Message.mn_Node.ln_Name;
	//    prj->Font.ta_YSize = prj->FontY = screen->RastPort.Font->tf_YSize;
//printf ("projectfont: %s\\%d, used:%s\\%d, fontname:%s \n",
//prj->GuiData->gui_Font.ta_Name, prj->GuiData->gui_Font.ta_YSize,
//prj->Font.ta_Name, prj->Font.ta_YSize,
//prj->GuiData->gui_FontName );
	//		       prj->FontX = screen->RastPort.Font->tf_XSize;
	//} else
	{
	    /* ---- use the font found referenced in the GUI */
	    prj->Font.ta_Name		    = prj->GuiData->gui_Font.ta_Name;
	    prj->Font.ta_YSize = prj->FontY = prj->GuiData->gui_Font.ta_YSize;
				 prj->FontX = prj->GuiData->gui_Font.ta_YSize;
	} /* if */

	prj->DivX  = prj->GuiData->gui_Font.ta_YSize;
	prj->DivY  = prj->GuiData->gui_Font.ta_YSize;
	prj->OffsY = screen->RastPort.TxHeight + screen->WBorTop + 1 - prj->DivY;
	prj->OffsX = screen->WBorLeft;
	prj->FactX = prj->FontX;
	prj->FactY = prj->FontY;
    }

    /* ---- Create (Appli-Items and) partly Intui-Items for all Gui-Items */
    ok = TRUE;
    DLL_Scan ((struct DList *)&prj->GuiWindows, (void *)_gtb_genappliwindow, prj);

    if (!ok) {
	GTB_CloseProject(prj);
	return GTB_NOMEM;
    } /* if */

    return GTB_OK;
} /* GTB_OpenProject */


/***************************************************
	      APPLICATION INTERFACE
***************************************************/


// std way is gonna be sprintf (GTB_Buffer, GTB_Format, wnd->Label, gad->Label, gad->Value); do_command (GTB_Buffer);
Prototype int GTB_Control (void);
int GTB_Control (void) {
    struct IntuiMessage     *m, msg;
    struct ExtNewGadget     *en;
    struct ExtNewMenu	    *em;
    struct MenuItem	    *n;
    struct Window	    *wnd;
    struct WinNode	    *wn;
    struct GadNode	    *gd;
    BOOL		    running = TRUE;
    char		    valbuffer[16];
    char		    *value;

    while(( m = GT_GetIMsg( GTB_Port ))) {

	msg = *m;
	wnd = msg.IDCMPWindow;
	wn  = (struct WinNode *)wnd->UserData;

	GT_ReplyIMsg( m );

	switch ( msg.Class ) {

	case	IDCMP_REFRESHWINDOW:
	    GT_BeginRefresh ( wnd );
	    GTB_RedrawWindow( wn, (struct GTB_Project *)wn->Node.Parent);
	    GT_EndRefresh   ( wnd, TRUE );
	    break;

	case	IDCMP_CLOSEWINDOW:
	    GTB_CloseWindow (wn, (struct GTB_Project *)wn->Node.Parent);
	    running = 0;
	    break;

	case	IDCMP_GADGETUP:
      //case	IDCMP_GADGETDOWN:
	    gd = ( void * )(( struct Gadget * )msg.IAddress )->UserData;
	    en = gd->GuiGadget;
//printf ("Selected Gadget: %s\n", en->en_GadgetLabel);
	    switch (en->en_Kind) {
	    case CHECKBOX_KIND:
#ifndef ONLY_V39
		gd->LastCode = !gd->LastCode;
		sprintf (valbuffer, "%d", gd->LastCode);
		value = valbuffer;
		break;
#endif
	    case LISTVIEW_KIND:
	    case MX_KIND:
	    case CYCLE_KIND:
	    case PALETTE_KIND:
	    case SCROLLER_KIND:
	    case SLIDER_KIND:
		sprintf (valbuffer, "%d", (int)msg.Code);
		value = valbuffer;
//printf (" value = %d\n", (int)msg.Code);
		gd->LastCode = msg.Code;
		break;
	    case INTEGER_KIND:
		gd->LastCode = ((struct StringInfo *)((struct Gadget *)msg.IAddress)->SpecialInfo)->LongInt;
	    case STRING_KIND:
//printf (" value = %s\n", ((struct StringInfo *)((struct Gadget *)msg.IAddress)->SpecialInfo)->Buffer);
		value = ((struct StringInfo *)((struct Gadget *)msg.IAddress)->SpecialInfo)->Buffer;
		break;
	    case BUTTON_KIND:
//printf (" button\n");
		value = "";
		break;
	    case TEXT_KIND:
	    case NUMBER_KIND:
//printf (" no value possible !?\n");
		/* nop */
		break;
	    } /* switch */

//printf ("build...\n");
	    sprintf (GTB_Buffer, GTB_Format,
		    wn->Node.Parent->Name,
		    wn->Node.Name,
		    en->en_GadgetLabel,
		    value,
		    wn->Node.Parent->Name,
		    wn->Node.Name,
		    en->en_GadgetLabel,
		    value,
		    wn->Node.Parent->Name,
		    wn->Node.Name,
		    en->en_GadgetLabel,
		    value );
//printf ("%s\neval...\n", GTB_Buffer);
	    do_command (GTB_Buffer);

	    break;

	case	IDCMP_MENUPICK:
	    while( msg.Code != MENUNULL ) {
		n = ItemAddress( wnd->MenuStrip, msg.Code );
		em = (void *)(GTMENUITEM_USERDATA( n ));
//printf ("Selected Menu: %s\n", em->em_MenuLabel);
		if (n->Flags & CHECKIT) {
//printf (" value = %d\n", (n->Flags & CHECKED) ? 1 : 0);
		    sprintf (valbuffer, "%d", (n->Flags & CHECKED) ? 1 : 0);
		    value = valbuffer;
		} else {
		    value = "";
//printf (" no value\n");
		} /* if */

		sprintf (GTB_Buffer, GTB_Format,
			wn->Node.Parent->Name,
			wn->Node.Name,
			em->em_MenuLabel,
			value,
			wn->Node.Parent->Name,
			wn->Node.Name,
			em->em_MenuLabel,
			value,
			wn->Node.Parent->Name,
			wn->Node.Name,
			em->em_MenuLabel,
			value );
		do_command (GTB_Buffer);

		msg.Code = n->NextSelect;
	    } /* while */
	    break;
	} /* switch */
    } /* while */

    return running;
} /* GTB_Control */



int libopen(void) {
    /* SysBase = *(struct Library **)4l; */

    GTXBase = (struct GTXBase *)OpenLibrary ("gadtoolsbox.library", 37);
    if (!GTXBase)
	return -1;

    NoFragBase = (struct NoFragBase *)OpenLibrary ("nofrag.library", 2);
    if (!NoFragBase)
	return -2;

    return 0;
}

static void libclose(void) {
    if (GTXBase)
	CloseLibrary((struct Library *)GTXBase);
    GTXBase = NULL;

    if (NoFragBase)
	CloseLibrary((struct Library *)NoFragBase);
    NoFragBase = NULL;

}


/* ---- close the whole GTB module */
DEFAUTOEXIT( GTB_Terminate )
{

    /* ---- close all Projects */
    HL_Scan   (GTBRoot, (void *)GTB_CloseProject, NULL);
    HL_Dispose(GTBRoot);

#ifndef LOCAL_MEM
    if (GTB_MemChain)
	FreeMemoryChain (GTB_MemChain, TRUE);
    GTB_MemChain = NULL;
#endif

    if (GTB_Port)
	DeleteMsgPort (GTB_Port);
    GTB_Port = NULL;

    if (GTB_Format)
	free (GTB_Format);
    GTB_Format = NULL;

    if (GTB_Buffer)
	free(GTB_Buffer);
    GTB_Buffer = NULL;

    if (GTB_DefWindow)
	CloseWindow(GTB_DefWindow);
    GTB_DefWindow = NULL;

    /* if (GTB_)
	(GTB_);
    GTB_ = NULL; */

    GTB_SigMask = 0;
    libclose();
} /* GTB_Terminate */


/* ---- init the GTB module */
DEFAUTOINIT( GTB_Initialize )
{
//puts (__FILE__);

    //GTB_Projects = &_GTB_Projects; DLL_Init (GTB_Projects);

    GTBRoot	 = HL_SystemList("*GtbProjects*");
    if (!GTBRoot)
	return;
    //GTB_Projects = HL_InstSubs(GTBRoot);

    if (libopen() != 0)
	return;

    /* ---- failing ops */
    GTB_Port	 = CreateMsgPort();
    GTB_Format	 = strdup(GTB_DEFFMT);
    GTB_Buffer	 = malloc(GTB_BUFFERSIZE);
#ifndef LOCAL_MEM
    GTB_MemChain = GetMemoryChain(4096);
#endif

    /* ---- validity checks */

#ifndef LOCAL_MEM
    if ( !GTB_Port || !GTB_MemChain || !GTB_Format || !GTB_Buffer )
#else
    if ( !GTB_Port ||                  !GTB_Format || !GTB_Buffer )
#endif
    {
	GTB_Terminate ();
	return;
    } /* if */

    /* ---- non-failing ops */
    GTB_SigMask = 1 << GTB_Port->mp_SigBit;

} /* GTB_Initialize */



int GTB_Error (int code) {
    //char **av; av = (char **)(&code+1);

    switch (code) {
    case GTB_OK:
	return RET_SUCC;
    case GTB_NOMEM:
	nomemory();
	break;
    case GTB_PROJECTACTIVE:
	error("%s:\nProject '%s' is already used!", av[0], av[1]);
	break;
    case GTB_WINDOWOPEN:
	error("%s:\nWindow '%s' is open!", av[0], av[2]);
	break;
    case GTB_WINDOWCLOSE:
	error("%s:\nWindow '%s' is closed!", av[0], av[2]);
	break;
    case GTB_NOPORT:
	error("%s:\nGadToolsBox module not active", av[0]);
	break;
    default:
	error("%s:\nunknown error code %ld", av[0], (long)code);
    } /* switch */
    return RET_FAIL;
} /* GTB_Error */



/*************************************************
	Fragments of other modules
*************************************************/

#ifdef MAIN_C

DEFSIGHANDLER( GTB_SigMask, GTB_Control(); )

#endif

/***************************************************
		COMMAND INTERFACE
***************************************************/

/*DEFHELP #cmd special GTB - The GadToolsBox Interface */

static void GTB_SetGadgetAttrsA (struct GadNode *gd, struct TagItem *tg)
{
    struct GTB_Project *prj;
    struct WinNode     *wn;
    if (gd) {
	wn  = (void *)gd->Node.Parent;

	if (!wn) {
	    return;
	} /* if */

#ifndef ONLY_V39
	    /* ---- V37 Fix ... the machine freezes, if we call     */
	    /*	    GT_SetGadgetAttrs with NULL windowptr in OS 2.x */
	    if ((GadToolsBase->/*LibNode.*/lib_Version == 37) && !(wn->IntuiWindow)) {
		prj = (void *)wn->Node.Parent;
		if (!AmTerminating) {
		    if (!(GTB_DefWindow) && !(GTB_DefWindow = OpenWindowTags(NULL,
			    WA_Height,	 1,
			    WA_Width,	 1,
			    WA_Left,	 0,
			    WA_Top,	20,
			    WA_IDCMP,	 0,
			    WA_Backdrop, 1,
			    WA_Gadgets,      wn->IntuiGadgets,
			    WA_CustomScreen, prj->IntuiScreen,
			    TAG_END))) {
			error ("%s:\nCannot open fallback window!", av[0]);
		    } else {
			GT_SetGadgetAttrsA (gd->IntuiGadget,
					GTB_DefWindow, NULL, tg);
			/* ---- since the defwindow contains our wingads, we must */
			/*	close it again to avoid confusion		  */
			if (!GTB_FixedDefWin) {
			    CloseWindow (GTB_DefWindow);
			    GTB_DefWindow = NULL;
			} /* if */
		    } /* if */
		} /* if */
	    } else
#endif
		GT_SetGadgetAttrsA (gd->IntuiGadget,
				wn->IntuiWindow, NULL, tg);
    } /* if */
} /* GTB_SetGadgetAttrsA */


static struct GTB_Project *_getgtbproject (void) {
    struct GTB_Project *prj;
    if ((prj = (void *)HL_FindName (GTBRoot, av[1])))
	return prj;
    error ("%s:\nProject %s does not (yet) exist", av[0], av[1]);
    return NULL;
} /* do_getgtbproject */

static struct WinNode *_getgtbwindow (void) {
    struct GTB_Project *prj;
    if (prj = _getgtbproject()) {
	struct WinNode *wn;
	if ((wn = (void *)HL_FindName (&prj->Node, av[2])))
	    return wn;
	error ("%s:\n No window of name '%s'\n in project '%s'", av[0], av[2], av[1]);
    } /* if */
    return NULL;
} /* _getgtbwindow */

static struct GadNode * _getgtbgadget (void) {
    struct WinNode *wn;
    if ((wn = _getgtbwindow())) {
	struct GadNode *gd;
	if ((gd = (void *)HL_FindName (&wn->Node, av[3])))
	    return gd;
	error ("%s:\n No gadget of name '%s'\n in window '%s' of project '%s'", av[0], av[3], av[2], av[1]);
    } /* if */
    return NULL;
} /* _getgtbgadget */

/*DEFHELP #cmd gtb SETGTBGADGET project window gadget value - set another value to a GTB gadget */
DEFUSERCMD("SetGTBGadget", 4, CF_VWM|CF_ICO|CF_COK, void, do_setgtbgadget, (void), )
{
    struct TagItem tg[2] = {TAG_IGNORE, 0, TAG_END };
    struct WinNode     *wn;
    struct GTB_Project *prj;
    struct GadNode     *gd;

    if (gd  = _getgtbgadget()) {
	wn  = (void *)gd->Node.Parent;
	prj = (void *)wn->Node.Parent;

	switch (gd->GuiGadget->en_Kind) {
	case CHECKBOX_KIND:
	case LISTVIEW_KIND:
	case MX_KIND:
	case CYCLE_KIND:
	case PALETTE_KIND:
	case SCROLLER_KIND:
	case SLIDER_KIND:
	case NUMBER_KIND:
	case INTEGER_KIND:
	    tg[0].ti_Data = atol (av[4]);
	    break;

	case STRING_KIND:
	    tg[0].ti_Data = (ULONG)(av[4]);
	    break;

	case TEXT_KIND: /* hmmm not sufficient ... how about abusing the */
			/* lastcode field ? */
	    tg[0].ti_Data = (ULONG)(av[4]);
	    error ("%s:\nText gadgets can not yet be set!", av[0]);
	    return;
	    break;

	case BUTTON_KIND:
	    error ("%s:\n Buttons can't get values!\n", av[0]);
	    return;
	default:
	    error ("%s:\nUnknown gadget type!", av[0]);
	    return;
	} /* switch */

	switch (gd->GuiGadget->en_Kind) {
	case CHECKBOX_KIND:
	    tg[0].ti_Tag = GTCB_Checked;
	    break;
	case LISTVIEW_KIND:
	    tg[0].ti_Tag = GTLV_Selected;
	    break;
	case MX_KIND:
	    tg[0].ti_Tag = GTMX_Active;
	    break;
	case CYCLE_KIND:
	    tg[0].ti_Tag = GTCY_Active;
	    break;
	case PALETTE_KIND:
	    tg[0].ti_Tag = GTPA_Color;
	    break;
	case SCROLLER_KIND:
	    tg[0].ti_Tag = GTSC_Top;
	    break;
	case SLIDER_KIND:
	    tg[0].ti_Tag = GTSL_Level;
	    break;
	case NUMBER_KIND:
	    tg[0].ti_Tag = GTNM_Number;
	    break;
	case INTEGER_KIND:
	    tg[0].ti_Tag = GTIN_Number;
	    break;
	case STRING_KIND:
	    tg[0].ti_Tag = GTST_String;
	    break;
	case TEXT_KIND:
	    tg[0].ti_Tag = GTTX_Text;
	    break;
	} /* switch */

	GTB_SetGadgetAttrsA(gd, tg);
    } /* if */

} /* do_setgtbgadget */

/*DEFHELP #cmd gtb OPENGTBWINDOW project window - open a window of a GTB project */
DEFUSERCMD("OpenGTBWindow", 2, CF_VWM|CF_ICO|CF_COK, void, do_opengtbwindow, (void), )
{
    struct GTB_Project *prj;
    struct WinNode     *wn;

    if ((wn = _getgtbwindow())) {
	prj = (void *)wn->Node.Parent;
	GTB_Error (GTB_OpenWindow (wn, prj));
    }
} /* do_opengtbwindow */

/*DEFHELP #cmd gtb ACTIVATEGTBWINDOW project window - open a window of a GTB project */
DEFUSERCMD("ActivateGTBWindow", 2, CF_VWM|CF_ICO|CF_COK, void, do_activategtbwindow, (void), )
{
    struct WinNode     *wn;

    if ((wn = _getgtbwindow())) {
	if (wn->IntuiWindow)
	    ActivateWindow (wn->IntuiWindow);
	else
	    do_opengtbwindow();
    }
} /* do_opengtbwindow */

/*DEFHELP #cmd gtb CLOSEGTBWINDOW project window - close a window of a GTB project */
DEFUSERCMD("CloseGTBWindow", 2, CF_VWM|CF_ICO|CF_COK, void, do_closegtbwindow, (void), )
{
    struct GTB_Project *prj;
    struct WinNode     *wn;

    if ((wn = _getgtbwindow())) {
	prj = _getgtbproject();
	GTB_Error (GTB_CloseWindow (wn, prj));
    }
} /* closegtbwindow */

/*DEFHELP #cmd gtb LOADGTBPROJECT project filename - read a GTB .GUI File  */
DEFUSERCMD("LoadGTBProject", 2, CF_VWM|CF_ICO|CF_COK, void, do_loadgtbproject, (void), )
{
    GTB_Error (GTB_OpenProject (av[2], av[1]));
} /* loadgtbproject */

/*DEFHELP #cmd gtb DROPGTBPROJECT project - free the resources needed for a GTB Project */
DEFUSERCMD("DropGTBProject", 1, CF_VWM|CF_ICO|CF_COK, void, do_dropgtbproject, (void), )
{
    struct GTB_Project *prj;
    if ((prj = _getgtbproject()))
	GTB_Error (GTB_CloseProject (prj));
} /* dropgtbproject */



int GTB_Notify (struct GadNode *gadget, ULONG attr, APTR value, APTR *base) {
//printf ("Notification: %d %08lx\n", attr, value);
    struct TagItem tg[2] = { TAG_IGNORE, NULL, TAG_DONE };
    if (attr == HLA_Labels) {
	tg[0].ti_Tag  = GTLV_Labels;
	tg[0].ti_Data = (ULONG)value;
	GTB_SetGadgetAttrsA (gadget, tg);
	gadget->gdata = base;
	return 1;
    } /* if */
    return 0;
} /* GTB_Notify */

/*DEFHELP #cmd gtb CONNECTGTBGADGET prj win gad list - connect a gadtoolsgadget with a list */
DEFUSERCMD("ConnectGTBGadget", 4, CF_VWM|CF_ICO|CF_COK, void, do_connectgtbgadget, (void), )
{
    struct WinNode     *wn;
    struct GTB_Project *prj;
    struct GadNode     *gd;
    APTR		list;

    if (gd  = _getgtbgadget()) {
	wn  = (void *)gd->Node.Parent;
	prj = (void *)wn->Node.Parent;

	if (gd->GuiGadget->en_Kind != LISTVIEW_KIND) {
	    error ("%s:\nConnect only works w/ Listviews!");
	    return;
	} /* if */

	if (!(list = HL_LockNode(av[4]))) {
	    error ("%s:\nCannot find List %s", av[0], av[4]);
	    return;
	} /* if */

	if (gd->gdata)
	    HL_Disconnect (gd->gdata, &gd->Node);

	HL_Connect (list, &gd->Node, HLA_Labels);
    } /* if */
} /* connectgtbgadget */


/*DEFLONG #long GTB,LOADGTBPROJECT,DROPGTBPROJECT,OPENGTBWINDOW,CLOSEGTBWINDOW,SETGTBGADGET

Interface To enable XDME to load and basically display (not everything is
currently handeled correctly) GadToolsBox Projects (namely ".GUI" Files)

the user has the possibility to draw his own asynch. requesters and load
and display them from within XDME; each time, a menu is selected
or a gadget is Selected (Select-UP), a XDME Command is called;

the command is currently build in the form
projectname"-"windowname"-"gadgetname" "value
for gadgets and
projectname"-"windowname"-"menuname" "value
for menus; value is the State of the toggle for a togglemenu,
the active label for a listview, and so on; for button-gadgets
and non-toggle menuitems, value is "".
(the format may be changed with the $gtbformat variable)

however I think about a more intuitive way of connecting
variables, gadgets and menues, so that macro-solution might
be removed in the near future ...

It is already possible to connect Listview Gadgets with Lists (see
the Lists section ... ahem where? =8-}) so that every change of a
List is immediately shown in the connected Listviews (sorry, but
the Cycle Gadgets are not yet supported nor any other structure
than Lists and LV-Gadgets, but this is a planned enhancement)



*WARNING* the GTB module is BETA and it is certainly not
  bulletproof - You should think twice about what You are
  doing ...

*BUG* (or not?) it is not defined whatever happens, if there is
  that Boopsi Pop-Image used inside a GTB Project, so better make
  sure it is not used ...

*BUG* (yea it is...) i have not (yet) added Fallback conditions,
  to make sure a window does not exceed Screensize... in that
  concern ... we do currently use the Screenfont also, if a
  non-topaz font was defined in the GTB Project (Any help how I can
  check, if the user wanted the GTB Project's font?)

*BUG* (probabely NOT subject of change) XDME ignores the settings
  for screens, it always uses the screen of the active TextWindow ...

*BUG* there is currently no support for Gadget Shortcuts in a
  GTB project (any suggestions?)

*BUG* there is currently no sufficient menu handling (e.g. setcheck
  is not possible)

*/

/******************************************************************************
*****  END GTB.c
******************************************************************************/


#ifdef TEST

#include <stdio.h>
#include <stdlib.h>



int main (int ac, char **av) {
    atexit (libclose);
    if (libopen() != 0) {
//fprintf (stderr, "noopenlib\n");
	return 20;
    }

    if (GTB_Initialize()) {
	atexit (GTB_Terminate);

	if (GTB_OpenProject("test.gui", "alpha") == GTB_OK) {
	    if (GTB_OpenWindow (
		GetHead(
		    &(((struct GTB_Project *)GetHead(
			GTB_Projects))->AppliWindows)),
		GetHead(GTB_Projects)) == GTB_OK)
		while (GTB_Handle())
		    WaitPort (GTB_Port);
	    return 0;
	} /* if */
    } /* if */

    return 10;
} /* main */


#endif /*  */

    DEFFLAG( 94-11-25, AmTerminating, 0 )

#ifdef SPC_VAR
// Information for Util/Var/Parser ...

spcvars += {
    strptr GtbFormat = {
	help = %[ format to convert Project, Window, Gadget|Menu and
		  Value Information of a GTB_Signal %];
	reference = GTB_Format;
    };
};

sighandler GTB = {
    signal = "GTB_SigMask";
    code = %[ GTB_Handler(); %];
};

#endif


#if 0

// gtbgadget has no OM_NEW, since it cannot be created on User request

class gtbgadget = {
    superclass = rootclass;
    contents = {
	slot IntuiGadget = {
	    type = "struct Gadget *";
	};
	slot LastCode = {
	    type = "ULONG";
	};
	slot gdata = {
	    type = "APTR";
	};
	slot GuiGadget = {
	    type = "struct ExtNewGadget *";
	};
    };

    attribute HA_Label = {
	type = "STRPTR";
	S = {{
	}};
	G = {{
	    *((struct opGet *)msg)->opg_Storage = inst->IntuiGadget->GadgetText->IText;
	}};
    };

    // only for Listview, Cycle
    attribute HA_LabelCarrier = {
	type = "HObject *";
	S = {{
	}};
	G = {{
	}};
    };
    attribute HA_GadValue = {
	S = {{
	}};
	G = {{
	}};
    };
    attribute HA_Disabled = {
	type = "BOOL";
	S = {{
	}};
	G = {{
	}};
    };
};

// gtbwindow has no OM_NEW, since it cannot be created on User request

class gtbwindow = {

    //struct Gadget	   *IntuiGadgets;
    //struct Window	   *IntuiWindow;
    //struct Menu	   *IntuiMenus;
    //HObject		   *AppliMenus;
    //struct ProjectWindow *GuiWindow;

    attribute HA_Visible = {
	type = "BOOL";
	S = {{
	}};
	G = {{
	}};
    };
};

// gtbmenu has no OM_NEW, since it cannot be created on User request

class gtbmenu = {
    superclass = subcarrierclass;
    contents = {
	slot IntuiMenu = {
	    type = "struct Menu *";
	};
	slot GuiGadget = {
	    type = "struct ExtNewMenu *";
	};

    };

    attribute HA_Label = {
	type = "STRPTR";
	S = {{
	    inst->IntuiMenu->MenuName = strrep (inst->IntuiMenu->MenuName, (STRPTR)ti->ti_Data);
	}};
	G = {{
	    *((struct opGet *)msg)->opg_Storage = inst->IntuiMenu->MenuName;
	}};
    };

    attribute HA_Disabled = {
	type = "BOOL";
	S = {{
	    if (inst->IntuiMenu->Flags & ITEMENABLED)
		OffMenu (GetMenuPos(o));
	    else
		OnMenu	(GetMenuPos(o));
	}};
	G = {{
	    *((struct opGet *)msg)->opg_Storage = !(inst->IntuiMenu->Flags & ITEMENABLED);
	}};
    };
};
class gtbmenuitem = {
    superclass = subcarrierclass;
    contents = {
	slot IntuiMenu = {
	    type = "struct MenuItem *";
	};
	slot GuiGadget = {
	    type = "struct ExtNewMenu *";
	};

    };

    attribute HA_Label = {
	type = "STRPTR";
	S = {{
	    if (IsTextItem(o))
		((struct IntuiText *)inst->IntuiMenu->ItemFill)->IText = strrep (((struct IntuiText *)inst->IntuiMenu->ItemFill)->IText, (STRPTR)ti->ti_Data);
	}};
	G = {{
	    if (IsTextItem(o))
		*((struct opGet *)msg)->opg_Storage = inst->IntuiMenu->MenuText->IText;
	}};
    };

    attribute HA_MenuCheck = {
	type = "BOOL";
	S = {{
	}};
	G = {{
	    *((struct opGet *)msg)->opg_Storage = (inst->IntuiMenu->Flags & ITEMCHECKED);
	}};
    };

    attribute HA_Disabled = {
	type = "BOOL";
	S = {{
	    if (inst->IntuiMenu->Flags & ITEMENABLED)
		OffMenu (GetMenuPos(o));
	    else
		OnMenu	(GetMenuPos(o));
	}};
	G = {{
	    *((struct opGet *)msg)->opg_Storage = !(inst->IntuiMenu->Flags & ITEMENABLED);
	}};
    };
};

#endif
