//
// Source from Bitline 0.5 from Aminet,
// modified by TetiSoft@apg.lahn.de (Detlef Würkner)
// for inclusion in T1Manager.
//

//#include <OSIncludes.h>
#include "t1manager.h"		// TetiSoft
#include <dos/doshunks.h>	// TetiSoft

//#pragma header

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>

/****************************************************/

//static char *VERSTRING = "$VER: Bitline 0.5 ("__DATE2__")";
//static char *AUTHSTRING = "$AUTH: Georg Steger";

//#define ARG_TEMPLATE "FROM/A,TO/A,FONTNAME/A,SIZES/N/M/A"

//enum {ARG_FROM,ARG_TO,ARG_FONTNAME,ARG_SIZES,NUM_ARGS};

/****************************************************/

struct MyDiskFontHeader
{
	WORD	 moveq;
	WORD	 rts;
	struct DiskFontHeader dfh;
};

struct MyHunkHeader
{
	LONG	id;
	LONG	unknown;
	LONG	numhunks;
	LONG	unknown2;
	LONG	unknown3;
	LONG	size;
};

struct MyHunkStruct
{
	LONG	id;
	LONG	size;
};

/****************************************************/
	
//struct GfxBase *GfxBase;
//struct Library *DiskfontBase;

//static struct RDArgs *MyArgs;
static struct TextFont *MyFont;
static struct MyDiskFontHeader MyDFH;
static struct FontContentsHeader *fch;

static BPTR MyHandle,lock;
//static LONG Args[NUM_ARGS];
//static char s[300],s2[50];
static char s[MAXFONTPATH+44],s2[50];
static char *fromname;
static char *fontname;
static char *toname;
static LONG	**sizes,l,segsize,numchars,actsize;
static UBYTE *buffer;

static LONG 	size_dfh,
//		size_name,
		size_bitplane,
		size_charloc,
		size_charspace,
		size_kern;

#define ALIGN(x) (((x) + 3) & -4)
#define NUM_RELOCS 6

static LONG relocoffset[NUM_RELOCS+1];

//static void Cleanup(char *msg,WORD rc)
static void Cleanup(char *msg)		// TetiSoft
{
	if (msg)
	{
//		printf("Bitline: %s\n",msg);
		MyErrorMsg1(LString(MSG_ERROR_BITLINE), msg);	// TetiSoft
	}
	
	if (fch) DisposeFontContents(fch);
	fch = NULL;					// TetiSoft
	if (lock) UnLock(lock);
	lock = NULL;					// TetiSoft
	if (MyHandle) Close(MyHandle);
	MyHandle = NULL;				// TetiSoft
	if (buffer) FreeVec(buffer);
	buffer = NULL;					// TetiSoft
	if (MyFont) CloseFont(MyFont);
	MyFont = NULL;					// TetiSoft
//	if (MyArgs) FreeArgs(MyArgs);

//	if (DiskfontBase) CloseLibrary(DiskfontBase);
//	if (GfxBase) CloseLibrary((struct Library *)GfxBase);

//	exit(rc);
}

//static void OpenLibs(void)
//{
//	if (!(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",36)))
//	{
//		Cleanup("Can't open graphics.library V36!",RETURN_FAIL);
//	}
//	
//	if (!(DiskfontBase=OpenLibrary("diskfont.library",36)))
//	{
//		Cleanup("Can't open diskfont.library V36!",RETURN_FAIL);
//	}
//}

//static void GetArguments(void)
//{
//	static LONG *lp;
//
//	if (!(MyArgs=ReadArgs(ARG_TEMPLATE,Args,0)))
//	{
//		Fault(IoErr(),0,s,256);
//		Cleanup(s,RETURN_FAIL);
//	}
//	
//	fromname = (char *)Args[ARG_FROM];
//	toname = (char *)Args[ARG_TO];
//	fontname = (char *)Args[ARG_FONTNAME];
//	sizes = (LONG **)Args[ARG_SIZES];
//	
//	if (!sizes[0])
//	{
//		Fault(ERROR_REQUIRED_ARG_MISSING,0,s,256);
//		Cleanup(s,RETURN_FAIL);
//	}
//}

static void CalcSegSize(void)
{
	segsize = /*(size_name = ALIGN(strlen(font->tf_Message.mn_Node.ln_Name) + 1)) +*/
				 (size_dfh = ALIGN(sizeof(struct MyDiskFontHeader))) + 
				 (size_bitplane = ALIGN(MyFont->tf_Modulo * (MyFont->tf_YSize+1))) +
				 (size_charloc = ALIGN(numchars * 4)) + 
				 (size_charspace = ALIGN(numchars * 2)) +
				 (size_kern = ALIGN(numchars * 2));

}

static void CalcReloc(void)
{
	LONG ofs;

//	relocoffset[0] = offsetof(MyDiskFontHeader,dfh.dfh_DF.ln_Name);
//	relocoffset[1] = offsetof(MyDiskFontHeader,dfh.dfh_TF.tf_Message.mn_Node.ln_Name);
//	relocoffset[2] = offsetof(MyDiskFontHeader,dfh.dfh_TF.tf_CharData);
//	relocoffset[3] = offsetof(MyDiskFontHeader,dfh.dfh_TF.tf_CharLoc);
//	relocoffset[4] = offsetof(MyDiskFontHeader,dfh.dfh_TF.tf_CharSpace);
//	relocoffset[5] = offsetof(MyDiskFontHeader,dfh.dfh_TF.tf_CharKern);
	relocoffset[0] = offsetof(struct MyDiskFontHeader,dfh.dfh_DF.ln_Name);				// TetiSoft
	relocoffset[1] = offsetof(struct MyDiskFontHeader,dfh.dfh_TF.tf_Message.mn_Node.ln_Name);	// TetiSoft
	relocoffset[2] = offsetof(struct MyDiskFontHeader,dfh.dfh_TF.tf_CharData);			// TetiSoft
	relocoffset[3] = offsetof(struct MyDiskFontHeader,dfh.dfh_TF.tf_CharLoc);			// TetiSoft
	relocoffset[4] = offsetof(struct MyDiskFontHeader,dfh.dfh_TF.tf_CharSpace);			// TetiSoft
	relocoffset[5] = offsetof(struct MyDiskFontHeader,dfh.dfh_TF.tf_CharKern);			// TetiSoft
	
//	MyDFH.dfh.dfh_DF.ln_Name = (char *) offsetof(MyDiskFontHeader,dfh.dfh_Name);
//	MyDFH.dfh.dfh_TF.tf_Message.mn_Node.ln_Name = (char *) offsetof(MyDiskFontHeader,dfh.dfh_Name);
	MyDFH.dfh.dfh_DF.ln_Name = (char *) offsetof(struct MyDiskFontHeader,dfh.dfh_Name);			// TetiSoft
	MyDFH.dfh.dfh_TF.tf_Message.mn_Node.ln_Name = (char *) offsetof(struct MyDiskFontHeader,dfh.dfh_Name);	// TetiSoft
	
	MyDFH.dfh.dfh_TF.tf_Message.mn_Node.ln_Succ = NULL;	// TetiSoft: Clear this
	MyDFH.dfh.dfh_TF.tf_Message.mn_Node.ln_Pred = NULL;	// TetiSoft: Clear this
	MyDFH.dfh.dfh_TF.tf_Message.mn_ReplyPort    = NULL;	// TetiSoft: Clear this

	ofs = size_dfh;
	
	MyDFH.dfh.dfh_TF.tf_CharData = (APTR) ofs;
	ofs += size_bitplane;
	MyDFH.dfh.dfh_TF.tf_CharLoc = (APTR) ofs;
	ofs += size_charloc;
	MyDFH.dfh.dfh_TF.tf_CharSpace = (APTR) ofs;
	ofs += size_charspace;
	MyDFH.dfh.dfh_TF.tf_CharKern = (APTR) ofs;
	
}

//static void SaveIt(void)
static int SaveIt(void)		// TetiSoft
{
	struct MyHunkHeader *hh;
	struct MyHunkStruct *hs;
	UBYTE *bufpos;
	LONG	*lp,filelen;

	filelen = sizeof(struct MyHunkHeader) + 
				 sizeof(struct MyHunkStruct)  +
				 segsize +
				 4 * 4 + NUM_RELOCS*4 /* +reloc */ +
				 4; /* HUNK_END */
				 
	if (!(buffer=AllocVec(filelen,MEMF_PUBLIC|MEMF_CLEAR)))
	{
//		Cleanup("Out of memory!",RETURN_FAIL);
		Cleanup(LString(MSG_ERROR_NOMEM));	// TetiSoft
		return FALSE;				// TetiSoft
	}

	bufpos=buffer;

	hh = (struct MyHunkHeader *)bufpos;
	hh->id = HUNK_HEADER;
	hh->numhunks = 1;
	hh->size = segsize/4;
	
	bufpos += sizeof(struct MyHunkHeader);
	hs = (struct MyHunkStruct *)bufpos;
	
	hs->id = HUNK_CODE;
	hs->size = segsize/4;

	bufpos += sizeof(struct MyHunkStruct);
	memcpy(bufpos,&MyDFH,sizeof(MyDFH));
	
	bufpos += size_dfh;
	memcpy(bufpos,MyFont->tf_CharData,size_bitplane);

	bufpos += size_bitplane;
	memcpy(bufpos,MyFont->tf_CharLoc,size_charloc);
	
	bufpos += size_charloc;
	memcpy(bufpos,MyFont->tf_CharSpace,size_charspace);
	
	bufpos += size_charspace;
	memcpy(bufpos,MyFont->tf_CharKern,size_kern);
	
	bufpos += size_kern;
	
	lp = (LONG *)bufpos;

	*lp++ = HUNK_RELOC32;
	*lp++ = NUM_RELOCS;
	*lp++ = 0;

	memcpy(lp,relocoffset,sizeof(relocoffset));
	
	lp += (NUM_RELOCS+1);
	
//	*lp++ = HUNK_END;
	*lp = HUNK_END;		// TetiSoft
	
	strcpy(s,toname);
	AddPart(s,fontname,MAXFONTPATH);
	sprintf(s2,"%ld",actsize);
	AddPart(s,s2,MAXFONTPATH);
	
	if (!(MyHandle=Open(s,MODE_NEWFILE)))
	{
//		Fault(IoErr(),0,s,256);
//		Cleanup(s,RETURN_ERROR);
		MyErrorMsg1(LString(MSG_ERROR_CREATE_FILE), s);	// TetiSoft
		Cleanup(NULL);					// TetiSoft
		return FALSE;					// TetiSoft
	}
	
	if (Write(MyHandle,buffer,filelen) != filelen)
	{
//		Fault(IoErr(),0,s,256);
//		Cleanup(s,RETURN_ERROR);
		MyErrorMsg1(LString(MSG_ERROR_WRITE), s);	// TetiSoft
		Cleanup(NULL);					// TetiSoft
		return FALSE;					// TetiSoft
	}
	
	Close(MyHandle);MyHandle=0;
	FreeVec(buffer);buffer=0;
	return TRUE;						// TetiSoft
}

//static void MakeFontContentsFile(void)
static int MakeFontContentsFile(void)		// TetiSoft
{
	LONG filesize;

	if (!(lock=Lock(toname,ACCESS_READ)))
	{
//		Fault(IoErr(),0,s,256);
//		Cleanup(s,RETURN_ERROR);
		MyErrorMsg1(LString(MSG_ERROR_LOCK), toname);	// TetiSoft
		Cleanup(NULL);					// TetiSoft
		return FALSE;					// TetiSoft
	}
	
	strcpy(s,fontname);
	strcat(s,".font");
	
	if (!(fch=NewFontContents(lock,s)))
	{
//		Cleanup("Could not create font contents header!",RETURN_ERROR);
		Cleanup(LString(MSG_ERROR_FCH));		// TetiSoft
		return FALSE;					// TetiSoft
	}

	UnLock(lock);lock=0;
	
	filesize = sizeof(struct FontContentsHeader);

	switch(fch->fch_FileID)
	{
		case FCH_ID:
			filesize += (fch->fch_NumEntries * sizeof(struct FontContents));
			break;
			
		case TFCH_ID:
		case OFCH_ID:	// TetiSoft: Forgotton?
			filesize += (fch->fch_NumEntries * sizeof(struct TFontContents));
			break;
		
		default:
//			Cleanup("Unexpected font contents ID!?",RETURN_ERROR);
			Cleanup(LString(MSG_ERROR_FCH_ID));	// TetiSoft
			return FALSE;				// TetiSoft
	}
	
	strcpy(s,toname);
	AddPart(s,fontname,MAXFONTPATH);
	strcat(s,".font");
	
	if (!(MyHandle=Open(s,MODE_NEWFILE)))
	{
//		Fault(IoErr(),0,s,256);
//		Cleanup(s,RETURN_ERROR);
		MyErrorMsg1(LString(MSG_ERROR_CREATE_FILE), s);	// TetiSoft
		Cleanup(NULL);					// TetiSoft
		return FALSE;					// TetiSoft
	}
	
	if (Write(MyHandle,fch,filesize) != filesize)
	{
//		Fault(IoErr(),0,s,256);
//		Cleanup(s,RETURN_ERROR);
		MyErrorMsg1(LString(MSG_ERROR_WRITE), s);	// TetiSoft
		Cleanup(NULL);					// TetiSoft
		return FALSE;					// TetiSoft
	}
	
	Close(MyHandle);MyHandle=0;
	return TRUE;						// TetiSoft
}

//static void Action(void)
static int Action(void)		// TetiSoft
{
	static struct TextAttr ta;
	BPTR lk;
	LONG *lp;

	ta.ta_Name=fromname;
	ta.ta_Style=0;
	ta.ta_Flags=0;
	
	MyDFH.moveq = 0x70FF;		/* moveq #-1 d0 */
	MyDFH.rts = 0x4E75;		/* rts */
	MyDFH.dfh.dfh_DF.ln_Type = NT_FONT;
	MyDFH.dfh.dfh_FileID = DFH_ID;

	l = strlen(fontname);
	if (l > (MAXFONTNAME-1)) l = MAXFONTNAME-1;
	memcpy(MyDFH.dfh.dfh_Name,fontname,l);
	MyDFH.dfh.dfh_Name[l] = '\0';

	strcpy(s,toname);
	AddPart(s,fontname,MAXFONTPATH);
	if ((lk=Lock(s,ACCESS_READ)))
	{
		UnLock(lk);
	} else {
		if (!(lk=CreateDir(s)))
		{
//			Fault(IoErr(),"Can't create directory",s,256);
//			Cleanup(s,RETURN_ERROR);
			MyErrorMsg1(LString(MSG_ERROR_CREATE_DIR), s);	// TetiSoft
			Cleanup(NULL);					// TetiSoft
			return FALSE;					// TetiSoft
		}
		UnLock(lk);
	}
	
	while ((lp = *sizes++))
	{
		ta.ta_YSize = actsize = *lp;

		if (!(MyFont=OpenDiskFont(&ta)))
		{
//			Fault(IoErr(),"Can't open font",s,256);
//			Cleanup(s,RETURN_FAIL);
			Cleanup(LString(MSG_ERROR_OPEN_FONT));		// TetiSoft
			return FALSE;					// TetiSoft

		} /* if (!(MyFont=OpenDiskFont(&ta))) */

		numchars = MyFont->tf_HiChar - MyFont->tf_LoChar + 1 + 1;
		
		CalcSegSize();
		
		MyDFH.dfh.dfh_TF = *MyFont;
		MyDFH.dfh.dfh_TF.tf_Flags |= (FPF_DESIGNED | FPF_REMOVED | FPF_DISKFONT);
		MyDFH.dfh.dfh_TF.tf_Flags &= ~FPF_ROMFONT;

		CalcReloc();
		
//		SaveIt();
		if(!SaveIt())			// TetiSoft
			return FALSE;		// TetiSoft

		CloseFont(MyFont);MyFont=0;
				
	} /* while ((lp = *sizes++)) */
	
//	MakeFontContentsFile();
	return MakeFontContentsFile();		// TetiSoft
}

//void main(void)
//{
//	OpenLibs();
//	GetArguments();
//	Action();
//	Cleanup(0,RETURN_OK);
//}

// New main func by TetiSoft
int bitline(char *FontDir, char *FontName, long **Sizes)
{
	int rc;
	static char fontfilename[MAXFONTPATH];

	strcpy(fontfilename, FontName);
	strcat(fontfilename, ".font");
	fromname = fontfilename;
	toname = FontDir;
	fontname = FontName;
	sizes = Sizes;
	rc = Action();
	Cleanup(NULL);
	return rc;
}
