/*** include files ***/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <proto/exec.h>
#include <proto/muimaster.h>
#include <libraries/mui.h>
#include <libraries/gadtools.h>
#include <intuition/intuition.h>
#include <intuition/classusr.h>
#include <proto/utility.h>
#include <utility/utility.h>
#include <utility/tagitem.h>
#include <clib/alib_protos.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define REG(x) register __ ## x
#define ASM __asm
#define SAVEDS __saveds

#ifndef MAKE_ID
#define MAKE_ID(a,b,c,d) ((((ULONG) (a)) << 24) | (((ULONG) (b)) << 16) | (((ULONG) (c)) << 8) | ((ULONG) (d)))
#endif

#define TAGBASE_KLJ (TAG_USER | (9999UL << 16))

/* counter for general use */
int i;

static const char *entries[] = { "Entry1","Entry2","Entry3", NULL };

/* Structure for use in listviews */
struct VBList
{ char *Value;
  char *Key;
};

struct VBList *vbl;

       
/* This structure contains the pointers to all our objects */
struct ObjApp
{
  /* Application and window objects */
  APTR App; APTR ToolBoxWindow; APTR MainWindow; APTR ObjectsWindow;
  APTR Toolbar; APTR MainWinGroup; APTR MenuStrip;

  /* The active object */
  APTR actobj;

  /* Array with windows created by the user. max is 16 for now */
  APTR UserWin[15];

  /* Menu items */
  APTR MenuFile; APTR MenuEdit; APTR MenuView; APTR MenuInsert; APTR MenuTools; APTR MenuHelp;
  APTR FileNew; APTR FileOpen; APTR FileSave; APTR FileSaveAs; APTR FileMakeExe; APTR FileQuit;
  APTR EditCut; APTR EditCopy; APTR EditPaste; APTR EditDelete;
  APTR ViewObjects; APTR ViewToolbox; APTR ViewToolbar;
  APTR InsertWindow;
  APTR ToolsMenuEditor; APTR ToolsOptions;
  APTR HelpContents; APTR HelpAboutVB; APTR HelpAboutMUI;

  /* Toolbar buttons */
  APTR ToolBarQuit; APTR ToolBarHelp;

  /* Objectswindow objects for notify class*/
  APTR HelpLine; APTR HelpNode; APTR ObjectID; 

  /* Objectswindow objects for area class*/
  APTR BackGround; APTR ContextMenu; APTR ControlChar; APTR CycleChain;
  APTR Disabled; APTR Draggable; APTR Dropable; APTR Font; APTR Frame;
  APTR FramePhantomHoriz; APTR FrameTitle; APTR HorizDisappear;
  APTR HorizWeight; APTR InnerBottom; APTR InnerLeft; APTR InnerRight;
  APTR InnerTop; APTR InputMode; APTR MaxHeigth; APTR MaxWidth;
  APTR Selected; APTR ShortHelp; APTR ShowMe; APTR ShowSelState;
  APTR VertDisappear; APTR VertWeight; APTR Weight;  

  /* General objects in objectswindow */
  APTR ApplyChanges; APTR ObjListPop; 
};

struct ObjApp *a;

struct Library *MUIMasterBase;
/*LONG __stack = 35000;*/

#include "Prototypes.c"
#include "ObjWinSubs.c"
#include "ListEntries.c"
#include "Menu.c"
#include "MainWin.c"
#include "DropObjClass.c"
#include "HookFuncs.c"
#include "ObjWin.c"
#include "DropAppClass.c"
#include "DropObjSubs.c"
#include "ToolBoxWin.c"
#include "CommonSubs.c"
                               
static VOID ShutDown(char *str)
{
  if (a->App)        MUI_DisposeObject(a->App);
  if (DropButClass)  MUI_DeleteCustomClass(DropButClass);
  if (DropGrpClass)  MUI_DeleteCustomClass(DropGrpClass);
  if (DropRadClass)  MUI_DeleteCustomClass(DropRadClass);
  if (DropCycClass)  MUI_DeleteCustomClass(DropCycClass);
  if (DropChkClass)  MUI_DeleteCustomClass(DropChkClass);
  if (DropTxtClass)  MUI_DeleteCustomClass(DropTxtClass);
  if (DropLstClass)  MUI_DeleteCustomClass(DropLstClass);
  if (DropStrClass)  MUI_DeleteCustomClass(DropStrClass);
  if (DropGauClass)  MUI_DeleteCustomClass(DropGauClass);
  if (DropSclClass)  MUI_DeleteCustomClass(DropSclClass);
  if (DropBalClass)  MUI_DeleteCustomClass(DropBalClass);
  if (DropImgClass)  MUI_DeleteCustomClass(DropImgClass);
  if (DropSldClass)  MUI_DeleteCustomClass(DropSldClass);
  if (DropKnbClass)  MUI_DeleteCustomClass(DropKnbClass);
  if (DropLvlClass)  MUI_DeleteCustomClass(DropLvlClass);
  if (DropNmbClass)  MUI_DeleteCustomClass(DropNmbClass);

  if (DropAppClass)  MUI_DeleteCustomClass(DropAppClass);
  if (MUIMasterBase) CloseLibrary(MUIMasterBase);

  if (a)             FreeVec(a);
  if (vbl)           FreeVec(vbl);
  
  if (str)
  { puts(str);
    exit(20);
  }

  exit(0);
}

BOOL BuildGUI(void)
{ 
  a->App = DropApplicationObject,
    MUIA_Application_Title,       "Visual Builder v1.0 alpha",
    MUIA_Application_Version,     "$VER: Visual Builder 1.0 (12.06.97)",
    MUIA_Application_Copyright,   "Copyright ©1997 by Jan Klok",
    MUIA_Application_Author,      "Jan Klok <jklok@hotmail.com>",
    MUIA_Application_Description, "A userfriendly application builder",
    MUIA_Application_Base,        "VisualBuilder",
    MUIA_Application_HelpFile,    "VisualBuilder.guide",
    MUIA_Application_Menustrip,   a->MenuStrip,

    SubWindow, a->ToolBoxWindow = BuildToolBoxWin(),
    SubWindow, a->MainWindow = BuildMainWin(),
    SubWindow, a->ObjectsWindow = BuildObjWin(),
  End;

  if(a->App)
  {
    /* Close application when closegadget of toolbarwindow is hit */
    DoMethod(a->MainWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
             a->App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);

    /* Install toolbar notifications */
    DoMethod(a->ToolBarQuit, MUIM_Notify, MUIA_Pressed, FALSE,
             a->App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);

    DoMethod(a->ToolBarHelp,MUIM_Notify, MUIA_Pressed, FALSE,
             a->App,5,MUIM_Application_ShowHelp,NULL,NULL,"MAIN",1);

    /* Install file menu notificatons */
    DoMethod(a->FileQuit, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
             a->App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);

    /* Install view menu notifications */
    DoMethod(a->ViewObjects, MUIM_Notify, MUIA_Menuitem_Checked, MUIV_EveryTime,
             a->ObjectsWindow, 3, MUIM_Set, MUIA_Window_Open, MUIV_TriggerValue);

    DoMethod(a->ObjectsWindow, MUIM_Notify, MUIA_Window_Open, MUIV_EveryTime,
             a->ViewObjects, 3, MUIM_Set, MUIA_Menuitem_Checked, MUIV_TriggerValue);

    DoMethod(a->ObjectsWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
             a->ObjectsWindow, 3, MUIM_Set, MUIA_Window_Open, FALSE);

    DoMethod(a->ViewToolbox, MUIM_Notify, MUIA_Menuitem_Checked, MUIV_EveryTime,
             a->ToolBoxWindow, 3, MUIM_Set, MUIA_Window_Open, MUIV_TriggerValue);

    DoMethod(a->ToolBoxWindow, MUIM_Notify, MUIA_Window_Open, MUIV_EveryTime,
             a->ViewToolbox, 3, MUIM_Set, MUIA_Menuitem_Checked, MUIV_TriggerValue);

    DoMethod(a->ToolBoxWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
             a->ToolBoxWindow, 3, MUIM_Set, MUIA_Window_Open, FALSE);

    DoMethod(a->ViewToolbar,MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
             a->Toolbar,3,MUIM_CallHook,&ShowHideToolBarHook,MUIV_TriggerValue);

    /* Install insert menu notifications */
    DoMethod(a->InsertWindow,MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
             a->MainWindow,3,MUIM_CallHook,&InsertWindowHook,1);

    /* Install edit menu notifications */
    DoMethod(a->EditDelete,MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
             a->MainWindow,3,MUIM_CallHook,&DeleteObjectHook,1);

    /* Install help menu notifications */
    DoMethod(a->HelpContents,MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
             a->App,5,MUIM_Application_ShowHelp,NULL,NULL,"MAIN",1);

    DoMethod(a->HelpAboutMUI,MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
             a->App,2,MUIM_Application_AboutMUI,a->MainWindow);
             
    DoMethod(a->HelpAboutVB,MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
             a->MainWindow,3,MUIM_CallHook,&AboutVBHook,1);
             
    /* Install objects window notifications */
    DoMethod(a->ApplyChanges, MUIM_Notify, MUIA_Pressed, FALSE,
             a->MainWindow, 3, MUIM_CallHook,&ApplyChangesHook,1);

    /* Install doubleclick for lists in objects window */
    DoMethod((Object *)XGet(a->ObjListPop,MUIA_Popobject_Object),MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
             a->ObjListPop,2,MUIM_Popstring_Close,TRUE);

    DoMethod((Object *)XGet(a->BackGround,MUIA_Popobject_Object),MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
             a->BackGround,2,MUIM_Popstring_Close,TRUE);

    DoMethod((Object *)XGet(a->Font,MUIA_Popobject_Object),MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
             a->Font,2,MUIM_Popstring_Close,TRUE);

    DoMethod((Object *)XGet(a->Frame,MUIA_Popobject_Object),MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
             a->Frame,2,MUIM_Popstring_Close,TRUE);

    DoMethod((Object *)XGet(a->InputMode,MUIA_Popobject_Object),MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
             a->InputMode,2,MUIM_Popstring_Close,TRUE);

    /* Insert items in BackGround list */
    for(i=0;backgrounds[i].Key!=NULL;i++)
    { vbl->Key=backgrounds[i].Key;
      vbl->Value=backgrounds[i].Value;
      DoMethod((Object *)XGet(a->BackGround,MUIA_Popobject_Object),MUIM_List_InsertSingle,vbl,MUIV_List_Insert_Bottom);
    }
       
    /* Insert items in Font list */
    for(i=0;fonts[i].Key!=NULL;i++)
    { vbl->Key=fonts[i].Key;
      vbl->Value=fonts[i].Value;
      DoMethod((Object *)XGet(a->Font,MUIA_Popobject_Object),MUIM_List_InsertSingle,vbl,MUIV_List_Insert_Bottom);
    }

    /* Insert items in Frame list */
    for(i=0;frames[i].Key!=NULL;i++)
    { vbl->Key=frames[i].Key;
      vbl->Value=frames[i].Value;
      DoMethod((Object *)XGet(a->Frame,MUIA_Popobject_Object),MUIM_List_InsertSingle,vbl,MUIV_List_Insert_Bottom);
    }

    /* Insert items in InputMode list */
    for(i=0;inputmodes[i].Key!=NULL;i++)
    { vbl->Key=inputmodes[i].Key;
      vbl->Value=inputmodes[i].Value;
      DoMethod((Object *)XGet(a->InputMode,MUIA_Popobject_Object),MUIM_List_InsertSingle,vbl,MUIV_List_Insert_Bottom);
    }
                
    /* Open the vb windows */
    set(a->MainWindow,    MUIA_Window_Open, TRUE);
    set(a->ToolBoxWindow, MUIA_Window_Open, TRUE);
    set(a->ObjectsWindow, MUIA_Window_Open, TRUE);

    /* Open the first user window */
    set(a->InsertWindow,MUIA_Menuitem_Trigger,TRUE);
    
    return(TRUE);
  }
  else return(FALSE);
}

static VOID Initialize(VOID)
{
  if (!(a = AllocVec(sizeof(struct ObjApp), MEMF_PUBLIC|MEMF_CLEAR)))
    ShutDown("No memory for ObjApp structure");

  if (!(vbl = AllocVec(sizeof(struct VBList), MEMF_PUBLIC|MEMF_CLEAR)))
    ShutDown("No memory for VBList structure");

  if (!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN)))
    ShutDown("Failed to open mui");

  if (!(DropAppClass = MUI_CreateCustomClass(NULL, MUIC_Application, NULL, sizeof(struct DropObjData), DropApp_Dispatcher)))
    ShutDown("Couldn't create DropAppClass!");

  if (!(DropButClass = MUI_CreateCustomClass(NULL, MUIC_Text, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropButClass!");

  if (!(DropGrpClass = MUI_CreateCustomClass(NULL, MUIC_Group, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropGrpClass!");

  if (!(DropStrClass = MUI_CreateCustomClass(NULL, MUIC_String, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropStrClass!");

  if (!(DropRadClass = MUI_CreateCustomClass(NULL, MUIC_Radio, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropRadClass!");

  if (!(DropCycClass = MUI_CreateCustomClass(NULL, MUIC_Cycle, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropCycClass!");

  if (!(DropLstClass = MUI_CreateCustomClass(NULL, MUIC_Listview, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropLstClass!");

  if (!(DropChkClass = MUI_CreateCustomClass(NULL, MUIC_Image, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropChkClass!");

  if (!(DropTxtClass = MUI_CreateCustomClass(NULL, MUIC_Text, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropLabClass!");

  if (!(DropGauClass = MUI_CreateCustomClass(NULL, MUIC_Gauge, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropGauClass!");

  if (!(DropSclClass = MUI_CreateCustomClass(NULL, MUIC_Scale, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropSclClass!");

  if (!(DropBalClass = MUI_CreateCustomClass(NULL, MUIC_Balance, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropBalClass!");

  if (!(DropImgClass = MUI_CreateCustomClass(NULL, MUIC_Image, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropImgClass!");

  if (!(DropSldClass = MUI_CreateCustomClass(NULL, MUIC_Slider, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropSldClass!");

  if (!(DropKnbClass = MUI_CreateCustomClass(NULL, MUIC_Knob, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropKnbClass!");

  if (!(DropLvlClass = MUI_CreateCustomClass(NULL, MUIC_Levelmeter, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropLvlClass!");

  if (!(DropNmbClass = MUI_CreateCustomClass(NULL, MUIC_Numericbutton, NULL, sizeof(struct DropObjData), DropObj_Dispatcher)))
    ShutDown("Couldn't create DropNmbClass!");

  if (!BuildMenu())
    ShutDown("Couldn't create menu!");

  if (!BuildGUI())
    ShutDown("Couldn't create application!");
}

int main(int argc,char *argv[])
{
  Initialize();

  { ULONG sigs = 0;

    while (DoMethod(a->App,MUIM_Application_NewInput,&sigs) != MUIV_Application_ReturnID_Quit)
    { if (sigs)
      { sigs = Wait(sigs | SIGBREAKF_CTRL_C);
        if (sigs & SIGBREAKF_CTRL_C) break;
      }
    }
  }

  ShutDown(NULL);
}
