#include <ctype.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include <workbench/icon.h>

#define REGS register


/*-------------------------------------------------------------------------+
 |									   |
 | Name:    atos							   |
 | Purpose: convert a string to a short integer 			   |
 |									   |
 | Author:  RWA 				   Date: 6/89		   |
 +-------------------------------------------------------------------------*/
short atos(s)
REGS char *s;
{
REGS short n;
for( n = 0; (*s) >= '0' && (*s) <= '9'; s++)
   n = 10 * n + (*s) - '0';
return(n);
}

typedef struct
{
short ToolNum;
char *Tool;
} ToolType;

#define PROJECT_ONLY 1
#define TOOL_ONLY 2

typedef struct
{
short only;
short verify;
char *files[21];
short StackSize;
char *DefaultTool;
ToolType ToolTypes[21];
} NewInfo;

/*-------------------------------------------------------------------------+
 |									   |
 | Name:    message							   |
 | Purpose: dispalys a string on the CLI				   |
 |									   |
 | Author:  RWA 				   Date: 7/89		   |
 +-------------------------------------------------------------------------*/

struct FileHandle *cliout;

void message(str)
char *str;
{
Write(cliout,str,(long)strlen(str));
}

void messages(strs)
char **strs;
{
while( *strs ) { message(*strs); strs++; }
}

char *help[]=
{
"\nInfoChange V1.0 by Robert W. Albrecht\n",
"\n",
"SYNTAX:\n",
"\n",
"InfoChange <files> -Yn<tool type> -S<stacksize> -D<tool> -V -T -P\n",
"\n",
"Where:\n",
"-D  sets the default tool to <tool>\n",
"-S  changes the stack size used by default tool\n",
"-Yn sets tool type number 'n' to <tool type>\n",
"-V  will ask for verification before changing an icon\n",
"-T  do only \"Tool\" (program) icons\n",
"-P  do only \"Project\" (file) icons\n",
"\n",
"Wild cards are accepted for the file name(s). (* and ?)\n",
"Only Project and Tool \".info\" files can be changed.\n\n",
0L,
};

/*-------------------------------------------------------------------------+
 |									   |
 | Name:    process_args						   |
 | Purpose: processes command line arguments				   |
 |									   |
 | Author:  RWA 				   Date: 7/89		   |
 +-------------------------------------------------------------------------*/
short process_args(ni,ac,av)
NewInfo *ni;
short ac;
char *av[];
{
REGS short i;
ToolType *ToolTypes;
char **files, *a;
short n;

ToolTypes = ni->ToolTypes;
files = ni->files;

for( i = 1; i < ac; i++)
   {
   if( av[i][0] == '-' )
      {
      switch( _toupper(av[i][1]) )
	 {
	 case 'Y':
	    if( (n = atos(&av[i][2])) > 0 )
	       {
	       ToolTypes->ToolNum = n;
	       a = &av[i][2];
	       while( *a >= '0' && *a <= '9' ) a++;
	       ToolTypes->Tool = a;
	       ToolTypes++;
	       }
	 break;

	 case 'S':
	    if( (n = atos(&av[i][2])) > 0 )
	       ni->StackSize = n;
	 break;

	 case 'D':
	    ni->DefaultTool = &av[i][2];
	 break;

	 case 'V':
	    ni->verify = 1;
	 break;

	 case 'P':
	    ni->only = PROJECT_ONLY;
	 break;

	 case 'T':
	    ni->only = TOOL_ONLY;
	 break;

	 default:
	    *files = av[i];
	    files++;
	 break;
	 }
      }
   else
      {
      *files = av[i];
      files++;
      }
   }
}

/*-------------------------------------------------------------------------+
 |									   |
 | Name:    check_todo							   |
 | Purpose: makes sure there is something to do 			   |
 |									   |
 | Author:  RWA 				   Date: 7/89		   |
 +-------------------------------------------------------------------------*/
short check_todo(ni)
NewInfo *ni;
{
if( ni->DefaultTool || ni->StackSize || ni->ToolTypes[0].ToolNum )
   return(1);
return(0);
}

/*-------------------------------------------------------------------------+
 |									   |
 | Name:    strlwr							   |
 | Purpose: converts a string to all lower case 			   |
 |									   |
 | Author:  RWA 				   Date: 7/89		   |
 +-------------------------------------------------------------------------*/
void strlwr(s)
char *s;
{
while( *s )
   {
   *s = _tolower(*s);
   s++;
   }
}

/*-------------------------------------------------------------------------+
 |									   |
 | Name:    fix_icon							   |
 | Purpose: changes a disk object structure and stores it to disk	   |
 |									   |
 | Author:  RWA 				   Date: 7/89		   |
 +-------------------------------------------------------------------------*/
void fix_icon(dobj,ni,fname)
struct DiskObject *dobj;
NewInfo *ni;
char *fname;
{
long PutDiskObject();
struct DiskObject new_dobj;
char *tooltypes[30], *ptr = 0L;

if( ni->verify )
   {
   char ibuf[4];
   message("Change");
   if( dobj->do_Type == WBTOOL )
      message(" Tool?");
   else message(" Project?");
   message(" <Y/N> [Y]");
   Read(cliout,ibuf,4L);
   if( ibuf[0] == 'n' || ibuf[0] == 'N' )
      return;
   }

movmem(dobj,&new_dobj,sizeof(struct DiskObject));

if( dobj->do_Type == WBPROJECT && ni->DefaultTool )
   new_dobj.do_DefaultTool = ni->DefaultTool;

if( ni->StackSize ) new_dobj.do_StackSize = ni->StackSize;

if( ni->ToolTypes[0].ToolNum )
   {
   ToolType *t;
   REGS short num_tooltypes, i;
   REGS char **a;

   num_tooltypes = 0;

   if( a = dobj->do_ToolTypes )
      {
      while( *a++ )
	 if( (num_tooltypes++) >= 30 ) break;

      for( i = 0, a = dobj->do_ToolTypes; i < num_tooltypes && i < 30; i++)
	 tooltypes[i] = a[i];
      }

   for(t = ni->ToolTypes; t->ToolNum; t++)
      {
      if( t->ToolNum > num_tooltypes && num_tooltypes < 30 )
	 tooltypes[num_tooltypes++] = t->Tool;
      else if( t->ToolNum < 30 ) tooltypes[t->ToolNum - 1] = t->Tool;
      }

   if( num_tooltypes )
      {
      tooltypes[num_tooltypes] = 0L;
      new_dobj.do_ToolTypes = tooltypes;
      }
   }

if( PutDiskObject(fname,&new_dobj) )
   message("Done");
else message("Error Saving");
}

/*-------------------------------------------------------------------------+
 |									   |
 | Name:    icon_change 						   |
 | Purpose: performs changes on a icon					   |
 |									   |
 | Author:  RWA 				   Date: 7/89		   |
 +-------------------------------------------------------------------------*/
void icon_change(fname,ni)
char *fname;
NewInfo *ni;
{
char *a, buf[256], *strcpy();
struct DiskObject *dobj, *GetDiskObject();

strcpy(buf,fname);
strlwr(a = buf);

while( *a )   /* look for the .info extention */
   {
   if( *a == '.' ) if( !strcmp(a,".info") ) break;
   a++;
   }
if( *a )
   {
   message(strcpy(buf,fname));
   message(" ... ");
   *a = '\0';

   if( dobj = GetDiskObject(buf) )
      {
      if( dobj->do_Type == WBTOOL && ni->only != PROJECT_ONLY )
	 fix_icon(dobj,ni,buf);
      else if( dobj->do_Type == WBPROJECT && ni->only != TOOL_ONLY )
	 fix_icon(dobj,ni,buf);
      else
	 message("Icon of Wrong Type");
      FreeDiskObject(dobj);
      }
   else
      message("Can't be Loaded");

   message("\n");
   }
}

/*-------------------------------------------------------------------------+
 |									   |
 | Name:    change_icons						   |
 | Purpose: perform the specified changes on the specified icons	   |
 |									   |
 | Author:  RWA 				   Date: 7/89		   |
 +-------------------------------------------------------------------------*/
void change_icons(ni)
NewInfo *ni;
{
char **files, *fname, *scdir();

files = ni->files;

while( *files )
   {
   while( fname = scdir(*files) )
      icon_change(fname,ni);
   files++;
   }

}

/*-------------------------------------------------------------------------+
 |									   |
 | Name:    main							   |
 | Purpose: main routine						   |
 |									   |
 | Author:  RWA 				   Date: 7/89		   |
 +-------------------------------------------------------------------------*/

main(argc,argv)
short argc;
char *argv[];
{
static NewInfo newinfo;
static char copyright[] =
{"Copyright (C) 1989 by Robert W. Albrecht, All Rights Reserved."};
extern void *OpenLibrary(), CloseLibrary(), *IconBase, *Open(), Close();

if( !argc ) _exit(0);

if( !(IconBase = OpenLibrary(ICONNAME,0L)) )
   _exit(11);

/* open up a way to the outside world */
if( !(cliout = Open("*",(long)MODE_OLDFILE)) )
   {
   CloseLibrary(IconBase);
   _exit(12);
   }

if( argc == 1 ) /* no arguments */
   messages(help);
else
   {
   setmem(&newinfo,sizeof(newinfo),0);
   process_args(&newinfo,argc,argv);
   if( check_todo(&newinfo) )
      change_icons(&newinfo);
   else
      message("I have nothing to do!\n");
   }

Close(cliout);
CloseLibrary(IconBase);
_exit(0);
}

