#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "wv.h"

void
wvInitFFN (FFN * item)
{
    U8 i;
    item->cbFfnM1 = 0;
    item->prq = 0;
    item->fTrueType = 0;
    item->reserved1 = 0;
    item->ff = 0;
    item->reserved2 = 0;
    item->wWeight = 0;
    item->chs = 0;
    item->ixchSzAlt = 0;
    wvInitPANOSE (&item->panose);
    wvInitFONTSIGNATURE (&item->fs);
    for (i = 0; i < 65; i++)
	item->xszFfn[i] = 0;
}

void
wvGetFFN6 (FFN * item, wvStream * fd)
{
    int len, i;
    U8 temp8;

#ifdef PURIFY
    wvInitFFN (item);
#endif

    item->cbFfnM1 = read_8ubit (fd);
    temp8 = read_8ubit (fd);
    item->prq = temp8 & 0x03;
    item->fTrueType = (temp8 & 0x04) >> 2;
    item->reserved1 = (temp8 & 0x08) >> 3;
    item->ff = (temp8 & 0x70) >> 4;
    item->reserved2 = (temp8 & 0x80) >> 7;
    item->wWeight = (S16) read_16ubit (fd);
    item->chs = read_8ubit (fd);
    item->ixchSzAlt = read_8ubit (fd);
    wvInitPANOSE (&(item->panose));
    wvInitFONTSIGNATURE (&(item->fs));
    len = item->cbFfnM1 - 5;
    if (len > 65)
	len = 65;
    for (i = 0; i < len; i++)
	item->xszFfn[i] = read_8ubit (fd);
}


void
wvGetFFN (FFN * item, wvStream * fd)
{
    int len, i;
    U8 temp8;

#ifdef PURIFY
    wvInitFFN (item);
#endif

    item->cbFfnM1 = read_8ubit (fd);
    temp8 = read_8ubit (fd);
    item->prq = temp8 & 0x03;
    item->fTrueType = (temp8 & 0x04) >> 2;
    item->reserved1 = (temp8 & 0x08) >> 3;
    item->ff = (temp8 & 0x70) >> 4;
    item->reserved2 = (temp8 & 0x80) >> 7;
    item->wWeight = (S16) read_16ubit (fd);
    item->chs = read_8ubit (fd);
    item->ixchSzAlt = read_8ubit (fd);
    wvGetPANOSE (&(item->panose), fd);
    wvGetFONTSIGNATURE (&(item->fs), fd);
    len = item->cbFfnM1 - 39;
    len = len / 2;
    /*
       item->xszFfn = (U16) wvMalloc(sizeof(U16) * len));
     */
    if (len > 65)
	len = 65;
    for (i = 0; i < len; i++)
	item->xszFfn[i] = read_16ubit (fd);
}

void
wvGetFFN_STTBF (FFN_STTBF * item, U32 offset, U32 len, wvStream * fd)
{
    int i;
    wvTrace (("reading fonts...\n"));
    wvTrace (("seeking to %x, len %d\n", offset, len));
    if (len == 0)
      {
	  item->nostrings = 0;
	  item->ffn = NULL;
      }
    else
      {
	  wvStream_goto (fd, offset);
	  item->extendedflag = read_16ubit (fd);
	  if (item->extendedflag == 0xFFFF)
	      item->nostrings = read_16ubit (fd);
	  else
	      item->nostrings = item->extendedflag;
	  item->extradatalen = read_16ubit (fd);
	  item->ffn = (FFN *) wvMalloc (item->nostrings * sizeof (FFN));
	  for (i = 0; i < item->nostrings; i++)
	    {
#ifdef DEBUG
		char *dbg;
#endif
		wvGetFFN (&(item->ffn[i]), fd);
#ifdef DEBUG
		dbg = wvWideStrToMB (item->ffn[i].xszFfn);
		wvTrace (("font %d: %s\n", i, dbg));
		if (dbg)
		    wvFree (dbg);
#endif
	    }
      }

    wvTrace (("done reading fonts.\n"));
}

void
wvGetFFN_STTBF6 (FFN_STTBF * item, U32 offset, U32 len, wvStream * fd)
{
    U32 count = 0;
    int noffn = 0;
    wvTrace (("reading fonts 6...\n"));
    wvTrace (("seeking to %x, len %d\n", offset, len));
    if (len == 0)
      {
	  item->nostrings = 0;
	  item->ffn = NULL;
	  return;
      }
    wvStream_goto (fd, offset);
    item->extendedflag = 0;
    item->nostrings = 5;	/* lets just set a val to start off with */
    item->extradatalen = 0;
    item->ffn = (FFN *) wvMalloc (item->nostrings * sizeof (FFN));
    if (len != read_16ubit (fd))
	wvError (("FFN STTBF lens differ\n"));
    count += 2;

    while (count < len)
      {
#ifdef DEBUG
	  char *dbg;
#endif
	  if (noffn == item->nostrings)
	    {
		/* need to extend the array just in case */
		item->nostrings += 5;
		item->ffn =
		    (FFN *) realloc (item->ffn, item->nostrings * sizeof (FFN));
	    }
	  wvGetFFN6 (&(item->ffn[noffn]), fd);
	  count += (item->ffn[noffn].cbFfnM1 + 1);
#ifdef DEBUG
	  dbg = wvWideStrToMB (item->ffn[noffn].xszFfn);
	  wvTrace (("font %d: %s\n", noffn, dbg));
	  if (dbg)
	      wvFree (dbg);
#endif
	  noffn++;
      }

    if (item->nostrings != noffn)
	item->nostrings = noffn;

    wvTrace (("done reading fonts 6.\n"));
}

void
wvReleaseFFN_STTBF (FFN_STTBF * item)
{
    if (item->ffn != NULL)
	wvFree (item->ffn);
}


/* 
This has to be extended in the future to return a list of possible 
font names, as the FFN spec mentions. It currently on does the first
one.
*/
char *
wvGetFontnameFromCode (FFN_STTBF * item, int fontcode)
{
    if (fontcode >= item->nostrings)
	return (NULL);

    return (wvWideStrToMB (item->ffn[fontcode].xszFfn));
}


#if 0
int
wvGetFRD_PLCF (FRD ** frd, U32 ** pos, int *nofrd, U32 offset, U32 len,
	       wvStream * fd)
{
    int i;
    if (len == 0)
      {
	  *frd = NULL;
	  *pos = NULL;
	  *nofrd = 0;
      }
    else
      {
	  *nofrd = (len - 4) / 6;
	  *pos = (U32 *) wvMalloc ((*nofrd + 1) * sizeof (U32));
	  if (*pos == NULL)
	    {
		wvError (
			 ("NO MEM 1, failed to alloc %d bytes\n",
			  (*nofrd + 1) * sizeof (U32)));
		return (1);
	    }

	  *frd = (FRD *) wvMalloc (*nofrd * sizeof (FRD));
	  if (*frd == NULL)
	    {
		wvError (
			 ("NO MEM 1, failed to alloc %d bytes\n",
			  *nofrd * sizeof (FRD)));
		wvFree (pos);
		return (1);
	    }
	  wvStream_goto (fd, offset);
	  for (i = 0; i < *nofrd + 1; i++)
	      (*pos)[i] = read_32ubit (fd);
	  for (i = 0; i < *nofrd; i++)
	      wvGetFRD (&((*frd)[i]), fd);
      }
    return (0);
}
#endif
