#include    <stdio.h>
#include    <ctype.h>
#include    "defs.h"

#define UNSIG   unsigned short int
#define PRNDEV  "PRN"

#define PRNIO   0
#define FUJITU  1
#define ESCP    2

extern void  prn_out();
extern int   PRB_chr();
extern void  wrtstr();
extern void  Dmy_form();
extern int   kbhit();
extern int   Get_key();

static int     left_mrg=12;
static int     head_pos=0;
static int     head_max=80;
static int     line_pos=0;
static int     line_max=58;
static int     page_pos=0;
static short   prn_flg=FALSE;
static short   prn_mode=FUJITU;
static short   prn_page=FALSE;
static short   prn_kin=FALSE;
static short   prn_ryo=TRUE;
static short   prn_odd=FALSE;
static FILE    *out_fp=stdout;

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 };

#ifdef	TOWNS
UNSIG   sjistojis(cd)
UNSIG   cd;
{
    int    hi,lo;

    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);
}
#endif
static UNSIG   han_to_zen(code)
UNSIG   code;
{
    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 ( prn_kin != 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;
{
    int     i,f=FALSE;

    if ( prn_ryo == FALSE && prn_odd != (page_pos % 2) )
	return;
    
    if ( prn_mode == PRNIO ) {
	putc(ch,out_fp);
	return;
    }
    while ( (i = PRB_chr(ch)) != 0 ) {
	if ( i == 0x04 )
	    wrtstr("プリンタに用紙をセットしてください",16,15,0x02);
	else if ( i == 0x05 )   
	    wrtstr("プリンタが用意されていません      ",16,15,0x02);
	else
	    wrtstr("プリンタに動作エラ−があります    ",16,15,0x02);
	f = TRUE;
	if ( kbhit() != 0 )
	    return;
    }
    if ( f != FALSE )
	wrtstr("                                  ",16,15,0x02);
}
static void    prn_kan_out(code)
UNSIG   code;
{
    if ( prn_mode != PRNIO )
	code = sjistojis(code);
    prn_chr_out((UCHAR)(code >> 8));
    prn_chr_out((UCHAR)code);
}
static void    prn_line_out(str)
char	*str;
{
    while ( *str != '\0' )
        prn_chr_out(*(str++));
}
static void    page_out()
{
    int     i;
    char    *p,tmp[20];

    head_pos = line_pos = 0;
    prn_out('\n');
    for ( i = head_max / 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)) > head_max &&
         kinsoku_chk(code) == FALSE )
        prn_out('\n');

    if ( head_pos == 0 && code >= 0x20 ) {
        switch(prn_mode) {
            case FUJITU: prn_line_out("\x1bQ1 |"); break;
            case ESCP:   prn_line_out("\x1cU\x1c&\x1c\x0f");
                         prn_flg = FALSE; break;
        }
        for ( i = 0 ; i < left_mrg ; i++ ) {
            head_pos = ERR;
            prn_out(' ');
        }
        head_pos = 0;
    }

    if ( (code & 0xFF00) != 0 ) {
        switch(prn_mode) {
            case FUJITU:
                if ( prn_flg == FALSE )
                    prn_line_out("\x1b$B");
                break;
            case ESCP:
                if ( prn_flg == FALSE )
                    prn_line_out("\x1c\x12");
                break;
        }
        prn_flg = TRUE;
        prn_kan_out(code);
        head_pos += 2;
    } else if ( code >= 0x20 ) {
        switch(prn_mode) {
            case FUJITU:
                if ( prn_flg != FALSE )
                    prn_line_out("\x1b(H");
                prn_chr_out((UCHAR)code);
                break;
            case ESCP:
                if ( prn_flg != FALSE )
                    prn_line_out("\x1c\x0f");
                code = han_to_zen(code);
                prn_kan_out(code);
                break;
            case PRNIO:
                prn_chr_out((UCHAR)code);
                break;
        }
        prn_flg = FALSE;
        head_pos++;
    } else if ( code == '\t' ) {
        i = 8 - (head_pos & 0x07);
        while ( i-- > 0 )
            prn_out(' ');
    } else if ( code == '\x0C' ) {
        if ( prn_page == FALSE ) {
            while ( line_pos++ < line_max )
                prn_chr_out('\n');
            page_out();
        }
        head_pos = line_pos = 0;
        prn_chr_out('\x0C');
	page_pos++;
    } else if ( code == '\n' ) {
        prn_chr_out((UCHAR)code);
        prn_chr_out((UCHAR)'\r');
        head_pos = 0;
        if ( ++line_pos >= line_max )
            prn_out('\x0C');
    } else
        prn_chr_out((UCHAR)code);
}
int	prn_init(lmrg,hmax,lmax,page,kin,ryo,mode)
int	lmrg,hmax,lmax,page,kin,ryo,mode;
{
    left_mrg = lmrg;
    head_pos = 0;
    head_max = hmax;
    line_pos = 0;
    line_max = lmax;
    page_pos = 0;
    prn_flg  = FALSE;
    prn_mode = mode;
    prn_page = page;
    prn_kin  = kin;
    prn_ryo  = ryo;

    if ( prn_page == FALSE )
	line_max -= 2;

    if ( prn_mode == PRNIO && (out_fp = fopen(PRNDEV,"w")) == NULL )
	return ERR;

    switch(prn_mode) {
        case FUJITU:
	    prn_line_out("\x1bQ3 \x5c\x1c$\x22\x77\x1b[30;18 G\x1b(H");
	    break;
        case ESCP:
	    prn_line_out("\x1c\x0f");
	    break;
    }
    return FALSE;
}
void	prn_end()
{
    prn_out('\x0C');
    if ( prn_mode == PRNIO )
	fclose(out_fp);
}
void    Printer_out()
{
    int    no,i,n,yo,cl,ch,ec,mrg;
    int    x=20,y=6,old_page=(-1);
    LONG   l;
    char   tmp[160];
    static char   lmrg_tmp[8],rmrg_tmp[8];
    static char   hmax_tmp[8],lmax_tmp[8];
    static struct {
	short	lmrg_pp;
	short	rmrg_pp;
	short	hmax_pp;
	short	lmax_pp;
    } yousi[]={
	{ 3,3,72,39 },{ 6,6,80,49 },{ 12,12,80,59 },{ 12,12,110,75 }
    };
    static struct {
	short	val_mn;
	short   max_mn;
	char	*ttl_mn;
	char	*sub_mn[4];
    } menu[]={
	{ 2,4,"用紙の選択","Ａ５","Ｂ５","Ａ４","Ｂ４" },
	{ 0,1,"左の 余 白",lmrg_tmp },
	{ 0,1,"右の 余 白",rmrg_tmp },
	{ 0,1,"印字文字数",hmax_tmp },
	{ 0,1,"印字 行 数",lmax_tmp },
	{ 0,2,"ペ−ジ印字","する","しない" },
	{ 0,2,"禁則 処 理","する","しない" },
	{ 1,2,"両面 印 刷","する","しない" },
	{ 0,3,"使用ﾌﾟﾘﾝﾀ","PRN","FM系","ESC/P" }
    };

    Dmy_form(tmp,42,0x98,0x95,0x99); 
    wrtstr(tmp,x,y,0x07);
    Dmy_form(tmp,42,0x96,0x20,0x96); 
    for ( i = 0 ; i < 9 ; i++ )
	wrtstr(tmp,x,y+i+1,0x07);
    Dmy_form(tmp,42,0x9A,0x95,0x9B); 
    wrtstr(tmp,x,y+10,0x07);
    x += 2; y += 1;

    for ( no = 0 ; ; ) {
	yo = menu[0].val_mn;
	sprintf(lmrg_tmp,"%d    ",yousi[yo].lmrg_pp);
	sprintf(rmrg_tmp,"%d    ",yousi[yo].rmrg_pp);
	sprintf(hmax_tmp,"%d    ",yousi[yo].hmax_pp);
	sprintf(lmax_tmp,"%d    ",yousi[yo].lmax_pp);
	for ( i = 0 ; i < 9 ; i++ ) {
	    if ( i == no ) cl = 0x14; else cl = 0x07;
	    wrtstr(menu[i].ttl_mn,x,y+i,cl);
	    for ( n = 0 ; n < menu[i].max_mn ; n++ ) {
		if ( menu[i].max_mn > 1 && n == menu[i].val_mn )
		    cl = 0x14;
		else
		    cl = 0x07;
		wrtstr(menu[i].sub_mn[n],x+14+n*7,y+i,cl);
	    }
	}
	ch = Get_key(&ec);
	if ( ch == '\x1B' || ec == 0x7200 )
	    return;
        else if ( ch == '\x0D' || ec == 0x7300 )
	    break;	
	else if ( ch == ' ' || ch == '\x1F' ) {
	    if ( ++no >= 9 )
		no = 0;
	} else if ( ch == '\x08' || ch == '\x1E' ) {
	    if ( --no < 0 )
		no = 8;
	} else if ( ch == '\x1C' ) {
	    if ( no == 1 )
		yousi[yo].lmrg_pp += 1;
	    else if ( no == 2 )
		yousi[yo].rmrg_pp += 1;
	    else if ( no == 3 )
		yousi[yo].hmax_pp += 1;
	    else if ( no == 4 )
		yousi[yo].lmax_pp += 1;
	    else {
	        menu[no].val_mn += 1;
	        if ( menu[no].val_mn >= menu[no].max_mn )
		    menu[no].val_mn = 0;
	    }
	} else if ( ch == '\x1D' ) {
	    if ( no == 1 )
		yousi[yo].lmrg_pp -= 1;
	    else if ( no == 2 )
		yousi[yo].rmrg_pp -= 1;
	    else if ( no == 3 )
		yousi[yo].hmax_pp -= 1;
	    else if ( no == 4 )
		yousi[yo].lmax_pp -= 1;
	    else {
	        menu[no].val_mn -= 1;
		if ( menu[no].val_mn < 0 )
		    menu[no].val_mn = menu[no].max_mn - 1;
	    }
	}
    }
    x = 13; y = 12;
    Dmy_form(tmp,54,0x98,0x95,0x99);
    wrtstr(tmp,x,y,0x05);
    Dmy_form(tmp,54,0x96,0x20,0x96);
    for ( i = 1 ; i <= 5 ; i++ )
	wrtstr(tmp,x,y+i,0x05);
    Dmy_form(tmp,54,0x9A,0x95,0x9B);
    wrtstr(tmp,x,y+6,0x05);
    wrtstr("印刷を中断する場合は，[取消]キ−を押してください",x+3,y+4,0x02);

    prn_odd = 0; mrg = yousi[yo].lmrg_pp;
REPRINT:
    prn_init(mrg,
	     yousi[yo].hmax_pp,
	     yousi[yo].lmax_pp,
	     menu[5].val_mn,
	     menu[6].val_mn,
	     menu[7].val_mn,
	     menu[8].val_mn);

    for ( l = 0l ; l < btm_ptr ; ) {
	if ( kbhit() != 0 ) {
	    ch = Get_key(&ec);
	    if ( ec == 0x7200 ) {
		prn_end();
		return;
	    }
	}
	ch = *Cnv_ptr(l++);
	if ( iskanji(ch) )
	    ch = (ch << 8) | *Cnv_ptr(l++);
	if ( ch != '\r' )
	    prn_out(ch);
	if ( page_pos != old_page ) {
	    if ( prn_ryo != FALSE || prn_odd == (page_pos % 2) ) {
   sprintf(tmp,"只今%dペ−ジ目を印刷しています             ",page_pos+1);
	        wrtstr(tmp,16,14,0x02);
	    }
	    old_page = page_pos;
	}
    }
    prn_end();

    if ( prn_ryo == FALSE && prn_odd == 0 ) {
	prn_odd = 1; mrg = yousi[yo].rmrg_pp;
        wrtstr("用紙を裏返しにして何かキ−を押してください",16,14,0x02);
	while ( kbhit() == 0 );
	ch = Get_key(&ec);
	if ( ec != 0x7200 )
	    goto REPRINT;
    }
}
