#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jstring.h>
#include <ctype.h>

void xdump(FILE *, FILE *);
int write_16multifont( unsigned int , unsigned char *);
int write_24multifont( unsigned int , unsigned char * );
int get_hankaku24_pattern(unsigned int , long , unsigned char *);
int get_zenkaku24_pattern(unsigned int , long , unsigned char *);
int write_32multifont( unsigned int , unsigned char * );
int get_zenkaku32_pattern(unsigned int , long , unsigned char *);
int write_48multifont( unsigned int , unsigned char * );
int get_zenkaku48_pattern(unsigned int , long , unsigned char *);
void MOJI_zentohan(unsigned int , unsigned char *);
void MOJI_32to16(unsigned char *);
void MOJI_48to24(unsigned char *);
unsigned int  jis_to_flocate( unsigned int );

#define maru24hk "q:\\fj2\\font\\maru24hk.fnt"
#define goth24hk "q:\\fj2\\font\\goth24hk.fnt"
#define kyou24hk "q:\\fj2\\font\\kyou24hk.fnt"
#define minn24hk "q:\\fj2\\font\\minn24hk.fnt"
#define maru24   "q:\\fj2\\font\\maru24.fnt"
#define goth24   "q:\\fj2\\font\\goth24.fnt"
#define kyou24   "q:\\fj2\\font\\kyou24.fnt"
#define minn24   "q:\\fj2\\font\\minn24.fnt"
#define syr3cg   "q:\\oasys\\syr3cg"
#define syg3cg   "q:\\oasys\\syg3cg"
#define syk3cg   "q:\\oasys\\syk3cg"
#define sys3cf   "q:\\oasys\\sys3cf"
#define mouh48   "q:\\fj2\\font\\mouh48.fnt"
#define goth48   "q:\\fj2\\font\\goth48.fnt"
#define minn48   "q:\\fj2\\font\\minn48.fnt"

FILE *fp,*fpout;

void main()
{
	unsigned char filename[30];
	unsigned char temp[81];
	unsigned int  fontno;
	
	printf("\x1b[2J");
	printf("--------------------------------------------------------------\n");
	printf("指定されたフォントで入力された文字列のパターンデータを作ります。\n");
	printf("--------------------------------------------------------------\n");
	printf("\n\n");
	
	printf("変換した文字データを格納するファイル名を入力してください。\n");
	scanf("%29s",filename);
	printf("\n");
	
	printf("フォント番号を指定してください。\n");
	printf("    16ドット文字→ まる文字=1  ゴシック体=2  教科書体=3\n");
	printf("    24ドット文字→ まる文字=4  ゴシック体=5  教科書体=6  明朝体=7  毛筆体=15\n");
	printf("    32ドット文字→ まる文字=8  ゴシック体=9  教科書体=10 明朝体=11\n");
	printf("    48ドット文字→             ゴシック体=13             明朝体=14 毛筆体=12\n");
	scanf("%i",&fontno);
	printf("\n");

	printf("変換する文字(\x1b[33m全角半角の混在は不可。半角換算80文字以内\x1b[0m)を入力してください。\n");
	printf("指定したフォント、全半角、入力した文字数は別に記録が必要です。\n\n");
	scanf("%80s",temp);
	
	fp=fopen( "temp.$$$", "wb" );
	if( fp==NULL ){	perror("temporary");	exit(2);}
	
	if(fontno<=3) write_16multifont(fontno, temp);
	else if(fontno<=7 || fontno==15) write_24multifont(fontno, temp);
	else if(fontno<=11) write_32multifont(fontno, temp);
	else if(fontno<=14) write_48multifont(fontno, temp);
	fclose(fp);

	fp=fopen( "temp.$$$", "rb" );
	fpout=fopen( filename, "wb" );
	if( fpout==NULL ){	perror(filename);	exit(2);}

	xdump(fp, fpout);

	fcloseall();
}

void xdump(FILE *fp, FILE *fpout)
{
	char *ptr,temp[256],buff[256];
    unsigned char c;
	int byte,blksiz;
    int i, j, k;

	blksiz = 256;
	
	do {
		byte=fread(buff, 1, blksiz, fp);

	    for ( j = 0; j < byte; j += 16 ) {
        	k = 0; 
        	ptr = buff + j;
          	for ( i = 0; i < 16; i++ ) {
				temp[k++]='0';
				temp[k++]='x';
            	c = ((*ptr & 0xf0) >> 4) & 0x0f;
               	if ( c > 9 )  c += 7;
               	temp[k++] = c + 0x30;
               	c = *ptr & 0x0f;
               	if ( c > 9 )  c += 7;
               	temp[k++] = c + 0x30;
               	temp[k++] = ',';
               	ptr++;
          	}
          	ptr = buff + j;
         	temp[k] = 0x00;
          	printf("%s", temp);
          	fprintf(fpout, "%s", temp);
     	}
	} while(!feof(fp));
}

/*	---------- 16dotマルチフォント書き込み	---------------------------------*/
int write_16multifont( unsigned int fontno, unsigned char *mojiretsu)
{
	unsigned char	pattern[300];
	unsigned int	i,len,c,code;
	int		j;
	long	loff;

	switch(fontno){
		case 1:	fontno=8;	break;
		case 2:	fontno=9;	break;
		case 3:	fontno=10;	break;
	}

	len=strlen(mojiretsu);
	for(i=0; i<len; i++){
		j=nthctype(mojiretsu,i);
		switch(j){
			case CT_ANK:
				c= hantozen(mojiretsu[i]);
				code=jis_to_flocate( jmstojis(c) );
				loff=128l*code;
				get_zenkaku32_pattern(fontno, loff, pattern);
				MOJI_32to16(pattern);
				MOJI_zentohan(16, pattern);
				fwrite( pattern, 16, 1, fp);
				break;
			case CT_KJ1:
				break;
			case CT_KJ2:
				c=mojiretsu[i-1]*0x0100+mojiretsu[i];
				code=jis_to_flocate( jmstojis(c) );
				loff=128l*code;
				get_zenkaku32_pattern(fontno, loff, pattern);
				MOJI_32to16(pattern);
				fwrite( pattern, 32, 1, fp);
				break;
			case CT_ILGL:
				printf("不正な文字 %x があります.\n",mojiretsu[i]);
				return(1);
		}
	}
	return(0);
}

/*	------- 24dotマルチフォント書き込み	-------------------------------------*/
int write_24multifont( unsigned int fontno, unsigned char *mojiretsu)
{
	unsigned char	pattern[300];
	unsigned int	i,len,c,code;
	int		j;
	long	loff;
	
	len=strlen(mojiretsu);
	for(i=0; i<len; i++){
		j=nthctype(mojiretsu,i);
		switch(j){
			case CT_ANK:
				if(fontno==15){
					c= hantozen(mojiretsu[i]);
					code=jis_to_flocate( jmstojis(c) );
					loff=288*(code+128l)+16l;
					get_zenkaku48_pattern(12, loff, pattern);
					MOJI_48to24(pattern);
					MOJI_zentohan(24,pattern);
					fwrite( pattern, 36, 1, fp);
				}
				else {
					code=mojiretsu[i];
					loff=74l*code+2l;
					get_hankaku24_pattern(fontno, loff, pattern);
					fwrite( pattern, 36, 1, fp);
				}
				break;
			case CT_KJ1:
				break;
			case CT_KJ2:
				c=mojiretsu[i-1]*0x0100+mojiretsu[i];
				code=jis_to_flocate( jmstojis(c) );
				if(fontno==15){
					loff=288*(code+128l)+16l;
					get_zenkaku48_pattern(12, loff, pattern);
					MOJI_48to24(pattern);
				}
				else {
					loff=74l*code+18l;
					get_zenkaku24_pattern(fontno, loff, pattern);
				}
				fwrite( pattern, 72, 1, fp);
				break;
			case CT_ILGL:
				printf("不正な文字 %x があります.\n",mojiretsu[i]);
				return(1);
		}
	}
	return(0);
}

/*	24dot半角フォント取得	*/
int get_hankaku24_pattern(unsigned int fontno, long loff, unsigned char *pattern)
{
	FILE 	*fp24hk;
	
	switch( fontno ){
		case 4:	fp24hk=fopen(maru24hk, "rb");	break;
		case 5:	fp24hk=fopen(goth24hk, "rb");	break;
		case 6:	fp24hk=fopen(kyou24hk, "rb");	break;
		case 7:	fp24hk=fopen(minn24hk, "rb");	break;
	}

	if( fp24hk==NULL ){	
		perror("24hk.font");
		exit(1);
	}

	fseek(fp24hk,loff,SEEK_SET);
	fread( pattern, 1,72, fp24hk );

	fclose(fp24hk);
	return(0);
}

/*	24dot全角フォント取得	*/
int get_zenkaku24_pattern(unsigned int fontno, long loff, unsigned char *pattern)
{
	FILE 	*fp24;
	
	switch( fontno ){
		case 4:	fp24=fopen(maru24, "rb");	break;
		case 5:	fp24=fopen(goth24, "rb");	break;
		case 6:	fp24=fopen(kyou24, "rb");	break;
		case 7:	fp24=fopen(minn24, "rb");	break;
	}

	if( fp24==NULL ){
		perror("24.font");
		exit(1);
	}

	fseek(fp24,loff,SEEK_SET);
	fread( pattern, 1,72, fp24 );

	fclose(fp24);
	return(0);
}

/*	---------- 32dotマルチフォント書き込み	----------------------------------*/
int write_32multifont( unsigned int fontno, unsigned char *mojiretsu)
{
	unsigned char	pattern[300];
	unsigned int	i,len,c,code;
	int		j;
	long	loff;
	
	len=strlen(mojiretsu);
	for(i=0; i<len; i++){
		j=nthctype(mojiretsu,i);
		switch(j){
			case CT_ANK:
				c= hantozen(mojiretsu[i]);
				code=jis_to_flocate( jmstojis(c) );
				loff=128l*code;
				get_zenkaku32_pattern(fontno, loff, pattern);
				MOJI_zentohan(32, pattern);
				fwrite( pattern, 64, 1, fp);
				break;
			case CT_KJ1:
				break;
			case CT_KJ2:
				c=mojiretsu[i-1]*0x0100+mojiretsu[i];
				code=jis_to_flocate( jmstojis(c) );
				loff=128l*code;
				get_zenkaku32_pattern(fontno, loff, pattern);
				fwrite( pattern, 128, 1, fp);
				break;
			case CT_ILGL:
				printf("不正な文字 %x があります.\n",mojiretsu[i]);
				return(1);
		}
	}
	return(0);
}

/*	32dot全角フォント取得	*/
int get_zenkaku32_pattern(unsigned int fontno, long loff, unsigned char *pattern)
{
	FILE 	*fp32;

	switch( fontno ){
		case 8:		fp32=fopen(syr3cg, "rb");	break;
		case 9:		fp32=fopen(syg3cg, "rb");	break;
		case 10:	fp32=fopen(syk3cg, "rb");	break;
		case 11:	fp32=fopen(sys3cf, "rb");	break;
	}
	if( fp32==NULL ){
		perror("oasys.font");
		exit(1);
	}

	fseek(fp32,loff,SEEK_SET);
	fread( pattern, 1, 128, fp32 );

	fclose(fp32);
	return(0);
}


/*	---------- 48dotマルチフォント書き込み	---------------------------------*/
int write_48multifont( unsigned int fontno, unsigned char *mojiretsu)
{
	unsigned char	pattern[300];
	unsigned int	i,len,c,code;
	int		j;
	long	loff;
	
	len=strlen(mojiretsu);
	for(i=0; i<len; i++){
		j=nthctype(mojiretsu,i);
		switch(j){
			case CT_ANK:
				c= hantozen(mojiretsu[i]);
				code=jis_to_flocate( jmstojis(c) );
				loff=288*(code+128l)+16l;
				get_zenkaku48_pattern(fontno, loff, pattern);
				MOJI_zentohan(48, pattern);
				fwrite( pattern, 144, 1, fp);
				break;
			case CT_KJ1:
				break;
			case CT_KJ2:
				c=mojiretsu[i-1]*0x0100+mojiretsu[i];
				code=jis_to_flocate( jmstojis(c) );
				loff=288*(code+128l)+16l;
				get_zenkaku48_pattern(fontno, loff, pattern);
				fwrite( pattern, 288, 1, fp);
				break;
			case CT_ILGL:
				printf("不正な文字 %x があります.\n",mojiretsu[i]);
				return(1);
		}
	}
	return(0);
}

/*	48dot全角フォント取得	*/
int get_zenkaku48_pattern(unsigned int fontno, long loff, unsigned char *pattern)
{
	FILE 	*fp48;
	
	switch( fontno ){
		case 12:	fp48=fopen(mouh48, "rb");	break;
		case 13:	fp48=fopen(goth48, "rb");	break;
		case 14:	fp48=fopen(minn48, "rb");	break;
	}

	if( fp48==NULL ){
		perror("48.font");
		exit(1);
	}

	fseek(fp48,loff,SEEK_SET);
	fread( pattern, 1, 288, fp48 );

	fclose(fp48);
	return(0);
}

/*----------文字変換 -----------------------------------------------------*/
void MOJI_zentohan(unsigned int dot, unsigned char *pattern)
{
	unsigned int	i,j,k,c1,c2,c3,c4;
	unsigned char 	ch,temp[300];
	
	for(i=0; i<dot; i++){
		for(j=0; j<(dot/8); j++){
			k=(dot/8)*i+j;
			ch=( pattern[k] | (pattern[k] << 1) );
			if( (ch & 0x80)==0x80 )	c1=1000; else c1=0;
			if( (ch & 0x20)==0x20 )	c2=100; else c2=0;
			if( (ch & 0x08)==0x08 )	c3=10; else c3=0;
			if( (ch & 0x02)==0x02 )	c4=1; else c4=0;
			
			switch( c1+c2+c3+c4 ){
				case    0:	temp[k]=0x00;	break;
				case    1:	temp[k]=0x01;	break;
				case   10:	temp[k]=0x02;	break;
				case   11:	temp[k]=0x03;	break;
				case  100:	temp[k]=0x04;	break;
				case  101:	temp[k]=0x05;	break;
				case  110:	temp[k]=0x06;	break;
				case  111:	temp[k]=0x07;	break;
				case 1000:	temp[k]=0x08;	break;
				case 1001:	temp[k]=0x09;	break;
				case 1010:	temp[k]=0x0a;	break;
				case 1011:	temp[k]=0x0b;	break;
				case 1100:	temp[k]=0x0c;	break;
				case 1101:	temp[k]=0x0d;	break;
				case 1110:	temp[k]=0x0e;	break;
				case 1111:	temp[k]=0x0f;	break;
			}
		}
	}	
	j=0;
	for(i=0; i<(dot*dot/8); i+=2){
		pattern[j]=(unsigned char)(temp[i]*0x10)+temp[i+1];
		j++;
	}
}

void MOJI_32to16(unsigned char *pattern)
{
	unsigned int	i,j,k,l;
	
	MOJI_zentohan(32, pattern);

	l=0;
	for(i=0; i<16; i++){
		for(j=0; j<2; j++){
			k=4*i+j;
			pattern[l]=(pattern[k] | pattern[k+2]);
			l++;
		}
	}
}

/*	48dotを24dotに変換の場合.*/

void MOJI_48to24(unsigned char *pattern)
{
	unsigned int	i,j,k,l;
	
	MOJI_zentohan(48, pattern);

	l=0;
	for(i=0; i<24; i++){
		for(j=0; j<3; j++){
			k=6*i+j;
			pattern[l]=(pattern[k] | pattern[k+3]);
			l++;
		}
	}
}


/*JIS漢字コードをフォントデータの位置に変換
		｢お気軽BASIC｣永倉一之著 SOFTBANK社を参考にしました.	*/
unsigned int  jis_to_flocate( unsigned int k )
{
	unsigned int	code=0;
	
 	if( k >= 0x2121 && k <=0x2220 ) code=	  k-0x2121;
 	if( k >= 0x2221 && k <=0x222E ) code=  94+k-0x2221;
 	if( k >= 0x223A && k <=0x2279 ) code= 119+k-0x223A;
 	if( k >= 0x2330 && k <=0x2339 ) code= 203+k-0x2330;
 	if( k >= 0x2341 && k <=0x235A ) code= 220+k-0x2341;
 	if( k >= 0x2361 && k <=0x237A ) code= 252+k-0x2361;
 	if( k >= 0x2421 && k <=0x2474 ) code= 282+k-0x2421;
 	if( k >= 0x2521 && k <=0x2576 ) code= 376+k-0x2521;
 	if( k >= 0x2621 && k <=0x2638 ) code= 470+k-0x2621;
 	if( k >= 0x2641 && k <=0x2658 ) code= 502+k-0x2641;
 	if( k >= 0x2721 && k <=0x2741 ) code= 564+k-0x2721;
 	if( k >= 0x2751 && k <=0x2771 ) code= 612+k-0x2751;
 	if( k >= 0x2321 && k <=0x2326 ) code= 897+k-0x2321;
 	if( k >= 0x2327 && k <=0x232F ) code= 906+k-0x2327;
 	if( k >= 0x233A && k <=0x233E ) code= 915+k-0x233A;
 	if( k >= 0x2660 && k <=0x267B ) code=1130+k-0x2660;
	   	 if( k >= 0x5021 ) code=4418+k-0x5021-162*( (k-0x5000)/0x100 );
 	else if( k >= 0x3021 ) code=1410+k-0x3021-162*( (k-0x3000)/0x100 );

	return(code);
}
