/*****************************************************************************/
#include <libraries/dos.h>
#include <exec/memory.h>
#include <workbench/workbench.h>
#include <workbench/icon.h>
#include <stdio.h>
#include <ctype.h>

struct Library *OpenLibrary();
void *AllocMem();
struct Lock *Lock();

struct Library *IconBase=NULL;

char *Tools[200],*Replace[30],GetSubDirs=1,CDName[1000],WantedTool[80];
int ReplaceNr[200];
/*****************************************************************************/
OpenAll()
{  
	if (!(IconBase = (struct Library *) OpenLibrary("icon.library",0L)))
		abort("ERROR: No icon.library in libs:");
	if ((Tools[0]=AllocMem(80L,0L))==NULL) abort("Not enough memory!");
	if ((Replace[0]=AllocMem(80L,0L))==NULL) abort("Not enough memory!");
}
/*****************************************************************************/
abort(errortext)
char *errortext;
{
	int i;

	if (errortext!=0) puts(errortext);
	for (i=0;Tools[i]!=0;i++)
	{
		if (Tools[i]!=0) FreeMem(Tools[i],80L);
		if ((Replace[i]!=0)&&(i<30)) FreeMem(Replace[i],80L);
	}
	if (IconBase) CloseLibrary(IconBase);
	exit(0);
}
/*****************************************************************************/
PrintUsage()
{
	puts("[1mFixIcons[0m ver 1.2 by Lars R. Clausen");
	puts("This program is PD, copy it as you want. (Boykot hacking!)");
	puts("[33mUsage:[0m FixIcons [rootdir] [-r|-w|-lTool] [-s] [-v] [-n] [-ddefinefile] ");
	puts("         Modes:       -r        Read only.");
	puts("                      -w        Also write replacements.");
	puts("                      -l[Tool]  Search for defaulttool Tool only.");
	puts("         Other stuff: -s        Don't scan subdirectories.");
	puts("                      -v        Be verbose.");
	puts("                      -n        Don't load definefile.");
	puts("                      -d[File]  Use File as definefile.");
	puts("  Default is: 'Fixicons dh0: -w -dS:FixIcons.Define'");
	abort(0L);
}
/*****************************************************************************/
int strcmpi(s,t)
char *s,*t;
{
	for (;toupper(*s)==toupper(*t);s++,t++)
		if (*s=='\0') return(0);
	return(*s-*t);
}

/*****************************************************************************/
int RemoveDups(list,string,maxstring)
char **list;
char *string;
int maxstring;
{
	int i;
	
	for (i=0;i<maxstring;i++)
		if (strcmpi(list[i],list[maxstring])==0)
			return(i);
	return(-1);
}
/*****************************************************************************/
int GetDefineFile(filename,mode)
char *filename;
int mode;
{
	int i=1,j,k,l,dupnr;
	char replacetool[80];
	FILE *definefile;
	
	if ((definefile=fopen(filename,"r"))!=0)
	{
		for (i=0,j=0,l=0;(k=getc(definefile))!=EOF;j++)
		{
			if (k=='\n')
			{
				Tools[i][j]=0;
				j=0;
				i++;
				if ((Tools[i]=AllocMem(80L,0L))==NULL) abort("Not enough memory!");
			}
			if (k=='=')
			{
				for (j--;(isspace(Tools[i][j]))&&(j>=0);Tools[i][j]=0,j--);
				for (k=getc(definefile);isspace(k);k=getc(definefile));
				replacetool[0]=k;
				for (j=1;(k=getc(definefile))!='\n';j++)
					replacetool[j]=k;
				replacetool[j]=0;
				strcpy(Replace[l],replacetool);
				dupnr=RemoveDups(Replace,Replace[l],l);
				ReplaceNr[i]=l;
				if (dupnr==-1)
				{
					if ((Replace[++l]=AllocMem(80L,0L))==NULL) abort("Not enough memory!");
				}
				else ReplaceNr[i]=dupnr;
				j=0;
				i++;
				if ((Tools[i]=AllocMem(80L,0L))==NULL) abort("Not enough memory!");
			}
			Tools[i][j]=k;
			if (k=='\n') j--;
		}
		fclose(definefile);
	}
	else
	if (mode%3==1) abort("Couldn't find definefile");
	if (mode==1)
	{
		puts("The following replacements will be used:");
		for (j=0;j<i;j++)
		if (ReplaceNr[j]!=-1) printf("%-35s => %s.\n",Tools[j],Replace[ReplaceNr[j]]);
	}
	return(i);
}
/*****************************************************************************/
PutDefineFile(tools,filename)
int tools;
char *filename;
{
	FILE *definefile;
	int i;

	if ((definefile=fopen(filename,"w"))!=0)
	{
		printf("Writing defines to file %s.\n",filename);
		for (i=0;i<tools;i++)
			if (ReplaceNr[i]!=-1)
				fprintf(definefile,"%s = %s\n",Tools[i],Replace[ReplaceNr[i]]);
			else
				fprintf(definefile,"%s\n",Tools[i]);
		fclose(definefile);
	}
	else printf("Couldn't write defines to file '%s'.\n",filename);
}
/*****************************************************************************/
int GetTools(dir,toolnr,mode)
char *dir;
int toolnr;
int mode;
{
	struct Lock *lock;
	int olddirlen,cdlen,internaltoolnr=toolnr,dupnr;
	short succes=1;
	char filename[100];
	struct FileInfoBlock *fileinfoblock;
	struct DiskObject *diskobj;

	olddirlen=strlen(CDName);
	if ((CDName[olddirlen-1]!=':')&&(olddirlen>0))
		strcat(CDName,"/");
	strcat(CDName,dir);
	if (mode<2) printf("Now examining %s...\n",CDName);
	if ((fileinfoblock=AllocMem((long)sizeof(struct FileInfoBlock),(long)0L))==NULL)
		abort("Couldn't allocate FileInfoBlock");
	if ((lock=Lock(CDName,ACCESS_READ))==0) abort("Couldn't find directory.");
	if (Examine(lock,fileinfoblock)==0) abort("Couldn't examine directory.");
	succes=ExNext(lock,fileinfoblock);
	strcpy(filename,fileinfoblock->fib_FileName);
	for (;(internaltoolnr<100)&&(succes!=0);)
	{
		if ((fileinfoblock->fib_DirEntryType>0)&&(GetSubDirs==1))
			internaltoolnr=GetTools(fileinfoblock->fib_FileName,internaltoolnr,mode);
		else
			if (strcmp(&filename[strlen(filename)-5],".info")==0)
			{
				filename[strlen(filename)-5]=0;
				cdlen=strlen(CDName);
				if ((CDName[cdlen-1]!=':')&&(cdlen>0))
					strcat(CDName,"/");
				strcat(CDName,filename);
				if ((diskobj=GetDiskObject(CDName))!=0)
					if (diskobj->do_Type==WBPROJECT)
					{
						if (mode%3==2)
						{
							if (strcmpi(diskobj->do_DefaultTool,WantedTool)==0)
								printf("Tool %s found in %s.info.\n",WantedTool,CDName);
						}
						else
						{
							strcpy(Tools[internaltoolnr],diskobj->do_DefaultTool);
							dupnr=RemoveDups(Tools,Tools[internaltoolnr],internaltoolnr);
							if (dupnr==-1)
							{
								internaltoolnr++;
								if (mode<2) printf("Found new tool '%s' in '%s'.\n",diskobj->do_DefaultTool,CDName);
								if ((Tools[internaltoolnr]=AllocMem(80L,0L))==NULL)
								{
									FreeDiskObject(diskobj);
									abort("Not enough memory!");
								}
							}
							else
							{
								if (((mode==1)||(mode==4))&&(ReplaceNr[dupnr]!=-1))
								{
									if (mode<2) printf("Changing %s.info from %s to %s.\n",
										CDName,diskobj->do_DefaultTool,Replace[ReplaceNr[dupnr]]);
									strcpy(diskobj->do_DefaultTool,Replace[ReplaceNr[dupnr]]);
									if (PutDiskObject(CDName,diskobj)==0)
										printf("Hey! Disk or file %s is write-protected!\n",CDName);
								}
							}
						}
						FreeDiskObject(diskobj);
					}
					else FreeDiskObject(diskobj);
				CDName[cdlen]=0;
			}
/* Not all disk perform ExNext properly, it seems. Could it be Aztec? */
		succes=ExNext(lock,fileinfoblock);
		strcpy(filename,fileinfoblock->fib_FileName);
	}
	UnLock(lock);
	FreeMem(fileinfoblock,(long)sizeof(struct FileInfoBlock));
	CDName[olddirlen]=0;
	return(internaltoolnr);
}
		
/*****************************************************************************/
main(argc,argv)
int argc;
char **argv;
{
	int tools=0,i,mode=4,erasedefine=0;
	char *filename="dh0:",*definefilename="S:FixIcons.define";
	
	if ((argc==2)&&((strcmpi(argv[1],"help")==0)||(strcmp(argv[1],"?")==0))) PrintUsage();
	printf("[1mFixIcons[0m ver 1.2 (c) 1989 by Lars R. Clausen.\n");
	for (i=1;i<argc;i++)
	{
		if (strcmp(argv[i],"-s")==0) GetSubDirs=0;
		if (strcmp(argv[i],"-r")==0) mode=3;/* Read-only mode */
		if (strcmp(argv[i],"-w")==0) mode=4;/* Also write defaults */
		if (strcmp(argv[i],"-v")==0) mode-=3;/* Verbose mode */
		if (strcmp(argv[i],"-n")==0) erasedefine=1;
		if (strncmp(argv[i],"-l",2)==0)
		{
			mode=5;
			strcpy(WantedTool,&argv[i][2]);/* Search for tool */
		}
		if (strncmp(argv[i],"-d",2)==0)	definefilename=&argv[i][2];
		if (strncmp(argv[i],"-",1)!=0) filename=argv[i];
	}
	for (i=0;i<200;i++) {ReplaceNr[i]=-1;Tools[i]=0;};
	for (i=0;i<30;i++) Replace[i]=0;
/* Allocate first tool and replacement, and open IconLibrary */
	OpenAll();
/* Load definefile */
	if ((mode%3!=2)&&(erasedefine==0)) tools=GetDefineFile(definefilename,mode);

	if (mode==2) printf("Searching for %s in %s.\n",WantedTool,filename);
/* Core of the program - recursive scanning routine */
	tools=GetTools(filename,tools,mode);
/* Output definefile */
	if (mode%3!=2) PutDefineFile(tools,definefilename);
	abort(0L);
}
