/* MostCurrent.c
 *
 * Programmed by: Peter A. Phelps 11/9/90
 *
 * See MostCurrent.doc for further info.
 *
 */

#include	<ctype.h>
#include	<stdio.h>
#include	<functions.h>
#include	<exec/types.h>
#include	<exec/memory.h>
#include	<intuition/intuition.h>

void	Upcase();
void	_abort();

#define	SIZE		10000
#define	BYTE_CNT	2048
#define	ESC			27

char	*EntryNames[SIZE];
int		HighestDisk[SIZE];

struct	NameData
{
	char	Bytes[BYTE_CNT];
} Element;

struct	IntuitionBase	*IntuitionBase;

struct	NameData	*ElementPointer = &Element;

struct	Remember	*RememberKey = (struct Remember *)NULL;

main()
{
	FILE	*Index, *NewIndex, *Names;
	union
	{
		struct
		{
			ULONG	BitMask;
			SHORT	FFDisk;
			ULONG	AbsAdr;
			SHORT	ContentsLength;
			UBYTE	Space___The_Final_Frontier;
		} Entry;
		struct
		{
			UBYTE	Byte[13];
		} ByteView;
	} Record;
	char	InChar, ThisEntry[20], Null = '\0';
	int		i, NextEntry = 1, Lowest, Highest, NextByte = 0;
	SHORT	ThisFish = 0;

	if((IntuitionBase = (struct IntuitionBase *)
		OpenLibrary("intuition.library",LIBRARY_VERSION)) ==
		(struct IntuitionBase *)NULL)
	{
		printf("Need intuition.library Ver >= %d.\n",LIBRARY_VERSION);
		exit(FALSE);
	}

	if((Index = fopen("index.tmp","r")) == (struct FILE *)NULL)
	{
		printf("index.tmp not found!\nSee MostCurrent.doc\n");
		exit(FALSE);
	}

	if((Names = fopen("Names","r")) == (struct FILE *)NULL)
	{
		printf("Names file not found!\nSee MostCurrent.doc\n");
		fclose(Index);
		exit(FALSE);
	}

	if((NewIndex = fopen("index","r")) != (struct FILE *)NULL)
	{
		printf("index already exists!\nSee MostCurrent.doc\n");
		fclose(NewIndex);
		fclose(Index);
		fclose(Names);
		exit(FALSE);
	}

	printf("Reading Names and index.tmp files\n");
	printf("to determine the MostCurrent Button data\n\n");

	EntryNames[0] = &Null;
	HighestDisk[0] = 0; /* In case there are any Null Names */

	while((InChar = getc(Index)) != EOF)
	{
		for(i=0;i<13;i++)
		{
			Record.ByteView.Byte[i] = InChar;
			InChar = getc(Index);
		}
		for(i=0;i<20;i++)
			ThisEntry[i] = getc(Names);
		for(i=0;i<19 && ThisEntry[i] != ' ';i++);
		ThisEntry[i] = '\0';
		Upcase(ThisEntry);
		Lowest = 0;
		Highest = NextEntry;
		while(Lowest+1 < Highest)
			if(!strcmp(EntryNames[(Highest-Lowest)/2+Lowest],ThisEntry))
				Lowest = Highest = (Highest-Lowest)/2+Lowest;
			else
				if(strcmp(EntryNames[(Highest-Lowest)/2+Lowest],ThisEntry)>0)
					Highest = (Highest-Lowest)/2+Lowest;
				else
					Lowest = (Highest-Lowest)/2+Lowest;
		if(strcmp(EntryNames[Lowest],ThisEntry))
		{
			Lowest++;
			for(i=NextEntry; i>Lowest; i--)
			{
				EntryNames[i] = EntryNames[i-1];
				HighestDisk[i] = HighestDisk[i-1];
			}
			NextEntry++;
			if(NextByte + strlen(ThisEntry) + 1 > BYTE_CNT)
			{
				if((ElementPointer = (struct NameData *)
				AllocRemember(&RememberKey,sizeof(struct NameData),
					MEMF_FAST)) == (struct NameData *)NULL)
				{
					FreeRemember(&RememberKey,TRUE);
					fclose(Index);
					CloseLibrary(IntuitionBase);
					printf("Out of Memory!\n");
					printf("Please free some memory,");
					printf("and run this program again.\n");
					exit(FALSE);
				}
				NextByte = 0;
			}
			EntryNames[Lowest] =
				&ElementPointer->Bytes[NextByte];
			i = 0;
			while(ThisEntry[i])
				ElementPointer->Bytes[NextByte++] =
					ThisEntry[i++];
			ElementPointer->Bytes[NextByte++] = '\0';
			HighestDisk[Lowest] = 0;
		}
		if(Record.Entry.FFDisk > HighestDisk[Lowest])
			HighestDisk[Lowest] = Record.Entry.FFDisk;
		if(Record.Entry.FFDisk != ThisFish)
			printf("%c[AFish #%d\n",ESC,Record.Entry.FFDisk);
		ThisFish = Record.Entry.FFDisk;
	}

	fseek(Index,0,0);
	fseek(Names,0,0);
	if((NewIndex = fopen("index","x")) == (struct FILE *)NULL)
	{
		printf("Problem opening index.\n");
		printf("This shouldn't happen!\n");
		printf("Is your disk write protected?\n");
		FreeRemember(&RememberKey,TRUE);
		exit(FALSE);
	}

	printf("%c[3A%c[JWriting MostCurrent Info\n\n",ESC,ESC);

	while((InChar = getc(Index)) != EOF)
	{
		for(i=0;i<13;i++)
		{
			Record.ByteView.Byte[i] = InChar;
			InChar = getc(Index);
		}
		for(i=0;i<20;i++)
			ThisEntry[i] = getc(Names);
		for(i=0;i<19 && ThisEntry[i] != ' '; i++);
		ThisEntry[i] = '\0';
		Upcase(ThisEntry);
		Lowest = 0;
		Highest = NextEntry;
		while(Lowest+1 < Highest)
			if(!strcmp(EntryNames[(Highest-Lowest)/2+Lowest],ThisEntry))
				Lowest = Highest = (Highest-Lowest)/2+Lowest;
			else
				if(strcmp(EntryNames[(Highest-Lowest)/2+Lowest],ThisEntry)>0)
					Highest = (Highest-Lowest)/2+Lowest;
				else
					Lowest = (Highest-Lowest)/2+Lowest;

		Record.Entry.BitMask &= ~0x20000000;
		if(Record.Entry.FFDisk == HighestDisk[Lowest])
			Record.Entry.BitMask |= 0x20000000;
		for(i=0; i<13;i++)
			putc(Record.ByteView.Byte[i],NewIndex);
		putc(0,NewIndex);
		if(Record.Entry.FFDisk != ThisFish)
			printf("%c[AFish #%d\n",ESC,Record.Entry.FFDisk);
		ThisFish = Record.Entry.FFDisk;
	}
	fclose(Names);
	fclose(Index);
	fclose(NewIndex);
	FreeRemember(&RememberKey,TRUE);
	CloseLibrary(IntuitionBase);
	printf("Program completed normally.\n");
}

void	Upcase(String)
char *String;

{
	do
		if(*String >= 'a' && *String <= 'z')
			*String  = _toupper(*String);
	while(*++String != '\0');
}

void	_abort()
{
	FreeRemember(&RememberKey,TRUE);
	exit(FALSE);
}
