;/*
sc nminc mccons streq nowvret strmerge nostkchk opttime params=r data=faronly modified ignore=73 opttime IconSort.c
slink IconSort.o to IconSort lib lib:scnb.lib lib:amiga.lib lib:debug.lib sc sd nd
protect IconSort +p
quit
*/

/*
**  IconSort © Copyright 1995 by Olaf Barthel
**      All Rights Reserved
*/

#include <intuition/intuition.h>
#include <intuition/classusr.h>
#include <intuition/imageclass.h>

#include <workbench/workbench.h>

#include <libraries/iffparse.h>

#include <dos/dosextens.h>

#include <exec/memory.h>

#include <prefs/prefhdr.h>
#include <prefs/font.h>

#include <clib/intuition_protos.h>
#include <clib/iffparse_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/icon_protos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>

#include <pragmas/dos_pragmas.h>
#include <pragmas/exec_sysbase_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/icon_pragmas.h>
#include <pragmas/diskfont_pragmas.h>
#include <pragmas/iffparse_pragmas.h>

#include <string.h>
#include <math.h>

void kprintf(const char *,...);

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

/* definitions for dd_ViewModes */
#define DDVM_BYDEFAULT		0	/* default (inherit parent's view mode) */
#define DDVM_BYICON		1	/* view as icons */
#define DDVM_BYNAME		2	/* view as text, sorted by name */
#define DDVM_BYDATE		3	/* view as text, sorted by date */
#define DDVM_BYSIZE		4	/* view as text, sorted by size */
#define DDVM_BYTYPE		5	/* view as text, sorted by type */

/* definitions for dd_Flags */
#define	DDFLAGS_SHOWDEFAULT	0	/* default (show only icons) */
#define	DDFLAGS_SHOWICONS	1	/* show only icons */
#define	DDFLAGS_SHOWALL		2	/* show all files */

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

#define SAME (0)

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

#define MAX_WIDTH	700
#define MAX_HEIGHT	400

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

struct cmd_Context
{
    struct ExecBase *cc_SysBase;
    struct Library  *cc_DOSBase;
    struct Library  *cc_IconBase;
    struct Library  *cc_IntuitionBase;
    struct Library  *cc_GfxBase;
    struct Library  *cc_UtilityBase;
};

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

struct IconNode
{
    struct Node		Node;
    struct DiskObject *	Icon;
    struct IBox		Bounds;
};

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

LONG
Main(VOID)
{
    struct ExecBase *SysBase;
    struct cmd_Context *Context;
    struct Process *Me;
    LONG Result;

    SysBase = *(struct ExecBase **)4;

    Me = (struct Process *)FindTask(NULL);

    Result = RETURN_FAIL;

    if(Me->pr_CLI)
    {
        if(Context = (struct cmd_Context *)AllocMem(sizeof(*Context),MEMF_ANY | MEMF_CLEAR))
        {
            #define DOSBase Context->cc_DOSBase
            #define IconBase Context->cc_IconBase
            #define IntuitionBase Context->cc_IntuitionBase
            #define GfxBase Context->cc_GfxBase
            #define UtilityBase Context->cc_UtilityBase

            Context->cc_SysBase = SysBase;

            if(DOSBase = OpenLibrary("dos.library",37))
            {
                STRPTR Message;
                LONG Error;

                if(UtilityBase = OpenLibrary("utility.library",37))
                {
                    if(IconBase = OpenLibrary("icon.library",37))
                    {
                        if(IntuitionBase = OpenLibrary("intuition.library",37))
                        {
                            if(GfxBase = OpenLibrary("graphics.library",37))
                            {
                                enum { ARG_Indent, ARG_Drawer, ARGCOUNT };
                                struct RDArgs *Args;
                                STRPTR Params[ARGCOUNT];
                                STRPTR *DrawerName;
                                BOOL Indent;

                                Message = NULL;
                                memset(Params,0,sizeof(Params));

                                if(Args = ReadArgs("INDENT/S,DRAWER/A/M" "\0$VER: IconSort 40.3 " __AMIGADATE__ "\r\n",(LONG *)Params,NULL))
                                {
                                    LONG IconSort(struct cmd_Context *Context,STRPTR DrawerName,BOOL Indent);

                                    DrawerName = (STRPTR *)Params[ARG_Drawer];
                                    Indent = (BOOL)(Params[ARG_Indent] != DOSFALSE);

                                    while(*DrawerName)
                                    {
                                        if(Error = IconSort(Context,*DrawerName++,Indent))
                                            break;
                                    }

                                    FreeArgs(Args);
                                }
                                else
                                    Error = IoErr();

                                CloseLibrary(GfxBase);
                            }
                            else
                                Message = "IconSort: Unable to open graphics.library v37\n";

                            CloseLibrary(IntuitionBase);
                        }
                        else
                            Message = "IconSort: Unable to open intuition.library v37\n";

                        CloseLibrary(IconBase);
                    }
                    else
                        Message = "IconSort: Unable to open icon.library v37\n";
                }
                else
                    Message = "IconSort: Unable to open utility.library v37\n";

                if(Message)
                    FPuts(Me->pr_COS,Message);
                else
                {
                    if(Error)
                    {
                        PrintFault(Error,"IconSort");
                        Result = RETURN_ERROR;
                    }
                    else
                        Result = RETURN_OK;
                }

                CloseLibrary(DOSBase);
            }
            else
                Me->pr_Result2 = ERROR_INVALID_RESIDENT_LIBRARY;

            FreeMem(Context,sizeof(*Context));
        }
        else
            Me->pr_Result2 = ERROR_NO_FREE_STORE;
    }
    else
    {
        struct MsgPort *Port;
        struct Message *Message;

        Port = &Me->pr_MsgPort;

        WaitPort(Port);
        Message = GetMsg(Port);

        Forbid();
        ReplyMsg(Message);
    }

    return(Result);
}

#define SysBase Context->cc_SysBase

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

VOID
ReadFontPrefs(struct cmd_Context *Context,struct FontPrefs *FontPrefs,LONG Which)
{
    struct Library *IFFParseBase;
    struct IFFHandle *Handle;

    memset(FontPrefs,0,sizeof(*FontPrefs));

    FontPrefs->fp_Type              = Which;
    FontPrefs->fp_FrontPen          = 1;
    FontPrefs->fp_BackPen           = 0;
    FontPrefs->fp_DrawMode          = JAM1;
    FontPrefs->fp_TextAttr.ta_Name  = FontPrefs->fp_Name;
    FontPrefs->fp_TextAttr.ta_YSize = 8;
    FontPrefs->fp_TextAttr.ta_Style = FS_NORMAL;
    FontPrefs->fp_TextAttr.ta_Flags = FPF_ROMFONT | FPF_DESIGNED;

    strcpy(FontPrefs->fp_Name,"topaz.font");

    if(IFFParseBase = OpenLibrary("iffparse.library",37))
    {
        if(Handle = AllocIFF())
        {
            if(Handle -> iff_Stream = (ULONG)Open("ENV:sys/font.prefs",MODE_OLDFILE))
            {
                InitIFFasDOS(Handle);

                if(!OpenIFF(Handle,IFFF_READ))
                {
                    STATIC LONG Stops[] =
                    {
                        ID_PREF,ID_PRHD,
                        ID_PREF,ID_FONT
                    };

                    if(!StopChunks(Handle,Stops,2))
                    {
                        struct ContextNode  *Chunk;
                        struct FontPrefs     Prefs;

                        while(!ParseIFF(Handle,IFFPARSE_SCAN))
                        {
                            Chunk = CurrentChunk(Handle);

                            switch(Chunk -> cn_ID)
                            {
                                case ID_PRHD:

                                    break;

                                case ID_FONT:

                                    if(ReadChunkBytes(Handle,&Prefs,sizeof(Prefs)) == sizeof(Prefs))
                                    {
                                        if(Prefs.fp_Type == Which)
                                        {
                                            CopyMem(&Prefs,FontPrefs,sizeof(Prefs));

                                            FontPrefs->fp_TextAttr.ta_Name = FontPrefs->fp_Name;
                                        }
                                    }

                                    break;
                            }
                        }
                    }

                    CloseIFF(Handle);
                }

                Close(Handle->iff_Stream);
            }

            FreeIFF(Handle);
        }

        CloseLibrary(IFFParseBase);
    }
}

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

VOID
CalculateHull(struct List *List,struct IBox *Hull)
{
    struct IconNode *Node;

    memset(Hull,0,sizeof(*Hull));

    for(Node = (struct IconNode *)List->lh_Head ; Node->Node.ln_Succ ; Node = (struct IconNode *)Node->Node.ln_Succ)
    {
        if(Hull->Left > Node->Icon->do_CurrentX)
            Hull->Left = Node->Icon->do_CurrentX;

        if(Hull->Top > Node->Icon->do_CurrentY)
            Hull->Top = Node->Icon->do_CurrentY;

        if(Hull->Width < Node->Icon->do_CurrentX + Node->Icon->do_Gadget.Width/2 + Node->Bounds.Width/2)
            Hull->Width = Node->Icon->do_CurrentX + Node->Icon->do_Gadget.Width/2 + Node->Bounds.Width/2;

        if(Hull->Height < Node->Icon->do_CurrentY + Node->Bounds.Height)
            Hull->Height = Node->Icon->do_CurrentY + Node->Bounds.Height;
    }
}

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

struct TextFont *
OpenThatFont(struct cmd_Context *Context,struct TextAttr *This)
{
    struct Library *DiskfontBase;
    struct TextFont *Font;

    if(DiskfontBase = OpenLibrary("diskfont.library",36))
    {
        Font = OpenDiskFont(This);

        CloseLibrary(DiskfontBase);
    }
    else
        Font = OpenFont(This);

    return(Font);
}

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

BOOL
CalculateBounds(struct cmd_Context *Context,struct List *List,struct IBox *MaxBounds,struct RastPort *RPort)
{
    struct FontPrefs FontPrefs;
    struct TextFont *Font;
    BOOL Result;

    Result = FALSE;

    memset(MaxBounds,0,sizeof(*MaxBounds));

    ReadFontPrefs(Context,&FontPrefs,FP_WBFONT);

    if(Font = OpenThatFont(Context,&FontPrefs.fp_TextAttr))
    {
        struct IconNode *Node;
        struct IBox Bounds;
        UWORD Width;

        Bounds.Left = Bounds.Top = 0;

        InitRastPort(RPort);
        SetFont(RPort,Font);

        for(Node = (struct IconNode *)List->lh_Head ; Node->Node.ln_Succ ; Node = (struct IconNode *)Node->Node.ln_Succ)
        {
            Bounds.Width    = 4 + Node->Icon->do_Gadget.Width + 4;
            Bounds.Height   = 3 + Node->Icon->do_Gadget.Height + 3 + 1 + RPort->TxHeight;   /* +3 */

            Width = TextLength(RPort,Node->Node.ln_Name,strlen(Node->Node.ln_Name));

            if(Width > Bounds.Width)
                Bounds.Width = Width;   /* +7 */

            Node->Bounds = Bounds;

            if(Node->Icon->do_Type != WBGARBAGE)
            {
                if(MaxBounds->Width < Bounds.Width)
                    MaxBounds->Width = Bounds.Width;

                if(MaxBounds->Height < Bounds.Height)
                    MaxBounds->Height = Bounds.Height;
            }
        }

        Result = TRUE;

        CloseFont(Font);
    }

    return(Result);
}

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

VOID
InsertSorted(struct cmd_Context *Context,struct List *List,struct Node *Node,BYTE Type)
{
    struct Node *Other,*Last;

    Node->ln_Type = Type;

    for(Other = List->lh_Head, Last = NULL ; Other->ln_Succ ; Last = Other, Other = Other->ln_Succ)
    {
        if(Other->ln_Type > Node->ln_Type || (Stricmp(Other->ln_Name,Node->ln_Name) > 0 && Other->ln_Type == Node->ln_Type))
        {
            Insert(List,Node,Last);
            return;
        }
    }

    AddTail(List,Node);
}

VOID
DeleteIconNode(struct cmd_Context *Context,struct IconNode *Node)
{
    if(Node)
    {
        if(Node->Icon)
            FreeDiskObject(Node->Icon);

        FreeVec(Node);
    }
}

struct IconNode *
CreateIconNode(struct cmd_Context *Context,STRPTR Name)
{
    struct IconNode *Node;

    if(Node = (struct IconNode *)AllocVec(sizeof(struct IconNode) + strlen(Name) + 1,MEMF_ANY))
    {
        strcpy(Node->Node.ln_Name = (char *)(Node + 1),Name);

        if(Node->Icon = GetDiskObject(Name))
            return(Node);

        FreeVec(Node);
    }

    return(NULL);
}

VOID
DeleteList(struct cmd_Context *Context,struct List *List)
{
    if(List)
    {
        struct IconNode *Node,*Next;

        for(Node = (struct IconNode *)List->lh_Head ; Next = (struct IconNode *)Node->Node.ln_Succ ; Node = Next)
            DeleteIconNode(Context,Node);

        FreeVec(List);
    }
}

struct List *
CreateList(struct cmd_Context *Context)
{
    struct List *List;

    if(List = (struct List *)AllocVec(sizeof(struct MinList),MEMF_ANY))
        NewList(List);

    return(List);
}

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

VOID
Optimize(struct cmd_Context *Context,struct List *List)
{
    struct IconNode *Node;
    ULONG **Room;
    LONG Columns,Rows;
    LONG LastY,x,y;

    LastY = -1;
    Columns = Rows = 0;
    x = 0;

    for(Node = (struct IconNode *)List->lh_Head ; Node->Node.ln_Succ ; Node = (struct IconNode *)Node->Node.ln_Succ)
    {
        if(Node->Icon->do_CurrentY + Node->Bounds.Height != LastY)
        {
            if(x > Columns)
                Columns = x;

            LastY = Node->Icon->do_CurrentY + Node->Bounds.Height;
            x = 0;

            Rows++;
        }
        else
            x++;
    }

    Columns++;
    Rows++;

    if(Room = (ULONG **)AllocVec(sizeof(ULONG **) * Rows + sizeof(ULONG) * Rows * Columns,MEMF_ANY|MEMF_CLEAR))
    {
        struct IconNode ***Matrix;
        ULONG *OneRow;
        LONG i,j,MaxSize,Stop;

        OneRow = (ULONG *)(((ULONG)Room) + sizeof(ULONG **) * Rows);

        for(i = 0 ; i < Rows ; i++)
        {
            Room[i] = OneRow;
            OneRow += Columns;
        }

        Matrix = (struct IconNode ***)Room;

        LastY = -1;
        x = y = 0;

        for(Node = (struct IconNode *)List->lh_Head ; Node->Node.ln_Succ ; Node = (struct IconNode *)Node->Node.ln_Succ)
        {
            if(Node->Icon->do_CurrentY + Node->Bounds.Height != LastY)
            {
                if(LastY != -1)
                {
                    y++;
                    x = 0;
                }

                LastY = Node->Icon->do_CurrentY + Node->Bounds.Height;
            }

            Matrix[y][x] = Node;

            x++;
        }

        Stop = 0;

        for(i = 0 ; i < Rows ; i++)
        {
            MaxSize = 0;

            for(j = 0 ; j < Columns ; j++)
            {
                if(Matrix[i][j])
                {
                    if(Matrix[i][j]->Bounds.Height > MaxSize)
                        MaxSize = Matrix[i][j]->Bounds.Height;
                }
            }

            for(j = 0 ; j < Columns ; j++)
            {
                if(Matrix[i][j])
                    Matrix[i][j]->Bounds.Top = Stop + MaxSize - Matrix[i][j]->Bounds.Height;
            }

            Stop += 4 + MaxSize + 4;
        }

        Stop = 0;

        for(i = 0 ; i < Columns ; i++)
        {
            MaxSize = 0;

            for(j = 0 ; j < Rows ; j++)
            {
                if(Matrix[j][i])
                {
                    if(Matrix[j][i]->Bounds.Width > MaxSize)
                        MaxSize = Matrix[j][i]->Bounds.Width;
                }
            }

            for(j = 0 ; j < Rows ; j++)
            {
                if(Matrix[j][i])
                    Matrix[j][i]->Bounds.Left = Stop + (MaxSize - Matrix[j][i]->Icon->do_Gadget.Width) / 2;
            }

            Stop += 8 + MaxSize + 8;
        }

        for(Node = (struct IconNode *)List->lh_Head ; Node->Node.ln_Succ ; Node = (struct IconNode *)Node->Node.ln_Succ)
        {
            Node->Icon->do_CurrentX = Node->Bounds.Left;
            Node->Icon->do_CurrentY = Node->Bounds.Top;
        }

        FreeVec(Room);
    }
}

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

LONG
IconSort(struct cmd_Context *Context,STRPTR DrawerName,BOOL Indent)
{
    BPTR FileLock;
    LONG Error;

    if(FileLock = Lock(DrawerName,SHARED_LOCK))
    {
        struct FileInfoBlock __aligned FileInfo;
        BPTR OldDir;

        OldDir = CurrentDir(FileLock);

        if(Examine(FileLock,&FileInfo))
        {
            struct List *List;

            if(List = CreateList(Context))
            {
                struct RastPort __aligned RastPort;
                struct IconNode *Node;
                struct IBox MaxBounds;
                LONG NumIcons;
                LONG NumOthers;
                LONG MaxNameLen;
                LONG Len;

				MaxNameLen = 0;
                NumIcons = NumOthers = 0;

                while(ExNext(FileLock,&FileInfo))
                {
                    Len = strlen(FileInfo.fib_FileName);

                    if(Len > 5 && !Stricmp(&FileInfo.fib_FileName[Len - 5],".info"))
                    {
                    	if(Stricmp(FileInfo.fib_FileName,"Disk.info") != SAME)
                    	{
	                        FileInfo.fib_FileName[Len - 5] = 0;

	                        if(Node = CreateIconNode(Context,FileInfo.fib_FileName))
	                        {
	                            InsertSorted(Context,List,(struct Node *)Node,WBAPPICON - Node->Icon->do_Type);
	                            NumIcons++;
	                        }
	                        else
	                            break;
						}
                    }
                    else
                    {
						if(Len > MaxNameLen)
							MaxNameLen = Len;

                    	NumOthers++;
                    }
                }

				MaxNameLen += 60; /* drawer protection bits date time */

                Error = IoErr();

                if(!Error || Error == ERROR_NO_MORE_ENTRIES)
                {
                    Error = 0;

                    if(CalculateBounds(Context,List,&MaxBounds,&RastPort))
                    {
                        LONG j,x,y,Range,DeltaX,DeltaY;
                        UBYTE FileName[256];
                        BPTR Parent;

                        Range = 1;

                        for(j = 1 ; j < NumIcons ; j++)
                        {
                            if(j * j >= NumIcons)
                            {
                                Range = j;
                                break;
                            }
                        }

                        DeltaX = 4  + MaxBounds.Width   + 4;
                        DeltaY = 2  + MaxBounds.Height  + 2;

                        if(Range < NumIcons / Range)
                            Range = NumIcons / Range;

Restart:
                        Node = (struct IconNode *)List->lh_Head;

                        for(y = 0 ; Node->Node.ln_Succ ; y++)
                        {
                            for(x = 0 ; x < Range ; x++)
                            {
                                Node->Icon->do_CurrentX = x * DeltaX + (MaxBounds.Width - Node->Icon->do_Gadget.Width) / 2;
                                Node->Icon->do_CurrentY = y * DeltaY + DeltaY - (Node->Bounds.Height + 2);

                                if(Node->Node.ln_Succ)
                                {
                                    Node = (struct IconNode *)Node->Node.ln_Succ;

                                    if(Node->Node.ln_Type != Node->Node.ln_Pred->ln_Type)
                                        break;
                                }
                                else
                                    break;
                            }
                        }

                        Optimize(Context,List);

                        Node = (struct IconNode *)List->lh_Head;

                        for(y = 0 ; Node->Node.ln_Succ ; y++)
                        {
                            for(x = 0 ; x < Range ; x++)
                            {
                            	if(Node->Icon->do_CurrentX+Node->Bounds.Width >= MAX_WIDTH)
                            	{
                            	    Range = x;
                            	    goto Restart;
                            	}

                                if(Node->Node.ln_Succ)
                                {
                                    Node = (struct IconNode *)Node->Node.ln_Succ;

                                    if(Node->Node.ln_Type != Node->Node.ln_Pred->ln_Type)
                                        break;
                                }
                                else
                                    break;
                            }
                        }

                        if(Parent = ParentDir(FileLock))
                        {
                            LONG Error;

                            if(NameFromLock(FileLock,FileName,256))
                                Error = 0;
                            else
                            {
                                Error = IoErr();
                                FileName[0] = 0;
                            }

                            UnLock(Parent);

                            SetIoErr(Error);
                        }
                        else
                            strcpy(FileName,"Disk");

                        if(FileName[0])
                        {
                            struct DiskObject *ParentDrawer;

                            if(ParentDrawer = GetDiskObjectNew(FileName))
                            {
                                if(ParentDrawer->do_DrawerData && (ParentDrawer->do_Type == WBDRAWER || ParentDrawer->do_Type == WBDISK))
                                {
                                    struct FontPrefs FontPrefs;
                                    struct TextFont *Font;
                                    struct IBox Hull;
                                    struct List *PubScreenList;
                                    ULONG TopBorder,LeftBorder,RightBorder,BottomBorder,RatioX,RatioY;

                                    TopBorder       = 2 + 1;    /* + fontHeight */
                                    LeftBorder      = 4;
                                    RightBorder     = 18;
                                    BottomBorder    = 10;
                                    RatioX          = 22;
                                    RatioY          = 22;

                                    if(PubScreenList = LockPubScreenList())
                                    {
                                        struct Node *Node;
                                        BOOL GotIt;

                                        GotIt = FALSE;

                                        for(Node = PubScreenList->lh_Head ; Node->ln_Succ ; Node = Node->ln_Succ)
                                        {
                                            if(!Stricmp(Node->ln_Name,"Workbench"))
                                            {
                                                GotIt = TRUE;
                                                Forbid();
                                                break;
                                            }
                                        }

                                        UnlockPubScreenList();

                                        if(GotIt)
                                        {
                                            struct Screen *Workbench;

                                            if(Workbench = LockPubScreen("Workbench"))
                                            {
                                                struct DrawInfo *DrawInfo;

                                                Permit();

                                                if(DrawInfo = GetScreenDrawInfo(Workbench))
                                                {
                                                    Object *SizeImage;
                                                    ULONG SizeType;

                                                    RatioX = DrawInfo->dri_Resolution.X;
                                                    RatioY = DrawInfo->dri_Resolution.Y;

                                                    if(Workbench->Flags & SCREENHIRES)
                                                        SizeType = SYSISIZE_MEDRES;
                                                    else
                                                        SizeType = SYSISIZE_LOWRES;

                                                    if(SizeImage = NewObject(NULL,SYSICLASS,
                                                        SYSIA_Size,     SizeType,
                                                        SYSIA_Which,    SIZEIMAGE,
                                                        SYSIA_DrawInfo, DrawInfo,
                                                    TAG_DONE))
                                                    {
                                                        GetAttr(IA_Width,   SizeImage,&RightBorder);
                                                        GetAttr(IA_Height,  SizeImage,&BottomBorder);

                                                        DisposeObject(SizeImage);
                                                    }

                                                    FreeScreenDrawInfo(Workbench,DrawInfo);
                                                }

                                                TopBorder = Workbench->WBorTop + 1;
                                                LeftBorder = Workbench->WBorLeft;

                                                UnlockPubScreen(NULL,Workbench);
                                            }
                                            else
                                                Permit();
                                        }
                                    }

                                    ReadFontPrefs(Context,&FontPrefs,FP_SCREENFONT);

                                    if(Font = OpenThatFont(Context,&FontPrefs.fp_TextAttr))
                                    {
                                        LONG ScaledTen;

                                        CalculateHull(List,&Hull);

                                        ScaledTen = (RatioX * 10) / RatioY;

										if(NumIcons > 0 || NumOthers == 0)
										{
                                        	ParentDrawer->do_DrawerData->dd_CurrentX = -Hull.Left;
                                        	ParentDrawer->do_DrawerData->dd_CurrentY = -(Hull.Top + ScaledTen);
                                        	ParentDrawer->do_DrawerData->dd_NewWindow.Width = LeftBorder + 10 + min(MAX_WIDTH,Hull.Width) + RightBorder;
                                        	ParentDrawer->do_DrawerData->dd_NewWindow.Height = TopBorder + Font->tf_YSize + ScaledTen + min(MAX_HEIGHT,Hull.Height) + ScaledTen + BottomBorder;
										}
										else
										{
                                        	ParentDrawer->do_DrawerData->dd_CurrentX = 0;
                                        	ParentDrawer->do_DrawerData->dd_CurrentY = -ScaledTen;
                                        	ParentDrawer->do_DrawerData->dd_NewWindow.Width = LeftBorder + 10 + min(MAX_WIDTH,MaxNameLen * Font->tf_XSize) + RightBorder;
                                        	ParentDrawer->do_DrawerData->dd_NewWindow.Height = TopBorder + Font->tf_YSize + ScaledTen + min(MAX_HEIGHT,NumOthers * (Font->tf_YSize+1)) + ScaledTen + BottomBorder;
										}

                                        if(ParentDrawer->do_Type != WBDISK)
                                        {
                                            UBYTE OtherName[256];
                                            BPTR This;

                                            OtherName[0] = 0;

                                            if(This = Lock(FileName,SHARED_LOCK))
                                            {
                                                BPTR Parent;

                                                if(Parent = ParentDir(This))
                                                {
                                                    if(!NameFromLock(Parent,OtherName,sizeof(OtherName)))
                                                        OtherName[0] = 0;

                                                    if(OtherName[0] && OtherName[strlen(OtherName) - 1] == ':')
                                                    {
                                                        if(!AddPart(OtherName,"Disk",sizeof(OtherName)))
                                                            OtherName[0] = 0;
                                                    }

                                                    UnLock(Parent);
                                                }
                                                else
                                                {
                                                    if(NameFromLock(This,OtherName,sizeof(OtherName)))
                                                    {
                                                        if(!AddPart(OtherName,"Disk",sizeof(OtherName)))
                                                            OtherName[0] = 0;
                                                    }
                                                    else
                                                        OtherName[0] = 0;
                                                }

                                                UnLock(This);
                                            }

                                            if(OtherName[0])
                                            {
                                                struct DiskObject *Icon;

                                                if(Icon = GetDiskObject(OtherName))
                                                {
                                                    if(Icon->do_DrawerData && (Icon->do_Type == WBDRAWER || Icon->do_Type == WBDISK))
                                                    {
                                                        if(Indent)
                                                        {
                                                            LONG ScaledTwenty;

                                                            ScaledTwenty = (RatioX * 20) / RatioY;

                                                            ParentDrawer->do_DrawerData->dd_NewWindow.LeftEdge = Icon->do_DrawerData->dd_NewWindow.LeftEdge + 20;
                                                            ParentDrawer->do_DrawerData->dd_NewWindow.TopEdge = Icon->do_DrawerData->dd_NewWindow.TopEdge + ScaledTwenty;
                                                        }
                                                        else
                                                        {
                                                            ParentDrawer->do_DrawerData->dd_NewWindow.LeftEdge = Icon->do_DrawerData->dd_NewWindow.LeftEdge;
                                                            ParentDrawer->do_DrawerData->dd_NewWindow.TopEdge = Icon->do_DrawerData->dd_NewWindow.TopEdge + TopBorder + Font->tf_YSize;
                                                        }
                                                    }

                                                    FreeDiskObject(Icon);
                                                }
                                            }
                                        }

                                        CloseFont(Font);

										if(NumIcons > 0 || NumOthers == 0)
										{
											ParentDrawer->do_DrawerData->dd_Flags		= DDFLAGS_SHOWDEFAULT;
											ParentDrawer->do_DrawerData->dd_ViewModes	= DDVM_BYDEFAULT;
										}
										else
										{
											ParentDrawer->do_DrawerData->dd_Flags		= DDFLAGS_SHOWALL;
											ParentDrawer->do_DrawerData->dd_ViewModes	= DDVM_BYNAME;
										}

                                        if(PutDiskObject(FileName,ParentDrawer))
                                        {
                                            for(Node = (struct IconNode *)List->lh_Head ; Node->Node.ln_Succ ; Node = (struct IconNode *)Node->Node.ln_Succ)
                                            {
                                                if(!PutDiskObject(Node->Node.ln_Name,Node->Icon))
                                                {
                                                    Error = IoErr();
                                                    break;
                                                }
                                            }
                                        }
                                        else
                                            Error = IoErr();
                                    }
                                    else
                                        Error = IoErr();
                                }

                                FreeDiskObject(ParentDrawer);
                            }
                            else
                                Error = IoErr();
                        }
                        else
                            Error = IoErr();
                    }
                    else
                        Error = IoErr();
                }

                DeleteList(Context,List);
            }
            else
                Error = IoErr();
        }
        else
            Error = IoErr();

        CurrentDir(OldDir);

        UnLock(FileLock);
    }
    else
        Error = IoErr();

    return(Error);
}
