/*
**
**  NewReadArgs() - 
**  a shell/workbench transparent ReadArgs() interface
**
**  © 1997-98 by Stephan Rupprecht
**  All rights reserved.
**
**  email: stephan.rupprecht@primus-online.de
**
**  FREEWARE - I am not responsible for any damage that
**  is caused by the (mis)use of this program.
**
**  MaxonC++, OS2.04+
**
*/

/*
** Slightly modified by Matteo Cortese
** to compile with Dice
*/

/*- INCLUDES & DEFINES -*/
#include <dos/dos.h>
#include <exec/memory.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include <string.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/icon_protos.h>
#include <clib/utility_protos.h>

#ifdef DEBUG
#define bug     kprintf
#define d(x)        (x)
#else
#define bug
#define d(x)        ;
#endif


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

/*- NEWRDARGS STRUCTURE -*/
struct NewRDArgs {
// initialize these fields before calling NewReadArgs() !!!
    STRPTR        Template;  // ReadArgs() template
    STRPTR        ExtHelp;   // ExtHelp string
    STRPTR        Window;    // workbench window -> eg. "CON:////Test"
    LONG         *Parameters;    // where to store the data
    LONG          FileParameter; // -1 = none, 0 = all
    LONG          PrgToolTypesOnly;

// private data section
    struct RDArgs    *RDArgs;   // RDArgs we give to ReadArgs()
        struct RDArgs    *FreeArgs; // RDArgs we get from ReadArgs()

    APTR            Pool;

    BPTR          WinFH;        // i/o window stream
    BPTR          OldInput; // old i/o streams
    BPTR          OldOutput;
};

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

const STRPTR NRDArgsID = "NewReadArgs 39.3 © 1997-1998 by Stephan Rupprecht";

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

void NewFreeArgs(struct NewRDArgs *);
LONG NewReadArgs(struct WBStartup *, struct NewRDArgs *);

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

void NewFreeArgs(struct NewRDArgs *rdargs)
{
    d(bug("--- NewFreeArgs ---\n"));
    FreeArgs(rdargs->FreeArgs);
    d(bug("FreeArgs( rdargs->FreeArgs )\n"));
    if(rdargs->RDArgs) 
        FreeDosObject(DOS_RDARGS, rdargs->RDArgs);
    d(bug("FreeDosObject( DOS_RDARGS, rdargs->RDArgs )\n"));
    if(rdargs->WinFH) 
    {
        SelectOutput(rdargs->OldOutput);
        Close(SelectInput(rdargs->OldInput));
        d(bug("SelectOutput( .. )\nClose( ... )\n"));
    }
    
    if(rdargs->Pool)
        DeletePool(rdargs->Pool);

    d(bug("memory freed\n"));
    d(bug("--- EXIT ---\n"));
}

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

LONG IsArg(STRPTR template, STRPTR keyword)
{
    UBYTE           buffer[128], c;
    register STRPTR     ptr = buffer;
    
    while((c = *keyword++) && (c != '=')) *ptr++ = c;
    
    *ptr = 0;
    
    /*- checks if keyword is specified in template -*/
    return(FindArg(template, buffer));
}

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

LONG NewReadArgs(struct WBStartup *WBStartup, struct NewRDArgs *nrdargs)
{   
    d(bug("--- NewReadArgs ---\n"));
    
    nrdargs->RDArgs     = 
    nrdargs->FreeArgs   = NULL;
    nrdargs->WinFH      = NULL;
    nrdargs->Pool       = NULL;
    
    if(nrdargs->RDArgs = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL))
    {
        STRPTR  ToolWindow = nrdargs->Window;
        
        if(WBStartup) 
        {
            APTR            pool;
            struct WBArg    *wbarg;
            STRPTR          *Args, ptr;
            LONG            MaxArgs = 1, *ArgLen, num = WBStartup->sm_NumArgs,
                            FileArgs = nrdargs->FileParameter, FArgNum = -1L;

            if(!(ptr = nrdargs->Template))
                return(ERROR_BAD_TEMPLATE);
            
            /*- count max number of args -*/
            while(*ptr)
            {
                if(*ptr++ == ',') 
                    MaxArgs++;
            }
            
            ptr = nrdargs->Template;
            
            /*- how many file args? -*/
            FileArgs = (FileArgs > num) ? num : ((FileArgs == -1) ? 0L : num);          
            MaxArgs += FileArgs;
            
            if(!(pool = nrdargs->Pool = CreatePool(MEMF_ANY, 1024, 1024)) || !(Args = AllocPooled(pool, MaxArgs*sizeof(STRPTR)*2)))
                return(ERROR_NO_FREE_STORE);
                
            for(num = 0L; num < (MaxArgs*2); num++)
                Args[num] = 0L;
                
            ArgLen = (LONG *)&Args[MaxArgs];
    
            for(    wbarg = WBStartup->sm_ArgList, num = 0L;
                    num < WBStartup->sm_NumArgs; 
                    num++, wbarg++  )
            {
                struct DiskObject   *dobj;
                BPTR            olddir;
                
                /*- get file-names if requested -*/
                if(FileArgs)
                {
                    TEXT    buf[300];
                    
                    if(FArgNum < FileArgs && FArgNum >= 0L)
                    {
                        d(bug("ICON: %s\n", wbarg->wa_Name));
                        
                        if( NameFromLock(wbarg->wa_Lock, buf, sizeof(buf)) &&
                            AddPart(buf, wbarg->wa_Name, sizeof(buf))   )
                        {
                            STRPTR  dst;
                            LONG    len = strlen(buf) + 2L;
                            if(Args[FArgNum] = dst = AllocPooled(pool, len))
                            {
                                CopyMem(buf, (dst+1), len-2L);
                                *dst = dst[len-1] = '"';
                                
                                ArgLen[FArgNum] = len;
                            }
                            else return(ERROR_NO_FREE_STORE);
                        }
                        else return(ERROR_LINE_TOO_LONG);
                    }
                    
                    FArgNum++;
                }
                                    
                if(nrdargs->PrgToolTypesOnly && num)
                    continue;
                
                olddir = CurrentDir(wbarg->wa_Lock);
                
                /*- get tooltypes from .info file -*/
                if(dobj = GetDiskObject(wbarg->wa_Name))
                {
                    if(dobj->do_Type == WBTOOL || dobj->do_Type == WBPROJECT)
                    {
                        STRPTR  *tarray = (STRPTR *)dobj->do_ToolTypes;
                        
                        while(*tarray)
                        {
                            if(**tarray != '(')
                            {
                                STRPTR  src = *tarray;
                                LONG    i;
                                
                                d(bug("tt: %s\n", *tarray));
                                                                
                                /*- valid arg ? -*/
                                if((i = IsArg(ptr, src)) > -1)
                                {           
                                    STRPTR  dst;
                                    LONG    len;
                                    
                                    i += FileArgs;
                                    if(Args[i] = dst = AllocPooled(pool, (len = strlen(src))+2L))
                                    {
                                        /*- copy arg -*/
                                        while(*src)
                                        {
                                            if(((*dst++ = *src++) == '=') && (*src != '"'))
                                            {
                                                *dst++ = Args[i][len+1] = '"';
                                                len+=2;
                                            }
                                        }
                                                                            
                                        ArgLen[i] = len;
                                    }
                                    else return(ERROR_NO_FREE_STORE);
                                }
                                /*- arg not specified in template, check for WINDOW tooltype -*/
                                else if(!IsArg("WINDOW", src))
                                {                                                                   
                                    if((i = strlen(src)-6L) > 1L)
                                    {
                                        if(ToolWindow = AllocPooled(pool, i))
                                            CopyMem((src+7L), ToolWindow, i);
                                    }
                                    else ToolWindow = "CON:";
                                }
                            }

                            tarray++;
                        }
                    }
                    
                    FreeDiskObject(dobj);
                }
                
                CurrentDir(olddir);
            }
            
            /*- now copy all given args to a single line -*/
            for(num = FileArgs = 0; FileArgs < MaxArgs; FileArgs++)
                num += ArgLen[FileArgs];
                                
            if(num)
            {
                nrdargs->RDArgs->RDA_Source.CS_Length = (num+=MaxArgs);

                if(nrdargs->RDArgs->RDA_Source.CS_Buffer = ptr = AllocPooled(pool, num+1))
                {    
                    for(FileArgs = 0; FileArgs < MaxArgs; FileArgs++)
                    {
                        if(num = ArgLen[FileArgs])
                        {
                            CopyMem(Args[FileArgs], ptr, num);
                            ptr += num;
                            *ptr++ = ' ';
                        }
                    }
                }
                else return(ERROR_NO_FREE_STORE);
                
                *(ptr-1) = '\n';
                *ptr = '\0'; // not really needed
                
                d(bug("CS_Buffer: %s", nrdargs->RDArgs->RDA_Source.CS_Buffer));
            }           
        }
        
        /*- call ReadArgs() -*/
        nrdargs->RDArgs->RDA_ExtHelp = nrdargs->ExtHelp;
        if(!(nrdargs->FreeArgs = ReadArgs(nrdargs->Template, nrdargs->Parameters, nrdargs->RDArgs)))
        {
            d(bug("ReadArgs() error\n"));
            return(IoErr());
        }
        
        d(bug("ReadArgs() okay\n"));
        
        /*- when started from wb, open window if requested -*/
        if(ToolWindow && WBStartup)
        {
            d(bug("WINDOW has been defined\n"));
            if(nrdargs->WinFH = Open(ToolWindow, MODE_READWRITE))
            {
                d(bug("Opened WINDOW=%s\n", ToolWindow));
                nrdargs->OldInput = SelectInput(nrdargs->WinFH);
                nrdargs->OldOutput = SelectOutput(nrdargs->WinFH);
            }
            else return(IoErr());
        }
    }
    else return(ERROR_NO_FREE_STORE);
    
    d(bug("--- EXIT ---\n"));
                
    return(RETURN_OK);
}

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

