/****** Font2Asm *****************************************************
*
*   NAME
*       Font2Asm - create an assembly file from a font image
*
*   A hack, nothing more
*
*  Copyright (c) 1988 Commodore-Amiga, Inc.
* 
*  Executables based on this information may be used in software
*  for Commodore Amiga computers.  All other rights reserved.
* 
*  This information is provided "as is"; no warranties are made.
*  All use is at your own risk, and no liability or responsibility is assumed.
*
*********************************************************************/
#include        "exec/types.h"
#include        "exec/nodes.h"
#include        "exec/lists.h"
#include        "exec/memory.h"
#include        "exec/ports.h"
#include	"graphics/gfxbase.h"
#include	"graphics/text.h"
#include	"graphics/view.h"
#include        "libraries/dos.h"
#include	"libraries/diskfont.h"

#include	"stdio.h"

#ifdef	MANX
#include	"functions.h"
#endif

#ifndef	ColorTextFont
#define	FSB_COLORFONT	6	/* this uses ColorTextFont structure */
#define	FSF_COLORFONT	0x40

/******	ColorTextFont node ******************************************/
/*-----	ctf_Flags --------------------------------------------------*/
#define	CT_COLORMASK	0x000F	/* mask to get to following color styles */
#define	CT_COLORFONT	0x0001	/* color map contains designer's colors */
#define	CT_GREYFONT	0x0002	/* color map describes even-stepped */
				/* brightnesses from low to high */
#define	CTB_MAPCOLOR	0	/* map ctf_FgColor to the rp_FgPen if it's */
#define	CTF_MAPCOLOR	0x0001	/* is a valid color within ctf_Low..ctf_High */

/*-----	ColorTextFont ----------------------------------------------*/
struct ColorTextFont {
    struct TextFont ctf_TF;
    UWORD	ctf_Flags;	/* extended flags */
    UBYTE	ctf_Depth;	/* number of bit planes */
    UBYTE	ctf_FgColor;	/* color that is remapped to FgPen */
    UBYTE	ctf_Low;	/* lowest color represented here */
    UBYTE	ctf_High;	/* highest color represented here */
    UBYTE	ctf_PlanePick;	/* PlanePick ala Images */
    UBYTE	ctf_PlaneOnOff;	/* PlaneOnOff ala Images */
    APTR	ctf_ColorMap;	/* struct ColorMap * for font */
    APTR	ctf_CharData[8]; /*pointers to bit planes ala tf_CharData */
};
#endif

struct ColorTextFont *FindName();
struct GfxBase *OpenLibrary();

FILE *file = 0;

int GetNum(b)
char *b;
{
    int result, base;

    result = 0;
    base = 10;
    while (*b) {
	result *= base;
	if ((*b >= '0') && (*b <= '9')) result += *b - '0';
	else {
	    if (((*b >= 'a') && (*b <= 'f')) ||
		    ((*b >= 'A') && (*b <= 'F'))) {
		if (base != 16) break;
		result += (*b & 0x1f) + 9;
	    }
	    else if ((*b != 'x') && (*b != '$')) base = 16;
	    else break;
	}
	b++;
    }
    if (*b) {
	printf("ERROR: ill formed number\n");
	return(-1);
    }
    else return(result);
}


dataDump(data, height, width)
UWORD *data, height, width;
{
    UWORD col;

    for (; height > 0; height--) {
	col = 0;
	do {
	    if ((col & 7) == 0)
		fprintf(file, "\n\t	dc.w	");
	    else fprintf(file, ",");
	    fprintf(file, "$%04lx", *data++);
	    col++;
	}
	    while (col < width);
	fprintf(file, "\n");
    }
}


main(argc, argv)
int argc;
char *argv[];
{
    struct GfxBase *GfxBase;
    struct ColorTextFont *ctf, *ctf2;
    int i, j, k;
    ULONG *longptr;
    WORD *wordptr;

    GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L);
    if (GfxBase == 0) {
	printf("ERROR: Cannot open \"graphics.library\"\n");
	exit(100);
    }
    if (argc >= 3) {
	file = fopen(argv[1], "w");
	if (file == 0) {
	    printf("ERROR: open failed for font file\n");
	    argc = 0;
	}
    }
    if (argc >= 3) {
      /* see if more than one with this name */
      ctf = FindName(&GfxBase->TextFonts, argv[2]);
      if (ctf) {
        if (FindName(ctf, argv[2])) {
          /* yes: get the one with this size */
          if (argc >= 4) {
            i = GetNum(argv[3]);
            if (i >= 0) {
              while ((ctf) && (ctf->ctf_TF.tf_YSize != i))
                ctf = FindName(ctf, argv[2]);
              if (ctf) {
                /* check for more than one */
                ctf2 = FindName(ctf, argv[2]);
                while ((ctf2) && (ctf2->ctf_TF.tf_YSize != i))
                  ctf2 = FindName(ctf2, argv[2]);
                if (ctf2) {
                  /* yes: get the one with this style */
		  if (argc >= 5) {
		    j = GetNum(argv[4]);
		    if (j >= 0) {
		      ctf = FindName(&GfxBase->TextFonts, argv[2]);
		      while ((ctf) && ((ctf->ctf_TF.tf_YSize != i) ||
			  (ctf->ctf_TF.tf_Style != j)))
			ctf = FindName(ctf, argv[2]);
		      if (ctf) {
			/* check for more than one */
			ctf2 = FindName(ctf, argv[2]);
			while ((ctf2) && ((ctf2->ctf_TF.tf_YSize != i) ||
			    (ctf2->ctf_TF.tf_Style != j)))
			  ctf2 = FindName(ctf2, argv[2]);
			if (ctf2) {
			  /* yes: get the one with this flags */
			  if (argc >= 6) {
			    k = GetNum(argv[5]);
			    if (k >= 0) {
			      ctf = FindName(&GfxBase->TextFonts, argv[2]);
			      while ((ctf) && ((ctf->ctf_TF.tf_YSize != i) ||
				  (ctf->ctf_TF.tf_Style != j) ||
				  (ctf->ctf_TF.tf_Flags != k)))
				ctf = FindName(ctf, argv[2]);
			      if (ctf) {
				/* check for more than one */
				ctf2 = FindName(ctf, argv[2]);
				while ((ctf2) && ((ctf2->ctf_TF.tf_YSize != i)
				    || (ctf->ctf_TF.tf_Style != j) ||
				    (ctf->ctf_TF.tf_Flags != k)))
				  ctf2 = FindName(ctf2, argv[2]);
				if (ctf2) {
				  printf("WARNING: There exists more than one font matching the specification.\n");
				  printf("         The first one found is being used.\n");
                                }
			      }
			      else /* ctf */ {
				printf("ERROR: No font with the specified flags\n");
				argc = 0;
			      }
			    }
			    else /* k */ argc = 0;
			  }
			  else /* argc */ {
			    printf("ERROR: More than one font with the specified name, size, and style\n");
			    argc = 0;
			  }
			}
		      }
		      else /* ctf */ {
		        printf("ERROR: No font with the specified flags\n");
			argc = 0;
		      }
		    }
		    else /* j */ argc = 0;
		  }
		  else /* argc */ {
		    printf("ERROR: More than one font with the specified name, and size\n");
		    argc = 0;
		  }
		}
	      }
	      else /* ctf */ {
		printf("ERROR: No font with the specified size\n");
		argc = 0;
	      }
            }
            else /* i */ argc = 0;
          }
          else /* argc */ {
            printf("ERROR: More than one font with the specified name\n");
            argc = 0;
          }
        }
      }
      else /* ctf */ {
        printf("ERROR: No font with the specified name\n");
        argc = 0;
      }
      CloseLibrary(GfxBase);
    }
    if (argc < 3) {
	printf(
	  "USAGE: Font2Asm <file> <font-name> [<size>] [<style>] [<flags>]\n");
	if (file) fclose(file);
	exit(5);
    }
    ctf->ctf_TF.tf_Accessors++;
    printf("\"%s\" Y %ld S $%02lx F $%02lx\n",
	    ctf->ctf_TF.tf_Message.mn_Node.ln_Name, ctf->ctf_TF.tf_YSize,
	    ctf->ctf_TF.tf_Style, ctf->ctf_TF.tf_Flags);

    /* write out the header */
    fprintf(file, ";------ Included Files ------\n");
    fprintf(file, "\n");
    fprintf(file, "	INCLUDE		\"exec/types.i\"\n");
    fprintf(file, "	INCLUDE		\"exec/nodes.i\"\n");
    fprintf(file, "	INCLUDE		\"libraries/diskfont.i\"\n");
    fprintf(file, "\n");
    fprintf(file, "		moveq	#100,D0\n");
    fprintf(file, "		rts\n");
    fprintf(file, "\n");
    fprintf(file, "		dc.l	0		; ln_Succ\n");
    fprintf(file, "		dc.l	0		; ln_Pred\n");
    fprintf(file, "		dc.b	NT_FONT		; ln_Type\n");
    fprintf(file, "		dc.b	0		; ln_Pri\n");
    fprintf(file, "		dc.l	fontName	; ln_Name\n");
    fprintf(file, "		dc.w	DFH_ID		; FileID\n");
    fprintf(file, "		dc.w	0		; Revision\n");
    fprintf(file, "		dc.l	0		; Segment\n");
    fprintf(file, "fontName:\n");
    fprintf(file, "		dcb.b	MAXFONTNAME,0	; Name\n");
    fprintf(file, "\n");
    fprintf(file, "font:\n");
    fprintf(file, "		dc.l	0		; ln_Succ\n");
    fprintf(file, "		dc.l	0		; ln_Pred\n");
    fprintf(file, "		dc.b	NT_FONT		; ln_Type\n");
    fprintf(file, "		dc.b	0		; ln_Pri\n");
    fprintf(file, "		dc.l	fontName	; ln_Name\n");
    fprintf(file, "		dc.l	0		; mn_ReplyPort\n");
    fprintf(file, "		dc.w	fontEnd-font	; mn_Length\n");
    fprintf(file, "		dc.w	%ld		; tf_YSize\n",
	    ctf->ctf_TF.tf_YSize);
    fprintf(file, "		dc.b	$%02lx		; tf_Style\n",
	    ctf->ctf_TF.tf_Style);
    fprintf(file, "		dc.b	$%02lx		; tf_Flags\n",
	    ctf->ctf_TF.tf_Flags);
    fprintf(file, "		dc.w	%ld		; tf_XSize\n",
	    ctf->ctf_TF.tf_XSize);
    fprintf(file, "		dc.w	%ld		; tf_Baseline\n",
	    ctf->ctf_TF.tf_Baseline);
    fprintf(file, "		dc.w	%ld		; tf_BoldSmear\n",
	    ctf->ctf_TF.tf_BoldSmear);
    fprintf(file, "		dc.w	0		; tf_Accessors\n");
    fprintf(file, "		dc.b	%ld		; tf_LoChar\n",
	    ctf->ctf_TF.tf_LoChar);
    fprintf(file, "		dc.b	%ld		; tf_HiChar\n",
	    ctf->ctf_TF.tf_HiChar);
    fprintf(file, "		dc.l	fontData	; tf_CharData\n");
    fprintf(file, "		dc.w	%ld		; tf_Modulo\n",
	    ctf->ctf_TF.tf_Modulo);
    fprintf(file, "		dc.l	fontLoc		; tf_CharLoc\n");
    if (ctf->ctf_TF.tf_CharSpace)
	fprintf(file, "		dc.l	fontSpace	; tf_CharSpace\n");
    else
	fprintf(file, "		dc.l	0		; tf_CharSpace\n");
    if (ctf->ctf_TF.tf_CharKern)
	fprintf(file, "		dc.l	fontKern	; tf_CharKern\n");
    else
	fprintf(file, "		dc.l	0		; tf_CharKern\n");
    fprintf(file, "\n");
    if (ctf->ctf_TF.tf_Style & FSF_COLORFONT) {
	fprintf(file, "		dc.w	$%04lx		; ctf_Flags\n",
		ctf->ctf_Flags);
	fprintf(file, "		dc.b	%ld		; ctf_Depth\n",
		ctf->ctf_Depth);
	fprintf(file, "		dc.b	%ld		; ctf_FgColor\n",
		ctf->ctf_FgColor);
	fprintf(file, "		dc.b	%ld		; ctf_Low\n",
		ctf->ctf_Low);
	fprintf(file, "		dc.b	%ld		; ctf_High\n",
		ctf->ctf_High);
	fprintf(file, "		dc.b	$%02lx		; ctf_PlanePick\n",
		ctf->ctf_PlanePick);
	fprintf(file, "		dc.b	$%02lx		; ctf_PlaneOnOff\n",
		ctf->ctf_PlaneOnOff);
	if (ctf->ctf_ColorMap &&
		(((struct ColorMap *) ctf->ctf_ColorMap)->Type == 0))
	    fprintf(file, "\t	dc.l	colorMap	; ctf_ColorMap\n");
	else
	    fprintf(file, "\t	dc.l	0		; ctf_ColorMap\n");
	for (i = 0; i < ctf->ctf_Depth; i++)
	    fprintf(file, "\t	dc.l	colorData%ld	; ctf_CharData[%ld]\n",
		    i, i);
	for (; i < 8; i++)
	    fprintf(file, "\t	dc.l	0		; ctf_CharData[%ld]\n",
		    i);
	if (ctf->ctf_ColorMap &&
		(((struct ColorMap *) ctf->ctf_ColorMap)->Type == 0))
	    fprintf(file, "\n");
	    fprintf(file, "colorMap:\n");
	    fprintf(file, "\t	dc.b	$%02lx		; Flags\n",
		    ((struct ColorMap *) ctf->ctf_ColorMap)->Flags);
	    fprintf(file, "\t	dc.b	0		; Type\n");
	    fprintf(file, "\t	dc.b	%ld		; Count\n",
		    ((struct ColorMap *) ctf->ctf_ColorMap)->Count);
	    fprintf(file, "\t	dc.l	colorTable	; ColorTable\n");
	    fprintf(file, "\n");
	    fprintf(file, "colorTable:\n");
	    for (i = 0; i < ((struct ColorMap *) ctf->ctf_ColorMap)->Count; i++)
		fprintf(file, "\t\tdc.w	$%04lx		; (color %ld)\n",
			((UWORD *) ((struct ColorMap *) ctf->ctf_ColorMap)
			->ColorTable)[i], i);
    }
    fprintf(file, "\n");
    fprintf(file, "fontLoc:");
    i = ctf->ctf_TF.tf_LoChar-1;
    longptr = (ULONG *) ctf->ctf_TF.tf_CharLoc;
    j = 0;
    do {
	if (j == 0)
	    fprintf(file, "\n\t	dc.l	");
	else fprintf(file, ",");
	fprintf(file, "$%08lx", *longptr++);
	j++;
	j &= 3;
	i++;
    }
	while (i <= ctf->ctf_TF.tf_HiChar);
    fprintf(file, "\n");

    if (ctf->ctf_TF.tf_CharSpace) {
	fprintf(file, "fontSpace:");
	i = ctf->ctf_TF.tf_LoChar-1;
	wordptr = (WORD *) ctf->ctf_TF.tf_CharSpace;
	j = 0;
	do {
	    if (j == 0)
		fprintf(file, "\n\t	dc.w	");
	    else fprintf(file, ",");
	    fprintf(file, "%04ld", *wordptr++);
	    j++;
	    j &= 7;
	    i++;
	}
	    while (i <= ctf->ctf_TF.tf_HiChar);
	fprintf(file, "\n");
    }

    if (ctf->ctf_TF.tf_CharKern) {
	fprintf(file, "fontKern:");
	i = ctf->ctf_TF.tf_LoChar-1;
	wordptr = (WORD *) ctf->ctf_TF.tf_CharKern;
	j = 0;
	do {
	    if (j == 0)
		fprintf(file, "\n\t	dc.w	");
	    else fprintf(file, ",");
	    fprintf(file, "%04ld", *wordptr++);
	    j++;
	    j &= 7;
	    i++;
	}
	    while (i <= ctf->ctf_TF.tf_HiChar);
	fprintf(file, "\n");
    }

    if (ctf->ctf_TF.tf_Style & FSF_COLORFONT) {
	for (i = 0; i < ctf->ctf_Depth; i++) {
	    for (j = 0; j < i; j++)
		if (ctf->ctf_CharData[i] == ctf->ctf_CharData[j]) break;
	    if (i == j) {
		if (ctf->ctf_TF.tf_CharData == ctf->ctf_CharData[i])
		    fprintf(file, "fontData:\n");
		fprintf(file, "colorData%ld:", i);
		for (j = i; j < ctf->ctf_Depth; j++)
		    if (ctf->ctf_CharData[i] == ctf->ctf_CharData[j])
			fprintf(file, "\ncolorData%ld:", j);
		dataDump(ctf->ctf_CharData[i],
			ctf->ctf_TF.tf_YSize, ctf->ctf_TF.tf_Modulo/2);
	    }
	}
    }
    else {
	fprintf(file, "fontData:");
	dataDump(ctf->ctf_TF.tf_CharData,
		ctf->ctf_TF.tf_YSize, ctf->ctf_TF.tf_Modulo/2);
    }
    fprintf(file, "fontEnd:\n");
    fprintf(file, "\n");
    fprintf(file, "	END\n");

    ctf->ctf_TF.tf_Accessors--;
    fclose(file);
}
