/* compose font from subfonts
 */

#include	"defs.h"
#include	"set.h"
#include	"global.h"
#include	"funcfont.h"
#include	"jsub.h"

int comptype_init();
int comptype_access();
void init_comp_fontinfo();
struct fontop cmpop = {
    "comp",
    comptype_init,
    comptype_access,
    init_comp_fontinfo,
};

comptype_init(pars, ff)
char *pars;
struct comp **ff;
{
    char *p1, *p2;
    int dt;
    struct comp *ffcmp;

    if (!getstrtok(pars, ',', &p1))
	return FALSE;
    if (!getstrtok(p1, '\0', &p2))
	return FALSE;
    dt = STREQ(p1, "ntt") ? CMP_NTT : CMP_DCD;
    ffcmp = NEW(struct comp, "comp init");
    ffcmp->cmp_type = dt;
    ffcmp->cmp_name = strsave(pars);
    *ff = ffcmp;
    return TRUE;
}

comptype_access(ffcmp, fe, acca)
struct comp *ffcmp;
struct font_entry *fe;
struct accarg *acca;
{
    BOOLEAN subpre;
    int s;
    char *se;
    struct comp *ffnew;

#ifdef DEBUG
    if (Debuguser)
	(void)fprintf(stderr, "trying to comp(ose) %s/%s\n",
		      fe->n, ffcmp->cmp_name);
#endif
    if (strncmp(fe->n, ffcmp->cmp_name, strlen(ffcmp->cmp_name)) == 0) {
	if (ffcmp->cmp_type == CMP_NTT)
	    subpre = (s = getjsubfont(fe->n+strlen(ffcmp->cmp_name), &se)) > 0;
	else
	    subpre = (s = getdcode(fe->n+strlen(ffcmp->cmp_name), &se)) > 0;
	if (subpre && numstr(se+1)) {
	    (void)sprintf(fe->name, "%s%s", ffcmp->cmp_name, se+1);
	    ffnew = NEW(struct comp, "comp init");
	    *ffnew = *ffcmp;
	    ffnew->cmp_sub = s;
	    fe->finfo = (struct finfo *)ffnew;
	    return TRUE;
	}
    }
    return FALSE;
}

void
init_comp_fontinfo(fe)
struct font_entry *fe;
{
    void init_cmpntt_fontinfo(), init_cmpdcd_fontinfo();

    if (cmpfinfo(fe)->cmp_type == CMP_NTT)
	init_cmpntt_fontinfo(fe);
    else
	init_cmpdcd_fontinfo(fe);
}

void
init_cmpntt_fontinfo(fe)
struct font_entry *fe;
{
    struct comp *ffcmp;
    struct font_index *fontidx;
    int cmpntt_markchar();
    void read_cmpntt_fontinfo();

    ffcmp = cmpfinfo(fe);
    fontidx = NULL;
    readfontdef(0, 0, fe->s, fe->d, 0, strlen(fe->name), fe->name, &fontidx);
    ffcmp->cmp_fe = fontidx->fent;
    fe->fnt_markchar = cmpntt_markchar;
    fe->fnt_readfontinfo = read_cmpntt_fontinfo;
}

#define	makejis(k,t)	((k)*256+t)

#define	cmp_markchar(save, ku, ten) \
	save = curfontent; \
	setcurfont(cmpfinfo(curfontent)->cmp_fe); \
	MarkChar(makejis(ku,ten)); \
	setcurfont(save);

cmpntt_markchar(fe, c)
struct font_entry *fe;
int c;
{
    unsigned short ku, ten;
    struct font_entry *save_curfontent;

    jsub_to_jis(cmpfinfo(curfontent)->cmp_sub, c, &ku, &ten);
    cmp_markchar(save_curfontent, ku, ten);
}

void
read_cmpntt_fontinfo(fe)
struct font_entry *fe;
{
    DEV_FONT cmpntt_fontdict();
    int cmpntt_setchar(), cmpntt_setstring();

    fe->rvf_setchar = virf_setchar;
    fe->rvf_setstring = virf_setstring;
    fe->dev_fontdict = cmpntt_fontdict;
    fe->dev_setchar = cmpntt_setchar;
    fe->dev_setstring = cmpntt_setstring;
}

DEV_FONT
cmpntt_fontdict(fe, c)
struct font_entry *fe;
int c;
{
    unsigned short ku, ten;
    struct font_entry *sfe;

    jsub_to_jis(cmpfinfo(curfontent)->cmp_sub, c, &ku, &ten);
    sfe = cmpfinfo(fe)->cmp_fe;
    return sfe->dev_fontdict(sfe, makejis(ku, ten));
}

#define	cmp_setchar(save, ku, ten) \
	save = curfontent; \
	setcurfont(cmpfinfo(curfontent)->cmp_fe); \
	SetChar(makejis(ku,ten), chmove); \
	setcurfont(save);

cmpntt_setchar(fe, c)
struct font_entry *fe;
unsigned int c;
{
    unsigned short ku, ten;
    struct font_entry *save_curfontent;

    jsub_to_jis(cmpfinfo(curfontent)->cmp_sub, c, &ku, &ten);
    cmp_setchar(save_curfontent, ku, ten);
    return 0;
}

cmpntt_setstring(fe, s, len)
struct font_entry *fe;
byte *s;
int len;
{
    unsigned char *sp;

    /* should be optimized */
    for (sp = s; sp < s+len; sp++)
	(void)cmpntt_setchar(fe, *sp);
    return 0;
}

void
init_cmpdcd_fontinfo(fe)
struct font_entry *fe;
{
    struct comp *ffcmp;
    struct font_index *fontidx;
    int cmpdcd_markchar();
    void read_cmpdcd_fontinfo();

    ffcmp = cmpfinfo(fe);
    fontidx = NULL;
    readfontdef(0, 0, fe->s, fe->d, 0, strlen(fe->name), fe->name, &fontidx);
    ffcmp->cmp_fe = fontidx->fent;
    fe->fnt_markchar = cmpdcd_markchar;
    fe->fnt_readfontinfo = read_cmpdcd_fontinfo;
}

cmpdcd_markchar(fe, c)
struct font_entry *fe;
int c;
{
    unsigned short ku, ten;
    struct font_entry *save_curfontent;

    code_to_jis(cmpfinfo(curfontent)->cmp_sub, c, &ku, &ten);
    cmp_markchar(save_curfontent, ku, ten);
}

void
read_cmpdcd_fontinfo(fe)
struct font_entry *fe;
{
    DEV_FONT cmpdcd_fontdict();
    int cmpdcd_setchar(), cmpdcd_setstring();

    fe->rvf_setchar = virf_setchar;
    fe->rvf_setstring = virf_setstring;
    fe->dev_fontdict = cmpdcd_fontdict;
    fe->dev_setchar = cmpdcd_setchar;
    fe->dev_setstring = cmpdcd_setstring;
}

DEV_FONT
cmpdcd_fontdict(fe, c)
struct font_entry *fe;
int c;
{
    unsigned short ku, ten;
    struct font_entry *sfe;

    code_to_jis(cmpfinfo(curfontent)->cmp_sub, c, &ku, &ten);
    sfe = cmpfinfo(fe)->cmp_fe;
    return sfe->dev_fontdict(sfe, makejis(ku, ten));
}

cmpdcd_setchar(fe, c)
struct font_entry *fe;
unsigned int c;
{
    unsigned short ku, ten;
    struct font_entry *save_curfontent;

    code_to_jis(cmpfinfo(curfontent)->cmp_sub, c, &ku, &ten);
    cmp_setchar(save_curfontent, ku, ten);
    return 0;
}

cmpdcd_setstring(fe, s, len)
struct font_entry *fe;
byte *s;
int len;
{
    unsigned char *sp;

    /* should be optimized */
    for (sp = s; sp < s+len; sp++)
	(void)cmpdcd_setchar(fe, *sp);
    return 0;
}
