#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "portable.h"
#include "chinese.h"
#include "vga.h"
#include "HBF_api.h"
static char *cfont;
static int maxfont=1011;
static char efont[256][15]; 
static int cmaplen,emaplen;
static struct {
  int empty;
  int start;
  int len;
  int maplen;
  FILE *fp;
} chfp[10];
static int chfpnum;

#define INTERNAL_FONT 0
#define HBF_FONT 1
static int FontType;
static void ReadHBFFont();
static WORD tran_code_HBF(int sys,CHAR b1,CHAR b2);
static void drawHBFFont(int x,int y,WORD code);
static char *chfontpath;
extern FILE *statuslog;
void load_sys_font_table()
{
  char *fname;
  FILE *fp,*ffp;
  char file[255];
  int i,j,clen,cloc,len,empty;
  char *buf;
  

  fname = getenv("CHFONT");
  if (fname == NULL)
    fname = "/usr/local/chinese/kcfont";
  else
    fname = strdup(fname);
  
  fp =fopen(fname,"rb");
  if (fp == NULL)
    {
      fprintf(statuslog,"Can't open %s\n",fname);
      exit(-1);
    }
  
  fname = getenv("LOADFONT");
  if (fname == NULL)
    maxfont = 1011;
  else
    {
      maxfont = atoi(fname);
      if (maxfont < 1011)
	maxfont = 1011;
    }
  chfontpath = getenv("CHFONTDIR");
  if (chfontpath == NULL)
    chfontpath = "/usr/local/chinese/";
  else
    chfontpath = strdup(chfontpath);
    
  cfont = (char *) malloc(32*maxfont);
  if (cfont == NULL)
    {
      fprintf(statuslog,"out of memory\n");
      exit(-1);
    }
  
  /* clear font pattern buffer */
  for(i=0;i<maxfont;i++)
    for(j=0;j<32;j++)
      cfont[i*32+j] = 0;
  for(i=0;i<256;i++)
    for(j=0;j<15;j++)
      efont[i][j] = 0;
  buf = (char *) malloc(maxfont*32);
  /* load ascii font */
  fscanf(fp,"%s",file);
  if (strcmp(file,"!!!HBF")==0)
    {
      FontType = HBF_FONT;
      fgets(file,255,fp);
      fscanf(fp,"%s",file);
    }
  else
    FontType = INTERNAL_FONT;
  fscanf(fp,"%d %d\n",&empty,&emaplen);
  if (emaplen != 15 && emaplen != 16)
    {
      fprintf(statuslog,"English font must be 14 or 16 height\n");
      exit(-1);
    }
  ffp = fopen(file,"rb");
  if (ffp == NULL)
    {
      fprintf(statuslog,"Can't open %s\n",file);
      exit(-1);
    }
  fseek(ffp,empty,SEEK_SET);
  len = fread(buf,emaplen,256,ffp);
  if (len != 256)
    {
      fprintf(statuslog,"English font error\n");
      exit(1);
    }
  fclose(ffp);
  /* strip the last line of char */
  for(i=0;i<256;i++)
    for(j=0;j<15;j++)
      efont[i][j] = buf[i*emaplen+j];

  /* load chinese font */
  if (FontType == HBF_FONT)
    {
      ReadHBFFont(fp);
      fclose(fp);
      return;
    }
  
  chfpnum = 0;
  while(!feof(fp))
    {
      *file = 0;
      fscanf(fp,"%s %d %d\n",file,&empty,&cmaplen);
      
      if (*file == 0)
	break;

      cmaplen *= 2;
      chfp[chfpnum].fp = fopen(file,"rb");
      if (chfp[chfpnum].fp == NULL)
	{
	  fprintf(statuslog,"Can't open %s\n",file);
	  exit(-1);
	}
      fseek(chfp[chfpnum].fp,empty,SEEK_SET);
      do{
	fscanf(fp,"%d %d",&cloc,&clen);
	if (cloc == 0 && clen == 0)
	  break;
	chfp[chfpnum].start = cloc;
	chfp[chfpnum].len = clen;
	chfp[chfpnum].empty = empty;
	chfp[chfpnum].maplen = cmaplen;
	if (cloc >= maxfont)
	  {
	    chfp[chfpnum+1].fp = chfp[chfpnum].fp;
	    chfpnum++;
	    continue;
	  }
	if (cloc+clen > maxfont)
	  clen = maxfont- cloc;
	len = fread(buf,cmaplen,clen,chfp[chfpnum].fp);
	if (len != clen)
	  {
	    fprintf(statuslog,"Chinese font error\n");
	    exit(-1);
	  }
	/* strip the last line */
	if (cmaplen >=30)
	  {
	    for(i=0;i<clen;i++)
	      memcpy(&cfont[30*(cloc+i)],&buf[i*cmaplen],30);
	  }
	else
	  {
	    for(i=0;i<clen;i++)
	      memcpy(&cfont[30*(cloc+i)],&buf[i*cmaplen],cmaplen);
	  }
		 
	chfp[chfpnum+1].fp = chfp[chfpnum].fp;
	chfpnum++;
	if (chfpnum == 10)
	  {
	    break;
	  }
      } while(1);
      
    }
  fclose(fp);
}

void ch_drawctext(int x,int y,WORD code)
{
  int i;
  char buf[30];

  if (FontType == HBF_FONT)
    {
      drawHBFFont(x,y,code);
      return;
    }

  if (code < maxfont)
    mon_drawctext(x,y,&cfont[code*30]);
  else
    {
      for(i=0;i<chfpnum;i++)
	if ((code >= chfp[i].start) && (code < (chfp[i].start + chfp[i].len)))
	  {
	    memset(buf,0,30);
	    fseek(chfp[i].fp,chfp[i].maplen*(code-chfp[i].start)+
		  chfp[i].empty,SEEK_SET);
	    if (cmaplen > 30)
	      fread(buf,30,1,chfp[i].fp);
	    else
	      fread(buf,chfp[i].maplen,1,chfp[i].fp);
	    break;
	  }
      if (i != chfpnum)
	mon_drawctext(x,y*16,buf);
    }
}


void ch_drawtext(int x,int y,CHAR c)
{
  mon_drawtext(x,y*16,efont[c]);
}
/* the transform rule is some bug now.I must be debug future */
WORD tran_code(int sys,CHAR b1,CHAR b2)
{
  WORD code;
  
  if (FontType == HBF_FONT)
    return tran_code_HBF(sys,b1,b2);
  switch(sys)
    {
    case CODE_BIG5:
      if (b2 < 0x40)
	return 0xffff;
      else if (b2 <0x7f)
	code = b2 - 0x40;
      else if (b2 < 0xa1)
	return 0xffff;
      else if (b2 < 0xff)
	code = b2 - 0xa1 + 0x3f;
      
      if (b1 < 0x81)
	return 0xffff;
      else if (b1 <= 0x8d)
	code += 0xeeb8 - 0x8001 + (b1 - 0x81)*157;
      else if (b1 <= 0xa0)
	code += 0xe311 - 0x8001 + (b1 - 0x8e)*157;
      else if (b1 <= 0xa3)
	code += 0x8400 - 0x8001 + (b1 - 0xa1)*157;
      else if (b1 < 0xc6)
	code += 0x8800 - 0x8001 + (b1 - 0xa4)*157;
      else if (b1 == 0xc6)
	{
	  if (b2 < 0x7f)
	    code += 0x8800 - 0x8001 + (b1 - 0xa4)*157;
	  else
	    code = 0x8001 - 0x8001 + (b2 -0xa1);
	}
      else if (b1 <= 0xc8)
	code += 0x803f - 0x8001 + (b1 - 0xc7)*157;
      else if (b1 <= 0xf9)
	code += 0x9d18 - 0x8001 + (b1 -0xc9)*157;
      else if (b1 <= 0xfe)
	code += 0xe000 -0x8001 + (b1 - 0xfa)*157;
      else
	return 0xffff;
      break;
    default:
      code = 0xffff;
    }

  if (code > 14000)
    {
      code = 0xffff;
    }

  return code;
}


static HBF *hbf;  

static void ReadHBFFont(FILE *fp)
{
  char buf[100],*tok;
  int ptr,i;
  fprintf(statuslog,"lsdkfjlds\n");
  fgets(buf,100,fp);
  tok = strtok(buf," \t\n");
  fprintf(statuslog,"Open HBF font %s\n",tok);  
  hbf = HBF_OpenFont(tok);

  if (hbf == NULL)
    return;
  hbf->chfp = (FILE **) malloc(sizeof(FILE *)*hbf->numcoderange);
  for(i=0;i<hbf->numcoderange;i++)
    {
      strcpy(buf,chfontpath);
      strcat(buf,hbf->chfile[i]);
      hbf->chfp[i] = fopen(buf,"r");
      if (hbf->chfp[i] == NULL)
	{
	  fprintf(statuslog,"Font file %s can't open\n",buf);
	  continue;
	}
      fseek(hbf->chfp[i],hbf->chlen[i],SEEK_SET);
      if (hbf->codestart[i] < maxfont)
	{
	  if (hbf->codestart[i+1] < maxfont)
	      fread(&cfont[hbf->codestart[i]*hbf->sizeb],hbf->sizeb,
		    hbf->codestart[i+1]-hbf->codestart[i],hbf->chfp[i]);
	      
	  else
	    fread(&cfont[hbf->codestart[i]*hbf->sizeb],hbf->sizeb,
		  maxfont-hbf->codestart[i],hbf->chfp[i]);
	}
    }
}

static WORD tran_code_HBF(int sys,CHAR b1,CHAR b2)
{
  int i;
  WORD code;
  WORD ch;
  ch = (b1 <<8)+b2;

  for(i=0;i<hbf->numcoderange;i++)
    if (ch >= hbf->coderange[i*2] && ch <= hbf->coderange[i*2+1])
      break;
  if (i == hbf->numcoderange)
    {
      return 0xffff;
    }
  else
    {
      CHAR c1 = hbf->coderange[i*2]/256;
      CHAR c2 = hbf->coderange[i*2]%256;
      return hbf->codestart[i]+(b1-c1)*hbf->charsofline+
	    (hbf->b2tran[b2]-hbf->b2tran[c2]);
    }
}

static void drawHBFFont(int x,int y,WORD code)
{
  int i;
  char buf[32];

  if (code < maxfont)
    {
      memcpy(buf,&cfont[hbf->sizeb*code],hbf->sizeb);
      if (hbf->sizeb < 32)
	memset(buf+hbf->sizeb,0,32-hbf->sizeb);
      mon_drawctext(x,y*16,buf);
      return;
    }

  for(i=0;i<hbf->numcoderange;i++)
    {
      if (code < hbf->codestart[i])
	continue;
      if (code >= hbf->codestart[i+1])
	continue;
      fseek(hbf->chfp[i],hbf->sizeb*(code-hbf->codestart[i])+hbf->chlen[i],SEEK_SET);
      fread(buf,hbf->sizeb,1,hbf->chfp[i]);
      if (hbf->sizeb < 32)
	memset(buf+hbf->sizeb,0,32-hbf->sizeb);
      mon_drawctext(x,y*16,buf);
      return;
    }
  fprintf(statuslog,"%x\n",code);
}
	    
	  
  
      





