/* MetaToolPrefs (C) by Martin Steigerwald */
/* Released under GPL license, version 2 and up,
   from version 3.3 and above 
*/

/* includes */
#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/locale_protos.h>
#include <clib/utility_protos.h>
#include <clib/dospath_protos.h>
#include <clib/muimaster_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>

// #include <pragmas/dospath_pragmas.h>
// DOSPath Pragmas im StormC-Format

#pragma amicall(DOSPathBase, 0x24,FreePathList(a0))
#pragma amicall(DOSPathBase, 0x36,FindFileInPathList(a0,a1))
#pragma amicall(DOSPathBase, 0x42,GetProcessPathList(a0))
#pragma amicall(DOSPathBase, 0x4e,CopyWorkbenchPathList(a0,a1))

#include <pragmas/intuition_pragmas.h>
#include <pragmas/locale_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/muimaster_pragmas.h>

#include <libraries/asl.h>
#include <libraries/dospath.h>
#include <libraries/gadtools.h>
#include <libraries/locale.h>
#include <libraries/mui.h>
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <dos/rdargs.h>
#include <libraries/gadtools.h>
#include <exec/memory.h>
#include <string.h>

#define CATCOMP_NUMBERS
#define CATCOMP_ARRAY
#include "MetaToolPrefs_strings.h"

/* defines */

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

#define APP_NAME        "MetaToolPrefs"
#define APP_AUTHOR      "Martin Steigerwald"
#define APP_COPYRIGHT   "© 1996-2002 by Martin Steigerwald"
#define APP_VERSION     "$VER: MetaToolPrefs 3.3 (16.3.2002)"
#define APP_BASE        "METATOOLPREFS"
#define ABOUTTEXT       "\33bMetaToolPrefs\33n\n\nVersion: %s\n%s"

#define MTPREFS_CATALOGVERSION 32

#define MAXMETATYPELENGTH       12
#define MAXTOOLLENGTH           80
#define MAXARGUMENTSLENGTH      80
#define MAXFILENAMELENGTH       108
#define MAXPATHNAMELENGTH       512

#define MODE_CHANGE_METATYPE    1    /* for updategadgets */
#define MODE_CHANGE_TOOL        2
#define MODE_CHANGE_ARGUMENTS   3
#define MODE_CHANGE_WB          4

#define LINEBUFFERSIZE          256  /* for config file loading routine */

/* ixemul */

int __nocommandline=1;

static const char *MetaTypeNames[] =
{
    "8SVX",     "ANIM",     "BIN",      "DVI",      "GIF",
    "GUIDE",    "HTML",     "ICONX",    "ILBM",     "INST",
    "JPEG",     "MOVIE",    "PS",       "REXX",     "SOURCE",
    "TEX",      "TEXT",     NULL
};


/* menudata */

enum { MEN_PROJECT_NEW=1, MEN_PROJECT_RELOAD, MEN_PROJECT_LOAD,
    MEN_PROJECT_SAVE, MEN_PROJECT_SAVEAS, MEN_PROJECT_QUIT,
    MEN_SETTINGS_CONFIGNAME, MEN_SETTINGS_MUI, MEN_ABOUT_APP, MEN_ABOUT_MUI };

static struct NewMenu MainMenu[] =
{
    { NM_TITLE, (STRPTR)MSG_MAINWINDOW_PROJECT_MENU    , 0  , 0, 0, 0 },
    { NM_ITEM,  (STRPTR)MSG_MAINWINDOW_PROJECT_NEW     , "L", 0, 0, (APTR)MEN_PROJECT_NEW },
    { NM_ITEM,  (STRPTR)MSG_MAINWINDOW_PROJECT_RELOAD  , "L", 0, 0, (APTR)MEN_PROJECT_RELOAD },
    { NM_ITEM,  (STRPTR)MSG_MAINWINDOW_PROJECT_SAVE    , "S", 0, 0, (APTR)MEN_PROJECT_SAVE },
    { NM_ITEM,  (STRPTR)MSG_MAINWINDOW_PROJECT_SAVEAS  , 0  , 0, 0, (APTR)MEN_PROJECT_SAVEAS },
    { NM_ITEM,  (STRPTR)NM_BARLABEL                    , 0  , 0, 0, (APTR)0 },
    { NM_ITEM,  (STRPTR)MSG_MAINWINDOW_PROJECT_QUIT    , "Q", 0, 0, (APTR)MEN_PROJECT_QUIT },
    { NM_TITLE, (STRPTR)MSG_MAINWINDOW_SETTINGS_MENU   , 0  , 0, 0, 0 },
    { NM_ITEM,  (STRPTR)MSG_MAINWINDOW_SETTINGS_CONFIGFILE
                                                       , 0  , 0, 0, (APTR)MEN_SETTINGS_CONFIGNAME },
    { NM_ITEM,  (STRPTR)MSG_MAINWINDOW_SETTINGS_MUI    , 0  , 0, 0, (APTR)MEN_SETTINGS_MUI },
    { NM_TITLE, (STRPTR)MSG_MAINWINDOW_ABOUT_MENU      , 0  , 0, 0, 0 },
    { NM_ITEM,  (STRPTR)MSG_MAINWINDOW_ABOUT_APP       , "?", 0, 0, (APTR)MEN_ABOUT_APP },
    { NM_ITEM,  (STRPTR)MSG_MAINWINDOW_ABOUT_MUI       , 0  , 0, 0, (APTR)MEN_ABOUT_MUI },
    { NM_END,   NULL                , 0  , 0, 0, 0 },
};

enum { MEN_MTENTRYPANEL_SELECT_ALL=1, MEN_MTENTRYPANEL_DESELECT_ALL,
    MEN_MTENTRYPANEL_TOGGLE_ALL, MEN_MTENTRYPANEL_CLOSE_ALL, MEN_MTENTRYPANEL_SETSAVE,
    MEN_MTENTRYPANEL_UNSETSAVE, MEN_MTENTRYPANEL_CHECKCONFIG };

static struct NewMenu MTEntryPanelMenu[] =
{
    { NM_TITLE, (STRPTR)MSG_MTENTRYPANEL_MENU,          0 , 0, 0, 0 },
    { NM_ITEM,  (STRPTR)MSG_MTENTRYPANEL_SELECT_ALL,    0 , 0, 0, (APTR)MEN_MTENTRYPANEL_SELECT_ALL },
    { NM_ITEM,  (STRPTR)MSG_MTENTRYPANEL_DESELECT_ALL,  0 , 0, 0, (APTR)MEN_MTENTRYPANEL_DESELECT_ALL },
    { NM_ITEM,  (STRPTR)MSG_MTENTRYPANEL_TOGGLE_ALL,    0 , 0, 0, (APTR)MEN_MTENTRYPANEL_TOGGLE_ALL },
    { NM_ITEM,  (STRPTR)MSG_MTENTRYPANEL_CHECKCONFIG,   0 , 0, 0, (APTR)MEN_MTENTRYPANEL_CHECKCONFIG },
    { NM_ITEM,  (STRPTR)MSG_MTENTRYPANEL_SETSAVE,       0 , 0, 0, (APTR)MEN_MTENTRYPANEL_SETSAVE },
    { NM_ITEM,  (STRPTR)MSG_MTENTRYPANEL_UNSETSAVE,     0 , 0, 0, (APTR)MEN_MTENTRYPANEL_UNSETSAVE },
    { NM_ITEM,  (STRPTR)MSG_MTENTRYPANEL_CLOSE_ALL,     0 , 0, 0, (APTR)MEN_MTENTRYPANEL_CLOSE_ALL },

    { NM_END,   NULL                , 0  , 0, 0, 0 },
};

/* global data for MetaToolPrefs routines */

struct  Library *MUIMasterBase=NULL, *DOSPathBase=NULL;
struct WBStartup *WBenchMsg;

struct Catalog *Catalog=NULL;

struct  MUI_CustomClass *DragCheckMark=NULL, *DragString_Class=NULL;
struct  MUI_CustomClass *MTEntryList_Class=NULL, *MTEntryPanel_Class=NULL;
struct  MUI_CustomClass *MTEditWindow_Class=NULL;
struct  MUI_CustomClass *MainWindow_Class=NULL, *App_Class=NULL;

Object  *App;

ULONG   OSVersion;

/* MetaTypeEntry */

struct MetaTypeEntry
{
    char    MetaType[MAXMETATYPELENGTH];
    char    Tool[MAXTOOLLENGTH];
    char    Arguments[MAXARGUMENTSLENGTH];
    BOOL    WB;
    BOOL    FromCD;
    Object  *EditWindow;
};

#define DRAGTYPE_METATYPE   1
#define DRAGTYPE_TOOL       2
#define DRAGTYPE_ARGUMENTS  3
#define DRAGTYPE_WB         4

#define MUISERIALNR_HELIOS  1007
#define TAGBASE_HELIOS      (TAG_USER | (MUISERIALNR_HELIOS << 16))

#define MUIA_DragString_ObjectID          (TAGBASE_HELIOS | 0x1010)

#define MUIM_MTEntryList_Load       (TAGBASE_HELIOS | 0x1020)
#define MUIM_MTEntryList_Save       (TAGBASE_HELIOS | 0x1021)

#define MUIA_MTEditWindow_Originator       (TAGBASE_HELIOS | 0x1030)
#define MUIA_MTEditWindow_Entry            (TAGBASE_HELIOS | 0x1031)
#define MUIA_MTEditWindow_CloseAble        (TAGBASE_HELIOS | 0x1032)
#define MUIM_MTEditWindow_UpdateGadgets    (TAGBASE_HELIOS | 0x1033)
#define MUIM_MTEditWindow_UpdateEntry      (TAGBASE_HELIOS | 0x1034)

#define MUIA_MTEntryPanel_CloseAble         (TAGBASE_HELIOS | 0x1040)
#define MUIM_MTEntryPanel_Edit              (TAGBASE_HELIOS | 0x1041)
#define MUIM_MTEntryPanel_New               (TAGBASE_HELIOS | 0x1042)
#define MUIM_MTEntryPanel_Remove            (TAGBASE_HELIOS | 0x1043)
#define MUIM_MTEntryPanel_QuitEdit          (TAGBASE_HELIOS | 0x1044)
#define MUIM_MTEntryPanel_QuitEditAll       (TAGBASE_HELIOS | 0x1045)
#define MUIM_MTEntryPanel_UpdateEntry       (TAGBASE_HELIOS | 0x1046)
#define MUIM_MTEntryPanel_CheckConfig       (TAGBASE_HELIOS | 0x1047)
#define MUIM_MTEntryPanel_SetSave           (TAGBASE_HELIOS | 0x1048)

#define MTEntryPanel_SetSave_Set        1
#define MTEntryPanel_SetSave_UnSet      2
#define MTEntryPanel_Edit_Active        1
#define MTEntryPanel_Edit_Selected      2

#define MUIM_MainWindow_About               (TAGBASE_HELIOS | 0x1050)
#define MUIM_MainWindow_Aboutmui            (TAGBASE_HELIOS | 0x1051)
#define MUIM_MainWindow_Reload              (TAGBASE_HELIOS | 0x1052)
#define MUIM_MainWindow_Save                (TAGBASE_HELIOS | 0x1053)
#define MUIM_MainWindow_SaveAs              (TAGBASE_HELIOS | 0x1054)
#define MUIM_MainWindow_ChangeConfigFile    (TAGBASE_HELIOS | 0x1055)
#define MUIM_MainWindow_MUISettings         (TAGBASE_HELIOS | 0x1056)
#define MUIM_MainWindow_Finish              (TAGBASE_HELIOS | 0x1057)

struct  MUIP_MTEntryList_Load       { ULONG MethodID; STRPTR file; ULONG FromCD; };
struct  MUIP_MTEntryList_Save       { ULONG MethodID; STRPTR file; };

struct  MUIP_MTEditWindow_UpdateEntry   { ULONG MethodID; LONG mode; };

struct  MUIP_MTEntryPanel_Edit          { ULONG MethodID; ULONG TriggerValue; };
struct  MUIP_MTEntryPanel_QuitEdit      { ULONG MethodID; struct MetaTypeEntry *entry; };
struct  MUIP_MTEntryPanel_UpdateEntry   { ULONG MethodID; struct MetaTypeEntry *entry; };
struct  MUIP_MTEntryPanel_SetSave       { ULONG MethodID; ULONG mode; };

struct  MUIP_MainWindow_Finish      { ULONG MethodID; ULONG quitmode; };


/* start of code */

/* locale support funcs
   taken from psi.c, thanks Stefan
*/

char *GetStr(int num)
{
        struct CatCompArrayType *cca = (struct CatCompArrayType *)CatCompArray;
        while (cca->cca_ID != num) cca++;
        if (LocaleBase) return(GetCatalogStr(Catalog,num,cca->cca_Str));
        return((char *)cca->cca_Str);
}

void LocalizeNewMenu(struct NewMenu *nm)
{
        for (;nm->nm_Type!=NM_END;nm++)
                if (nm->nm_Label != NM_BARLABEL)
                        nm->nm_Label = GetStr((int)nm->nm_Label);
}

/* support funcs
   taken from psi.c, Thanks Stefan.
*/

ULONG DoSuperNew(struct IClass *cl, Object *obj, ULONG tag1,...)
{
    return(DoSuperMethod(cl, obj, OM_NEW, &tag1, NULL));
}

LONG xget(Object *obj, ULONG attribute)
{
    LONG x=0; get(obj, attribute, &x); return(x);
}

/* DragString Class */

struct DragString_Data
{
    ULONG   ObjectID;
};

ULONG DragString_mDragQuery(struct IClass *cl, Object *obj,
    struct MUIP_DragQuery *msg)
{
    struct DragString_Data *data = INST_DATA(cl, obj);

    if (msg->obj==obj)
       return(MUIV_DragQuery_Refuse);
    if (xget(msg->obj,MUIA_DragString_ObjectID)==data->ObjectID)
       return(MUIV_DragQuery_Accept);
    {
        struct MetaTypeEntry *entry=NULL;
        DoMethod(msg->obj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active,
            &entry);
        if(entry) return(MUIV_DragQuery_Accept);
    }
    return(MUIV_DragQuery_Refuse);
}


ULONG DragString_mDragDrop(struct IClass *cl, Object *obj,
    struct MUIP_DragDrop *msg)
{
    STRPTR ptr;
    if(ptr=(STRPTR)xget(msg->obj, MUIA_String_Contents))
        set(obj, MUIA_String_Contents, (ULONG) ptr);
    else
    {
        struct MetaTypeEntry *entry=NULL;
        DoMethod(msg->obj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &entry);
        if (entry)
        {
            struct DragString_Data  *data = INST_DATA(cl, obj);
            switch(data->ObjectID)
            {
                case DRAGTYPE_METATYPE :
                    set(obj, MUIA_String_Contents, (ULONG) entry->MetaType); break;
                case DRAGTYPE_TOOL :
                    set(obj, MUIA_String_Contents, (ULONG) entry->Tool); break;
                case DRAGTYPE_ARGUMENTS :
                    set(obj, MUIA_String_Contents, (ULONG) entry->Arguments); break;
            }
        }
    }
    return(0);
}

ULONG DragString_mGet(struct IClass *cl, Object *obj, Msg msg)
{
    struct DragString_Data *data = INST_DATA(cl, obj);
    ULONG *store = ((struct opGet *)msg)->opg_Storage;

    switch ( ((struct opGet *)msg)->opg_AttrID )
    {
        case MUIA_DragString_ObjectID: *store = data->ObjectID; break;
    }
    return(DoSuperMethodA(cl, obj, msg));
}

ULONG DragString_mNew(struct IClass *cl, Object *obj, struct opSet *msg)
{
    obj=(Object *)DoSuperNew(cl,obj,
        MUIA_Draggable,              TRUE,
        TAG_MORE,                   msg->ops_AttrList);

    if(obj)
    {
        struct DragString_Data *data = INST_DATA(cl, obj);

        data->ObjectID = (ULONG) GetTagData(MUIA_DragString_ObjectID,
            0, msg->ops_AttrList);
    }
    return((ULONG)obj);
}

ULONG __saveds DragString_Dispatcher(register __a0 struct IClass *cl,
                                     register __a2 Object        *obj,
                                     register __a1 Msg           msg)
{
    switch (msg->MethodID)
    {
        case OM_NEW         : return(DragString_mNew       (cl, obj, (APTR)msg));
        case OM_GET         : return(DragString_mGet       (cl, obj, (APTR)msg));
        case MUIM_DragQuery : return(DragString_mDragQuery (cl, obj, (APTR)msg));
        case MUIM_DragDrop  : return(DragString_mDragDrop  (cl, obj, (APTR)msg));
    }
    return(DoSuperMethodA(cl, obj, msg));
}

/* MTEntryList Class */

struct MTEntryList_Data
{
    struct Hook ConHook, DesHook, CmpHook, DispHook;
};

ULONG __saveds MTEntryList_ConFunc(register __a2 APTR pool,
                                   register __a1 struct MetaTypeEntry *entry)
{
    if (entry) {
        struct MetaTypeEntry *newentry;
        if (newentry = AllocMem(sizeof(struct MetaTypeEntry), MEMF_ANY))
        {
            CopyMem(entry, newentry, sizeof(struct MetaTypeEntry));
        }
        return( (int) newentry);
    }
    else
    {
        return(NULL);
    }
}

ULONG __saveds MTEntryList_DesFunc(register __a2 APTR pool,
                                   register __a1 struct MetaTypeEntry *entry)
{
    if (entry) FreeMem(entry, sizeof(struct MetaTypeEntry));
    return(NULL);
}

ULONG __saveds MTEntryList_DispFunc(register __a2 char **array,
                                    register __a1 struct MetaTypeEntry *entry)

{
    if (entry)
    {
        if(strlen(entry->MetaType)>0)
        {
            static char buf[MAXMETATYPELENGTH+4];
            if (entry->FromCD) strcpy(buf, ""); else strcpy(buf, "\33b");
            strcat(buf, entry->MetaType);
            *array++ = buf;
        }
        else *array++ = GetStr(MSG_MTENTRYLIST_WB_NEWENTRY);
        *array++ = (char *) &entry->Tool;
        *array++ = (char *) &entry->Arguments;
        if(entry->WB) *array = GetStr(MSG_MTENTRYLIST_WB_YES);
            else *array = GetStr(MSG_MTENTRYLIST_WB_NO);
    }
    else
    {
        *array++ = GetStr(MSG_MTENTRYLIST_TYPE);
        *array++ = GetStr(MSG_MTENTRYLIST_TOOL);
        *array++ = GetStr(MSG_MTENTRYLIST_ARGUMENTS);
        *array++ = GetStr(MSG_MTENTRYLIST_WB);
    }
    return(0);
}

LONG __saveds MTEntryList_CmpFunc(register __a1 struct MetaTypeEntry *entry1,
                                  register __a2 struct MetaTypeEntry *entry2)

{
    return(stricmp(entry1->MetaType, entry2->MetaType));
}

int GetWord(STRPTR str, int start)
{
    int i;
    i=start; while((*(str+i) != ' ') && (*(str+i) != 9) && (*(str+i) != 10) && (*(str+i) != 0)) i++;
    return(i);
}

void CopyItem(STRPTR source, STRPTR dest, int len)
{
    CopyMem(source, dest, len); dest[len] = 0;
}

void MTListInsert(Object *list, struct MetaTypeEntry *entry)
{
    LONG entries, i;
    BOOL equal;
    struct  MetaTypeEntry *cmpentry;

    get(list, MUIA_List_Entries, &entries); i=0; equal=FALSE;
    while ((i<entries) && (equal == FALSE))
    {
        DoMethod(list, MUIM_List_GetEntry, i, &cmpentry);
        if(cmpentry)
        {
            if(!stricmp(cmpentry->MetaType, entry->MetaType)) equal=TRUE;
        }
        i++;
    }
    if(!equal) DoMethod(list, MUIM_List_InsertSingle, entry, 1,
                        MUIV_List_Insert_Sorted);
}

ULONG MTEntryList_Load(struct IClass *cl, Object *obj, struct MUIP_MTEntryList_Load *msg)
{
    BOOL    retval = TRUE;
    APTR    reading;
    BPTR    fh = NULL; STRPTR  linebuf = NULL;
    struct  MetaTypeEntry entry;
    int     cursor, oldcursor, len;

    if (!(fh = Open(msg->file, MODE_OLDFILE))) goto exit;
    if (!(linebuf = AllocMem(LINEBUFFERSIZE, MEMF_ANY))) goto exit;

    strcpy(entry.Tool, ""); strcpy(entry.Arguments, "");
    entry.FromCD = msg->FromCD; entry.EditWindow=NULL;

    while(reading)
    {
        reading = FGets(fh, linebuf, LINEBUFFERSIZE);
        cursor=0; while(*(linebuf+cursor) == ' ') cursor++;

        if(reading && (*(linebuf+cursor) != ';') && (*(linebuf+cursor) != 10)
           && (*(linebuf+cursor) != '0')  && (*(linebuf+cursor) != ' '))
        {
            oldcursor=cursor; cursor=GetWord(linebuf, oldcursor);

            if((cursor>0) && (cursor<MAXMETATYPELENGTH))
            {
                CopyItem(linebuf, (STRPTR) &entry.MetaType, cursor); oldcursor=cursor+1;
                cursor=GetWord(linebuf, oldcursor); len=cursor-oldcursor;
                if((len>0) && (len<MAXTOOLLENGTH))
                {
                    CopyItem(linebuf+oldcursor, (STRPTR) &entry.Tool, len); oldcursor=cursor+1;

                    entry.WB = TRUE;
                    if (!stricmp(entry.Tool, "CLI"))
                    {
                        cursor=GetWord(linebuf, oldcursor); len=cursor-oldcursor;
                        entry.WB = FALSE;
                        if ((len>0) && (len<MAXTOOLLENGTH))
                        {
                            CopyItem(linebuf+oldcursor, (STRPTR) &entry.Tool, len);
                            oldcursor=cursor+1;

                            while((*(linebuf+cursor) != 10) && (*(linebuf+cursor) != 9)
                                  && (*(linebuf+cursor) != ';')) cursor++;

                            while(*(linebuf+cursor) == ' ') cursor--;
                            len=cursor-oldcursor;

                            if ((len>0) && (len<MAXARGUMENTSLENGTH))
                                CopyItem(linebuf+oldcursor, (STRPTR) &entry.Arguments, len);

                            MTListInsert(obj, &entry);
                        }
                        else
                        {
                            retval = FALSE;
                        }
                        oldcursor=cursor+1;
                    }
                    else
                    {
                        strcpy(entry.Arguments, "");
                        MTListInsert(obj, &entry);
                    }
                }
                else
                {
                    retval = FALSE;
                }
            }
            else
            {
                retval = FALSE;
            }
        }
    }

exit:
    if (linebuf)    FreeMem(linebuf, LINEBUFFERSIZE);
    if (fh)         Close(fh);
    return(retval);
}

ULONG MTEntryList_Save(struct IClass *cl, Object *obj, struct MUIP_MTEntryList_Save *msg)
{
    BPTR    fh = NULL;
    LONG    entries, i=0, res, retval=FALSE;
    struct  MetaTypeEntry *entry;

    if(!(fh=Open(msg->file, MODE_NEWFILE))) goto exit;

    res=FPrintf(fh, "; MetaTool Configuration File\n; Created by MetaToolPrefs (C) Martin Steigerwald\n\n");
    if (res==-1) goto exit;

    get(obj, MUIA_List_Entries, &entries);
    while ((i<entries) && (retval == 0))
    {
        DoMethod(obj, MUIM_List_GetEntry, i,
                 &entry);
        if ((!(entry->FromCD)) && (strlen(entry->MetaType)>0))
        {
            if (entry->WB)
                res=FPrintf(fh, "%s\t%s\n", (LONG) entry->MetaType, (LONG) entry->Tool);
            else
                res=FPrintf(fh, "%s\tCLI %s %s\n", (LONG) entry->MetaType,
                            (LONG) entry->Tool, (LONG) entry->Arguments);
            if(res==-1) goto exit;
        }
        i++;
    }
    retval=TRUE;

exit:
    if (fh) Close(fh);
    if(!retval) MUI_Request((APTR) xget(obj, MUIA_ApplicationObject),
        (APTR) xget(obj, MUIA_WindowObject), 0, NULL, GetStr(MSG_OK),
        GetStr(MSG_MTENTRYLIST_CANNOTSAVE_ERR));
    return(retval);
}

ULONG MTEntryList_mNew(struct IClass *cl, Object * obj, struct opSet *msg)
{
    obj=(Object *)DoSuperNew(cl,obj,
        InputListFrame,
        MUIA_List_Format,           "BAR,BAR,BAR,",
        MUIA_List_Title,            TRUE,
        MUIA_List_DragSortable,     TRUE,
        TAG_MORE,                   msg->ops_AttrList);

    if (obj)
    {
        struct MTEntryList_Data *data = INST_DATA(cl, obj);
        data->ConHook.h_Entry  = (VOID *) MTEntryList_ConFunc;
        data->DesHook.h_Entry  = (VOID *) MTEntryList_DesFunc;
        data->CmpHook.h_Entry  = (VOID *) MTEntryList_CmpFunc;
        data->DispHook.h_Entry = (VOID *) MTEntryList_DispFunc;
        set(obj, MUIA_List_CompareHook,   (ULONG) &data->CmpHook);
        set(obj, MUIA_List_ConstructHook, (ULONG) &data->ConHook);
        set(obj, MUIA_List_DestructHook,  (ULONG) &data->DesHook);
        set(obj, MUIA_List_DisplayHook,   (ULONG) &data->DispHook);
    }
    return((ULONG)obj);
}

ULONG __saveds MTEntryList_Dispatcher(register __a0 struct IClass *cl,
                                      register __a2 Object        *obj,
                                      register __a1 Msg           msg)
{
    switch (msg->MethodID)
    {
        case OM_NEW                 : return(MTEntryList_mNew  (cl, obj, (APTR)msg));
        case MUIM_MTEntryList_Load  : return(MTEntryList_Load  (cl, obj, (APTR)msg));
        case MUIM_MTEntryList_Save  : return(MTEntryList_Save  (cl, obj, (APTR)msg));
    }
    return(DoSuperMethodA(cl, obj, msg));
}

/* MTEditWindow Class */

struct MTEditWindow_Data
{
    struct MetaTypeEntry *entry;
    Object *Originator;
    Object *MetaTypePop, *MetaTypeString, *MetaTypeList;
    Object *ToolPop, *ToolString;
    Object *ArgumentsString, *WBBut;
    struct Hook StrObjHook, ObjStrHook, WindowHook;
};

/* support functions */

ULONG __saveds StrObjFunc(register __a2 Object *pop,
                          register __a1 Object *str)
{
    char *x,*s; int i;

    get(str, MUIA_String_Contents,&s);

    for (i=0;;i++)
    {
        DoMethod(pop, MUIM_List_GetEntry, i, &x);
        if (!x)
        {
            set(pop,MUIA_List_Active, MUIV_List_Active_Off);
            break;
        }
        else if (!stricmp(x,s))
        {
            set(pop, MUIA_List_Active,i);
            break;
        }
    }
    return(TRUE);
}

ULONG __saveds ObjStrFunc(register __a2 Object *pop,
                          register __a1 Object *str)
{
    char *x;

    DoMethod(pop, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &x);
    set(str, MUIA_String_Contents, (ULONG) x);
    return(0);
}

ULONG __saveds WindowFunc(register __a2 Object *pop,
                          register __a1 Object *win)
{
    set(win, MUIA_Window_DefaultObject, (ULONG) pop);
    return(0);
}

/* class functions */

ULONG MTEditWindow_UpdateGadgets(struct IClass *cl, Object *obj, Msg msg)
{
    struct MTEditWindow_Data *data = INST_DATA(cl, obj);

    if(data->entry)
    {
        nnset(data->MetaTypeString, MUIA_String_Contents, (ULONG) data->entry->MetaType);
        nnset(data->ToolString, MUIA_String_Contents, (ULONG) data->entry->Tool);
        nnset(data->ArgumentsString, MUIA_String_Contents, (ULONG) data->entry->Arguments);
        nnset(data->WBBut, MUIA_Selected, data->entry->WB);
        DoMethod(data->ArgumentsString, MUIM_Set, MUIA_Disabled, data->entry->WB);
    }
    return(0);
}

ULONG MTEditWindow_UpdateEntry(struct IClass *cl, Object *obj,
    struct MUIP_MTEditWindow_UpdateEntry *msg)
{
    struct MTEditWindow_Data *data = INST_DATA(cl, obj);
    STRPTR arg;

    if(data->entry)
    {
        data->entry->FromCD = FALSE;
        switch (msg->mode)
        {
            case MODE_CHANGE_METATYPE:
                get(data->MetaTypeString, MUIA_String_Contents, &arg);
                strcpy(data->entry->MetaType, arg); break;
            case MODE_CHANGE_TOOL:
                get(data->ToolString, MUIA_String_Contents, &arg);
                strcpy(data->entry->Tool, arg); break;
            case MODE_CHANGE_ARGUMENTS:
                get(data->ArgumentsString, MUIA_String_Contents, &arg);
                strcpy(data->entry->Arguments, arg); break;
            case MODE_CHANGE_WB:
                if (data->entry->WB) data->entry->WB=FALSE; else data->entry->WB=TRUE;
       }
       DoMethod((Object *)xget(obj, MUIA_ApplicationObject), MUIM_Application_PushMethod,
           data->Originator, 2, MUIM_MTEntryPanel_UpdateEntry, data->entry);
    }
    return(0);
}

          /*
ULONG MTEditWindow_mDragQuery(struct IClass *cl, Object *obj,
    struct MUIP_DragQuery *msg)
{
        return(MUIV_DragQuery_Accept);

    if (msg->obj==obj)
       return(MUIV_DragQuery_Refuse);
    {
        struct MetaTypeEntry *entry=NULL;
        DoMethod(msg->obj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active,
            &entry);
        if(entry)
        return(MUIV_DragQuery_Accept);
    }
    return(MUIV_DragQuery_Refuse);
}


ULONG MTEditWindow_mDragDrop(struct IClass *cl, Object *obj,
    struct MUIP_DragDrop *msg)
{
    struct MetaTypeEntry *entry=NULL;
    DoMethod(msg->obj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &entry);
    if (entry)
    {
        struct MTEditWindow_Data *data = INST_DATA(cl, obj);
        set(data->MetaTypeString, MUIA_String_Contents, (ULONG) entry->MetaType);
        set(data->ToolString, MUIA_String_Contents, (ULONG) entry->Tool);
        set(data->ArgumentsString, MUIA_String_Contents, (ULONG) entry->Arguments);
    }
    return(0);
}
*/

ULONG MTEditWindow_mGet(struct IClass *cl, Object *obj, struct opGet *msg)
{
    struct MTEditWindow_Data *data = INST_DATA(cl, obj);
    ULONG *store = msg->opg_Storage;

    switch (msg->opg_AttrID)
    {
        case MUIA_MTEditWindow_CloseAble:
            *store = !(xget(data->ToolPop, MUIA_Popasl_Active)); return(TRUE);
    }
    return(DoSuperMethodA(cl, obj, (Msg) msg));
}

ULONG MTEditWindow_mNew(struct IClass *cl, Object *obj, struct opSet *msg)
{
    struct MTEditWindow_Data tmp = {0};

    obj = (Object *)DoSuperNew(cl, obj,
        WindowContents, VGroup,
            Child, ColGroup(2),
                Child, Label2(GetStr(MSG_MTEDITWINDOW_METATYPE_GAD)),
                Child, tmp.MetaTypePop = PopobjectObject,
                    MUIA_Popstring_String,      tmp.MetaTypeString =
                        (Object *)NewObject(DragString_Class->mcc_Class, NULL,
                        StringFrame,
                        MUIA_String_MaxLen,     MAXMETATYPELENGTH,
                        MUIA_DragString_ObjectID,     DRAGTYPE_METATYPE),
                    MUIA_Popstring_Button,      PopButton(MUII_PopUp),
                    MUIA_Popobject_Object,  tmp.MetaTypeList = ListviewObject,
                        MUIA_Listview_List, ListObject,
                            InputListFrame,
                            MUIA_List_SourceArray, MetaTypeNames,
                        End,
                    End,
                End,
                Child, Label2(GetStr(MSG_MTEDITWINDOW_TOOL_GAD)),
                Child, tmp.ToolPop = PopaslObject,
                    MUIA_Popstring_String, tmp.ToolString =
                        (Object *)NewObject(DragString_Class->mcc_Class, NULL,
                        StringFrame,
                        MUIA_String_MaxLen,     MAXTOOLLENGTH,
                        MUIA_DragString_ObjectID,     DRAGTYPE_TOOL),
                    MUIA_Popstring_Button, PopButton(MUII_PopFile),
                    ASLFR_TitleText,       GetStr(MSG_MTEDITWINDOW_TOOL_FREQ),
                    ASLFR_RejectIcons,     TRUE,
                End,
                Child, Label2(GetStr(MSG_MTEDITWINDOW_ARGUMENTS_GAD)),
                Child, tmp.ArgumentsString =
                        (Object *)NewObject(DragString_Class->mcc_Class, NULL,
                        StringFrame,
                        MUIA_String_MaxLen,     MAXARGUMENTSLENGTH,
                        MUIA_DragString_ObjectID,     DRAGTYPE_ARGUMENTS),
            End,
            Child, HGroup,
                Child, HSpace(0),
                Child, Label2(GetStr(MSG_MTEDITWINDOW_WB_GAD)),
                Child, tmp.WBBut = CheckMark(FALSE),
            End,
        End,
        TAG_MORE, msg->ops_AttrList);

    if (obj)
    {
        struct MTEditWindow_Data *data = INST_DATA(cl, obj);

        tmp.entry = (struct MetaTypeEntry *)GetTagData(MUIA_MTEditWindow_Entry,
            0, msg->ops_AttrList);
        tmp.Originator = (Object *)GetTagData(MUIA_MTEditWindow_Originator,
            0, msg->ops_AttrList);

        tmp.StrObjHook.h_Entry = (VOID *) StrObjFunc;
        tmp.ObjStrHook.h_Entry = (VOID *) ObjStrFunc;
        tmp.WindowHook.h_Entry = (VOID *) WindowFunc;

        *data = tmp;

        DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
                 MUIV_Notify_Application, 5, MUIM_Application_PushMethod,
                 tmp.Originator, 2, MUIM_MTEntryPanel_QuitEdit, tmp.entry );

        DoMethod(tmp.MetaTypeString, MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime,
                 obj, 2, MUIM_MTEditWindow_UpdateEntry, MODE_CHANGE_METATYPE);
        DoMethod(tmp.ToolString, MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime,
                 obj, 2, MUIM_MTEditWindow_UpdateEntry, MODE_CHANGE_TOOL);
        DoMethod(tmp.ArgumentsString, MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime,
                 obj, 2, MUIM_MTEditWindow_UpdateEntry, MODE_CHANGE_ARGUMENTS);
        DoMethod(tmp.WBBut, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
                 obj, 2, MUIM_MTEditWindow_UpdateEntry, MODE_CHANGE_WB);

        DoMethod(tmp.WBBut, MUIM_Notify, MUIA_Selected, TRUE,
                 tmp.ArgumentsString, 3, MUIM_Set, MUIA_Disabled, TRUE);

        DoMethod(tmp.WBBut, MUIM_Notify, MUIA_Selected, FALSE,
                 tmp.ArgumentsString, 3, MUIM_Set, MUIA_Disabled, FALSE);

        DoMethod(tmp.MetaTypeList, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE,
                 tmp.MetaTypePop, 2, MUIM_Popstring_Close, TRUE);

        DoMethod(obj, MUIM_Window_SetCycleChain, tmp.MetaTypePop, tmp.ToolPop,
                 tmp.ArgumentsString, tmp.WBBut, NULL);

        set(tmp.MetaTypePop, MUIA_Popobject_StrObjHook, (ULONG) &data->StrObjHook);
        set(tmp.MetaTypePop, MUIA_Popobject_ObjStrHook, (ULONG) &data->ObjStrHook);
        set(tmp.MetaTypePop, MUIA_Popobject_WindowHook, (ULONG) &data->WindowHook);

        set(tmp.MetaTypePop,     MUIA_ShortHelp,
            (ULONG) GetStr(MSG_MTEDITWINDOW_METATYPE_GAD_HELP));
        set(tmp.ToolPop,         MUIA_ShortHelp,
            (ULONG) GetStr(MSG_MTEDITWINDOW_TOOL_GAD_HELP));
        set(tmp.ArgumentsString, MUIA_ShortHelp,
            (ULONG) GetStr(MSG_MTEDITWINDOW_ARGUMENTS_GAD_HELP));
        set(tmp.WBBut,           MUIA_ShortHelp,
            (ULONG) GetStr(MSG_MTEDITWINDOW_WB_GAD_HELP));

        set(obj, MUIA_Window_ActiveObject, (ULONG)tmp.ToolPop);

        DoMethod(obj, MUIM_MTEditWindow_UpdateGadgets);

    }
    return((ULONG)obj);
}

ULONG __saveds MTEditWindow_Dispatcher(register __a0 struct IClass *cl,
                                       register __a2 Object        *obj,
                                       register __a1 Msg           msg)
{
    switch (msg->MethodID)
    {
        case OM_NEW                             : return(MTEditWindow_mNew     (cl, obj, (APTR)msg));
        case OM_GET                             : return(MTEditWindow_mGet     (cl, obj, (APTR)msg));
        /*
        case MUIM_DragQuery                     : return(MTEditWindow_mDragQuery (cl, obj, (APTR)msg));
        case MUIM_DragDrop                      : return(MTEditWindow_mDragDrop  (cl, obj, (APTR)msg));
        */
        case MUIM_MTEditWindow_UpdateGadgets    : return(MTEditWindow_UpdateGadgets (cl, obj, (APTR)msg));
        case MUIM_MTEditWindow_UpdateEntry      : return(MTEditWindow_UpdateEntry (cl, obj, (APTR)msg));
    }
    return(DoSuperMethodA(cl, obj, msg));
}


/* MTEntryPanel Class */


struct MTEntryPanel_Data
{
    Object  *Listview, *ContextMenu;
    Object  *EditBut, *SortBut, *NewBut, *RemoveBut;
};

ULONG MTEntryPanel_ToggleEdit(Object *obj, struct MetaTypeEntry *entry)
{
    if(entry)
    {
        if(entry->EditWindow)
            DoMethod(obj, MUIM_MTEntryPanel_QuitEdit, entry);
        else
        {
            entry->EditWindow=(Object *)NewObject(MTEditWindow_Class->mcc_Class, NULL,
                MUIA_Window_Title,              (ULONG) GetStr(MSG_MTEDITWINDOW_TITLE),
                MUIA_Window_ScreenTitle,        (ULONG) GetStr(MSG_APP_TITLE),
                MUIA_Window_ID,
                    MAKE_ID(entry->MetaType[0], entry->MetaType[1],
                        entry->MetaType[2], entry->MetaType[3]),
                MUIA_MTEditWindow_Entry,        (ULONG) entry,
                MUIA_MTEditWindow_Originator,   (ULONG) obj,
                TAG_DONE);
            if(entry->EditWindow)
            {
                DoMethod((Object *)xget(obj, MUIA_ApplicationObject),
                    OM_ADDMEMBER, entry->EditWindow);
                set(entry->EditWindow, MUIA_Window_Open, TRUE);
            }
        }
    }
    return(0);
}

ULONG MTEntryPanel_Edit(struct IClass *cl, Object *obj,
    struct MUIP_MTEntryPanel_Edit *msg )
{
    struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
    struct MetaTypeEntry *entry; LONG entrynum=MUIV_List_NextSelected_Start;

    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, TRUE);

    switch(msg->TriggerValue)
    {
        case MTEntryPanel_Edit_Active:
        {
            DoMethod(data->Listview, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &entry);
            MTEntryPanel_ToggleEdit(obj, entry); break;
        }
        case MTEntryPanel_Edit_Selected:
        {
            for(;;)
            {
                DoMethod(data->Listview, MUIM_List_NextSelected, &entrynum);
                if (entrynum==MUIV_List_NextSelected_End) break;
                DoMethod(data->Listview, MUIM_List_GetEntry, entrynum, &entry);
                MTEntryPanel_ToggleEdit(obj, entry);
            }
            break;
        }
    }
    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, FALSE);

    return(0);
}

ULONG MTEntryPanel_QuitEdit(struct IClass *cl, Object *obj,
    struct MUIP_MTEntryPanel_QuitEdit *msg)
{
    if(msg->entry)
    {
        if(msg->entry->EditWindow)
        {
            if (xget(msg->entry->EditWindow, MUIA_MTEditWindow_CloseAble))
            {
                set(msg->entry->EditWindow, MUIA_Window_Open, FALSE);
                DoMethod((Object *)xget(msg->entry->EditWindow, MUIA_ApplicationObject),
                    OM_REMMEMBER, msg->entry->EditWindow);
                MUI_DisposeObject(msg->entry->EditWindow);
                msg->entry->EditWindow=NULL;
            }
            else
            {
                MUI_Request((APTR)xget(obj, MUIA_ApplicationObject), msg->entry->EditWindow,
                0, NULL, GetStr(MSG_OK), GetStr(MSG_MTENTRYPANEL_CANNOTCLOSE_ERR));
            }
        }
    }
    return(0);
}

ULONG MTEntryPanel_QuitEditAll(struct IClass *cl, Object *obj, Msg *msg)
{
    struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
    struct MetaTypeEntry *entry;
    LONG i, entries;

    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, TRUE);
    entries=xget(data->Listview, MUIA_List_Entries);

    for(i=0; i<entries; i++)
    {
        DoMethod(data->Listview, MUIM_List_GetEntry, i, &entry);
        if(entry->EditWindow) DoMethod(obj, MUIM_MTEntryPanel_QuitEdit, entry);
    }
    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, FALSE);
    return(0);
}

ULONG MTEntryPanel_UpdateEntry(struct IClass *cl, Object *obj,
    struct MUIP_MTEntryPanel_UpdateEntry *msg)
{
    struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
    struct  MetaTypeEntry *entry;
    LONG i,entries;
    BOOL equal;

    if(msg->entry)
    {
        entries=xget(data->Listview, MUIA_List_Entries);
        i=0; equal=FALSE;
        while ((i<entries) && (equal == FALSE))
        {
            DoMethod(data->Listview, MUIM_List_GetEntry, i, &entry);
            if(msg->entry==entry) equal = TRUE; else i++;
        }
        DoMethod(data->Listview, MUIM_List_Redraw, i);
    }
    return(0);
}

ULONG MTEntryPanel_New(struct IClass *cl, Object *obj, Msg msg)
{
    struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
    struct MetaTypeEntry entry;

    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, TRUE);

    strcpy(entry.MetaType, ""); strcpy(entry.Tool, ""); strcpy(entry.Arguments, "");
    entry.WB = FALSE; entry.FromCD = FALSE; entry.EditWindow = NULL;

    DoMethod((APTR)data->Listview, MUIM_List_InsertSingle, &entry, MUIV_List_Insert_Bottom);
    set((APTR)data->Listview, MUIA_List_Active, MUIV_List_Active_Bottom);
    DoMethod((Object *)xget(obj, MUIA_ApplicationObject), MUIM_Application_PushMethod,
        obj, 2, MUIM_MTEntryPanel_Edit, MTEntryPanel_Edit_Active);
    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, FALSE);
    return(NULL);
}

ULONG MTEntryPanel_Sort(struct IClass *cl, Object *obj, Msg msg)
{
    struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
    DoMethod(data->Listview, MUIM_List_Sort);
    return(0);
}

ULONG MTEntryPanel_Remove(struct IClass *cl, Object *obj, Msg msg)
{
    struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
    struct MetaTypeEntry *entry;
    LONG id = MUIV_List_NextSelected_Start;

    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, TRUE);
    for (;;)
    {
        DoMethod(data->Listview,MUIM_List_NextSelected,&id);
        if (id==MUIV_List_NextSelected_End) break;
        DoMethod(data->Listview,MUIM_List_GetEntry,id,&entry);

        // Nur schließen und entfernen, wenn es schließbar ist
        if (entry)
        {
            if (entry->EditWindow)
            {
                if (xget(entry->EditWindow, MUIA_MTEditWindow_CloseAble))
                {
                    DoMethod(obj, MUIM_MTEntryPanel_QuitEdit, entry);
                    DoMethod(data->Listview, MUIM_List_Remove, id);
                } // CloseAble?
                else
                {
                    MUI_Request((APTR)xget(obj, MUIA_ApplicationObject), NULL,
                    0, NULL, GetStr(MSG_OK), GetStr(MSG_MTENTRYPANEL_CANNOTREMOVE_ERR));
                }
            }
            else
            {
                DoMethod(data->Listview, MUIM_List_Remove, id);
            } // EditWindow?
        } // entry
    }
    // Do not close all selected anymore!!! To avoid closing uncloseable editwindows
    // DoMethod(data->Listview, MUIM_List_Remove, MUIV_List_Remove_Selected);
    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, FALSE);
    return(0);
}

ULONG MTEntryPanel_CheckConfig(struct IClass *cl, Object *obj, Msg msg)
{
    if (!DOSPathBase) DOSPathBase=OpenLibrary(DOSPATH_NAME, DOSPATH_VERSION);

    if (DOSPathBase)
    {
        struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
        struct MetaTypeEntry *entry;
        BOOL   wbmode = FALSE;
        struct Process *myprocess = (struct Process *) FindTask(NULL);
        struct PathListEntry *path=NULL;
        APTR   winptr;

        if (WBenchMsg)
        {
            path = CopyWorkbenchPathList(WBenchMsg, NULL); wbmode = TRUE;
        }
        else
            path = GetProcessPathList(myprocess);

        if (path)
        {
            LONG i, entries;
            set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, TRUE);
            set(data->Listview, MUIA_List_Quiet, TRUE);
            winptr=myprocess->pr_WindowPtr; myprocess->pr_WindowPtr=(APTR) -1;

            entries=xget(data->Listview, MUIA_List_Entries);
            for(i=0; i<entries; i++)
            {
                struct PathListEntry *state = path;
                DoMethod(data->Listview, MUIM_List_GetEntry, i, &entry);
                if(entry)
                {
                    if(FindFileInPathList(&state, entry->Tool))
                        DoMethod(data->Listview, MUIM_List_Select, i,
                            MUIV_List_Select_Off, NULL);
                    else
                        DoMethod(data->Listview, MUIM_List_Select, i,
                            MUIV_List_Select_On, NULL);
                }
            }

            myprocess->pr_WindowPtr=winptr;  if(wbmode && path) FreePathList(path);
            set(data->Listview, MUIA_List_Quiet, FALSE);
            set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, FALSE);
        }
    }
    else
    {
        MUI_Request((APTR)xget(obj, MUIA_ApplicationObject), (APTR) xget(obj, MUIA_WindowObject),
            0, NULL, GetStr(MSG_OK), GetStr(MSG_MTENTRYPANEL_CANNOTCHECKCONFIG));
    }
    return(0);
}

ULONG MTEntryPanel_SetSave(struct IClass *cl, Object *obj,
    struct MUIP_MTEntryPanel_SetSave *msg)
{
    struct  MTEntryPanel_Data *data = INST_DATA(cl, obj);
    struct  MetaTypeEntry *entry; BOOL FromCD;
    LONG    id = MUIV_List_NextSelected_Start;

    if(msg->mode==MTEntryPanel_SetSave_Set) FromCD=FALSE; else FromCD=TRUE;

    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, TRUE);
    set(data->Listview, MUIA_List_Quiet, TRUE);
    for (;;)
    {
        DoMethod(data->Listview,MUIM_List_NextSelected,&id);
        if (id==MUIV_List_NextSelected_End) break;
        DoMethod(data->Listview,MUIM_List_GetEntry,id,&entry);
        if(entry)
        {
            entry->FromCD=FromCD;
            DoMethod(data->Listview, MUIM_List_Redraw, id);
        }
    }
    set(data->Listview, MUIA_List_Quiet, FALSE);
    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, FALSE);
    return(0);
}


ULONG MTEntryPanel_ContextMenuChoice(struct IClass *cl, Object *obj,
    struct MUIP_ContextMenuChoice *msg)
{
    struct  MTEntryPanel_Data *data = INST_DATA(cl, obj);

    switch(muiUserData(msg->item))
    {
        case MEN_MTENTRYPANEL_SELECT_ALL :
            DoMethod(data->Listview, MUIM_List_Select, MUIV_List_Select_All,
                MUIV_List_Select_On, NULL); break;
        case MEN_MTENTRYPANEL_DESELECT_ALL :
            DoMethod(data->Listview, MUIM_List_Select, MUIV_List_Select_All,
                MUIV_List_Select_Off, NULL); break;
        case MEN_MTENTRYPANEL_TOGGLE_ALL :
            DoMethod(data->Listview, MUIM_List_Select, MUIV_List_Select_All,
                MUIV_List_Select_Toggle, NULL); break;
        case MEN_MTENTRYPANEL_CHECKCONFIG :
            DoMethod(obj, MUIM_MTEntryPanel_CheckConfig); break;
        case MEN_MTENTRYPANEL_SETSAVE :
            DoMethod(obj, MUIM_MTEntryPanel_SetSave, MTEntryPanel_SetSave_Set); break;
        case MEN_MTENTRYPANEL_UNSETSAVE :
            DoMethod(obj, MUIM_MTEntryPanel_SetSave, MTEntryPanel_SetSave_UnSet); break;
        case MEN_MTENTRYPANEL_CLOSE_ALL :
            DoMethod(obj, MUIM_MTEntryPanel_QuitEditAll); break;
    }
    return(0);
}

ULONG MTEntryPanel_mGet(struct IClass *cl, Object *obj, struct opGet *msg)
{
    struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
    ULONG *store = msg->opg_Storage;

    switch (msg->opg_AttrID)
    {
        case MUIA_MTEntryPanel_CloseAble:
        {
            struct MetaTypeEntry *entry;
            LONG i, entries; LONG CloseAble=TRUE;

            set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, TRUE);
            entries=xget(data->Listview, MUIA_List_Entries);

            for(i=0; (i<entries) && CloseAble; i++)
            {
                DoMethod(data->Listview, MUIM_List_GetEntry, i, &entry);
                if(entry->EditWindow)
                    CloseAble=xget(entry->EditWindow, MUIA_MTEditWindow_CloseAble);
            }
            set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, FALSE);
            *store = CloseAble; return(TRUE);
        }
    }
    return(DoSuperMethodA(cl, obj, (Msg) msg));
}

ULONG MTEntryPanel_mNew(struct IClass *cl, Object *obj, struct opSet *msg)
{
    struct MTEntryPanel_Data tmp = {0};

    obj = (Object *)DoSuperNew(cl, obj,
        MUIA_ContextMenu,   tmp.ContextMenu = MUI_MakeObject(MUIO_MenustripNM,
            MTEntryPanelMenu, MUIO_MenustripNM_CommandKeyCheck),

        Child, tmp.Listview = ListviewObject,
            MUIA_Listview_Input,        TRUE,
            MUIA_Listview_DragType,     MUIV_Listview_DragType_Immediate,
            MUIA_Listview_MultiSelect,  MUIV_Listview_MultiSelect_Default,
            MUIA_Listview_List,
                (Object *) NewObject(MTEntryList_Class->mcc_Class, NULL, TAG_DONE),
        End,
        Child, HGroup,
            Child, tmp.EditBut      = SimpleButton(GetStr(MSG_MTENTRYPANEL_EDIT_GAD)),
            Child, tmp.NewBut       = SimpleButton(GetStr(MSG_MTENTRYPANEL_NEW_GAD)),
            Child, tmp.SortBut      = SimpleButton(GetStr(MSG_MTENTRYPANEL_SORT_GAD)),
            Child, tmp.RemoveBut    = SimpleButton(GetStr(MSG_MTENTRYPANEL_REMOVE_GAD)),
        End,
        TAG_MORE, msg->ops_AttrList);

    if (obj)
    {
        struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
        *data = tmp;

        DoMethod(tmp.Listview, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE,
                 obj, 2, MUIM_MTEntryPanel_Edit, MTEntryPanel_Edit_Active);
        DoMethod(tmp.EditBut, MUIM_Notify, MUIA_Pressed, FALSE,
                 obj, 2, MUIM_MTEntryPanel_Edit, MTEntryPanel_Edit_Selected);
        DoMethod(tmp.NewBut, MUIM_Notify, MUIA_Pressed, FALSE,
                 obj, 1, MUIM_MTEntryPanel_New);
        DoMethod(tmp.SortBut, MUIM_Notify, MUIA_Pressed, FALSE,
                 data->Listview, 1, MUIM_List_Sort);
        DoMethod(tmp.RemoveBut, MUIM_Notify, MUIA_Pressed, FALSE,
                 obj, 1, MUIM_MTEntryPanel_Remove );

        set(tmp.EditBut,   MUIA_ShortHelp, (ULONG) GetStr(MSG_MTENTRYPANEL_EDIT_GAD_HELP));
        set(tmp.NewBut,    MUIA_ShortHelp, (ULONG) GetStr(MSG_MTENTRYPANEL_NEW_GAD_HELP));
        set(tmp.SortBut,   MUIA_ShortHelp, (ULONG) GetStr(MSG_MTENTRYPANEL_SORT_GAD_HELP));
        set(tmp.RemoveBut, MUIA_ShortHelp, (ULONG) GetStr(MSG_MTENTRYPANEL_REMOVE_GAD_HELP));
        set(tmp.Listview,  MUIA_ShortHelp, (ULONG) GetStr(MSG_MTENTRYPANEL_LISTVIEW_HELP));
    }
    return((ULONG)obj);
}

ULONG MTEntryPanel_mDispose(struct IClass *cl, Object *obj, Msg msg)
{
    struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
    if (data->ContextMenu) MUI_DisposeObject(data->ContextMenu);
    return(DoSuperMethodA(cl, obj, (APTR) msg));
}

ULONG __saveds MTEntryPanel_Dispatcher(register __a0 struct IClass *cl,
                                       register __a2 Object        *obj,
                                       register __a1 Msg           msg)
{
    switch (msg->MethodID)
    {
        case OM_NEW                        : return(MTEntryPanel_mNew        (cl, obj, (APTR)msg));
        case OM_DISPOSE                    : return(MTEntryPanel_mDispose    (cl, obj, (APTR)msg));
        case OM_GET                        : return(MTEntryPanel_mGet        (cl, obj, (APTR)msg));
        case MUIM_ContextMenuChoice        : return(MTEntryPanel_ContextMenuChoice (cl, obj, (APTR)msg));
        case MUIM_MTEntryPanel_New         : return(MTEntryPanel_New         (cl, obj, (APTR)msg));
        case MUIM_MTEntryPanel_Edit        : return(MTEntryPanel_Edit        (cl, obj, (APTR)msg));
        case MUIM_MTEntryPanel_Remove      : return(MTEntryPanel_Remove      (cl, obj, (APTR)msg));
        case MUIM_MTEntryPanel_QuitEdit    : return(MTEntryPanel_QuitEdit    (cl, obj, (APTR)msg));
        case MUIM_MTEntryPanel_QuitEditAll : return(MTEntryPanel_QuitEditAll (cl, obj, (APTR)msg));
        case MUIM_MTEntryPanel_UpdateEntry : return(MTEntryPanel_UpdateEntry (cl, obj, (APTR)msg));
        case MUIM_MTEntryPanel_SetSave     : return(MTEntryPanel_SetSave     (cl, obj, (APTR)msg));
        case MUIM_MTEntryPanel_CheckConfig : return(MTEntryPanel_CheckConfig (cl, obj, (APTR)msg));
        case MUIM_MTEntryList_Load  :
        case MUIM_MTEntryList_Save  :
        {
            struct MTEntryPanel_Data *data = INST_DATA(cl, obj);
            return(DoMethodA((APTR)xget(data->Listview, MUIA_Listview_List), msg));
        }
    }
    return(DoSuperMethodA(cl, obj, msg));
}

/* mainwindow class */

#define MAINWINDOW_JUSTQUIT     0
#define MAINWINDOW_SAVEQUIT     1

struct MainWindow_Data
{
    Object  *MTEntryPanel;
    Object  *AboutmuiWin;
    BOOL    ChangeEnv;
    char    ConfigFile[MAXPATHNAMELENGTH], SaveAsFile[MAXPATHNAMELENGTH];
};


STRPTR getfilename(Object *win,char *title,char *initialname, BOOL save)
{
    static char buf[MAXPATHNAMELENGTH];
    char filename[MAXFILENAMELENGTH], pathname[MAXPATHNAMELENGTH];
    STRPTR temp;
    struct FileRequester *req;
    struct Window *w=(struct Window *) xget(win, MUIA_Window_Window);
    Object *app = (Object *)xget(win,MUIA_ApplicationObject);
    STRPTR res = NULL;

    strcpy(filename, FilePart(initialname));
    strcpy(pathname, initialname);
    temp=PathPart(pathname); *temp=0;

    if (req=MUI_AllocAslRequestTags(ASL_FileRequest,
        ASLFR_Window,           w,
        ASLFR_TitleText,        title,
        ASLFR_DoSaveMode,       save,
        ASLFR_InitialFile,      filename,
        ASLFR_InitialDrawer,    pathname,
        ASLFR_RejectIcons,      TRUE,
        TAG_DONE))
    {
        set(app,MUIA_Application_Sleep,TRUE);
        if (MUI_AslRequestTags(req,TAG_DONE))
        {
            if (*req->fr_File)
            {
                res = buf;
                CopyMem(req->fr_Drawer, buf, sizeof(buf));
                AddPart(buf,req->fr_File,sizeof(buf));
            }
        }
        MUI_FreeAslRequest(req);
        set(app,MUIA_Application_Sleep,FALSE);
    }
    return(res);
}

void MainWindow_LoadConfig(struct IClass *cl, Object *obj)
{
    struct MainWindow_Data *data = INST_DATA(cl, obj);
    ULONG   i; char file[30];

    i = GetVar("METACONFIG", (STRPTR) &data->ConfigFile, MAXPATHNAMELENGTH, 0L);

    if(i>0) DoMethod((APTR)data->MTEntryPanel, MUIM_MTEntryList_Load, (STRPTR) data->ConfigFile, FALSE);
    else    strcpy(data->ConfigFile,"");

    strcpy(file,":MetaTool/MetaTool40.config");
    if (OSVersion>39)
        DoMethod((APTR)data->MTEntryPanel, MUIM_MTEntryList_Load, (STRPTR) file, TRUE);

    file[18] = '3'; i=9;
    for(; i>2; i--)
    {
        file[19] = '0' + i;
        DoMethod((APTR)data->MTEntryPanel, MUIM_MTEntryList_Load, (STRPTR) file, TRUE);
    }

    DoMethod((APTR)data->MTEntryPanel, MUIM_List_Sort);
}

ULONG MainWindow_SaveConfig(struct IClass *cl, Object *obj)
{
    struct MainWindow_Data *data = INST_DATA(cl, obj);

    if(strlen(data->ConfigFile)>0)
    {

        if(DoMethod((APTR)data->MTEntryPanel, MUIM_MTEntryList_Save, data->ConfigFile))
        {
            if(data->ChangeEnv)
            {
                BPTR fh;
                SetVar("METACONFIG", (STRPTR) data->ConfigFile,
                    strlen(data->ConfigFile), GVF_GLOBAL_ONLY);
                if(fh=Open("ENVARC:METACONFIG", MODE_NEWFILE))
                {
                    FPuts(fh, data->ConfigFile); Close(fh);
                    data->ChangeEnv=FALSE;
                }
            }
            return(TRUE);
        }
    }
    return(FALSE);
}

ULONG MainWindow_About(struct IClass *cl, Object *obj, Msg msg)
{
    Object *app = (Object *) xget(obj, MUIA_ApplicationObject);
    MUI_Request(app, obj, 0, NULL, GetStr(MSG_OK), ABOUTTEXT,
        (char *)xget(app, MUIA_Application_Version)+20,
        (char *)xget(app, MUIA_Application_Copyright));
    return(0);
}

ULONG MainWindow_Aboutmui(struct IClass *cl, Object *obj, Msg msg)
{
    struct MainWindow_Data *data = INST_DATA(cl, obj);

    if (!data->AboutmuiWin)
    {
        data->AboutmuiWin = AboutmuiObject,
            MUIA_Window_RefWindow, obj,
            MUIA_Aboutmui_Application, xget(obj, MUIA_ApplicationObject),
        End;
    }
    if (data->AboutmuiWin) set(data->AboutmuiWin,MUIA_Window_Open,TRUE);
        else DisplayBeep(0);
    return(0);
}

ULONG MainWindow_Reload(struct IClass *cl, Object *obj, Msg msg)
{
    struct MainWindow_Data *data = INST_DATA(cl, obj);

    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, TRUE);
    DoMethod(data->MTEntryPanel, MUIM_MTEntryPanel_QuitEditAll);
    set(data->MTEntryPanel, MUIA_List_Quiet, TRUE);
    DoMethod(data->MTEntryPanel, MUIM_List_Clear);
    MainWindow_LoadConfig(cl, obj);
    set(data->MTEntryPanel, MUIA_List_Quiet, FALSE);
    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, FALSE);
    return(0);
}

ULONG MainWindow_Save(struct IClass *cl, Object *obj, Msg msg)
{
    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, TRUE);
    MainWindow_SaveConfig(cl, obj);
    set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, FALSE);

    return(0);
}

ULONG MainWindow_SaveAs(struct IClass *cl, Object *obj, Msg msg)
{
    struct MainWindow_Data *data = INST_DATA(cl, obj);
    STRPTR file;

    if((file=getfilename(obj, GetStr(MSG_MAINWINDOW_PROJECT_SAVEAS),
        data->SaveAsFile, TRUE)) && *file)
    {
        set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, TRUE);
        strcpy(data->SaveAsFile, file);
        DoMethod((APTR)data->MTEntryPanel, MUIM_MTEntryList_Save, data->SaveAsFile);
        set((Object *)xget(obj, MUIA_ApplicationObject), MUIA_Application_Sleep, FALSE);
    }
    return(0);
}

ULONG MainWindow_ChangeConfigFile(struct IClass *cl, Object *obj, Msg msg)
{
    struct MainWindow_Data *data = INST_DATA(cl, obj);
    STRPTR file;

    if((file=getfilename(obj, GetStr(MSG_MAINWINDOW_SETTINGS_CONFIGFILE),
        data->ConfigFile, FALSE)) && *file)
    {
        strcpy(data->ConfigFile, file); data->ChangeEnv = TRUE;
    }
    return(0);
}

ULONG MainWindow_MUISettings(struct IClass *cl, Object *obj, Msg msg)
{
    DoMethod((Object *) xget(obj, MUIA_ApplicationObject),
        MUIM_Application_OpenConfigWindow, 0);
    return(0);
}

ULONG MainWindow_Finish(struct IClass *cl, Object *obj,
                        struct MUIP_MainWindow_Finish *msg)
{
    struct MainWindow_Data *data = INST_DATA(cl, obj);

    if (xget(data->MTEntryPanel, MUIA_MTEntryPanel_CloseAble))
    {
        if (msg->quitmode==MAINWINDOW_SAVEQUIT)
            if(!MainWindow_SaveConfig(cl, obj))
                return(0);
        DoMethod((Object *) xget(obj, MUIA_ApplicationObject), MUIM_Application_ReturnID,
            MUIV_Application_ReturnID_Quit);
    }
    else
    {
        MUI_Request((APTR)xget(obj, MUIA_ApplicationObject), obj,
        0, NULL, GetStr(MSG_OK), GetStr(MSG_MAINWINDOW_CANNOTQUIT_ERR));
    }
    return(0);
}

ULONG MainWindow_mNew(struct IClass *cl, Object *obj, struct opSet *msg)
{
    Object  *SaveBut, *CancelBut;
    Object  *Menustrip, *MTEntryPanel;

    obj = (Object *) DoSuperNew(cl,obj,
        MUIA_Window_Title,          GetStr(MSG_APP_TITLE),
        MUIA_Window_ScreenTitle,    GetStr(MSG_APP_TITLE),
        MUIA_Window_ID,             MAKE_ID('M','A','I','N'),
        MUIA_Window_Width,          MUIV_Window_Width_Visible(50),
        MUIA_Window_Height,         MUIV_Window_Height_Visible(50),
        MUIA_Window_Menustrip,      Menustrip =
                                        MUI_MakeObject(MUIO_MenustripNM, MainMenu, 0),
        WindowContents, VGroup,
            Child, MTEntryPanel = (Object *) NewObject(MTEntryPanel_Class->mcc_Class,
                       NULL, TAG_DONE),
            Child, MUI_MakeObject(MUIO_HBar, 2),
            Child, HGroup,
                Child, SaveBut    = SimpleButton(GetStr(MSG_MAINWINDOW_SAVE_GAD)),
                Child, CancelBut  = SimpleButton(GetStr(MSG_MAINWINDOW_CANCEL_GAD)),
            End,
        End,
        TAG_MORE, msg->ops_AttrList);

    if(obj)
    {
        struct MainWindow_Data *data = INST_DATA(cl, obj);

        data->MTEntryPanel = MTEntryPanel;
        data->AboutmuiWin  = NULL; data->ChangeEnv=FALSE;
        strcpy(data->SaveAsFile, "MetaTool.prefs");

        DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
                 obj, 2, MUIM_MainWindow_Finish, MAINWINDOW_JUSTQUIT);
        DoMethod(CancelBut, MUIM_Notify, MUIA_Pressed, FALSE,
                 obj, 2, MUIM_MainWindow_Finish, MAINWINDOW_JUSTQUIT);
        DoMethod(SaveBut, MUIM_Notify, MUIA_Pressed, FALSE,
                 obj, 2, MUIM_MainWindow_Finish, MAINWINDOW_SAVEQUIT);
        DoMethod((Object *) DoMethod(Menustrip, MUIM_FindUData, MEN_PROJECT_QUIT),
            MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
            obj, 1, MUIM_MainWindow_Finish, MAINWINDOW_JUSTQUIT);

        DoMethod((Object *) DoMethod(Menustrip, MUIM_FindUData, MEN_PROJECT_NEW),
            MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
            data->MTEntryPanel, 1, MUIM_List_Clear);
        DoMethod((Object *) DoMethod(Menustrip, MUIM_FindUData, MEN_PROJECT_RELOAD),
            MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
            obj, 1, MUIM_MainWindow_Reload);
        DoMethod((Object *) DoMethod(Menustrip, MUIM_FindUData, MEN_PROJECT_SAVE),
            MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
            obj, 1, MUIM_MainWindow_Save);
        DoMethod((Object *) DoMethod(Menustrip, MUIM_FindUData, MEN_PROJECT_SAVEAS),
            MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
            obj, 1, MUIM_MainWindow_SaveAs);

        DoMethod((Object *) DoMethod(Menustrip, MUIM_FindUData, MEN_SETTINGS_CONFIGNAME),
            MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
            obj, 1, MUIM_MainWindow_ChangeConfigFile);
        DoMethod((Object *) DoMethod(Menustrip, MUIM_FindUData, MEN_SETTINGS_MUI),
            MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
            obj, 1, MUIM_MainWindow_MUISettings);

        DoMethod((Object *) DoMethod(Menustrip, MUIM_FindUData, MEN_ABOUT_APP),
            MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
            obj, 1, MUIM_MainWindow_About);
        DoMethod((Object *) DoMethod(Menustrip, MUIM_FindUData, MEN_ABOUT_MUI),
            MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
            obj, 1, MUIM_MainWindow_Aboutmui);

        set(SaveBut,   MUIA_ShortHelp, (ULONG) GetStr(MSG_MAINWINDOW_SAVE_GAD_HELP));
        set(CancelBut, MUIA_ShortHelp, (ULONG) GetStr(MSG_MAINWINDOW_CANCEL_GAD_HELP));

        MainWindow_LoadConfig(cl, obj);
    }
    return((ULONG)obj);
}

ULONG __saveds MainWindow_Dispatcher(register __a0 struct IClass *cl,
                                     register __a2 Object        *obj,
                                     register __a1 Msg           msg)
{
    switch (msg->MethodID)
    {
        case OM_NEW                     : return(MainWindow_mNew     (cl, obj, (APTR)msg));
        case MUIM_MainWindow_About      : return(MainWindow_About    (cl, obj, (APTR)msg));
        case MUIM_MainWindow_Aboutmui   : return(MainWindow_Aboutmui (cl, obj, (APTR)msg));
        case MUIM_MainWindow_Reload     : return(MainWindow_Reload   (cl, obj, (APTR)msg));
        case MUIM_MainWindow_Save       : return(MainWindow_Save     (cl, obj, (APTR)msg));
        case MUIM_MainWindow_SaveAs     : return(MainWindow_SaveAs   (cl, obj, (APTR)msg));
        case MUIM_MainWindow_ChangeConfigFile :
            return(MainWindow_ChangeConfigFile (cl, obj, (APTR)msg));
        case MUIM_MainWindow_MUISettings :
            return(MainWindow_MUISettings      (cl, obj, (APTR)msg));
        case MUIM_MainWindow_Finish : return(MainWindow_Finish (cl, obj, (APTR)msg));
    }
    return(DoSuperMethodA(cl, obj, msg));
}

/* app class */

ULONG App_mNew(struct IClass *cl, Object *obj, struct opSet *msg)
{
    Object  *mainwindow;

    obj = (Object *)DoSuperNew(cl, obj,
        MUIA_Application_Title,         GetStr(MSG_APP_TITLE),
        MUIA_Application_Version,       APP_VERSION,
        MUIA_Application_Copyright,     APP_COPYRIGHT,
        MUIA_Application_Author,        APP_AUTHOR,
        MUIA_Application_Description,   GetStr(MSG_APP_DESCRIPTION),
        MUIA_Application_Base,          APP_BASE,
        MUIA_Application_Window,        mainwindow = NewObject(MainWindow_Class->mcc_Class,
                                            NULL, TAG_DONE),
        TAG_MORE, msg->ops_AttrList);

    if(obj)
    {
        set(mainwindow, MUIA_Window_Open, TRUE);
    }
    return((ULONG)obj);
}

ULONG __saveds App_Dispatcher(register __a0 struct IClass *cl,
                              register __a2 Object        *obj,
                              register __a1 Msg           msg)
{
    switch (msg->MethodID)
    {
        case OM_NEW                 : return(App_mNew   (cl, obj, (APTR)msg));
    }
    return(DoSuperMethodA(cl, obj, msg));
}

/* headquarter ;-) */


int main();

int wbmain(struct WBStartup *wb)
{
    LONG rc;
    WBenchMsg=wb;
    rc=main();
    return(rc);
}

int main()
{
    BPTR olddir=NULL; ULONG i; struct Library *lib;

    if (WBenchMsg)
        if (WBenchMsg->sm_ArgList->wa_Lock)
            olddir = CurrentDir(WBenchMsg->sm_ArgList->wa_Lock);

    if(!(MUIMasterBase=(struct Library *) OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN)))
        goto exit;

    i=40; while(!(lib = OpenLibrary("intuition.library", i))) i--;
    CloseLibrary(lib); OSVersion=i;


    if(LocaleBase)
    {
        Catalog = OpenCatalog(NULL, "MetaToolPrefs.catalog",
            OC_Version, MTPREFS_CATALOGVERSION, TAG_DONE);
        LocalizeNewMenu(MainMenu); LocalizeNewMenu(MTEntryPanelMenu);
    }

    DragString_Class  = MUI_CreateCustomClass(NULL, MUIC_String, NULL,
        sizeof(struct DragString_Data), DragString_Dispatcher);
    if(!DragString_Class) goto exit;

    MTEntryList_Class   = MUI_CreateCustomClass(NULL, MUIC_List, NULL,
        sizeof(struct MTEntryList_Data), MTEntryList_Dispatcher);
    if(!MTEntryList_Class) goto exit;

    MTEditWindow_Class  = MUI_CreateCustomClass(NULL, MUIC_Window, NULL,
        sizeof(struct MTEditWindow_Data), MTEditWindow_Dispatcher);
    if(!MTEditWindow_Class) goto exit;

    MTEntryPanel_Class  = MUI_CreateCustomClass(NULL, MUIC_Group, NULL,
        sizeof(struct MTEntryPanel_Data), MTEntryPanel_Dispatcher);
    if(!MTEntryPanel_Class) goto exit;

    MainWindow_Class = MUI_CreateCustomClass(NULL, MUIC_Window, NULL,
        sizeof(struct MainWindow_Data), MainWindow_Dispatcher);
    if(!MainWindow_Class) goto exit;

    App_Class = MUI_CreateCustomClass(NULL, MUIC_Application, NULL,
        0L, App_Dispatcher);
    if(!App_Class) goto exit;

    App = NewObject(App_Class->mcc_Class, NULL, TAG_DONE);

    if (!App) goto exit;

    {
        ULONG signals=0;
        while (DoMethod(App, MUIM_Application_Input,&signals)!=
            MUIV_Application_ReturnID_Quit)
        {
            if (signals) Wait(signals);
        }
    }

exit:
    if (App)                MUI_DisposeObject(App);
    if (App_Class)          MUI_DeleteCustomClass(App_Class);
    if (MainWindow_Class)   MUI_DeleteCustomClass(MainWindow_Class);
    if (MTEntryPanel_Class) MUI_DeleteCustomClass(MTEntryPanel_Class);
    if (MTEditWindow_Class) MUI_DeleteCustomClass(MTEditWindow_Class);
    if (MTEntryList_Class)  MUI_DeleteCustomClass(MTEntryList_Class);
    if (DragString_Class)   MUI_DeleteCustomClass(DragString_Class);
    if (Catalog)            CloseCatalog(Catalog);
    if (DOSPathBase)        CloseLibrary(DOSPathBase);
    if (MUIMasterBase)      CloseLibrary(MUIMasterBase);
    if (olddir)             CurrentDir(olddir);
}

