/**
 * Scout - The Amiga System Monitor
 *
 *------------------------------------------------------------------
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * You must not use this source code to gain profit of any kind!
 *
 *------------------------------------------------------------------
 *
 * @author Andreas Gelhausen
 * @author Richard Körber <rkoerber@gmx.de>
 */

#include "system_headers.h"

static void SetDetails( struct IClass *cl,
                        Object *obj,
                        struct ExpansionEntry *ee )
{
    struct ExpansionsDetailWinData *edwd = INST_DATA(cl, obj);
    struct ConfigDev *exp = ee->ee_Addr;
    UBYTE *tmp, *tmp2;
    static UWORD cdflags[] = { CDF_SHUTUP, CDF_CONFIGME, CDF_BADMEMORY, CDF_PROCESSED, 0 };
    static UBYTE *cdflagstext[] = { "SHUTUP", "CONFIGME", "BADMEMORY", "PROCESSED" };
    static UBYTE ertype[] = { ERTF_MEMLIST, ERTF_DIAGVALID, ERTF_CHAINEDCONFIG, 0 };
    static UBYTE *ertypetext[] = { "MEMLIST", "DIAGVALID", "CHAINEDCONFIG" };
    static UBYTE erflags[] = { ERFF_MEMSPACE, ERFF_NOSHUTUP, ERFF_EXTENDED, ERFF_ZORRO_III, 0 };
    static UBYTE *erflagstext[] = { "MEMSPACE", "NOSHUTUP", "EXTENDED", "ZORRO_III" };
    static UBYTE *z3subsize[] = { "SAME", "AUTO", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "6M", "8M", "10M", "12M", "14M", "RESERVED", "RESERVED" };

    tmp = tbAllocVecPooled(globalPool, PATH_LENGTH);
    tmp2 = tbAllocVecPooled(globalPool, PATH_LENGTH);
    if (tmp != NULL && tmp2 != NULL) {
        ULONG i;
        UBYTE memsize;

        MySetContents(edwd->edwd_ExpansionMoreText[2], MUIX_R "$%08lx\n$%08lx\n$%08lx\n$%02lx", exp, exp->cd_BoardAddr, exp->cd_BoardSize, exp->cd_Rom.er_Reserved03);
        MySetContents(edwd->edwd_ExpansionMoreText[3], MUIX_R "%lD\n%lD\n$%04lx\n%lu", exp->cd_SlotAddr, exp->cd_SlotSize, exp->cd_Rom.er_InitDiagVec, exp->cd_Rom.er_SerialNumber);
        MySetContents(edwd->edwd_ExpansionMoreText[4], MUIX_R "$%08lx\n$%08lx\n$%08lx\n$%02lx%02lx%02lx%02lx", exp->cd_Driver, exp->cd_NextCD, exp->cd_Unused[4], exp->cd_Rom.er_Reserved0c, exp->cd_Rom.er_Reserved0d, exp->cd_Rom.er_Reserved0e, exp->cd_Rom.er_Reserved0f);
        MySetContents(edwd->edwd_ExpansionMoreText[5], "$%02lx", exp->cd_Flags);

        tmp[0] = 0x00;
        i = 0;
        while (cdflags[i]) {
            if (exp->cd_Flags & cdflags[i]) {
                if (strlen(tmp)) _strcatn(tmp, ", ", PATH_LENGTH);
                _strcatn(tmp, cdflagstext[i], PATH_LENGTH);
            }
            i++;
        }
        MySetContents(edwd->edwd_ExpansionMoreText[8], nonetest(tmp));

        MySetContents(edwd->edwd_ExpansionMoreText[6], "$%02lx", exp->cd_Rom.er_Type);
        tmp[0] = 0x00;
        if (exp->cd_Rom.er_Type & ERT_TYPEMASK) {
            if (exp->cd_Rom.er_Type & ERT_ZORROIII) {
                _strcatn(tmp, "ZORRO", PATH_LENGTH);
                if (exp->cd_Rom.er_Type & 0x40) {
                    _strcatn(tmp, "2, ", PATH_LENGTH);
                } else {
                    _strcatn(tmp, "3, ", PATH_LENGTH);
                }
            }
        }
        i = 0;
        while (ertype[i]) {
            if (exp->cd_Rom.er_Type & ertype[i]) {
                _strcatn(tmp, ertypetext[i], PATH_LENGTH);
                _strcatn(tmp, ", ", PATH_LENGTH);
            }
            i++;
        }

        memsize = exp->cd_Rom.er_Type & ERT_MEMMASK;
        _strcatn(tmp, "MEMSIZE=", PATH_LENGTH);

        if (exp->cd_Rom.er_Flags & ERFF_EXTENDED) {
            switch (memsize) {
                case 0x07: stccpy(tmp2, "?", PATH_LENGTH); break;
                case 0x06: stccpy(tmp2, "1G", PATH_LENGTH); break;
                default: _snprintf(tmp2, PATH_LENGTH, "%lDM", (1 << memsize) << 4); break;
            }
        } else {
            switch (memsize) {
                case 0x00: stccpy(tmp2, "8M", PATH_LENGTH); break;
                case 0x01:
                case 0x02:
                case 0x03:
                case 0x04: _snprintf(tmp2, PATH_LENGTH, "%lDK", (1 << (memsize - 1) << 6)); break;
                default: _snprintf(tmp2, PATH_LENGTH, "%lDM", (1 << (memsize - 5))); break;
            }
        }
        _strcatn(tmp, tmp2, PATH_LENGTH);
        if ((exp->cd_Rom.er_Type & ERT_TYPEMASK) == ERT_ZORROIII) {
            if (strlen(tmp)) _strcatn(tmp, ", SUBSIZE=", PATH_LENGTH);
            _strcatn(tmp, z3subsize[exp->cd_Rom.er_Flags & 0x0f], PATH_LENGTH);
        }
        MySetContents(edwd->edwd_ExpansionMoreText[9], nonetest(tmp));

        MySetContents(edwd->edwd_ExpansionMoreText[7], "$%02lx", exp->cd_Rom.er_Flags);

        tmp[0] = 0x00;
        i = 0;
        while (erflags[i]) {
            if (exp->cd_Rom.er_Flags & erflags[i]) {
                if (strlen(tmp)) _strcatn(tmp, ", ", PATH_LENGTH);
                _strcatn(tmp, erflagstext[i], PATH_LENGTH);
            }
            i++;
        }
        MySetContents(edwd->edwd_ExpansionMoreText[10], nonetest(tmp));

        if (exp->cd_Rom.er_Type & ERTF_DIAGVALID) {
            struct DiagArea *diag = (struct DiagArea *)((ULONG)exp->cd_BoardAddr + exp->cd_Rom.er_InitDiagVec);

            MySetContents(edwd->edwd_ExpansionMoreText[11], MUIX_R "$%08lx\n$%02lx", diag, diag->da_Flags);
            MySetContents(edwd->edwd_ExpansionMoreText[12], MUIX_R "$%04lx\n$%04lx", diag->da_Size, diag->da_Name);
            MySetContents(edwd->edwd_ExpansionMoreText[13], MUIX_R "$%04lx\n$%04lx", diag->da_DiagPoint, diag->da_BootPoint);
            MySetContents(edwd->edwd_ExpansionMoreText[14], "$%02lx", diag->da_Config);

            stccpy(tmp, "BUSWIDTH=", PATH_LENGTH);
            if (diag->da_Config & DAC_WORDWIDE) {
                _strcatn(tmp, "WORDWIDE", PATH_LENGTH);
            } else if (diag->da_Config & DAC_BYTEWIDE) {
                _strcatn(tmp, "BYTEWIDE", PATH_LENGTH);
            } else {
                _strcatn(tmp, "NIBBLEWIDE", PATH_LENGTH);
            }

            _strcatn(tmp, ", BOOTTIME=", PATH_LENGTH);
            if (diag->da_Config & DAC_BINDTIME) {
                _strcatn(tmp, "BINDTIME", PATH_LENGTH);
            } else if (diag->da_Config & DAC_CONFIGTIME) {
                _strcatn(tmp, "CONFIGTIME", PATH_LENGTH);
            } else {
                _strcatn(tmp, "NEVER", PATH_LENGTH);
            }
            MySetContents(edwd->edwd_ExpansionMoreText[15], tmp);

            set(edwd->edwd_ExpansionMoreAdd[0], MUIA_ShowMe, TRUE);
            set(edwd->edwd_ExpansionMoreAdd[1], MUIA_ShowMe, TRUE);
        }

        if (IdentifyBase) {
            MySetContents(edwd->edwd_ExpansionMoreText[0], ee->ee_ManufName);
            MySetContents(edwd->edwd_ExpansionMoreText[1], ee->ee_ProdClass);
            MySetContents(edwd->edwd_ExpansionMoreText[16], ee->ee_ProdName);
        } else {
            MySetContents(edwd->edwd_ExpansionMoreText[0], msgNoIdentifyLibrary);
            MySetContents(edwd->edwd_ExpansionMoreText[1], msgNoIdentifyLibrary);
            MySetContents(edwd->edwd_ExpansionMoreText[16], msgNoIdentifyLibrary);
        }

        set(obj, MUIA_Window_Title, MyGetChildWindowTitle("EXPANSION", ee->ee_ProdName, edwd->edwd_Title, sizeof(edwd->edwd_Title)));
    }
    if (tmp) tbFreeVecPooled(globalPool, tmp);
    if (tmp2) tbFreeVecPooled(globalPool, tmp2);
}

static ULONG __saveds mNew( struct IClass *cl,
                            Object *obj,
                            struct opSet *msg )
{
    APTR expmoretext[17], ExpMoreGroup[2], ExpMoreAdd[2];

    if (obj = (Object *)DoSuperNew(cl, obj,
        MUIA_HelpNode, ExpansionsText,
        MUIA_Window_ID, MakeID('.','E','X','P'),
        WindowContents, HGroup,
            Child, ExpMoreGroup[0] = VGroup,
                Child, MyLabel2("Manufacturer:"),
                Child, MyLabel2("Product:"),
                Child, MyLabel2("Class:"),
                Child, MyLabel2("Address:\nBoardAddr:\nBoardSize:\nReserved03:"),
                Child, MyLabel2("Flags:"),
                Child, MyLabel2("er_Type:"),
                Child, MyLabel2("er_Flags:"),
                Child, ExpMoreAdd[0] = VGroup, MUIA_ShowMe, FALSE,
                    Child, MyLabel2("DiagArea:\nda_Flags:"),
                    Child, MyLabel2("da_Config:"),
                End,
            End,
            Child, ExpMoreGroup[1] = VGroup, MUIA_Group_SameWidth, TRUE,
                Child, expmoretext[0] = MyTextObject(),
                Child, expmoretext[1] = MyTextObject(),
                Child, expmoretext[16] = MyTextObject(),
                Child, HGroup,
                    Child, expmoretext[2] = MyTextObject2(),
                    Child, MyLabel("SlotAddr:\nSlotSize:\nInitDiagVec:\nSerialNumber:"),
                    Child, expmoretext[3] = MyTextObject2(),
                    Child, MyLabel("Driver:\nNextCD:\nUnused[4]:\nReserved[4]:"),
                    Child, expmoretext[4] = MyTextObject2(),
                End,
                Child, HGroup,
                    Child, VGroup, MUIA_Group_SameWidth, TRUE,
                        Child, expmoretext[5] = MyTextObject2(),
                        Child, expmoretext[6] = MyTextObject2(),
                        Child, expmoretext[7] = MyTextObject2(),
                    End,
                    Child, VGroup, MUIA_Group_SameWidth, TRUE,
                        Child, MyLabel2(" = "),
                        Child, MyLabel2(" = "),
                        Child, MyLabel2(" = "),
                    End,
                    Child, VGroup, MUIA_Group_SameWidth, TRUE,
                        Child, expmoretext[8] = MyTextObject(),
                        Child, expmoretext[9] = MyTextObject(),
                        Child, expmoretext[10] = MyTextObject(),
                    End,
                End,
                Child, ExpMoreAdd[1] = VGroup, MUIA_Group_SameWidth, TRUE, MUIA_ShowMe, FALSE,
                    Child, HGroup,
                        Child, expmoretext[11] = MyTextObject2(),
                        Child, MyLabel ("da_Size:\nda_Name:"),
                        Child, expmoretext[12] = MyTextObject2(),
                        Child, MyLabel ("da_DiagPoint:\nda_BootPoint:"),
                        Child, expmoretext[13] = MyTextObject2(),
                    End,
                    Child, HGroup,
                        Child, expmoretext[14] = MyTextObject2(),
                        Child, MyLabel2 (" = "),
                        Child, expmoretext[15] = MyTextObject(),
                    End,
                End,
            End,
        End,
        TAG_MORE, msg->ops_AttrList))
    {
        struct ExpansionsDetailWinData *edwd = INST_DATA(cl, obj);
        APTR parent;

        CopyMem(expmoretext, edwd->edwd_ExpansionMoreText, sizeof(edwd->edwd_ExpansionMoreText));
        CopyMem(ExpMoreGroup, edwd->edwd_ExpansionMoreGroup, sizeof(edwd->edwd_ExpansionMoreGroup));
        CopyMem(ExpMoreAdd, edwd->edwd_ExpansionMoreAdd, sizeof(edwd->edwd_ExpansionMoreAdd));

        parent = (APTR)GetTagData(MUIA_Window_ParentWindow, (ULONG)NULL, msg->ops_AttrList);

        DoMethod(parent, MUIM_Window_AddChildWindow, obj);
        DoMethod(obj,    MUIM_Notify,              MUIA_Window_CloseRequest, TRUE, MUIV_Notify_Application, 5, MUIM_Application_PushMethod, parent, 2, MUIM_Window_RemChildWindow, obj);
    }

    return (ULONG)obj;
}

static ULONG __saveds mDispose( struct IClass *cl,
                                Object *obj,
                                struct opSet *msg )
{
    set(obj, MUIA_Window_Open, FALSE);

    return (DoSuperMethodA(cl, obj, msg));
}

static ULONG __saveds mSet( struct IClass *cl,
                            Object *obj,
                            Msg msg )
{
    struct TagItem *tags, *tag;

    for (tags = ((struct opSet *)msg)->ops_AttrList; tag = NextTagItem(&tags); ) {
        switch (tag->ti_Tag) {
            case MUIA_Window_ParentWindow:
                DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, MUIV_Notify_Application, 5, MUIM_Application_PushMethod, (APTR)tag->ti_Data, 2, MUIM_Window_RemChildWindow, obj);
                break;

            case MUIA_ExpansionsDetailWin_Expansion:
                SetDetails(cl, obj, (struct ExpansionEntry *)tag->ti_Data);
                break;
        }
    }

    return (DoSuperMethodA(cl,obj,msg));
}

ULONG __asm __saveds ExpansionsDetailWinDispatcher( register __a0 struct IClass *cl,
                                                    register __a2 Object *obj,
                                                    register __a1 Msg msg )
{
    switch (msg->MethodID) {
        case OM_NEW:     return (mNew(cl, obj, (APTR)msg));
        case OM_DISPOSE: return (mDispose(cl, obj, (APTR)msg));
        case OM_SET:     return (mSet(cl, obj, (APTR)msg));
    }

    return (DoSuperMethodA(cl, obj, msg));
}

