#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "HBF_api.h"

#define NUM_SCHEME 4
static char *known_scheme[4] = {"GB2312-80","Big5","Big5 Eten v2.00.03",
				  "Unicode vendor v1.1"};
static char *font_property(HBF *hbf,char *sbuf)
{
  int num = atoi(strtok(NULL," \t\n"));
  int i;
  char *buf;

  i = 0;
  while(i<=num)
    {
      /* skip comment first*/
      if (strncmp("COMMENT ",sbuf,8)==0)
	{
	  buf = strtok(sbuf,"\n");
	  sbuf = buf+strlen(buf)+1;
	  continue;
	}
      else
	buf = strtok(sbuf," \t\n");
      i++;
      if (buf == NULL)
	break;
      sbuf = buf+strlen(buf)+1;
      if (strcmp("FAMILY_NAME",buf)==0)
	hbf->family_name = strdup(strtok(NULL,"\n"));
      else if (strcmp("ADD_STYLE_NAME",buf)==0)
	hbf->add_style_name = strdup(strtok(NULL,"\n"));
      else if (strcmp("DEFAULT_CHAR",buf)==0)
	hbf->default_char = strtol(strtok(NULL," \t\n"),NULL,0);
      else if (strcmp("COPYRIGHT",buf)==0)
	hbf->copyright = strdup(strtok(NULL,"\n"));
      else if (strcmp("NOTICE",buf)==0)
	hbf->notice = strdup(strtok(NULL,"\n"));
      else if (strcmp("ENDPROPERTIES",buf)==0)
	return;
      else 
	i--;
    }
  while((buf = strtok(sbuf,"\t\n"))!=NULL)
    {
      sbuf = buf+strlen(buf)+1;
      if (strcmp("ENDPROPERTIES",buf) == 0)
	break;
    }
  return sbuf;
}

static char *setup_b2range(HBF *hbf,char *sbuf)
{
  char *buf;
  int num = atoi(buf=strtok(sbuf," \n\t"));
  int i;
  hbf->numb2range = num;
  hbf->b2range = (unsigned char *) malloc(num*2);
  sbuf = buf+strlen(buf)+1;
  for(i=0;i<=num;i++)
    {
      /* skip comment first*/
      if (strncmp("COMMENT ",sbuf,8)==0)
	{
	  buf = strtok(sbuf,"\n");
	  sbuf = buf+strlen(buf)+1;
	  continue;
	}
      else
	buf = strtok(sbuf," \t\n");
      
      if (buf == NULL)
	break;
      sbuf = buf+strlen(buf)+1;
      if (strcmp("HBF_BYTE_2_RANGE",buf)==0)
	{
	  buf = strtok(NULL," \t\n");
	  sbuf = buf + strlen(buf)+1;
	  hbf->b2range[i*2]   = strtol(buf,&buf,0);
	  buf++;
	  hbf->b2range[i*2+1] = strtol(buf,NULL,0);
	}
      else if (strtok("HBF_END_BYTE_2_RANGES",buf)==0)
	return sbuf;
      else
	i--;
    }
  return sbuf;
}

static char *setup_coderange(HBF *hbf,char *sbuf)
{
  char *buf;
  int num = atoi(buf=strtok(NULL," \n\t"));
  int i;
  
  hbf->coderange = (unsigned short *) malloc(sizeof(unsigned short)*num*2);
  hbf->chfile    = (char **) malloc(sizeof(char *)*num);
  hbf->chlen = (int *) malloc(sizeof(int)*num);
  hbf->codestart = (unsigned short *) malloc(sizeof(unsigned short)*(num+1));
  hbf->numcoderange = num;
  sbuf = buf + strlen(buf)+1;
  for(i=0;i<=num;i++)
    {
      /* skip comment first*/
      if (strncmp("COMMENT",sbuf,7)==0)
	{
	  buf = strtok(sbuf,"\n");
	  sbuf = buf+strlen(buf)+1;
	  i--;
	  continue;
	}
      else
	buf = strtok(sbuf," \t\n");
      
      if (buf == NULL)
	break;
      sbuf = buf+strlen(buf)+1;
      if (strcmp("HBF_CODE_RANGE",buf)==0)
	{
	  if (i >=num)
	    break;
	  buf = strtok(sbuf," \t\n");
	  sbuf = buf+strlen(sbuf)+1;
	  hbf->coderange[i*2] = strtol(buf,&buf,0);
	  buf++;
	  hbf->coderange[i*2+1] = strtol(buf,NULL,0);
	  hbf->chfile[i] = strdup(strtok(sbuf," \t\n"));
	  hbf->chlen[i] = atoi(buf = strtok(NULL," \t\n"));
	  sbuf = buf+strlen(buf)+1;
	}
      else if (strcmp("HBF_END_CODE_RANGES",buf)==0)
	return sbuf;
      else
	i--;
    }
  return sbuf;
}

HBF *ReadHBFFile(FILE *in,HBF *hbf)
{
  char *buf,*sbuf,*ebuf;
  int len,i,j,k;

  buf = (char *) malloc(0x10240);
  fseek(in,0,SEEK_SET);
  if (buf == NULL)
    {
      return NULL;
    }
  len = fread(buf,1,0x10240,in);
  sbuf = buf;
  ebuf = buf+len;
  while(1)
    {
      if (sbuf >= ebuf)
	break;
      /* skip comment first*/
      if (strncmp("COMMENT ",sbuf,8)==0)
	{
	  buf = strtok(sbuf,"\n");
	  sbuf = buf+strlen(buf)+1;
	  continue;
	}
      else
	buf = strtok(sbuf," \t\n");

      if (buf == NULL)
	break;
      sbuf = buf+strlen(buf)+1;
      if (strcmp("HBF_START_FONT",buf)==0)
	{
	  hbf->ver = atof(strtok(NULL," \t\n"));
	  if (hbf->ver != 1.0)
	    {
	      free(buf);
	      return NULL;
	    }
	}
      else if (strcmp("HBF_CODE_SCHEME",buf)==0)
	{
	  int i;
	  char *scheme = strtok(NULL," \t\n");
	  for(i=0;i<NUM_SCHEME;i++)
	    if (strcmp(scheme,known_scheme[i])==0)
	      break;
	  if (i == NUM_SCHEME)
	    hbf->scheme = -1;
	  else
	    hbf->scheme = i;
	}
      else if (strcmp("FONT",buf)==0)
	hbf->font = strdup(strtok(NULL," \t\n"));
      else if (strcmp("HBF_BITMAP_BOUNDING_BOX",buf)==0)
	{
	  hbf->wx = atoi(strtok(NULL," \t\n"));
	  hbf->wy = atoi(strtok(NULL," \t\n"));
	  hbf->dx = atoi(strtok(NULL," \t\n"));
	  hbf->dy = atoi(strtok(NULL," \t\n"));
	}
      else if (strcmp("FONTBOUNDINGBOX",buf)==0)
	{
	  hbf->fwx = atoi(strtok(NULL," \t\n"));
	  hbf->fwy = atoi(strtok(NULL," \t\n"));
	  hbf->fdx = atoi(strtok(NULL," \t\n"));
	  hbf->fdy = atoi(strtok(NULL," \t\n"));
	}
      else if (strcmp("COMMENT",buf)==0)
	  strtok(NULL,"\n");
      else if (strcmp("STARTPROPERTIES",buf)==0)
	sbuf= font_property(hbf,sbuf);
      else if (strcmp("CHARS",buf)==0)
	hbf->chars = atoi(strtok(NULL," \t\n"));
      else if (strcmp("HBF_START_BYTE_2_RANGES",buf)==0)
	sbuf = setup_b2range(hbf,sbuf);
      else if (strcmp("HBF_START_CODE_RANGES",buf)==0)
	sbuf = setup_coderange(hbf,sbuf);
      else if (strcmp("HBF_END_FONT",buf)==0)
	break;
      else
	{
	  /* We just ignore all unknown keyword */
	  strtok(NULL,"\n");
	}
    }
  hbf->charsofline = 0;
  for(i=0;i<hbf->numb2range;i++)
    hbf->charsofline += hbf->b2range[i*2+1]-hbf->b2range[i*2]+1;

  for(i=k=j=0;i<256;i++)
    {
      if (i < hbf->b2range[j*2])
	hbf->b2tran[i]=255;
      else if (i == hbf->b2range[j*2+1])
	{
	  j++;
	  hbf->b2tran[i]=k;
	  k++;
	}
      else 
	{
	  hbf->b2tran[i]=k;
	  k++;
	}
    }
  for(k=0;k<=hbf->numcoderange;k++)
    if (k==0)
      hbf->codestart[k] = 0;
    else
      {
	CHAR start2,end2,start1,end1;
	int num;
	
	i = k-1;
	start2 = hbf->coderange[2*i] % 256;
	start1 = hbf->coderange[2*i] / 256;
	end2 = hbf->coderange[2*i+1] % 256;
	end1 = hbf->coderange[2*i+1] / 256;
	hbf->codestart[k] = hbf->codestart[k-1]+
	                    (end1-start1)*hbf->charsofline+(end2-start2+1);
      }
  j = 0;
  k = 0;
  hbf->sizeb = (hbf->wx+7)/8*hbf->wy;

  free(buf);
  return hbf;
}
	 
HBF *HBF_OpenFont(char *hbfFileName)
{
  HBF *hbf = (HBF *) malloc(sizeof(HBF));
  FILE *fp;

  if (hbf == NULL)
    return NULL;

  if (!(fp = fopen(hbfFileName,"r")))
    return NULL;

  if (ReadHBFFile(fp,hbf)==NULL)
    return NULL;
  fclose(fp);

  return hbf;
}











