/*----------------------------------------------------------------------*
    binary.c Version 3.0 - © Copyright 1990-91 Jaba Development

    Author : Jan van den Baard
    Purpose: The reading and writing of binary PS files.
 *----------------------------------------------------------------------*/

/*
 *  External data references.
 */
extern struct Screen            *MainScreen;
extern struct Window            *MainWindow;
extern struct FileSelector      *IODir;
extern struct Image             *active;
extern struct MyMenu            *MenuStrip, *ParentMenu;
extern struct ItemList          *MenusList, *ItemsList, *SubsList;
extern struct MyMenuItem        *ParentItem, dummy;
extern struct GadgetList         Gadgets;
extern struct BorderList         SBorders;
extern struct SharedList         Images;
extern struct NewWindow          nw_main;
extern struct Gadget             TextGadget;
extern struct ge_prefs           prefs;
extern struct MemoryChain        Misc, Memory;
extern ULONG                     WindowFlags, IDCMPFlags;
extern UWORD                     GadgetCount, id, BackFill, WDBackFill;
extern UWORD                     FrontPen, BackPen, Colors[], WBColors[];
extern UWORD                     LightSide, DarkSide, ItemCount, SubCount, MenuCount;
extern UWORD                     ItemTotal, SubTotal, MenuTotal, DEPTH;
extern BOOL                      Saved, REQUESTER, WBSCREEN, bo_added;
extern UBYTE                     name[512], wdt[80], wlb[MAXLABEL];
extern UBYTE                     TextLabel[32];

extern struct ListItem          *CreateListItem();
extern struct SharedBorder      *CreateSBorder();
extern APTR                      GetBorder(), withdraw();

#define NUMLABELS                11

/*
 *  Icon data.
 */
USHORT Image0_data[] = {
  0x0000,  0x0000,  0x0000,  0x0800,  0x0000,  0x0000,  0x0000,  0x1800,
  0x0000,  0x0000,  0x0000,  0x1800,  0x0000,  0x0000,  0x0000,  0x1800,
  0x0000,  0x0000,  0x0000,  0x1800,  0x0000,  0x0000,  0x0000,  0x1800,
  0x0020,  0xF800,  0x3E00,  0x1800,  0x0000,  0x0000,  0xC180,  0x1800,
  0x0000,  0x0000,  0x0060,  0x1800,  0x0000,  0x0008,  0x0000,  0x1800,
  0x0000,  0x0006,  0x0000,  0x1800,  0x0000,  0x00C1,  0xE000,  0x1800,
  0x0000,  0xFF00,  0x1800,  0x1800,  0x0000,  0x0000,  0x0600,  0x1800,
  0x0000,  0x0000,  0x0000,  0x1800,  0x0000,  0x0000,  0x0000,  0x1800,
  0x0000,  0x0000,  0x0030,  0x1800,  0x0000,  0x0006,  0x00C0,  0x1800,
  0x003F,  0x8019,  0xFF00,  0x1800,  0x0000,  0x0000,  0x0000,  0x1800,
  0x0000,  0x0000,  0x0000,  0x1800,  0x0000,  0x0000,  0x0000,  0x1800,
  0x7FFF,  0xFFFF,  0xFFFF,  0xF800,  0xFFFF,  0xFFFF,  0xFFFF,  0xF000,
  0xEAAA,  0xAAAA,  0xAAAA,  0xA000,  0xEAAA,  0xAAAA,  0xAAAA,  0xA000,
  0xEAAA,  0xAAAA,  0xAAAA,  0xA000,  0xEAAA,  0xAAAA,  0xAAAA,  0xA000,
  0xEA80,  0x02AA,  0x008A,  0xA000,  0xEA80,  0x00A8,  0x000A,  0xA000,
  0xEAA0,  0xA820,  0x2A0A,  0xA000,  0xEAA0,  0xA820,  0x2A8A,  0xA000,
  0xEAA0,  0xA820,  0x02AA,  0xA000,  0xEAA0,  0xA828,  0x002A,  0xA000,
  0xEAA0,  0x002A,  0x000A,  0xA000,  0xEAA0,  0x00AA,  0xA00A,  0xA000,
  0xEAA0,  0xAAAA,  0xA80A,  0xA000,  0xEAA0,  0xAAA2,  0xAA0A,  0xA000,
  0xEAA0,  0xAAA0,  0xA80A,  0xA000,  0xEAA0,  0xAAA0,  0x280A,  0xA000,
  0xEA80,  0x2AA0,  0x002A,  0xA000,  0xEA80,  0x2AA2,  0x00AA,  0xA000,
  0xEAAA,  0xAAAA,  0xAAAA,  0xA000,  0xEAAA,  0xAAAA,  0xAAAA,  0xA000,
  0xEAAA,  0xAAAA,  0xAAAA,  0xA000,  0x8000,  0x0000,  0x0000,  0x0000
};

USHORT Image1_data[] = {
  0xFFFF,  0xFFFF,  0xFFFF,  0xF000,  0xC000,  0x0000,  0x0000,  0x0000,
  0xC000,  0x0000,  0x0000,  0x0000,  0xC000,  0x0000,  0x0000,  0x0000,
  0xC03F,  0xFC01,  0xFF70,  0x0000,  0xC000,  0x0306,  0x0080,  0x0000,
  0xC000,  0x00C8,  0x0000,  0x0000,  0xC000,  0x0000,  0xC000,  0x0000,
  0xC000,  0x0000,  0x3C00,  0x0000,  0xC000,  0x0000,  0x03C0,  0x0000,
  0xC000,  0xF800,  0x0020,  0x0000,  0xC000,  0x0000,  0x0000,  0x0000,
  0xC000,  0x0000,  0x0000,  0x0000,  0xC000,  0x0018,  0x0000,  0x0000,
  0xC000,  0x0006,  0x0000,  0x0000,  0xC000,  0x0001,  0xC400,  0x0000,
  0xC020,  0x8000,  0x3800,  0x0000,  0xC000,  0x0000,  0x0000,  0x0000,
  0xC000,  0x0000,  0x0000,  0x0000,  0xC000,  0x0000,  0x0000,  0x0000,
  0xC000,  0x0000,  0x0000,  0x0000,  0xC000,  0x0000,  0x0000,  0x0000,
  0x8000,  0x0000,  0x0000,  0x0000,  0x0000,  0x0000,  0x0000,  0x0800,
  0x2AAA,  0xAAAA,  0xAAAA,  0xB800,  0x2AAA,  0xAAAA,  0xAAAA,  0xB800,
  0x2AAA,  0xAAAA,  0xAAAA,  0xB800,  0x2A80,  0x02AA,  0x008A,  0xB800,
  0x2A80,  0x00A8,  0x000A,  0xB800,  0x2A80,  0xA820,  0x2A0A,  0xB800,
  0x2AA0,  0xA820,  0x2A8A,  0xB800,  0x2AA0,  0xA820,  0x02AA,  0xB800,
  0x2AA0,  0xA828,  0x002A,  0xB800,  0x2AA0,  0x002A,  0x000A,  0xB800,
  0x2AA0,  0x00AA,  0xA00A,  0xB800,  0x2AA0,  0xAAAA,  0xA80A,  0xB800,
  0x2AA0,  0xAAA2,  0xAA0A,  0xB800,  0x2AA0,  0xAAA0,  0xAA0A,  0xB800,
  0x2AA0,  0xAAA0,  0x280A,  0xB800,  0x2A80,  0x2AA0,  0x002A,  0xB800,
  0x2A80,  0x2AA2,  0x00AA,  0xB800,  0x2AAA,  0xAAAA,  0xAAAA,  0xB800,
  0x2AAA,  0xAAAA,  0xAAAA,  0xB800,  0x2AAA,  0xAAAA,  0xAAAA,  0xB800,
  0x2AAA,  0xAAAA,  0xAAAA,  0xB800,  0x7FFF,  0xFFFF,  0xFFFF,  0xF800
};

struct Image Image1_image = {
  0,0,53,23,2,(USHORT *)&Image1_data,0x03,0x00,NULL };
struct Image Image0_image = {
  0,0,53,23,2,(USHORT *)&Image0_data,0x03,0x00,NULL };

struct IconBase *IconBase;

/*
 * write a 'PS' icon
 */
BOOL WriteIcon(UBYTE *nme)
{
    struct DiskObject  icon;
    struct Gadget      icon_Gadget;
    BOOL               ret;

    if((IconBase = OpenLibrary(ICONNAME,0L))) {
        icon_Gadget.NextGadget   =   NULL;
        icon_Gadget.LeftEdge     =   0;
        icon_Gadget.TopEdge      =   0;
        icon_Gadget.Width        =   53;
        icon_Gadget.Height       =   23;
        icon_Gadget.Flags        =   GADGIMAGE+GADGHIMAGE;
        icon_Gadget.Activation   =   RELVERIFY+GADGIMMEDIATE;
        icon_Gadget.GadgetType   =   BOOLGADGET;
        icon_Gadget.GadgetRender =   (APTR)&Image0_image;
        icon_Gadget.SelectRender =   (APTR)&Image1_image;
        icon_Gadget.GadgetText   =   NULL;
        icon_Gadget.MutualExclude=   NULL;
        icon_Gadget.SpecialInfo  =   NULL;
        icon_Gadget.GadgetID     =   NULL;
        icon_Gadget.UserData     =   NULL;

        icon.do_Magic            =   WB_DISKMAGIC;
        icon.do_Version          =   WB_DISKVERSION;
        icon.do_Gadget           =   icon_Gadget;
        icon.do_Type             =   WBPROJECT;
        icon.do_DefaultTool      =   (char *)":PowerSource";
        icon.do_ToolTypes        =   NULL;
        icon.do_CurrentX         =   NO_ICON_POSITION;
        icon.do_CurrentY         =   NO_ICON_POSITION;
        icon.do_DrawerData       =   NULL;
        icon.do_ToolWindow       =   NULL;
        icon.do_StackSize        =   8192;
        ret = PutDiskObject((char *)nme,&icon);

        CloseLibrary(IconBase);
        if(NOT ret) return(FALSE);
        return(TRUE);
    }
    return(FALSE);
}

/*
 * Check for an error.
 */
long CheckErr( void )
{
    char    *err;

    if(err = IoErrToStr()) {
        enable_window();
        ok();
        Error(err);
        return(FALSE);
    }
    return(TRUE);
}

/*
 * Write the source labels.
 */
long WriteLabels( BPTR file )
{
    ULONG   num = NUMLABELS;

    Write(file,(char *)&num,4L);
    Write(file,(char *)&TextLabel[0],NUMLABELS * 32);

    return(CheckErr());
}

/*
 * Write the gadget shared borders.
 */
long WriteSBord( BPTR file )
{
    register struct SharedBorder    *sbrd;
    register struct Border          *brd;
    ULONG                            ac;

    for(sbrd = SBorders.Head, ac = 0L; sbrd->Succ; sbrd = sbrd->Succ, ac++);

    Write(file,(char *)&ac,4L);

    for(sbrd = SBorders.Head; sbrd->Succ; sbrd = sbrd->Succ) {
        brd = sbrd->Border;
        Write(file,(char *)&sbrd->SpecialFlags,2L);
        while(1) {
            Write(file,(char *)brd,(long)sizeof(struct Border));
            if(NOT TestBits((ULONG)sbrd->SpecialFlags,SB_HIGHBORDER))
                Write(file,(char *)brd->XY,(long)(brd->Count << 2));
            if(NOT(brd = brd->NextBorder)) break;
        }
    }

    return(CheckErr());
}

/*
 * Get the account number of each border.
 */
void BuildBAccounts( void )
{
    register struct MyGadget    *mg;
    register struct Gadget      *g;

    for(mg = Gadgets.Head; mg->Succ; mg = mg->Succ) {
        g = &mg->Gadget;
        if(NOT TestBits((ULONG)g->GadgetType,PROPGADGET)) {
            if(NOT TestBits((ULONG)mg->SpecialFlags,BORDERONLY)) {
                if(NOT TestBits((ULONG)g->Flags,GADGIMAGE))
                    mg->BorderAccount = Account(g->GadgetRender);
                if(TestBits((ULONG)mg->SpecialFlags,OS20HIGHBORDER))
                    mg->HBorderAccount = Account(g->SelectRender);
            }
        }
    }
}

/*
 * Write the image bank.
 */
long WriteBank( BPTR file )
{
    register struct SharedImage  *sim;
    register struct Image        *image;
    ULONG                         ac;

    for(sim = Images.Head, ac = 0L; sim->Succ; sim = sim->Succ, ac++);

    Write(file,(char *)&ac,4L);

    for(sim = Images.Head; sim->Succ; sim = sim->Succ) {
        image = sim->Image;
        Write(file,(char *)image,(long)sizeof(struct Image));
        Write(file,(char *)image->ImageData,(long)(RASSIZE(image->Width,image->Height) * image->Depth));
        Write(file,(char *)&sim->Colors[0],64L);
        Write(file,(char *)&sim->CheckSum,4L);
    }
    return(CheckErr());
}

/*
 * Get the account number of each image used by a gadget.
 */
void BuildAccounts( void )
{
    register struct MyGadget    *mg;
    register struct Gadget      *g;

    for(mg = Gadgets.Head; mg->Succ; mg = mg->Succ) {
        g = &mg->Gadget;
        if(TestBits((ULONG)g->Flags,GADGIMAGE))
            mg->RenderAccount = bank_account(g->GadgetRender);
        if(TestBits((ULONG)g->Flags,GADGHIMAGE)) {
            if(NOT TestBits((ULONG)g->Flags,GADGHBOX)) {
                if(NOT TestBits((ULONG)mg->SpecialFlags,OS20HIGHBORDER))
                    mg->SelectAccount = bank_account(g->SelectRender);
            }
        }
    }
}

/*
 * Write a gadget.
 */
long WriteGadget( BPTR file, struct MyGadget *g )
{
    struct Gadget       *gadget;
    struct IntuiText    *t;
    struct StringInfo   *s;
    struct Border       *b;

    gadget = &g->Gadget;

    Write(file,(char *)gadget,(long)(sizeof(struct MyGadget) - 8L));

    if(t = gadget->GadgetText) {
        while(1) {
            Write(file,(char *)t,(long)sizeof(struct IntuiText));
            Write(file,(char *)t->IText,80L);
            if(NOT (t = t->NextText)) break;
        }
    }

    if((TestBits((ULONG)g->SpecialFlags,BORDERONLY)) OR
       (TestBits((ULONG)g->SpecialFlags,NOBORDER))) {
        b = (struct Border *)gadget->GadgetRender;
        while(1) {
            Write(file,(char *)b,(long)sizeof(struct Border));
            Write(file,(char *)b->XY,(long)(b->Count << 2));
            if(NOT(b = b->NextBorder)) break;
        }
    }

    if(TestBits((ULONG)gadget->GadgetType,PROPGADGET))
        Write(file,(char *)gadget->SpecialInfo,(long)sizeof(struct PropInfo));

    if(TestBits((ULONG)gadget->GadgetType,STRGADGET)) {
        s = (struct StringInfo *)gadget->SpecialInfo;
        Write(file,(char *)s,(long)sizeof(struct StringInfo));
        Write(file,(char *)s->Buffer,(long)s->MaxChars);
    }
    return(CheckErr());
}

/*
 * Write the window/requester texts.
 */
long WriteWRTexts( BPTR file )
{
    register struct IntuiText   *t;
    ULONG                        num = 0L;

    if(t = TextGadget.GadgetText) {
        num++;
        while(1) {
            if(NOT (t = t->NextText)) break;
            num++;
        }
    }

    Write(file,(char *)&num,4L);

    if(num) {
        t = TextGadget.GadgetText;
        while(1) {
            Write(file,(char *)t,(long)sizeof(struct IntuiText));
            Write(file,(char *)t->IText,80L);
            if(NOT (t = t->NextText)) break;
        }
    }
    return(CheckErr());
}

/*
 * Write a menuitem.
 */
void WriteItem( BPTR file, struct MyMenuItem *item )
{
    struct IntuiText    *itext;

    Write(file,(char *)item,(long)sizeof(struct MyMenuItem));
    if(TestBits((ULONG)item->Flags,ITEMTEXT)) {
        itext = (struct IntuiText *)item->ItemFill;
        Write(file,(char *)itext,(long)sizeof(struct IntuiText));
        Write(file,(char *)itext->IText,80L);
    }
}

/*
 * Write the menus.
 */
long WriteMenus( BPTR file )
{
    register struct MyMenu      *menu;
    register struct MyMenuItem  *item, *item1, *sub, *sub1;
    ULONG                        menus;

    if(MenuStrip) {
        menus = 1L;
        Write(file,(char *)&menus,4L);

        for(menu = MenuStrip; menu; menu = menu->NextMenu) {
            if(menu->FirstItem == &dummy) {
                menu->FirstItem = NULL;
                Write(file,(char *)menu,(long)sizeof(struct MyMenu));
                menu->FirstItem = &dummy;
            } else
                Write(file,(char *)menu,(long)sizeof(struct MyMenu));

            if((item = menu->FirstItem) AND (item != &dummy)) {
                while(1) {
                    item1 = item->NextItem;
                    WriteItem(file,item);
                    if((sub = item->SubItem)) {
                        while(1) {
                            sub1 = sub->NextItem;
                            WriteItem(file,sub);
                            if(NOT(sub = sub1)) break;
                        }
                    }
                    if(NOT(item = item1)) break;
                }
            }
            if(NOT CheckErr())
                return(FALSE);
        }
    } else {
        menus = 0L;
        Write(file,(char *)&menus,4L);
    }
    return(CheckErr());
}

/*
 * Write the binary file.
 */
void WriteBinGadgets( void )
{
    register struct MyGadget    *g;
    struct ViewPort             *vp;
    struct NewWindow             nw;
    struct BinHeader             head;
    ULONG                        rc;
    BPTR                         file;
    UWORD                        i;

    strcpy((char *)IODir->fr_HeadLine,"Save Binary");

    IODir->fr_Screen = MainScreen;
    IODir->fr_Caller = MainWindow;

    IODir->fr_Flags |= FR_NoInfo;

    rc = FileRequest(IODir);

    if(rc == FREQ_CANCELED)
        return;
    else if(rc) {
        Error("FileRequester won't open !");
        return;
    }

    strcpy((char *)&name[0],(char *)IODir->fr_DirName);
    strcat((char *)&name[0],(char *)IODir->fr_FileName);

    CheckName();

    disable_window();
    buisy();

    SetWindowTitles(MainWindow,(char *)-1L,"Saving Binary......");

    vp = &MainScreen->ViewPort;

    if(NOT(file = Open((char *)&name[0],MODE_NEWFILE))) {
        enable_window();
        ok();
        Error("Can't open write file !");
        return;
    }

    /* write file header */
    head.FileType   =   TYPE;
    head.Version    =   GE_VERSION;
    head.ScrDepth   =   MainScreen->BitMap.Depth;

    for(i = 0; i < 32; i++)
        head.Colors[i] = (USHORT)GetRGB4(vp->ColorMap,(long)i);

    head.FPen       =   FrontPen;
    head.BPen       =   BackPen;
    head.BackFill   =   BackFill;
    head.WDBackFill =   WDBackFill;
    head.LightSide  =   LightSide;
    head.DarkSide   =   DarkSide;
    head.FlagsBits  =   NULL;
    head.SpareFlags =   NULL;

    for(i = 0; i < 6; i++)
        head.Spare[i] = 0;

    if(REQUESTER)   head.FlagsBits |= BH_REQUESTER;
    if(WBSCREEN)    head.FlagsBits |= BH_WORKBENCH;

    Write(file,(char *)&head,(long)sizeof(struct BinHeader));

    /* write preferences */
    Write(file,(char *)&prefs,(long)sizeof(struct ge_prefs));

    /* write window specifics */
    nw.LeftEdge     =   MainWindow->LeftEdge;
    nw.TopEdge      =   MainWindow->TopEdge;
    nw.Width        =   MainWindow->Width;
    nw.Height       =   MainWindow->Height;
    nw.DetailPen    =   MainWindow->DetailPen;
    nw.BlockPen     =   MainWindow->BlockPen;
    nw.Flags        =   WindowFlags;
    nw.IDCMPFlags   =   IDCMPFlags;
    nw.FirstGadget  =   NULL;
    nw.CheckMark    =   NULL;
    nw.Title        =   NULL;
    nw.Screen       =   NULL;
    nw.BitMap       =   NULL;
    nw.MinWidth     =   MainWindow->MinWidth;
    nw.MinHeight    =   MainWindow->MinHeight;
    nw.MaxWidth     =   MainWindow->MaxWidth;
    nw.MaxHeight    =   MainWindow->MaxHeight;
    nw.Type         =   CUSTOMSCREEN;

    Write(file,(char *)&nw,(long)sizeof(struct NewWindow));

    /* write title + label */
    Write(file,(char *)&wdt[0],80L);
    Write(file,(char *)&wlb[0],MAXLABEL);

    if(NOT CheckErr())
        goto writeError;

    /* write the source labels */
    if(NOT WriteLabels(file))
        goto writeError;

    /* write the gadget borders */
    BuildBAccounts();
    if(NOT WriteSBord(file))
        goto writeError;

    /* write the image bank */
    BuildAccounts();
    if(NOT WriteBank(file))
        goto writeError;

    /* write the window/requester texts */
    if(NOT WriteWRTexts(file))
        goto writeError;

    /* write the gadgets */
    rc = (ULONG)GadgetCount;

    Write(file,(char *)&rc,4L);

    if(rc) {
        for(g = Gadgets.Head; g->Succ; g = g->Succ) {
            if(NOT WriteGadget(file,g))
                goto writeError;
        }
    }

    /* write the menus */
    if(NOT WriteMenus(file))
        goto writeError;

    if(NOT CheckErr())
        goto writeError;

    Close(file);
    enable_window();
    ok();

    if(NOT WriteIcon((UBYTE *)&name[0]))
        Error("Error writing the Icon !");

    Saved = TRUE;

    refresh();
    return;

writeError:
    Close(file);
    DeleteFile((char *)&name[0]);
    refresh();
}

/*
 * Read the source labels.
 */
long ReadLabels( BPTR file )
{
    ULONG   num;

    Read(file,(char *)&num,4L);
    Read(file,(char *)&TextLabel[0],num * 32);

    return(CheckErr());
}

/*
 * Read a single border.
 */
struct Border *ReadBorder( BPTR file , ULONG flags )
{
    struct Border   *brd;

    if(NOT(brd = (struct Border *)Alloc(&Memory,(long)sizeof(struct Border))))
        return(NULL);
    Read(file,(char *)brd,(long)sizeof(struct Border));
    if(NOT TestBits(flags,SB_HIGHBORDER)) {
        if(NOT(brd->XY = (SHORT *)Alloc(&Memory,(long)(brd->Count << 2))))
            return(NULL);
        Read(file,(char *)brd->XY,(long)(brd->Count << 2));
    }
    return(brd);
}

/*
 * Read the gadget shared borders.
 */
long ReadSBord( BPTR file )
{
    register struct SharedBorder    *sbrd;
    register struct Border          *brd, *brd1;
    ULONG                            ac,i;

    Read(file,(char *)&ac,4L);

    for(i = 0; i < ac; i++) {
        if(NOT(sbrd = CreateSBorder(NULL)))
            goto noMem;
        sbrd->UseCount = NULL;
        Read(file,(char *)&sbrd->SpecialFlags,2L);
        if(NOT(brd = ReadBorder(file,(ULONG)sbrd->SpecialFlags)))
            goto noMem;
        sbrd->Border = brd;
        if(TestBits((ULONG)sbrd->SpecialFlags,SB_HIGHBORDER))
            brd->XY = sbrd->Pred->Border->XY;
        if(brd->NextBorder) {
            while(1) {
                if(NOT(brd1 = ReadBorder(file,(ULONG)sbrd->SpecialFlags)))
                    goto noMem;
                if(TestBits((ULONG)sbrd->SpecialFlags,SB_HIGHBORDER))
                    brd1->XY = sbrd->Pred->Border->NextBorder->XY;
                brd->NextBorder = brd1;
                if(NOT brd1->NextBorder) break;
                brd = brd1;
            }
        }
    }
    return(CheckErr());

noMem:
    enable_window();
    ok();
    Error("Out of memory !");
    return(FALSE);
}

/*
 * Read the image bank.
 */
long ReadBank( BPTR file )
{
    register struct SharedImage *sim;
    register struct Image       *image;
    ULONG                        ac, i, rs;

    Read(file,(char *)&ac,4L);

    for(i = 0; i < ac; i++) {
        if(NOT(sim = (struct SharedImage *)Alloc(&Memory,(long)sizeof(struct SharedImage))))
            goto noMem;
        AddTail((void *)&Images,(void *)sim);
        if(NOT(image = (struct Image *)Alloc(&Memory,(long)sizeof(struct Image))))
            goto noMem;
        Read(file,(char *)image,(long)sizeof(struct Image));
        rs = (ULONG)(RASSIZE(image->Width,image->Height) * image->Depth);
        if(NOT(image->ImageData = (UWORD *)AllocMem(rs,MEMF_CHIP)))
            goto noMem;
        Read(file,(char *)image->ImageData,rs);
        Read(file,(char *)&sim->Colors[0],64L);
        Read(file,(char *)&sim->CheckSum,4L);
        sim->Image = image;

        if(NOT CheckErr())
            return(FALSE);
    }
    active = Images.Head->Image;
    return(CheckErr());

noMem:
    enable_window();
    ok();
    Error("Out of memory !");
    return(FALSE);
}

/*
 * Read a single IntuiText.
 */
struct IntuiText *ReadIText( BPTR file )
{
    struct IntuiText    *t;

    if(NOT(t = (struct IntuiText *)Alloc(&Memory,(long)sizeof(struct IntuiText))))
        return(NULL);
    Read(file,(char *)t,(long)sizeof(struct IntuiText));
    if(NOT(t->IText = (UBYTE *)Alloc(&Memory,80L)))
        return(NULL);
    Read(file,(char *)t->IText,80L);
    return(t);
}

/*
 * Read a gadget.
 */
long ReadGadget( BPTR file )
{
    struct MyGadget     *g;
    struct Gadget       *gadget;
    struct IntuiText    *t, *t1;
    struct StringInfo   *s;
    struct Border       *b, *b1;

    if(NOT(g = (struct MyGadget *)Alloc(&Memory,(long)sizeof(struct MyGadget))))
        goto noMem;
    AddTail((void *)&Gadgets,(void *)g);

    gadget = &g->Gadget;

    Read(file,(char *)gadget,(long)(sizeof(struct MyGadget) - 8L));

    if(gadget->GadgetText) {
        if(NOT(t = ReadIText(file)))
            goto noMem;
        gadget->GadgetText = t;
        if(t->NextText) {
            while(1) {
                if(NOT(t1 = ReadIText(file)))
                    goto noMem;
                t->NextText = t1;
                if(NOT t1->NextText) break;
                t = t1;
            }
        }
    }

    if((TestBits((ULONG)g->SpecialFlags,BORDERONLY)) OR
       (TestBits((ULONG)g->SpecialFlags,NOBORDER))) {
        if(NOT(b = ReadBorder(file,NULL)))
            goto noMem;
        gadget->GadgetRender = (APTR)b;

        if(b->NextBorder) {
            while(1) {
                if(NOT(b1 = ReadBorder(file,NULL)))
                    goto noMem;
                b->NextBorder = b1;
                if(NOT b1->NextBorder) break;
                b = b1;
            }
        }
    } else if(NOT TestBits((ULONG)gadget->GadgetType,PROPGADGET)) {
        if(NOT TestBits((ULONG)gadget->Flags,GADGIMAGE)) {
            gadget->GadgetRender = GetBorder(g->BorderAccount);
            AddUser(gadget->GadgetRender);
        }
        if(TestBits((ULONG)g->SpecialFlags,OS20HIGHBORDER)) {
            gadget->SelectRender = GetBorder(g->HBorderAccount);
            AddUser(gadget->SelectRender);
        }
    }

    if(TestBits((ULONG)gadget->Flags,GADGIMAGE)) {
        gadget->GadgetRender = withdraw(g->RenderAccount);
        add_user(gadget->GadgetRender);
    }

    if(TestBits((ULONG)gadget->Flags,GADGHIMAGE)) {
        if(NOT TestBits((ULONG)gadget->Flags,GADGHBOX)) {
            if(NOT TestBits((ULONG)g->SpecialFlags,OS20HIGHBORDER)) {
                gadget->SelectRender = withdraw(g->SelectAccount);
                add_user(gadget->SelectRender);
            }
        }
    }

    if(TestBits((ULONG)gadget->GadgetType,PROPGADGET)) {
        if(NOT TestBits((ULONG)gadget->Flags,GADGIMAGE)) {
            if(NOT(gadget->GadgetRender = (APTR)Alloc(&Memory,(long)sizeof(struct Image))))
                goto noMem;
        }
        if(NOT(gadget->SpecialInfo = (APTR)Alloc(&Memory,(long)sizeof(struct PropInfo))))
            goto noMem;
        Read(file,(char *)gadget->SpecialInfo,sizeof(struct PropInfo));
    } else if(TestBits((ULONG)gadget->GadgetType,STRGADGET)) {
        if(NOT(s = (struct StringInfo *)Alloc(&Memory,(long)sizeof(struct StringInfo))))
            goto noMem;
        Read(file,(char *)s,(long)sizeof(struct StringInfo));
        if(NOT(s->Buffer = (UBYTE *)Alloc(&Memory,(long)s->MaxChars)))
            goto noMem;
        Read(file,(char *)s->Buffer,(long)s->MaxChars);
        if(s->UndoBuffer) {
            if(NOT(s->UndoBuffer = (UBYTE *)Alloc(&Memory,(long)s->MaxChars)))
                goto noMem;
        }
        gadget->SpecialInfo = (APTR)s;
    }

    return(CheckErr());

noMem:
    enable_window();
    ok();
    Error("Out of memory !");
    return(FALSE);
}

/*
 * Read the window/requester texts.
 */
long ReadWRTexts( BPTR file )
{
    register struct IntuiText   *t, *t1;
    ULONG                        num;

    Read(file,(char *)&num,4L);

    if(num) {
        if(NOT(t = ReadIText(file)))
            goto noMem;
        TextGadget.GadgetText = t;
        if(t->NextText) {
            while(1) {
                if(NOT(t1 = ReadIText(file)))
                    goto noMem;
                t->NextText = t1;
                if(NOT t1->NextText) break;
                t = t1;
            }
        }
    }
    return(CheckErr());

noMem:
    enable_window();
    ok();
    Error("Out of memory !");
    return(FALSE);
}

/*
 * Read a single MenuItem.
 */
struct MyMenuItem *ReadItem( BPTR file )
{
    register struct MyMenuItem  *item;

    if(NOT(item = (struct MyMenuItem *)Alloc(&Memory,(long)sizeof(struct MyMenuItem))))
        goto noMem;
    Read(file,(char *)item,(long)sizeof(struct MyMenuItem));
    if(TestBits((ULONG)item->Flags,ITEMTEXT)) {
        if(NOT(item->ItemFill = (APTR)ReadIText(file)))
            goto noMem;
    }
    if(NOT CheckErr())
        return(NULL);
    return(item);

noMem:
    enable_window();
    ok();
    Error("Out of memory !");
    return(NULL);
}

/*
 * Read the menus.
 */
long ReadMenus( BPTR file )
{
    register struct MyMenu      *menu, *menu1;
    register struct MyMenuItem  *item, *item1, *sub, *sub1;
    BOOL                         gotstrip = FALSE, gotitem = FALSE, gotsub = FALSE;
    ULONG                        menus;

    Read(file,(char *)&menus,4L);

    if(menus) {
        while(1) {
            if(NOT(menu = (struct MyMenu *)Alloc(&Memory,(long)sizeof(struct MyMenu))))
                goto noMem;
            Read(file,(char *)menu,(long)sizeof(struct MyMenu));
            menu->MenuName = &menu->TheMenuName[0];
            if(NOT(menu->ItsListItem = CreateListItem(menu,MENUED,FALSE,NULL,FALSE)))
                goto noMem;
            ParentMenu = menu;
            MenuTotal++;
            MenuCount++;
            if(NOT gotstrip) {
                MenuStrip = menu;
                gotstrip  = TRUE;
            } else
                menu1->NextMenu = menu;

            if(menu->FirstItem) {
                while(1) {
                    if(NOT(item = ReadItem(file)))
                        return(FALSE);
                    if(NOT(item->ItsListItem = CreateListItem(item,ITEMED,FALSE,NULL,FALSE)))
                        goto noMem;
                    ParentItem = item;
                    ItemTotal++;
                    ItemCount++;
                    if(NOT gotitem) {
                        menu->FirstItem = item;
                        gotitem         = TRUE;
                    } else
                        item1->NextItem = item;

                    if(item->SubItem) {
                        while(1) {
                            if(NOT(sub = ReadItem(file)))
                                return(FALSE);
                            if(NOT(sub->ItsListItem = CreateListItem(sub,SUBED,FALSE,NULL,FALSE)))
                                goto noMem;
                            SubTotal++;
                            SubCount++;
                            if(NOT gotsub) {
                                item->SubItem  = sub;
                                gotsub         = TRUE;
                            } else
                                sub1->NextItem = sub;

                            if(NOT sub->NextItem) {
                                gotsub   = FALSE;
                                SubsList = NULL;
                                break;
                            }
                            sub1 = sub;
                        }
                    }
                    if(NOT item->NextItem) {
                        gotitem   = FALSE;
                        ItemsList = NULL;
                        break;
                    }
                    item1 = item;
                }
            } else
                menu->FirstItem = &dummy;

            if(NOT menu->NextMenu) break;
            menu1 = menu;
        }
        if(NOT CheckErr())
            return(FALSE);
    }
    ReformatList(MENUED);
    ReformatList(ITEMED);
    ReformatList(SUBED);
    return(TRUE);

noMem:
    enable_window();
    ok();
    Error("Out of memory !");
    return(FALSE);
}

/*
 * Read the binary file.
 */
void ReadBinGadgets( long fsu )
{
    register struct MyGadget    *g;
    struct ViewPort             *vp;
    struct BinHeader             head;
    BPTR                         file;
    ULONG                        rc;
    UWORD                        i;

    if(NOT fsu) {
        if(Saved == FALSE) {
            if(Ask("Current work isn't saved !","Load a file anyway ?") == FALSE)
                return;
        }
        strcpy((char *)IODir->fr_HeadLine,"Load Binary");

        IODir->fr_Screen = MainScreen;
        IODir->fr_Caller = MainWindow;

        IODir->fr_Flags |= FR_NoInfo;

        rc = FileRequest(IODir);

        if(rc == FREQ_CANCELED)
            return;
        else if(rc) {
            Error("FileRequester won't open !");
            return;
        }

        strcpy((char *)&name[0],(char *)IODir->fr_DirName);
        strcat((char *)&name[0],(char *)IODir->fr_FileName);
    }

    if(NOT(file = Open((char *)&name[0],MODE_OLDFILE))) {
        CheckName();
        if(NOT(file = Open((char *)&name[0],MODE_OLDFILE))) {
            if(fsu) {
                WBSCREEN = TRUE;
                change_depth(2);
            }
            Error("Can't open read file !");
            return;
        }
    }

    /* read the file header */
    Read(file,(char *)&head,(long)sizeof(struct BinHeader));

    if(head.FileType == TYPE AND head.Version > GE_VERSION) {
        if(fsu) {
            WBSCREEN = TRUE;
            change_depth(2);
        }
        Close(file);
        Error("Unknown PowerSource Binary !");
        return;
    }

    if(head.FileType != TYPE) {
        if(fsu) {
            WBSCREEN = TRUE;
            change_depth(2);
        }
        Close(file);
        Error("Not a PowerSource Binary !");
        return;
    }

    FreeGList();
    free_all();
    FreeMenuStrip();

    GadgetCount = id = 0;

    if(TestBits(head.FlagsBits,BH_REQUESTER))
        REQUESTER = TRUE;
    else
        REQUESTER = FALSE;
    if(TestBits(head.FlagsBits,BH_WORKBENCH))
        WBSCREEN  = TRUE;
    else
        WBSCREEN  = FALSE;

    DEPTH           =   head.ScrDepth;
    FrontPen        =   head.FPen;
    BackPen         =   head.BPen;
    BackFill        =   head.BackFill;
    WDBackFill      =   head.WDBackFill;
    LightSide       =   head.LightSide;
    DarkSide        =   head.DarkSide;

    /* read the preferences */
    Read(file,(char *)&prefs,(long)sizeof(struct ge_prefs));

    /* read the window specifics */
    Read(file,(char *)&nw_main,(long)sizeof(struct NewWindow));

    WindowFlags = nw_main.Flags;
    IDCMPFlags  = nw_main.IDCMPFlags;

    if(REQUESTER)
        nw_main.Flags   = FLAGS_RQ;
    else {
        nw_main.Flags = NULL;
        if(TestBits(WindowFlags,WINDOWCLOSE))   nw_main.Flags |= WINDOWCLOSE;
        if(TestBits(WindowFlags,WINDOWDEPTH))   nw_main.Flags |= WINDOWDEPTH;
        if(TestBits(WindowFlags,WINDOWDRAG))    nw_main.Flags |= WINDOWDRAG;
        if(TestBits(WindowFlags,WINDOWSIZING))  nw_main.Flags |= WINDOWSIZING;
        if(TestBits(WindowFlags,SIZEBRIGHT))    nw_main.Flags |= SIZEBRIGHT;
        if(TestBits(WindowFlags,SIZEBBOTTOM))   nw_main.Flags |= SIZEBBOTTOM;
        nw_main.Flags |= SMART_REFRESH|NOCAREREFRESH|ACTIVATE;
    }
    nw_main.IDCMPFlags = IDCMP_NM;

    /* read title + label */
    Read(file,(char *)&wdt[0],80L);
    Read(file,(char *)&wlb[0],MAXLABEL);

    /* open main screen and window */
    change_depth(DEPTH);
    disable_window();
    buisy();
    SetWindowTitles(MainWindow,(char *)-1L,"Reading Binary......");

    vp = &MainScreen->ViewPort;
    if(NOT WBSCREEN) LoadRGB4(vp,(void *)&head.Colors[0],(long)(1 << DEPTH));
    else             LoadRGB4(vp,(void *)&WBColors[0],4L);

    if(NOT CheckErr())
        goto readError;

    /* read the source labels */
    if(NOT ReadLabels(file))
        goto readError;

    /* read the gadget borders */
    if(NOT ReadSBord(file))
        goto readError;

    /* read the image bank */
    if(NOT ReadBank(file))
        goto readError;

    /* read the window/requester texts */
    if(NOT ReadWRTexts(file))
        goto readError;

    /* read the gadgets */
    Read(file,(char *)&rc,4L);
    GadgetCount = rc;

    if(GadgetCount) {
        for(i = 0; i < GadgetCount; i++) {
            if(NOT ReadGadget(file))
                goto readError;
        }
    }

    /* read the menus */
    if(NOT ReadMenus(file))
        goto readError;

    if(NOT CheckErr())
        goto readError;

    Close(file);
    add_no();
    bo_added = FALSE;
    add_bo();
    bo_added = TRUE;
    Saved = TRUE;
    renumber();
    enable_window();
    ok();
    refresh();
    return;

readError:
    Close(file);
    FreeGList();
    free_all();
    FreeMenuStrip();
    refresh();
}
