/*
GetFile. Public Domain by Magnus Holmgren in 1992.

Compile with DICE:
dcc -pr -2.0 -ms -proto -mRR -o GetFile GetFile.c

Note that in order to compile with other compilers, changes are neccessary.
*/

#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <dos/rdargs.h>
#include <dos/dos.h>
#include <libraries/asl.h>
#include <clib/asl_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>

extern struct DOSBase *DOSBase;
extern struct AslBase *AslBase;
extern struct ExecBase *SysBase;

#define FILE    0
#define TITLE   1
#define VAR     2
#define PATTERN 3
#define GLOBAL  4
#define NOFILES 5
#define SAVE    6
#define MULTI   7

VOID quotename( STRPTR );

VOID quotename( STRPTR name )
{
  if( strchr( name, ' ' ) )
  {
    LONG i;

    for( i = strlen( name ); i >= 0; i-- )
      *( name + i + 1 ) = *( name + i );

    *name = '\"';
    strcat( name, "\"" );
  }
}

_main()
{
  struct RDArgs *rdargs;
  struct FileRequester *req = NULL;
  STRPTR title, var, pos, pattern = NULL, buf = NULL;
  LONG extflags = 0, funcflags = 0, len;

  static const TEXT VersTag[] = "$VER: GetFile 1.1 (19.03.92)";
  static const TEXT OS2Required_Msg[] = "You need OS 2.04+\n";
  static ULONG flags[ 8 ];
  static TEXT fullpath[ 512 ], dir[ 256 ];

  LONG ret = RETURN_FAIL;

  dir[ 0 ] = fullpath[ 0 ] = '\0';

  if( SysBase -> LibNode . lib_Version < 37 )
  {
      Write( ( BPTR ) Output(),
             OS2Required_Msg,
             sizeof( OS2Required_Msg ) - 1 );
      _exit( RETURN_FAIL );
  }

  flags[ TITLE ] = "Select a file";
  rdargs = ReadArgs( "FILE,TITLE,VAR,PATTERN,GLOBAL/S,NOFILES/S,"
                     "SAVE/S,MULTISELECT/S", flags, NULL );

  if( rdargs == NULL )
  {
    PrintFault( IoErr(), "Error in argument line", );
    _exit( RETURN_ERROR );
  }

  if( flags[ FILE ] )
    strncpy( fullpath, ( STRPTR ) flags[ FILE ], 511 );

  if( FilePart( fullpath ) == fullpath )
  {
    TEXT work[ 512 ];

    if( !GetCurrentDirName( work, 511 ) )
    {
      if( IoErr() == ERROR_OBJECT_WRONG_TYPE )
        PutStr( "No CLI structure available\n" );
      else
        PutStr( "Error getting name of current directory\n" );

      goto fail;
    }

    if( !AddPart( work, fullpath, 511 ) )
      goto lenerr;

    strncpy( fullpath, work, 511 );
  }

  if( !flags[ VAR ] || *( ( STRPTR ) flags[ VAR ] ) == '\0' )
    flags[ VAR ] = "GetFileResult";

  var = ( STRPTR ) flags[ VAR ];
  title = ( STRPTR ) flags[ TITLE ];

  if( flags[ SAVE ] )
    funcflags = FILF_SAVE;
  else
    if( flags[ MULTI ] )
      funcflags = FILF_MULTISELECT;

  if( flags[ PATTERN ] )
  {
    pattern = ( STRPTR ) flags[ PATTERN ];
    funcflags |= FILF_PATGAD;
  }

  if( flags[ NOFILES ] )
    extflags = FIL1F_NOFILES;

  pos = PathPart( fullpath );
  len = ( LONG ) pos - ( LONG ) fullpath;

  if( len > 0 )
  {
    if ( len > 255 )
    {

lenerr:
      PutStr( "Filename is too long" );
      goto fail;
    }

    strncpy( dir, fullpath, len );
  }

  if( !( req = AllocAslRequestTags( ASL_FileRequest,
                                    ASL_Hail, title,
                                    ASL_File, FilePart( fullpath ),
                                    ASL_Dir, dir,
                                    ASL_FuncFlags, funcflags,
                                    ASL_ExtFlags1, extflags,
                                    ASL_Pattern, pattern,
                                    TAG_END ) ) )
  {
    PutStr( "Couldn't allocate FileRequester structure\n" );
    ret = RETURN_FAIL;
    goto fail1;
  }

  if( !RequestFile( req ) )
  {
    ret = RETURN_WARN;
    goto fail;
  }

  fullpath[ 0 ] = '\0';

  if( funcflags & FILF_MULTISELECT )
  {
    ULONG i, len = 0, dirlen = 0;

    dirlen = strlen( req -> rf_Dir );

    for( i = 0; i < req -> rf_NumArgs; i++ )
      len += strlen( req -> rf_ArgList[ i ] . wa_Name ) + 3 + dirlen;

    if( !( buf = AllocVec( len + 1, MEMF_CLEAR | MEMF_PUBLIC ) ) )
    {
      PutStr( "Ran out of memory\n" );
      ret = RETURN_FAIL;
      goto fail;
    }

    for( i = 0; i < req -> rf_NumArgs; i++ )
    {
      strncpy( fullpath, req -> rf_Dir, 511 );

      if( !AddPart( fullpath, req -> rf_ArgList[ i ] . wa_Name, 511 ) )
        goto builderror;

      quotename( fullpath );
      strcat( buf, fullpath );
      strcat( buf, " " );
    }
  }
  else
  {
    strncpy( fullpath, req -> rf_Dir, 511 );

builderror:
    if( !AddPart( fullpath, req -> rf_File, 511 ) )
    {
      PutStr( "Buffer overflow building full filename\n" );
      ret = RETURN_FAIL;
      goto fail;
    }

    quotename( fullpath );
  }

  if( !SetVar( var,
               buf ? buf : fullpath, -1,
               flags[ GLOBAL ] ? GVF_GLOBAL_ONLY : GVF_LOCAL_ONLY ) )
  {
    PutStr( "Error setting result variable\n" );
    ret = RETURN_FAIL;
  }

  ret = RETURN_OK;

fail:

  FreeAslRequest( req );

fail1:

  FreeVec( buf );
  FreeArgs( rdargs );
  _exit( ret );
}
