/*
 * DEVICE dependent, built-in font dependent
 */

#include	"defs.h"
#include	"emit.h"
#include	"global.h"
#include	"bifont.h"
#include	"jsub.h"
#include	"ps.h"


/* TYPE: tfm
 */
void
dev_tfm_initfontdict(fe)
struct font_entry *fe;
{
    struct psbiops po;

    fe->k = dev_newdevfont();
    get_tfm_psbiops(fe, &po);
    psfindfontop(psfname(fe->k), &po);
    fe->ncdl = 0;
}

void
dev_tfm_initfe(fe)
struct font_entry *fe;
{
    DEV_FONT tfm_fontdict();
    int tfm_setchar(), tfm_setstring();
    int tfm_setchar_abs(), tfm_setstring_abs();

    fe->dev_fontdict = tfm_fontdict;
    if (bifpos_relun(tfmfinfo(fe)->tfm_bf)) {
	fe->dev_setchar = tfm_setchar;
	fe->dev_setstring = tfm_setstring;
    } else {
	fe->dev_setchar = tfm_setchar_abs;
	fe->dev_setstring = tfm_setstring_abs;
    }
}

tfm_setchar(c)
int c;
{
    struct tfmchar_entry *ce = &(tfmfinfo(curfontent)->ch[c]);
    int cw;

    begin_string();
    pschar(ce->dev_char);
    *ps_move += (cw = ce->tfmw);
    return cw;
}

tfm_setstring(s, len)
char *s;
int len;
{
    char *sp;
    struct tfmchar_entry *ce = tfmfinfo(curfontent)->ch;
    int cw;

    begin_string();
    for (sp = s, cw = 0; sp < s+len; sp++) {
	pschar((ce+*sp)->dev_char);
	cw += (ce+*sp)->tfmw;
    }
    *ps_move += cw;
    return cw;
}

tfm_setchar_abs(c)
int c;
{
    int cw;

    cw = tfm_setchar(c);
    dev_setposn_abs(ps_h, ps_v);
    return cw;
}

tfm_setstring_abs(s, len)
char *s;
int len;
{
    char *sp;
    struct tfmchar_entry *ce = tfmfinfo(curfontent)->ch;
    int cw, w;

    for (sp = s, cw = 0; sp < s+len; sp++) {
	begin_string();
	pschar((ce+*sp)->dev_char);
	end_string();
	cw += (w = (ce+*sp)->tfmw);
	*ps_move += w;
	dev_setposn_abs(ps_h, ps_v);
    }
    return cw;
}


/* TYPE: jstfm
 */
void
dev_jstfm_initfontdict(fe)
struct font_entry *fe;
{
    struct jsubshare *jss;
    struct psbiops po;

    jss = jstfmfinfo(fe)->js_share;
    jss->jss_dev_font = dev_newdevfont();
    get_jstfm_psbiops(fe, &po);
    psfindfontop(psfname(jss->jss_dev_font), &po);
    /*fe->ncdl = 0;*/
}

void
dev_jstfm_initfe(fe)
struct font_entry *fe;
{
    struct bifont *bf;
    DEV_FONT jstfm_fontdict();
    int jstfm_setchar(), jstfm_setchar_euc(), jstfm_setchar_sjis();
    int jstfm_setstring(), jstfm_setstring_euc(), jstfm_setstring_sjis();
    int jstfm_setchar_abs(), jstfm_setchar_abs_euc(), jstfm_setchar_abs_sjis();
    int jstfm_setstring_abs(), jstfm_setstring_abs_euc(),
	jstfm_setstring_abs_sjis();

    fe->dev_fontdict = jstfm_fontdict;
    bf = jstfmfinfo(fe)->js_bf;
    if (bifpos_relun(bf)) {
	switch (bif_coding(bf)) {
	case BF_CODING_JIS:
	    fe->dev_setchar = jstfm_setchar;
	    fe->dev_setstring = jstfm_setstring;
	    break;
	case BF_CODING_EUC:
	    fe->dev_setchar = jstfm_setchar_euc;
	    fe->dev_setstring = jstfm_setstring_euc;
	    break;
	case BF_CODING_SJIS:
	    fe->dev_setchar = jstfm_setchar_sjis;
	    fe->dev_setstring = jstfm_setstring_sjis;
	    break;
	}
    } else {
	switch (bif_coding(bf)) {
	case BF_CODING_JIS:
	    fe->dev_setchar = jstfm_setchar_abs;
	    fe->dev_setstring = jstfm_setstring_abs;
	    break;
	case BF_CODING_EUC:
	    fe->dev_setchar = jstfm_setchar_abs_euc;
	    fe->dev_setstring = jstfm_setstring_abs_euc;
	    break;
	case BF_CODING_SJIS:
	    fe->dev_setchar = jstfm_setchar_abs_sjis;
	    fe->dev_setstring = jstfm_setstring_abs_sjis;
	    break;
	}
    }
}

pschar_jis(c1, c2)
int c1, c2;
{
    pschar(c1);
    pschar(c2);
}

pschar_euc(c1, c2)
int c1, c2;
{
    pschar(c1+0x80);
    pschar(c2+0x80);
}

pschar_sjis(c1, c2)
int c1, c2;
{
    int c = jis_to_sjis((c1<<8)+c2);

    pschar(c>>8);
    pschar(c&0xff);
}

jstfm_setchar_gen(c, psch)
int c;
int (*psch)();
{
    struct jstfmchar_entry *ce = &(jstfmfinfo(curfontent)->ch[c]);
    int cw;

    begin_string();
    psch((int)ce->dev_ku, (int)ce->dev_ten);
    *ps_move += (cw = ce->tfmw);
    return cw;
}

jstfm_setchar(c)
int c;
{
    return jstfm_setchar_gen(c, pschar_jis);
}

jstfm_setchar_euc(c)
int c;
{
    return jstfm_setchar_gen(c, pschar_euc);
}

jstfm_setchar_sjis(c)
int c;
{
    return jstfm_setchar_gen(c, pschar_sjis);
}

jstfm_setstring_gen(s, len, psch)
char *s;
int len;
int (*psch)();
{
    char *sp;
    struct jstfmchar_entry *ce = jstfmfinfo(curfontent)->ch;
    int cw;

    begin_string();
    for (sp = s, cw = 0; sp < s+len; sp++) {
	psch((int)(ce+*sp)->dev_ku, (int)(ce+*sp)->dev_ten);
	cw += (ce+*sp)->tfmw;
    }
    *ps_move += cw;
    return cw;
}

jstfm_setstring(s, len)
char *s;
int len;
{
    return jstfm_setstring_gen(s, len, pschar_jis);
}

jstfm_setstring_euc(s, len)
char *s;
int len;
{
    return jstfm_setstring_gen(s, len, pschar_euc);
}

jstfm_setstring_sjis(s, len)
char *s;
int len;
{
    return jstfm_setstring_gen(s, len, pschar_sjis);
}

setchar_abs_gen(c, setch)
int c;
int (*setch)();
{
    int cw;

    cw = setch(c);
    dev_setposn_abs(ps_h, ps_v);
    return cw;
}

jstfm_setchar_abs(c)
int c;
{
    return setchar_abs_gen(c, jstfm_setchar);
}

jstfm_setchar_abs_euc(c)
int c;
{
    return setchar_abs_gen(c, jstfm_setchar_euc);
}

jstfm_setchar_abs_sjis(c)
int c;
{
    return setchar_abs_gen(c, jstfm_setchar_sjis);
}

jstfm_setstring_abs_gen(s, len, psch)
char *s;
int len;
int (*psch)();
{
    char *sp;
    struct jstfmchar_entry *ce = jstfmfinfo(curfontent)->ch;
    int cw, w;

    for (sp = s, cw = 0; sp < s+len; sp++) {
	begin_string();
	psch((int)(ce+*sp)->dev_ku, (int)(ce+*sp)->dev_ten);
	end_string();
	cw += (w = (ce+*sp)->tfmw);
	*ps_move += w;
	dev_setposn_abs(ps_h, ps_v);
    }
    return cw;
}

jstfm_setstring_abs(s, len)
char *s;
int len;
{
    return jstfm_setstring_abs_gen(s, len, pschar_jis);
}

jstfm_setstring_abs_euc(s, len)
char *s;
int len;
{
    return jstfm_setstring_abs_gen(s, len, pschar_euc);
}

jstfm_setstring_abs_sjis(s, len)
char *s;
int len;
{
    return jstfm_setstring_abs_gen(s, len, pschar_sjis);
}


/* TYPE: jfm
 */
void
dev_jfm_initfontdict(fe)
struct font_entry *fe;
{
    struct psbiops po;

    fe->k = dev_newdevfont();
    get_jfm_psbiops(fe, &po);
    psfindfontop(psfname(fe->k), &po);
    fe->ncdl = 0;
}

void
dev_jfm_initfe(fe, id)
struct font_entry *fe;
int id;
{
    struct bifont *bf;
    DEV_FONT tfm_fontdict();
    int jfm_setchar(), jfm_setchar_euc(), jfm_setchar_sjis();
    int jfm_setstring();
    int jfm_setchar_abs(), jfm_setchar_abs_euc(), jfm_setchar_abs_sjis();
    int jfm_setstring_abs();
    int jfm_setchar_v(), jfm_setchar_v_euc(), jfm_setchar_v_sjis();
    int jfm_setstring_v();
    int jfm_setchar_vabs(), jfm_setchar_vabs_euc(), jfm_setchar_vabs_sjis();
    int jfm_setstring_vabs();

    fe->dev_fontdict = tfm_fontdict;
    bf = jfmfinfo(fe)->jfm_bf;
    if (id == JFM_ID) {
	if (bifpos_rel(bf)) {
	    switch (bif_coding(bf)) {
	    case BF_CODING_JIS:
		fe->dev_setchar = jfm_setchar;
		break;
	    case BF_CODING_EUC:
		fe->dev_setchar = jfm_setchar_euc;
		break;
	    case BF_CODING_SJIS:
		fe->dev_setchar = jfm_setchar_sjis;
		break;
	    }
	    fe->dev_setstring = jfm_setstring;
	} else {
	    switch (bif_coding(bf)) {
	    case BF_CODING_JIS:
		fe->dev_setchar = jfm_setchar_abs;
		break;
	    case BF_CODING_EUC:
		fe->dev_setchar = jfm_setchar_abs_euc;
		break;
	    case BF_CODING_SJIS:
		fe->dev_setchar = jfm_setchar_abs_sjis;
		break;
	    }
	    fe->dev_setstring = jfm_setstring_abs;
	}
    } else {
	if (bifpos_rel(jfmfinfo(fe)->jfm_bf)) {
	    fe->dev_setchar = jfm_setchar_v;
	    fe->dev_setstring = jfm_setstring_v;
	} else {
	    fe->dev_setchar = jfm_setchar_vabs;
	    fe->dev_setstring = jfm_setstring_vabs;
	}
    }
}

jfm_setchar_gen(c, bstr, psch)
int c;
int (*bstr)(), (*psch)();
{
    int cw;
    struct jfmfntinfo *jfmfi = jfmfinfo(curfontent);

    bstr();
    psch(c>>8, c&0xff);
    *ps_move += (cw = jfmfi->ch[getctype(c,jfmfi)].tfmw);
    return cw;
}

int begin_string(), begin_string_v();

jfm_setchar(c)
int c;
{
    return jfm_setchar_gen(c, begin_string, pschar_jis);
}

jfm_setchar_euc(c)
int c;
{
    return jfm_setchar_gen(c, begin_string, pschar_euc);
}

jfm_setchar_sjis(c)
int c;
{
    return jfm_setchar_gen(c, begin_string, pschar_sjis);
}

/* ARGSUSED */
jfm_setstring(s, len)
char *s;
int len;
{
    Fatal("%s implementation error: jfm_setstring", G_progname);
}

jfm_setchar_abs(c)
int c;
{
    return setchar_abs_gen(c, jfm_setchar);
}

jfm_setchar_abs_euc(c)
int c;
{
    return setchar_abs_gen(c, jfm_setchar_euc);
}

jfm_setchar_abs_sjis(c)
int c;
{
    return setchar_abs_gen(c, jfm_setchar_sjis);
}

/* ARGSUSED */
jfm_setstring_abs(s, len)
char *s;
int len;
{
    Fatal("%s implementation error: jfm_setstring_abs", G_progname);
}

jfm_setchar_v(c)
int c;
{
    return jfm_setchar_gen(c, begin_string_v, pschar_jis);
}

jfm_setchar_v_euc(c)
int c;
{
    return jfm_setchar_gen(c, begin_string_v, pschar_euc);
}

jfm_setchar_v_sjis(c)
int c;
{
    return jfm_setchar_gen(c, begin_string_v, pschar_sjis);
}

/* ARGSUSED */
jfm_setstring_v(s, len)
char *s;
int len;
{
    Fatal("%s implementation error: jfm_setstring_v", G_progname);
}

/* quick hack to disable USERELPOS */
#define	no_userelpos()	--ps_v;

setchar_vabs_gen(c, setch)
int c;
int (*setch)();
{
    int cw;

    cw = setch(c);
    no_userelpos();
    /*dev_setposn_abs(ps_h, ps_v);*/
    return cw;
}

jfm_setchar_vabs(c)
int c;
{
    return setchar_vabs_gen(c, jfm_setchar_v);
}

jfm_setchar_vabs_euc(c)
int c;
{
    return setchar_vabs_gen(c, jfm_setchar_v_euc);
}

jfm_setchar_vabs_sjis(c)
int c;
{
    return setchar_vabs_gen(c, jfm_setchar_v_sjis);
}

/* ARGSUSED */
jfm_setstring_vabs(s, len)
char *s;
int len;
{
    Fatal("%s implementation error: jfm_setstring_vabs", G_progname);
}
