/*
	源二郎 	v1.7b   By SAKU
	 [tabsize 4]
*/

#include "genji.h"

char	*errmes[8] = {
					"\x0",
					"\x0",
					"プリンタ指定エラー1です",
					"プリンタ指定エラー2です",
					"用紙が切れています",
					"プリンタがオフラインです",
					"次のページの紙をセットしてください",
					"プリンタが原因不明のエラーです" };

char	pool[256];

#include "netdata.c"
#include "printcom.c"

void	main( int argc, char *argv[] )
{
	FILE	*fp;
	union
	{
		unsigned short int	sjis;
		char	c[2];
	} moji;
	struct ffblk	fb;
	unsigned int	size;
	int		ch,e,i,j,comflg,sflg;
	char	combuf[16],usrbuf[256],gjbuf[288],gjbuf2[72];
	char	defname[64] = "GENJI.DEF";

	colrev_flg = OFF;
	pitchmask = 2;	/* truepitch = pitch * pitchmask / 2 */
	tabsize = 4;
	pitch = 54;		/* 全角文字の文字ピッチ */
	cr_p = 60;		/* 改行幅 */
	net_length = 0;
	net_flg = OFF;
	jisflg = OFF;
	leftmargin = 0;
	pageflg = OFF;
	np = 1;
	info[np][0] = 0;/*現在明朝体*/
	info[np][1] = KS_XN_YN;/*現在文字サイズ標準*/
	y_pos = 0;
	endflg = OFF;
	page = 1;
	mode = 'A';
	writepage = OFF;
	lnum = 0;
	control = OFF;
	bufp = outbuf;
	betaflg = OFF;

	if( argc < 2 )
	{
		printf( "[源二郎ver 1.7b]  By SAKU\n\n<使用方法>\n\trun386 genji [-option] [filename]\n\n<オプション>\n\t-D[file-name]  file-nameを定義ファイルとする(デフォルトはGENJI.DEF)\n\t-B             単純に印刷する(コマンドの解析等はいっさい行わない)\n" );
		return;
	}

	++ argv;
	while(1)
	{
		if( **argv != '-' && **argv != '/' )
			break;
		++ *argv;
		switch( **argv )
		{
			case 'D':
			case 'd':
				++ *argv;
				strcpy( defname, *argv );
				break;
			case 'B':
			case 'b':
				betaflg = ON;
				break;
			default:
				printf( "'%s' is not proper option.\n", *argv );
				break;
		}
		++ argv;
	}

	if( findfirst( *argv, &fb, 0 ) )
	{
		printf( "'%s'が見つかりません。\n", *argv );
		return;
	}

	size = fb.ff_fsize.high<<16 | fb.ff_fsize.low;

	if( ( file = (char *)malloc( size ) ) == NULL )
	{
		printf( "メモリが足りません。\n" );
		return;
	}

	if( ( fp = fopen( *argv, "rb" ) ) == NULL )
	{
		printf( "'%s'が読み込めません。\n", *argv );
		return;
	}

	if( fread( file, 1, size, fp ) < size )
	{
		printf( "データの読み込みに失敗しました。\n" );
		fclose( fp );
		return;
	}
	fclose( fp );

	file_ = file;

	if( setInit( defname ) )	/*解像度360dpi + 半角1byte指定*/
	{
		printf( "定義ファイルが読み込めません。\n" );
		return;
	}
	printf( "現在%dページ目を印刷中です。\n", page );

	while( endflg == OFF )
	{
		lineInit();
		sflg = ON;
		while( lineflg == OFF )
		{
			comflg = OFF;
			ch = (*file++) & 0xff;

			if( file - file_ > size )
			{
				*bufp++ = 0x0a;
				pageflg = ON;
				endflg = ON;
				break;
			}

			if( betaflg == ON )
				goto LABEL01;

			if( sflg == ON && ch == '#' )
			{
				control = ON;
				continue;
			}
			sflg = OFF;

			if( ch == '}' && np > 1 )
			{
				switch( nest[np--] )
				{
					case 10:/*文字サイズ*/
						setKanjiSize( info[np][1] );
						break;
					case 19:/*フォント*/
						setFontType( info[np][0] );
						break;
					case 21:/*漢字アンダーライン解除*/
						setUnderline( OFF );
						break;
					case 32:/*欧文ピッチ解除*/
						bufp += addstrings( prooff, bufp );
						break;
					case 40:/*網掛け解除*/
						setNetEnd();
						break;
					case 47:/*白黒反転*/
						setColorReverse();
						break;
				}
				continue;
			}

			if( ch == '/' )
			{
				for( i=0; i<15; i++ )
					combuf[i] = (*(file+i)) & 0xff;
				combuf[16] = 0;

				switch( getCommand2() )
				{
					char	*p;

					case 1:/*半角1byte指定*/
						bufp += addstrings( hss2, bufp );
						comflg = ON;
						break;
					case 2:/*上付文字開始*/
						if( pool[0] == 0 )
							break;
						incNest( 10 );
						setBaseLine( BL_UPPER );
						setKanjiSize( KS_XH_YH );
						comflg = ON;
						break;
					case 4:/*下付文字開始*/
						if( pool[0] == 0 )
							break;
						incNest( 10 );
						setBaseLine( BL_BOTTOM );
						setKanjiSize( KS_XH_YH );
						comflg = ON;
						break;
					case 6:/*漢字文字ピッチ*/
						if( pool[1] == 0 )
							break;
						i = DWORD( pool+2 );
						if( i<48 || i>120 )
							break;
						pitch = i;
						setKanjiPitch( pitch );
						comflg = ON;
						break;
					case 8:/*改行ピッチ*/
						if( pool[1] == 0 )
							break;
						i = DWORD( pool+2 );
						if( i<1 || i>120 )
							break;
						cr_p = i;
						setReturnPitch( cr_p );
						comflg = ON;
						break;
					case 10:/*標準*/
						if( pool[0] )
							incNest( 10 );
						pitchmask = 2;
						setKanjiSize( KS_XN_YN );
						comflg = ON;
						break;
					case 11:/*横倍*/
						if( pool[0] )
							incNest( 10 );
						pitchmask = 4;
						setKanjiSize( KS_XD_YN );
						comflg = ON;
						break;
					case 12:/*縦倍*/
						if( pool[0] )
							incNest( 10 );
						pitchmask = 2;
						setKanjiSize( KS_XN_YD );
						comflg = ON;
						break;
					case 13:/*縦横倍*/
						if( pool[0] )
							incNest( 10 );
						pitchmask = 4;
						setKanjiSize( KS_XD_YD );
						comflg = ON;
						break;
					case 14:/*縦半分*/
						if( pool[0] )
							incNest( 10 );
						pitchmask = 2;
						setKanjiSize( KS_XN_YH );
						comflg = ON;
						break;
					case 15:/*横半分*/
						if( pool[0] )
							incNest( 10 );
						pitchmask = 1;
						setKanjiSize( KS_XH_YN );
						comflg = ON;
						break;
					case 16:/*縦半分横倍*/
						if( pool[0] )
							incNest( 10 );
						pitchmask = 4;
						setKanjiSize( KS_XD_YH );
						comflg = ON;
						break;
					case 17:/*縦倍横半分*/
						if( pool[0] )
							incNest( 10 );
						pitchmask = 1;
						setKanjiSize( KS_XH_YD );
						comflg = ON;
						break;
					case 18:/*縦横半分*/
						if( pool[0] )
							incNest( 10 );
						pitchmask = 1;
						setKanjiSize( KS_XH_YH );
						comflg = ON;
						break;
					case 19:/*ゴシック*/
						if( pool[0] )
							incNest( 19 );
						setFontType( 1 );
						comflg = ON;
						break;
					case 20:/*明朝体*/
						if( pool[0] )
							incNest( 19 );
						setFontType( 0 );
						comflg = ON;
						break;
					case 21:/*漢字アンダーライン指定*/
						if( ! pool[0] )
							break;
						incNest( 21 );
						setUnderline( ON );
						comflg = ON;
						break;
					case 27:/*罫線接続指定*/
						setLineConnect( ON );
						comflg = ON;
						break;
					case 28:/*罫線接続解除*/
						setLineConnect( OFF );
						comflg = ON;
						break;
					case 29:/*漢字縦倍上端合わせ*/
						setBaseLine( 0 );
						comflg = ON;
						break;
					case 30:/*漢字縦倍下端合わせ*/
						setBaseLine( 1 );
						comflg = ON;
						break;
					case 31:/*漢字縦倍中心合わせ*/
						setBaseLine( 2 );
						comflg = ON;
						break;
					case 32:/*欧文ピッチ指定*/
						if( pool[0] == 0 )
							break;
						bufp += addstrings( proon, bufp );
						incNest( 32 );
						comflg = ON;
						break;
					case 38:/*ページ変更*/
						pageflg = ON;
						comflg = ON;
						break;
					case 39:/*レフトマージン指定*/
						if( pool[1] == 0 )
							break;
						i = DWORD( pool+2 );
						if( i<0 || i>80 )
							break;
						setLeftmargin( i );
						leftmargin = i;
						comflg = ON;
						break;
					case 40:/*網掛け*/
						if( pool[1] == 0 || pool[0] == 0 )
							break;
						net_sort = DWORD( pool+2 );
						if( net_sort<0 || net_sort>4 )
							break;
						setNetStart();
						incNest( 40 );
						comflg = ON;
						break;
					case 41:/*漢字縦書き指定*/
						setPrintDirection( 1 );
						comflg = ON;
						break;
					case 42:/*漢字横書き指定*/
						setPrintDirection( 0 );
						comflg = ON;
						break;
					case 43:/*毛筆体*/
						if( pool[0] )
							incNest( 19 );
						setFontType( 2 );
						comflg = ON;
						break;
					case 44:/*丸文字*/
						if( pool[0] )
							incNest( 19 );
						setFontType( 3 );
						comflg = ON;
						break;
					case 45:/*教科書体*/
						if( pool[0] )
							incNest( 19 );
						setFontType( 4 );
						comflg = ON;
						break;
					case 46:/*JIS指定*/
						if( pool[1] == 0 )
							break;
						jiscode = DWORD( pool+2 );
						goto D_JIS_IN;
						break;
					case 47:/*白黒反転*/
						if( pool[0] )
							incNest( 47 );
						setColorReverse();
						comflg = ON;
						break;
					case 48:/*タブサイズ指定*/
						if( pool[1] == 0 )
							break;
						i = DWORD( pool+2 );
						if( i<0 || i>8 )
							break;
						tabsize = i;
						comflg = ON;
						break;
				}

				if( comflg == ON )
					continue;

				ch = (*file++) & 0xff;
			}
LABEL01:
			if( ch == 0x0a )
			{
				if( control == OFF )
				{
					if( net_flg == ON )
						net_length = x_pos - net_sp;
					if( net_length > 0 )
						printNet();
					*bufp++ = 0x0a;
				}
				lineflg = ON;
				break;
			}

			if( control )
				continue;

			if( ch == 0x09 )
			{
				setAsciiMode();
				do
				{
					addstrings( "\x20", bufp );
					bufp ++;
					x_pos += pitch*pitchmask/4;
				}
				while( ( ( x_pos - leftmargin*27 )/ (pitch/2) ) % tabsize );

				continue;
			}

			if( ch>0xe0 || (ch>0x80 && ch<0xa0) )
			{
				moji.c[1] = (unsigned char)ch;
				moji.c[0] = (unsigned char)(*file) & 0xff;
				file++;

				jiscode = FNT_sjisToJis( (int)moji.sjis );
D_JIS_IN:
				setKanjiMode();
				moji.sjis = (unsigned short int)jiscode;
				i = ( moji.c[1] == 0x28 )? 0: info[np][0];
				switch( i )
				{
					case 0:/*明朝体*/
						if( colrev_flg == OFF )
							break;
						if( mint_flg == OFF )
							break;
						fseek( mint_fp, ((moji.c[1]-0x21)*94+(moji.c[0]-0x21)+128)*288+16, SEEK_SET );
						fread( gjbuf, 1, 288, mint_fp );
						break;
					case 1:/*ゴシック体*/
						if( colrev_flg == OFF )
							break;
						if( goth_flg == OFF )
							break;
						fseek( goth_fp, ((moji.c[1]-0x21)*94+(moji.c[0]-0x21)+128)*288+16, SEEK_SET );
						fread( gjbuf, 1, 288, goth_fp );
						break;
					case 2:/*毛筆体*/
						if( mouh_flg == OFF )
							break;
						fseek( mouh_fp, ((moji.c[1]-0x21)*94+(moji.c[0]-0x21)+128)*288+16, SEEK_SET );
						fread( gjbuf, 1, 288, mouh_fp );
						break;
					case 3:/*丸文字*/
						if( maru_flg == OFF )
							break;
						fseek( maru_fp, ((moji.c[1]-0x21)*94+(moji.c[0]-0x21))*74+18, SEEK_SET );
						fread( gjbuf2, 1, 72, maru_fp );
						convert24to48( gjbuf2, gjbuf );
						break;
					case 4:/*教科書体*/
						if( kyou_flg == OFF )
							break;
						fseek( kyou_fp, ((moji.c[1]-0x21)*94+(moji.c[0]-0x21))*74+18, SEEK_SET );
						fread( gjbuf2, 1, 72, kyou_fp );
						convert24to48( gjbuf2, gjbuf );
						break;
				}

				if( ( i != 0 && i != 1 ) || ( colrev_flg == ON ) )
				{
					*(defgj+5) = (usrjis>>8)&0xff;
					*(defgj+6) = (usrjis)&0xff;
					bufp += addstrings( defgj, bufp );

					if( colrev_flg == ON )
					{
						for( i=0; i<72; i++ )
							DWORD( gjbuf+i*4 ) ^= 0xffffffff;
					}

					for( i=0; i<72; i++ )
						DWORD( bufp+i*4 ) = DWORD( gjbuf+i*4 );
					bufp += 288;

					moji.sjis = (unsigned short int)usrjis;
					++ usrjis;
				}

				*bufp++ = moji.c[1];
				*bufp++ = moji.c[0];
				x_pos += pitch*pitchmask/2;
			}
			else
			{
				setAsciiMode();
				*bufp++ = (char)ch;
				x_pos += pitch*pitchmask/4;
			}
		}

		if( flushBuffer() )
			break;

		lineTerm();
		if( ! control )
			++ lnum;
		if( lnum == lpp )
			pageflg = ON;

		if( pageflg == ON )
		{
			lnum = 0;
			if( writepage == ON )
			{
				printPage( page );
				if( flushBuffer() )
					break;
			}

			if( endflg == OFF )
			{
				page++;
				y_pos = 0;
				pageflg = OFF;
				printReady( 6 );
				printf( "現在%dページ目を印刷中です。\n", page );
			}
		}
	}

	end_();
	exit(0);
}

