/*
 * PS included font
 */

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

static void scanifont();

ps_scanifont(str)
char *str;
{
    int found;
    char newf[PATHLEN];

    if (found = ps_searchfile(str, newf)) {
	scanifont(found == SEARCH_ORIG ? str : newf);
    } /*else
	Warning("File %s not found", str);*/
}

#define	hex(c)	(c<='9' ? c-'0' : (c<='F' ? c-'A'+10 : c-'a'+10))

struct ifonts {
    struct ifsizes *if_ss;
    struct ifonts *if_next;
} *if_list = NULL;
struct ifsizes {
    char *is_sstr;
    struct font_entry *is_fe;
    struct ifsizes *is_next;
};

static void
scanifont(fn)
char *fn;
{
    FILE *spfp;
    char buffer[PSFLEN];
    char *p, *q, *n, *sstr;
    int s, d, c;
    float f;
    struct ifonts *ifl;
    struct ifsizes *isl;
    struct font_entry *fe;
    struct font_entry *save_curfontent;
    int mask, b;

    if ((spfp = fopen(fn,"r")) == NULL) {
	/*Warning("Unable to open file %s", fn);*/
	return;
    }

    while (fgets(buffer, PSFLEN, spfp) != NULL) {
	if (buffer[0] != '%' ||
	    (buffer[1] != '%' && buffer[1] != '*' && buffer[1] != '!'))
	    break;
	if (strncmp(buffer, "%*Font:", 7))
            continue;

	skipstrblank(buffer+7, &n);
	if (!getstrtok(n, ' ', &p)) {
	    Warning("PS included font: illegal font name");
	    break;
	}
	skipstrblank(p, &p);
	if (!getstrtok(p, ' ', &q)) {
	    Warning("PS included font: no scaled size");
	    break;
	}
	(void)sscanf(p, "%f", &f);
	s = bp2sp(f);
	sstr = p;
	skipstrblank(q, &p);
	if (!getstrtok(p, ' ', &q)) {
	    Warning("PS included font: no design size");
	    break;
	}
	(void)sscanf(p, "%f", &f);
	d = bp2sp(f);
	skipstrblank(q, &p);
	if (!isxdigit(*p) || !isxdigit(*(p+1)) || *(p+2) != ':') {
	    Warning("PS included font: illegal included chars");
	    break;
	}

#ifdef DEBUG
	if (Debug)
	    (void)fprintf(stderr, "psfile-fontdef %s s = %d d = %d",
			  n, s, d);
#endif
	fe = get_font_entry(0, s, d, 0, strlen(n), n);
	for (ifl = if_list; ifl != NULL; ifl = ifl->if_next)
	    if (STREQ(ifl->if_ss->is_fe->n, n)) {
		for (isl = ifl->if_ss; isl != NULL; isl = isl->is_next)
		    if (STREQ(isl->is_sstr, sstr))
			goto found;
		isl = NEW(struct ifsizes, "ifsizes");
		isl->is_sstr = strsave(sstr);
		isl->is_fe = fe;
		isl->is_next = ifl->if_ss;
		ifl->if_ss = isl;
		goto found;
	    }
	ifl = NEW(struct ifonts, "ifonts");
	ifl->if_next = if_list;
	isl = NEW(struct ifsizes, "ifsizes");
	isl->is_sstr = strsave(sstr);
	isl->is_fe = fe;
	isl->is_next = NULL;
	ifl->if_ss = isl;
	if_list = ifl;
    found:
	save_curfontent = curfontent;
	setcurfont(fe);
	c = hex(*p)*16+hex(*(p+1));
	for (p += 3; isxdigit(*p); p++) {
	    mask = hex(*p);
	    for (b = 8; b > 0; b >>= 1) {
		if (mask&b)
		    MarkChar(c);
		if (++c >= 256)
		    goto charend;
	    }
	}
    charend:
	setcurfont(save_curfontent);
    }

    fclose(spfp);
}

bp2sp(f)
float f;
{
    return (int)(f*65536*72.27/72);
}

useifont()
{
    return if_list != NULL;
}

ifont_setup()
{
#if 0
    char incfile[PATHLEN];
    char newlibdir[PATHLEN];	/* dummy */
#endif
    struct ifonts *ifl;
    struct ifsizes *isl;
    int i;
    DEV_FONT null_fontdict();

    EMIT(outfp, "end\n");
    for (ifl = if_list; ifl != NULL; ifl = ifl->if_next) {
	EMITC('(');
	EMITS(ifl->if_ss->is_fe->n);
	EMITS(")cvn ");
	for (isl = ifl->if_ss, i = 0; isl != NULL; isl = isl->is_next, i++) {
	    EMITS(isl->is_sstr);
	    if (isl->is_fe->dev_fontdict == null_fontdict)
		EMIT(outfp, " /nullfont ");
	    else
		EMIT(outfp, " /%s ", psfname(isl->is_fe->k));
	}
	EMIT(outfp, "%d fstore\n", i);
    }
    EMIT(outfp, "TeXDict begin\n");
}
