/*
 *
 * fwindex.c
 *
 *	14 Feb. 1997  by E.Terakawa
 *
 */

/* This file is part of VFlib
 *
 * Copyright (C) 1995 Hirotsugu KAKUGAWA.   All rights reserved.
 *
 * VFlib is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
 * to anyone for the consequences of using it or for whether it serves any
 * particular purpose or works at all, unless he says so in writing.  Refer
 * to the GNU General Public License for full details.
 *
 * Everyone is granted permission to copy, modify and redistribute
 * VFlib, but only under the conditions described in the GNU
 * General Public License.  A copy of this license is supposed to have been
 * given to you along with VFlib so you can know your rights and
 * responsibilities.  It should be in a file named COPYING.  Among other
 * things, the copyright notice and this notice must be preserved on all
 * copies.
 */

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

#include "fwindex.h"

#ifndef SEEK_SET
#  define SEEK_SET 0
#endif

#ifndef SEEK_END
#  define SEEK_END 2
#endif

#define BUFSIZE (16*1024)

unsigned char buf[BUFSIZE+4],buf2[4],tategaki[(0x5e*(0x26-0x21+1)+7)/8];
int address_table[10000],first_byte[10000];
int first_byte_count[256],first_byte_table2[256];

void set_word(unsigned char *p,int b,unsigned int d){
  p[b]=d & 0xff;
  p[b+1]=(d>>8)& 0xff;
}

void set_dword(unsigned char *p,int b,unsigned long d){
  p[b]=d & 0xff;
  p[b+1]=(d>>8)& 0xff;
  p[b+2]=(d>>16)& 0xff;
  p[b+3]=d>>24;
}

int issjis1(unsigned char c){
  if(((0x81<=c)&&(c<=0x9f))||((0xe0<=c)&&(c<=0xef)))return -1;
  else return 0;
}

int issjis2(unsigned char c){
  if((0x40<=c)&&(c<=0xfc)&&(c!=0x7f))return -1;
  else return 0;
}

unsigned int sjistojis(unsigned int s){
  int b1,b2;
  b1=(s>>8)& 0xff; b2=s & 0xff;
  if(!issjis1(b1)||!issjis2(b2))return 0;
  if(b1>=0xe0)b1-=0x40;
  b1-=0x71;
  b1*=2;
  b1++;
  if(b2<=0x9e){
    if(b2>=0x80)b2--;
    b2-=0x1f;
  }else{
    b2-=0x7e;
    b1++;
  }
  return b1*0x100+b2;
}

int iskana(unsigned char c){
  if((0xa1<=c)&&(c<=0xdf))return 1;
  else return 0;
}

void convsjistoeuc(unsigned char *sjis,unsigned char *euc){
  int i,j,len,code;
  len=strlen(sjis);
  j=0;
  for(i=0;i<len;i++){
    if((code=sjistojis(sjis[i]*0x100+sjis[i+1]))!=0){
      euc[j++]=((code >> 8)&0xff)|0x80;
      euc[j++]=(code & 0xff)|0x80;
      i++;
    }else{
      if(iskana(sjis[i]))
	euc[j++]=0x8e;
      euc[j++]=sjis[i];
    }
  }
  euc[j++]=0;
}

int main(int argc,char *argv[]){
  FILE *infile,*outfile;
  unsigned char filename[256],szbuf[256],fontname[256];
  char *p;
  int argcount,count;
  int infilesize;
  int startpoint,endpoint,seekpoint,bufhead;
  int len,jis,font_data_start,table2_start;
  int i,j,tmp,flag;
  int OptionDebug,OptionList;
  if(argc<2){
    printf("USAGE: fwindex filename[.fws]\n");
    exit(-1);
  }

  argcount=1;
  OptionDebug=OptionList=0;
  while(argcount<argc && argv[argcount][0]=='-'){
    if(strcasecmp(argv[argcount]+1,"d")==0){
      OptionDebug=1;
    }
    if(strcasecmp(argv[argcount]+1,"l")==0){
      OptionList=1;
    }
    argcount++;
  }

  for(;argcount<argc;argcount++){

    count=0;
    for(i=0;i<256;i++)first_byte_count[i]=0;
    for(i=0;i<(0x5e*(0x26-0x21+1)+7)/8;i++)tategaki[i]=0;


    strcpy(filename,argv[argcount]);
    if(strstr(filename,".fws")==NULL)
      strcat(filename,".fws");

    if((infile=fopen(filename,"rb"))==NULL){
      printf("%s :Cannot Open File!\n",filename);
      exit(-1);
    }

    strcpy(filename,argv[argcount]);
    if((p=strstr(filename,".fws"))==NULL)
      strcat(filename,".fwi");
    else
      strcpy(p,".fwi");

    printf("outfilename: %s\n",filename);

    fseek(infile,0,SEEK_END);
    infilesize=ftell(infile);
    if(OptionDebug)
      printf("infilesize: %08X(%d)\n",infilesize,infilesize);

    fseek(infile,FWS_FONTNAME,SEEK_SET);
    fread(buf,1,0x20,infile);
    buf[0x20]=0;
    convsjistoeuc(buf,fontname);
    printf("fontname: %s\n",fontname);

    if(OptionList)continue;

    if((outfile=fopen(filename,"wb"))==NULL){
      printf("%s :Cannot Open File!\n",filename);
      exit(-1);
    }

    bufhead=((infilesize-1)/BUFSIZE)*BUFSIZE;
    fseek(infile,bufhead,SEEK_SET);
    fread(buf,1,BUFSIZE,infile);
    endpoint=infilesize-1-bufhead;
    seekpoint=endpoint-4;

/*  printf("bufhead: %08X(%d)\n",bufhead,bufhead);
    printf("endpoint: %08X(%d)\n",endpoint,endpoint);
*/

/* 文字データのアドレステーブルをつくる。（一番最初の一文字を除く）*/
    count=0;
    while(1){
      seekpoint--;
      if(seekpoint<0){
	int i;
	bufhead-=BUFSIZE;
	if(bufhead<0)break;
	for(i=0;i<4;i++)buf[BUFSIZE+i]=buf[i];
	fseek(infile,bufhead,SEEK_SET);
	fread(buf,1,BUFSIZE,infile);
	seekpoint+=BUFSIZE;
	endpoint+=BUFSIZE;
/*	printf("bufhead: %08X(%d)\n",bufhead,bufhead);*/
      }
      if(buf[seekpoint]==0xf){
/*	printf("seekpoint: %08X(%d)\n",seekpoint,seekpoint);*/
	len=buf[seekpoint+3]+buf[seekpoint+4]*256;
	if(seekpoint+2+len==endpoint){
	  endpoint=seekpoint;
	  startpoint=bufhead+seekpoint+1;
	  address_table[count]=startpoint;
	  jis=buf[seekpoint+1]+buf[seekpoint+2]*0x100;
	  first_byte[count++]=jis>>8;
	  first_byte_count[jis>>8]++;
	  /*縦書き用が別に用意されている文字のテーブルを作る*/
	  if((jis>=0x2121)&&(jis<0x2600)&&(jis & 0x80)){
	    int tmp;
	    tmp= ((jis >> 8) - 0x21)*0x5e + (jis & 0x7f) - 0x21;
	    tategaki[tmp / 8]|=(1 << (tmp & 7));
	  }
	  seekpoint=endpoint-4;
/*	  printf("startpoint: %08X(%d)\n",startpoint,startpoint);*/
	}
      }
    }

/* 一番最初の文字データの先頭を探す */
    bufhead=((startpoint-2)/BUFSIZE)*BUFSIZE;
    fseek(infile,bufhead,SEEK_SET);
    fread(buf,1,BUFSIZE,infile);
    endpoint=startpoint-bufhead;

    if(buf[endpoint-1]!=0xf){
      printf("ERROR: Cannot handle this format!\n");
      exit(-1);
    }
    seekpoint=endpoint-2;

    while(1){
      seekpoint--;
      if(seekpoint<0){
	int i;
	bufhead-=BUFSIZE;
	if(bufhead<0){
	  startpoint=-1;
	  break;
	}
	for(i=0;i<4;i++)buf[BUFSIZE+i]=buf[i];
	fseek(infile,bufhead,SEEK_SET);
	fread(buf,1,BUFSIZE,infile);
	seekpoint+=BUFSIZE;
	endpoint+=BUFSIZE;
	printf("bufhead: %08X(%d)\n",bufhead,bufhead);
      }
      len=buf[seekpoint]+buf[seekpoint+1]*256;
/*      printf("seek:%04X  len:%04X\n",seekpoint,len);*/
      if(seekpoint+len==endpoint){
	startpoint=bufhead+seekpoint-2;
	j=0;
	flag=0;
	do{
	  fseek(infile,startpoint-5*j-4,SEEK_SET);
	  fread(buf2,1,4,infile);
	  tmp=buf2[0]+buf2[1]*0x100+buf2[2]*0x10000+buf2[3]*0x1000000;
	  if(tmp!=0){
	    flag=1;
	    break;
	  }
	  j++;
	}while(j<count);
	if(flag!=0){
	  flag=0;	
	  for(i=0;i<count;i++){
	    if(address_table[i]==tmp+startpoint){
	      flag=1;
	      break;
	    }
	  }
	  if(flag!=0)break;
	}
      }
    }
    if(startpoint<0){
      printf("ERROR: Cannot handle this format!\n");
      exit(-1);
    }
    font_data_start=startpoint;
    address_table[count]=startpoint;
    fseek(infile,font_data_start+1,SEEK_SET);
    first_byte[count]=fgetc(infile);
    first_byte_count[first_byte[count++]]++;

    if(OptionDebug){
      printf("FONT DATA start: %08X(%d)\n",font_data_start,font_data_start);
      printf("Number of Characters: %04X(%d)\n",count,count);
      printf("Debug: %08X\n",address_table[0]);
    }

    if(font_data_start-5*count<0){
      printf("申し訳ありませんが、\n"
	     "現バージョンではこのフォントに対応できないようです。\n"
	     "寺川 t50942@hongo.ecc.u-tokyo.ac.jp まで御連絡下さい。\n");
      exit(-1);
    }

    /* Table2 のチェック */
    fseek(infile,font_data_start-5*count,SEEK_SET);
    for(i=0;i<count;i++){
      fread(buf,1,5,infile);
      tmp=buf[1]+buf[2]*0x100+buf[3]*0x10000+buf[4]*0x1000000;
      flag=0;	
      for(i=0;i<count;i++){
	if(address_table[i]==tmp+font_data_start){
	  flag=1;
	  break;
	}
      }
      if(flag==0)break;
    }

    if(flag==0){
      printf("ERROR!!!\n");
      exit(-1);
    }
    table2_start=font_data_start-5*count;
    if(OptionDebug){
      printf("Table2 Address: %08X\n",table2_start);
    }
/*
    for(i=0x20;i<0x80;i++){
      printf("%02X:%02X",i,first_byte_count[i]);
      if((i%8)==7)printf("\n");
      else printf(" ");
    }
*/

    i=0;
    while(i<count){
      fseek(infile,table2_start+5*i+1,SEEK_SET);
      fread(buf2,1,4,infile);
      tmp=buf2[0]+buf2[1]*0x100+buf2[2]*0x10000+buf2[3]*0x1000000;
      for(j=0;j<count;j++){
	if(address_table[j]==font_data_start+tmp)break;
      }
      first_byte_table2[first_byte[j]]=i+1;
      i+=first_byte_count[first_byte[j]];
    }

    if(OptionDebug){
      for(i=0x20;i<0x80;i++){
	printf("%04X:%04X",first_byte_table2[i],first_byte_count[i]);
	if((i%4)==3)printf("\n");
	else printf(" ");
      }

      for(i=0;i<(0x5e*6+7)/8;i++){
	printf("%02X",tategaki[i]);
	if((i%16)==15)printf("\n");
	else printf(" ");
      }
      printf("\n");
    }

    /* インデックスファイルへの出力 */
    strcpy(buf,"FW_INDEX");
    for(i=8;i<0x10;i++)buf[i]=0;
    set_dword(buf,FWI_NUMBER_OF_CHARS,count);
    set_dword(buf,FWI_TABLE2_START,table2_start);
    set_dword(buf,FWI_FONT_DATA_START,font_data_start);
    set_dword(buf,FWI_TABLE1_START,0x20);
    for(i=0x20;i<0x80;i++){
      set_word(buf,0x20+(i-0x20)*4,first_byte_table2[i]);
      set_word(buf,0x20+(i-0x20)*4+2,first_byte_count[i]);
    }
    fwrite(buf,1,(0x80-0x20)*4+0x20,outfile);
    close(outfile);

    /* イラストフォントの場合は一覧をTeX形式で作成 */
    if(table2_start - count * 0x22 >0x400){
      strcpy(filename,argv[argcount]);
      if((p=strstr(filename,".fws"))==NULL)
	strcat(filename,".tex");
      else
	strcpy(p,".tex");
      if((outfile=fopen(filename,"wb"))==NULL){
	printf("%s :Cannot Open File!\n",filename);
	exit(-1);
      }
      p=strstr(filename,".tex");
      *p=0;
      i=strlen(filename)-1;
      while(i>=0){
	if(filename[i]=='/'){
	  i++;
	  break;
	}
	i--;
      }
      if(i<0)i=0;
      p=&filename[i];
      fseek(infile,table2_start - count * 0x22,SEEK_SET);
      fprintf(outfile,"\\documentstyle[12pt,a4j]{jarticle}\n");
      fprintf(outfile,"\\font\\twty%s=%s at 20pt\n",p,p);
      fprintf(outfile,"\\begin{document}\n");
      fprintf(outfile,"\\twtymin %s \\\\\n",fontname);
      for(i=0;i<count;i++){
	fread(buf,1,0x22,infile);
	convsjistoeuc(buf,szbuf);
	if((buf[0x21]==0x20)&&!iskana(buf[0x20])){
	  fprintf(outfile,"“\\twty%s %c\\twtymin ”：",p,buf[0x20]);
	  fprintf(outfile,"“%c”：%s\\\\\n",buf[0x20],szbuf);
	  
	}else{
	  if((buf[0x21]==0x20)&&iskana(buf[0x20]))buf[0x21]=0x8e;
	  fprintf(outfile,"“\\twty%s %c%c\\twtymin ”：",p,
		  buf[0x21]|0x80,buf[0x20]|0x80);
	  fprintf(outfile,"“%c%c”：%s\\\\\n",
		  buf[0x21]|0x80,buf[0x20]|0x80,szbuf);
	}
      }
      fprintf(outfile,"\\end{document}\n");
      close(outfile);
    }


    close(infile);
  }

  return 0;
}










