/* decompose font to subfonts
 */

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

int decomptype_init();
int decomptype_access();
void init_decomp_fontinfo();
struct fontop dcmpop = {
    "decomp",
    decomptype_init,
    decomptype_access,
    init_decomp_fontinfo,
};

decomptype_init(pars, ff)
char *pars;
struct decomp **ff;
{
    char *p1, *p2;
    int dt;
    struct decomp *ffdcmp;

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

decomptype_access(ffdcmp, fe, acca)
struct decomp *ffdcmp;
struct font_entry *fe;
struct accarg *acca;
{
    struct decomp *ffnew;

#ifdef DEBUG
    if (Debuguser)
	(void)fprintf(stderr, "trying to decompose %s/%s\n",
		      fe->n, ffdcmp->dcmp_name);
#endif
    if (strncmp(fe->n, ffdcmp->dcmp_name, strlen(ffdcmp->dcmp_name)) == 0) {
	if (numstr(fe->n+strlen(ffdcmp->dcmp_name)) ) {
	    ffnew = (struct decomp *)
		alloc_check(malloc((unsigned)sizeof(struct decomp)+
				   (ffdcmp->dcmp_type == CMP_NTT ?
				        NJSUBS : NCSUBS)*
				   sizeof(struct font_entry *)),
			 "decomp init");
	    *ffnew = *ffdcmp;
	    fe->finfo = (struct finfo *)ffnew;
	    return TRUE;
	}
    }
    return FALSE;
}

void
init_decomp_fontinfo(fe)
struct font_entry *fe;
{
    void init_dcmpntt_fontinfo(), init_dcmpdcd_fontinfo();

    if (dcmpfinfo(fe)->dcmp_type == CMP_NTT)
	init_dcmpntt_fontinfo(fe);
    else
	init_dcmpdcd_fontinfo(fe);
}

void
init_dcmpntt_fontinfo(fe)
struct font_entry *fe;
{
    struct decomp *ffdcmp;
    char *ntail;
    byte n[STRSIZE];
    int i;
    struct font_index *fontidx;
    int dcmpntt_markchar();
    void read_dcmpntt_fontinfo();

    ffdcmp = dcmpfinfo(fe);
    ntail = fe->n+strlen(ffdcmp->dcmp_name);
    fontidx = NULL;
    for (i = 1; i <= NJSUBS; i++) {
	(void)sprintf(n, "%s%s%s", ffdcmp->dcmp_name, jsubfontname(i), ntail);
	readfontdef(i, 0, fe->s, fe->d, 0, strlen(n), (char *)n, &fontidx);
	ffdcmp->dcmp_fetab[i] = fontidx->fent;
    }
    fe->fnt_markchar = dcmpntt_markchar;
    fe->fnt_readfontinfo = read_dcmpntt_fontinfo;
}

#define	ku(c)	((c)>>8)
#define	ten(c)	((c)&0xff)

#define	dcmp_markchar(save, f, c) \
	save = curfontent; \
	setcurfont(dcmpfinfo(curfontent)->dcmp_fetab[f]); \
	MarkChar(c); \
	setcurfont(save);

dcmpntt_markchar(fe, c)
struct font_entry *fe;
int c;
{
    unsigned short f, cc;
    struct font_entry *save_curfontent;

    jis_to_jsub(ku(c), ten(c), &f, &cc);
    dcmp_markchar(save_curfontent, f, cc);
}

void
read_dcmpntt_fontinfo(fe)
struct font_entry *fe;
{
    DEV_FONT dcmpntt_fontdict();
    int dcmpntt_setchar(), dcmpntt_setstring();

    fe->rvf_setchar = virf_setchar;
    fe->rvf_setstring = virf_setstring;
    fe->dev_fontdict = dcmpntt_fontdict;
    fe->dev_setchar = dcmpntt_setchar;
    fe->dev_setstring = dcmpntt_setstring;
}

DEV_FONT
dcmpntt_fontdict(fe, c)
struct font_entry *fe;
int c;
{
    unsigned short f, cc;
    struct font_entry *sfe;

    jis_to_jsub(ku(c), ten(c), &f, &cc);
    sfe = dcmpfinfo(fe)->dcmp_fetab[f];
    return sfe->dev_fontdict(sfe, cc);
}

#define	dcmp_setchar(save, f, c) \
	save = curfontent; \
	setcurfont(dcmpfinfo(curfontent)->dcmp_fetab[f]); \
	SetChar(c, chmove); \
	setcurfont(save);

dcmpntt_setchar(fe, c)
struct font_entry *fe;
int c;
{
    unsigned short f, cc;
    struct font_entry *save_curfontent;

    jis_to_jsub(ku(c), ten(c), &f, &cc);
    dcmp_setchar(save_curfontent, f, cc);
    return 0;
}

/* ARGSUSED */
dcmpntt_setstring(fe, s, len)
struct font_entry *fe;
byte *s;
int len;
{
    Fatal("%s implementation error: dcmpntt_setstring", G_progname);
}

void
init_dcmpdcd_fontinfo(fe)
struct font_entry *fe;
{
    struct decomp *ffdcmp;
    char *ntail;
    byte n[STRSIZE];
    int i;
    struct font_index *fontidx;
    int dcmpdcd_markchar();
    void read_dcmpdcd_fontinfo();

    ffdcmp = dcmpfinfo(fe);
    ntail = fe->n+strlen(ffdcmp->dcmp_name);
    fontidx = NULL;
    for (i = 1; i <= NCSUBS; i++) {
	(void)sprintf(n, "%s%c%02x%c%s",
		      ffdcmp->dcmp_name, CSUB_SEP, 31+i*2, CSUB_SEP, ntail);
	readfontdef(i, 0, fe->s, fe->d, 0, strlen(n), (char *)n, &fontidx);
	ffdcmp->dcmp_fetab[i] = fontidx->fent;
    }
    fe->fnt_markchar = dcmpdcd_markchar;
    fe->fnt_readfontinfo = read_dcmpdcd_fontinfo;
}

dcmpdcd_markchar(fe, c)
struct font_entry *fe;
int c;
{
    unsigned short f, cc;
    struct font_entry *save_curfontent;

    jis_to_dcode(ku(c), ten(c), &f, &cc);
    dcmp_markchar(save_curfontent, f, cc);
}

void
read_dcmpdcd_fontinfo(fe)
struct font_entry *fe;
{
    DEV_FONT dcmpdcd_fontdict();
    int dcmpdcd_setchar(), dcmpdcd_setstring();

    fe->rvf_setchar = virf_setchar;
    fe->rvf_setstring = virf_setstring;
    fe->dev_fontdict = dcmpdcd_fontdict;
    fe->dev_setchar = dcmpdcd_setchar;
    fe->dev_setstring = dcmpdcd_setstring;
}

DEV_FONT
dcmpdcd_fontdict(fe, c)
struct font_entry *fe;
int c;
{
    unsigned short f, cc;
    struct font_entry *sfe;

    jis_to_dcode(ku(c), ten(c), &f, &cc);
    sfe = dcmpfinfo(fe)->dcmp_fetab[f];
    return sfe->dev_fontdict(sfe, cc);
}

dcmpdcd_setchar(fe, c)
struct font_entry *fe;
int c;
{
    unsigned short f, cc;
    struct font_entry *save_curfontent;

    jis_to_dcode(ku(c), ten(c), &f, &cc);
    dcmp_setchar(save_curfontent, f, cc);
    return 0;
}

/* ARGSUSED */
dcmpdcd_setstring(fe, s, len)
struct font_entry *fe;
byte *s;
int len;
{
    Fatal("%s implementation error: dcmpdcd_setstring", G_progname);
}
