#include    <stdio.h>
#include    <ctype.h>
#include    <dos.h>
#include    "defs.h"

#define DSP_X   0
#define DSP_Y   19

#define	MAX_BUF	0x8000

       char 	skl_chr[]={ 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x87 };
static int	left_mrg=0;
static int	page_max=0;
static int	head_pos=0;
static int	line_pos=0;
static int	page_pos=0;
static int	cur_x=0,cur_y=0;
static int	top_flg=0;
static int	act_typ=0;

static int      ank_count=0;
static int	kan_spc=0;
static int	ank_spc=0;

static int	prb_count=0;
static int	prb_ptr=0;
static int	prb_bas=0;
static int	prb_flg=FALSE;
static UCHAR	prb_buff[MAX_BUF];

extern void	prn_out();
extern char     *subname();

/*********** Print Out Program Start **************/
int	PRB_status()
{
    int   port;

    port = inp(0x0800);
    if ( (port & 0x80) == 0 )
	return (port & 0x01);
    else
	return 0;
}
void	PRB_out()
{
    while ( prb_count > 0 && PRB_status() != 0 ) {
	outp(0x0800,prb_buff[prb_bas++]);
	prb_bas &= (MAX_BUF-1); prb_count--;
    }
}
int	get_key()
{
    int     ch;

    while ( kbhit() == 0 )
	PRB_out();
    return getch();
}
void	PRB_chr(ch)
UCHAR	ch;
{
    while ( prb_count >= (MAX_BUF-1000) ) {
	PRB_out();
        if ( kbhit() != 0 )
	    break;
    }
    prb_buff[prb_ptr++] = ch;
    prb_ptr &= (MAX_BUF-1); prb_count++;
}
void    PRB_byte(str,n)
char    *str;
int     n;
{
    while ( n-- > 0 )
        PRB_chr(*(str++));
}
void    DMY_chr(ch)     /* DUMMY Out */
UNSIG   ch;
{
    int     x,y,n,off;
    static int  offx,offy;
    static int  sx,sy;

    if ( ch == 0x0D )
	return;

    if ( cur_x == 0 && cur_y == 0 ) {
	x = (yousi[paper].yoko * 225L) / 254L;
	y = (yousi[paper].tate * 225L) / 254L;
	x = ((GRA_MAXX - GRA_OFFX) - x) / 10;
	y = ((GRA_MAXY - GRA_OFFY) - y) / 30;
	offx = (page_pos % x) * 10;
	offy = (3 * offx / x) + ((page_pos / x) % y) * 30;
	pp_box(offx,offy);
	sx = (printer[typ_flg].yoko * 1800L) / 254L;
	sy = (printer[typ_flg].tate * 1800L) / 254L;
    }
    if ( ch == ' ' ) {
	cur_x++;
	return;
    } else if ( ch == 0x8140 ) {
	cur_x += 2;
	return;
    } else if ( ch == '\n' ) {
	cur_x = 0;
	cur_y++;
	return;
    } else if ( ch == '\x0c' ) {
	cur_x = cur_y = 0;
	return;
    }
    x = sx + cur_x * (yousi[paper].spc + 24);
    y = sy + cur_y * (yousi[paper].lf + 24);
    x = (x >> 4) + GRA_OFFX + offx;
    y = (y >> 3) + GRA_OFFY + offy;

    if ( (ch & 0xFF00) != 0 ) {
	cur_x += 2; n = 1;
    } else {
	cur_x += 1; n = 0;
    }
    line(x,y,x+n,y+1,PSET,0,FBOX,LINE_1);
}
UNSIG   sjistojis(cd)
UNSIG   cd;
{
    int    hi,lo;

    if ( (cd & 0x8000) == 0 )
	return cd;

    hi=(cd >> 8)&0xff;
    lo=cd & 0xff;
    hi -= ( hi <= 0x9f) ? 0x71 : 0xb1;
    hi = hi * 2 +1;
    if ( lo > 0x7f )
        lo--;
    if ( lo >= 0x9e ) {
        lo -= 0x7d;
        hi++;
    }
    else
        lo -= 0x1f;
    return (hi << 8 | lo);
}
static UNSIG   han_to_zen(code)
UNSIG   code;
{
    static UNSIG ank_tbl[]={
        0x8140,0x8149,0x8168,0x8194,0x8190,0x8193,0x8195,0x8166,
        0x8169,0x816A,0x8196,0x817B,0x8143,0x817C,0x8144,0x815E,
        0x824F,0x8250,0x8251,0x8252,0x8253,0x8254,0x8255,0x8256,
        0x8257,0x8258,0x8146,0x8147,0x8183,0x8181,0x8184,0x8148,
        0x8197,0x8260,0x8261,0x8262,0x8263,0x8264,0x8265,0x8266,
	0x8267,0x8268,0x8269,0x826A,0x826B,0x826C,0x826D,0x826E,
        0x826F,0x8270,0x8271,0x8272,0x8273,0x8274,0x8275,0x8276,
        0x8277,0x8278,0x8279,0x816D,0x818F,0x816E,0x814F,0x8151,
        0x8166,0x8281,0x8282,0x8283,0x8284,0x8285,0x8286,0x8287,
        0x8288,0x8289,0x828A,0x828B,0x828C,0x828D,0x828E,0x828F,
        0x8290,0x8291,0x8292,0x8293,0x8294,0x8295,0x8296,0x8297,
        0x8298,0x8299,0x829A,0x816F,0x8162,0x8170,0x8150,0x85A1 };
    static UNSIG kana_tbl[]={
        0x8140,0x8142,0x8175,0x8176,0x8141,0x8145,0x8392,0x8340,
        0x8342,0x8344,0x8346,0x8348,0x8383,0x8385,0x8387,0x8362,
        0x815B,0x8341,0x8343,0x8345,0x8347,0x8349,0x834A,0x834C,
        0x834E,0x8350,0x8352,0x8354,0x8356,0x8358,0x835A,0x835C,
        0x835E,0x8360,0x8363,0x8365,0x8367,0x8369,0x836A,0x836B,
        0x836C,0x836D,0x836E,0x8371,0x8374,0x8377,0x837A,0x837D,
        0x837E,0x8380,0x8381,0x8382,0x8384,0x8386,0x8388,0x8389,
        0x838A,0x838B,0x838C,0x838D,0x838F,0x8393,0x814A,0x814B };

    if ( 0x20 <= code && code <= 0x7F )
        return ank_tbl[code-0x20];
    else if ( 0xA0 <= code && code <= 0xDF )
	return kana_tbl[code-0xA0];
    else
        return 0x85A1;
}
/*  .(.全角禁足文字のチェック.).  */
static int     kinsoku_chk(i)
UNSIG   i;
{
    if ( kin_flg != FALSE )
        return FALSE;

    if ( (i & 0xFF00) == 0 ) {
        switch(i) {
            case 0x27: case 0x29: case 0x2c: case 0x2e: case 0x3a:
            case 0x3b: case 0x7d:
            case 0xa1: case 0xa3: case 0xa4: case 0xde: case 0xdf:
                return TRUE;
        }
        return FALSE;
    }

    if (i >= 0x8141 && i <= 0x814c)
        return TRUE;
    if (i >= 0x8165 && i <= 0x817a) {
        if ((i % 2) == 0)
            return TRUE;
    }
    switch(i) {
        case 0x829f: case 0x82a1: case 0x82a3: case 0x82a5: case 0x82a7:
        case 0x82c1: case 0x82e1: case 0x82e3: case 0x82e5: case 0x82ec:
        case 0x8340: case 0x8342: case 0x8344: case 0x8346: case 0x8348:
        case 0x8362: case 0x8383: case 0x8385: case 0x8387: case 0x838e:
        case 0x8395: case 0x8396:
            return TRUE;
    }
    return FALSE;
}
static void    prn_chr_out(ch)
UCHAR   ch;
{
    if ( ryo_flg == FALSE && odd_flg != (page_pos & 1) )
	return;

    if ( typ_flg != DUMMY ) {
	if ( fnt_flg != 0 )
	    fnt_ank(ch);
	else {
	    if ( ch == '\n' )
		PRB_chr('\x0D');
	    PRB_chr(ch);
	}
    }
    DMY_chr(ch);
}
static void    prn_kan_out(code)
UNSIG   code;
{
    if ( ryo_flg == FALSE && odd_flg != (page_pos & 1) )
	return;

    if ( typ_flg != DUMMY ) {
        code = sjistojis(code);
	if ( fnt_flg != 0 )
	    fnt_kan(code);
	else {
            PRB_chr(code >> 8);
            PRB_chr((UCHAR)code);
	}
    }
}
void    prn_line_out(str)
char    *str;
{
    if ( ryo_flg == FALSE && odd_flg != (page_pos & 1) )
        return;

    if ( typ_flg != DUMMY ) {
        while ( *str != '\0' )
            PRB_chr(*(str++));
    }
}
static void    page_out()
{
    int     i;
    char    *p,tmp[20];

    head_pos = 0; line_pos = (-2);
    prn_out('\n');
    for ( i = yousi[paper].lmax / 2 - 2 ; i > 0 ; i-- )
        prn_out(' ');
    sprintf(tmp,"-%d-\n",page_pos+1);
    for ( p = tmp ; *p != '\0' ; p++ )
        prn_out(*p);
}
void    prn_out(code)
UNSIG   code;
{
    int     i;

    if ( code >= ' ' &&
        (head_pos + ((code & 0xFF00) != 0 ? 2:1)) > yousi[paper].lmax &&
         kinsoku_chk(code) == FALSE )
        prn_out('\n');

    if ( top_flg == FALSE && head_pos == 0 && line_pos == 0 ) {
	top_flg = TRUE;
	for ( i = yousi[paper].pmrg ; i > 0 ; i-- )
            prn_chr_out('\n');
    }

    if ( head_pos == 0 && code >= 0x20 ) {
	if ( fnt_flg == 0 ) {
	    switch(typ_flg) {
                case FUJITU: prn_line_out("\x1bQ1 |"); break;
                case ESCP:   prn_line_out("\x1c&\x1c\x0f");
                             kan_flg = FALSE; break;
	    }
        }
	for ( i = 0 ; i < left_mrg ; i++ ) {
	    head_pos = ERR;
	    prn_out(' ');
        }
	head_pos = 0;
    }

    if ( (code & 0xFF00) != 0 ) {
	if ( ryo_flg != FALSE || odd_flg != (page_pos & 1) )
            DMY_chr(code);              /* 注意 */
        switch(typ_flg) {
            case FUJITU:
                if ( kan_flg == FALSE && fnt_flg == 0 )
                    prn_line_out("\x1b$B");
        	prn_kan_out(code);
                break;
            case ESCP:
                if ( kan_flg == FALSE && fnt_flg == 0 )
                    prn_line_out("\x1c\x12");
        	prn_kan_out(code);
                break;
            case PC98:
        	prn_kan_out(code);
		PRB_chr('\x1b');
		PRB_chr(kan_spc);
                break;
        }
        kan_flg = TRUE;
        head_pos += 2;
    } else if ( code >= 0x20 ) {
	switch(typ_flg) {
	    case FUJITU:
                if ( kan_flg != FALSE && fnt_flg == 0 )
                    prn_line_out("\x1b(H");
                prn_chr_out((UCHAR)code);
                break;
            case ESCP:
		if ( fnt_flg == 0 ) {
		    if ( ryo_flg != FALSE || odd_flg != (page_pos & 1) )
	                DMY_chr(code);              /* 注意 */
                    if ( kan_flg != FALSE )
                        prn_line_out("\x1c\x0f");
                    code = han_to_zen(code);
                    prn_kan_out(code);
		} else
		    prn_chr_out(code);
                break;
            case PC98:
		if ( fnt_flg == 0 ) {
		    if ( ryo_flg != FALSE || odd_flg != (page_pos & 1) )
                        DMY_chr(code);              /* 注意 */
                    prn_kan_out(code);
		    PRB_chr('\x1b');
		    if ( (kan_spc  & 1) != 0 && 
			 (ank_count & 1) != 0 )
			PRB_chr(ank_spc + 1);
		    else
			PRB_chr(ank_spc);
		} else
		    prn_chr_out(code);
                break;
            case DUMMY:
		prn_chr_out((UCHAR)code);
		break;
        }
        kan_flg = FALSE;
        head_pos++;
        ank_count++;
    } else if ( code == '\t' ) {
        i = 8 - (head_pos & 0x07);
        while ( i-- > 0 )
            prn_out(' ');
    } else if ( code == '\x0C' ) {
        if ( page_flg == FALSE ) {
            while ( line_pos++ < page_max )
                prn_chr_out('\n');
            page_out();
        }
        head_pos = line_pos = ank_count = 0;
        prn_chr_out('\x0C');
        page_pos++;
	top_flg = FALSE;
    } else if ( code == '\n' ) {
        prn_chr_out((UCHAR)code);
        head_pos = ank_count = 0;
        if ( ++line_pos >= page_max )
            prn_out('\x0C');
    } else
        prn_chr_out((UCHAR)code);
}
void    prnerr(str)
char    *str;
{
    locate(DSP_X+1,DSP_Y+3);
    printf("%-34s",str);
    fflush(stdout);
}
void    file_out(file)
char    *file;
{
    int     i,ch,old_mrg;
    int     old_page=(-1);
    long    l,size;
    FILE    *inp_fp;
    char    *p,tmp[80];

    if ( prb_count > 0 &&
	 typ_flg != DUMMY && act_typ != DUMMY && 
	 act_typ != typ_flg ) {
        prnerr("印字中です");
        return;
    }
    act_typ = typ_flg;

    if ( (inp_fp = fopen(file,"rb")) == NULL ) {
        prnerr("ファイルが見当たりません");
        return;
    }
    if ( gra_img(inp_fp,file) != FALSE ) {
	fclose(inp_fp);
	return;
    }
    if ( fnt_flg != 0 && typ_flg != DUMMY && fnt_init() != 0 ) {
        prnerr("ﾌｫﾝﾄ ﾌｧｲﾙが見当たりません");
	fclose(inp_fp);
        return;
    }
    fseek(inp_fp,0L,2);
    size = ftell(inp_fp);
    fseek(inp_fp,0L,0);

    if ( dsp_flg != FALSE )
	G_era();

    switch(typ_flg) {
        case FUJITU:
	    prn_line_out("\x1bQ3 \x5c");
	    i = yousi[paper].spc + 24;
	    sprintf(tmp,"\x1c$%c%c",i/10+0x20,i%10+0x70);
	    prn_line_out(tmp);
	    i = yousi[paper].lf + 24;
	    sprintf(tmp,"\x1c%%%c%c\x1b(H",i/10+0x20,i%10+0x70);
	    prn_line_out(tmp);
	    break;
	case ESCP:
	    PRB_chr('\x1c');
	    PRB_chr('S');
	    i = yousi[paper].spc / 2;
	    PRB_chr(i);
	    i = yousi[paper].spc - i;
	    PRB_chr(i);

	    PRB_chr('\x1c');
	    PRB_chr('T');
	    i = (yousi[paper].spc + 24) / 2 - 11;
	    PRB_chr(i / 2);
	    i = i - (i / 2);
	    PRB_chr(i);

	    if ( (yousi[paper].spc & 1) != 0 )
		prn_line_out("\x1cU");
	    else
		prn_line_out("\x1cV");

	    PRB_chr('\x1B'); PRB_chr('3');
	    PRB_chr(yousi[paper].lf + 24);

	    prn_line_out("\x1c\x0f");
	    break;
        case PC98:
	    prn_line_out("\x1b\x45");
	    i = yousi[paper].lf + 24;
	    i = (i * 120) / 180;
	    sprintf(tmp,"\x1bT%02d\x1bK",i);
	    prn_line_out(tmp);

	    if ( (kan_spc = yousi[paper].spc - 3) < 0 )
		kan_spc = 0;
	    kan_spc = (kan_spc * 120) / 180;
	    ank_spc = kan_spc / 2;
	    break;
    }
    odd_flg = 0;
    old_mrg = left_mrg = yousi[paper].lmrg;
    page_max = yousi[paper].pmax;
    if ( page_flg == 0 )
	page_max -= 2;
REPRINT:
    locate(DSP_X+1,DSP_Y+1);
    repchr(34,' ');
    l = 0l; i = 0;
    cur_x = cur_y = 0; top_flg = FALSE;
    head_pos = line_pos = page_pos = 0;
    while ( (ch = getc(inp_fp)) != EOF ) {
	l += 272;
	if ( old_page != page_pos ) {
	    locate(DSP_X+1,DSP_Y+3);
	    printf("只今%d枚目を印刷してます  ",page_pos+1);
	    old_page = page_pos;
	}
	if ( iskanji(ch) ) {
            ch = (ch << 8) | getc(inp_fp);
            l += 272;
        }
	if ( ch != '\x1a' && ch != '\x0D' )
	    prn_out(ch);
        if ( kbhit() != 0 ) {
            getch();
            break;
        }
        while ( l >= size ) {
            locate(DSP_X+1+(i / 8),DSP_Y+1);
            repchr(1,skl_chr[i % 8]);
            l -= size;
            i++;
        }
	PRB_out();
    }
    prn_out('\x0C');
    if ( ryo_flg == 0 && odd_flg == 0 && page_pos > 1 ) {
        fseek(inp_fp,0L,0);
        odd_flg = 1;
        i = (yousi[paper].yoko * 1800L) / 127L;
        i = i / (yousi[paper].spc + 24);
        left_mrg = i - (yousi[paper].lmrg + yousi[paper].lmax);
        locate(DSP_X+1,DSP_Y+3);
        printf("用紙を裏返してください      ");
        fflush(stdout);
        get_key();
        yousi[paper].lmrg = left_mrg;
        pp_box(TRUE);
        goto REPRINT;
    }
    if ( ryo_flg == 0 )
        yousi[paper].lmrg = old_mrg;
    fclose(inp_fp);

    locate(DSP_X+1,DSP_Y+3);
    printf("全部で%d枚印刷しました      ",page_pos);
    if ( fnt_flg != 0 && typ_flg != DUMMY )
	fnt_close();
}
