/*
**	otag.c - .otag files reading routines
**	Copyright © 1995 Michael Letowski
*/

#include <exec/types.h>
#include <dos/dos.h>
#include <diskfont/diskfont.h>
#include <diskfont/diskfonttag.h>
#include <graphics/text.h>
#include <support/types.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/diskfont.h>
#include <proto/utility.h>

#include "classbase.h"
#include "otag.h"

#define FTSUFFIX				".font"

#define SUFFIX_LEN			5
#define MAX_NAME_LEN		32

/* Get size of FontContentHeader */
#define SizeOfFCH(fch)	(sizeof(struct FontContentsHeader)+\
															(fch)->fch_NumEntries*sizeof(struct FontContents))
#define VarSizeOfFCH(x)	(sizeof(struct FontContentsHeader)+\
															(x)*sizeof(struct FontContents))

INLINE STATIC struct FontContentsHeader *ReadOutlines(struct ClassBase *cb,
																											BPTR lock, STRPTR name);
STATIC LONG LocSeekFileSize(struct ClassBase *cb, BPTR fh);

/****************************************************************************/
/*    These functions are necessary, because Diskfont doesn't work well     */
/****************************************************************************/

struct FontContentsHeader *NewFC(struct ClassBase *cb, BPTR lock, STRPTR name)
{
	struct FontContentsHeader *FCH,*MyFCH=NULL;
	ULONG Size;

	if(FCH=NewFontContents(lock,name))						/* Use Diskfont to get contents */
	{
		if(FCH->fch_NumEntries)											/* Some entries exist */
		{
			Size=SizeOfFCH(FCH);
			if(MyFCH=AllocVec(Size,MEMF_CLEAR))				/* Allocate new space */
				CopyMem(FCH,MyFCH,Size);								/* Make a copy */
		}
		else if(FCH->fch_FileID==OFCH_ID)						/* This is outline font */
		{
			if(MyFCH=ReadOutlines(cb,lock,name))			/* Read tags and sizes */
				MyFCH->fch_FileID=FCH->fch_FileID;
		}
		DisposeFontContents(FCH);										/* Free unused header */
	}
	return(MyFCH);
}	/* NewFC */

VOID DisposeFC(struct ClassBase *cb, struct FontContentsHeader *fch)
{
	FreeVec(fch);
}	/* DisposeFC */

INLINE STATIC struct FontContentsHeader *ReadOutlines(struct ClassBase *cb,
																											BPTR lock, STRPTR name)
{
	struct FontContentsHeader *FCH=NULL;
	struct TFontContents *TFC;
	struct TagItem *Tags;
	struct FileInfoBlock *FIB;
	UWORD *Sizes;
	CHAR NewName[MAX_NAME_LEN];
	STRPTR Suffix;
	BPTR FH,OldLock;
	ULONG Offset,I;
	LONG FileLen;

	OldLock=CurrentDir(lock);											/* Change to FONTS: dir */

	/* Chage extension */
	clear(&NewName);															/* Set to NULLs */
	strncpy(NewName,name,MAX_NAME_LEN-1);					/* Copy name to buffer */
	unless(Suffix=strstr(NewName,FTSUFFIX))
		throw2(SetIoErr(ERROR_OBJECT_WRONG_TYPE),	EXIT);
	strncpy(Suffix,OTSUFFIX,SUFFIX_LEN);					/* Replace ".font" with ".otag" */

	/* Open .otag file and get its size */
	try(FH=Open(NewName,MODE_OLDFILE),						NO_FILE);
	if(FIB=AllocDosObject(DOS_FIB,NULL))
	{
		if(ExamineFH(FH,FIB))												/* Examine it */
			FileLen=FIB->fib_Size;										/* Get length of file */
		else
			FileLen=LocSeekFileSize(cb,FH);						/* Get size by seeking */
		FreeDosObject(DOS_FIB,FIB);
	}
	else
		FileLen=LocSeekFileSize(cb,FH);								/* No FIB? - seek */

	try(FileLen>=0,	ERROR1);											/* Make sure size is positive */
	try(Tags=AllocVec(FileLen,MEMF_ANY),					NO_TAGS);	/* Allocate space for tags */
	try(Read(FH,Tags,FileLen)==FileLen,						ERROR2);	/* Read tags */
	try(GetTagData(OT_FileIdent,0,Tags)==FileLen,	ERROR2);	/* Verify size */

	/* Get size of new FCH and set up data */
	try(Offset=GetTagData(OT_AvailSizes,0,Tags),	ERROR2);
	Sizes=(UWORD *)((ULONG)Tags+Offset);					/* Calculate position of data */
	if(FCH=AllocVec(VarSizeOfFCH(*Sizes),MEMF_CLEAR))
	{
		FCH->fch_NumEntries=*Sizes;
		for(I=0; I<*Sizes; I++)
		{
			TFC=&TFontContents(FCH)[I];
			SNPrintf(TFC->tfc_FileName,MAXFONTPATH,"%s/%ld",name,Sizes[I+1]);
			TFC->tfc_TagCount=1;											/* TAG_DONE */
			TFC->tfc_YSize=Sizes[I+1];
			TFC->tfc_Style=FS_NORMAL;									/* Really ??? */
			TFC->tfc_Flags=FPF_DISKFONT;							/* Really ??? */
		}
	}

	except(ERROR2,	);
	except(NO_TAGS,	FreeVec(Tags));
	except(ERROR1,	);
	except(NO_FILE,	Close(FH));										/* Close opened .otag file */
	except(EXIT,		);

	CurrentDir(OldLock);													/* Get back to old dir */
	return(FCH);
}	/* ReadOutlines */

STATIC LONG LocSeekFileSize(struct ClassBase *cb, BPTR fh)
{
	LONG Size;

	if((Size=Seek(fh,0,OFFSET_END))>=0)						/* Seek to end of file */
		Size=Seek(fh,0,OFFSET_BEGINNING);						/* Seek back to beginning */
	return(Size);
}	/* LocSeekFileSize */
