#include	"defs.h"
#include	"global.h"
#include	"commands.h"

extern struct fontop
    vfop,	/* virfont.c */
    jvfop,	/* virfont.c */
    tfmop,	/* bifont.c */
    jfmop,	/* bifont.c */
    cmpop,	/* compfont.c */
    dcmpop,	/* decompfont.c */
    execop,	/* execfont.c */
    funcop;	/* funcfont.c */
struct fontop *fontops[] = {
    &vfop,
    &jvfop,
    &tfmop,
    &jfmop,
    &cmpop,
    &dcmpop,
    &execop,
    &funcop,
    NULL
};

extern struct confop
    fdcop,	/* fontdesc.c */
    fontcop,	/* fontdesc.c */
    vfontcop,	/* fontdesc.c */
    defcop,	/* fontdesc.c */
    replfcop,	/* fontdesc.c */
    ptexcop;	/* fontdesc.c */
struct confop *confops[] = {
    &fdcop,
    &fontcop,
    &vfontcop,
    &defcop,
    &replfcop,
    &ptexcop,
    NULL
};


/*
 * read_fontdesc
 */
static struct fdin {
    char *name;
    FILE *file;
    int ch;
    int line;
} fdin;
#define	fdname	fdin.name
#define	fdf	fdin.file
#define	fdch	fdin.ch
#define	fdline	fdin.line

static struct libdir {
    char *dir, *lcldir;	/* library directory and local directory */
    char *defpath;	/* default path used when not found */
} libdir = {
    "", "", ""
};
struct libdir_body {
    char dir[PATHLEN], lcldir[PATHLEN];
    char *defpath;
};

static void
setlibdir(nld)
struct libdir_body *nld;
{
    libdir.dir = nld->dir;
    libdir.lcldir = nld->lcldir;
    libdir.defpath = nld->defpath;
}

void
read_fontdesc(fdn, top)
char *fdn;
BOOLEAN top;
{
    char fdfile[PATHLEN];
    FILE *f;
    char field[STRSIZE];
    struct libdir_body newlibdir;
    struct fdin save_fdin;
    struct libdir save_libdir;
    struct confop *findconfop();

    if (searchfile(fdn, fdfile, &newlibdir, top, (char *)NULL)) {
#ifdef DEBUG
	if (Debuguser)
	    (void)fprintf(stderr, "open fontdesc %s\n", fdfile);
#endif
	f = fopen(fdfile, "r");
    } else
	Fatal("cannot open fontdesc file %s", fdn);
    save_fdin = fdin;
    save_libdir = libdir;
    fdname = fdfile;
    fdf = f;
    setlibdir(&newlibdir);
    for (fdline = 1; (fdch = getc(fdf)) != EOF; fdline++) {
	if (fdch == '#' || fdch == '\n') {
	    skipline();
	    continue;
	}
	getfield(field);
	(*(findconfop(field)->co_get))();
    }
    (void)fclose(fdf);
    fdin = save_fdin;
    libdir = save_libdir;
}

/* newf <- ld+lcd+f(+ext)
 * newlcd <- dir part of lcd+f
 */
static
findsearchfile(newf, newlcd, ld, lcd, f, ext)
char *newf, *newlcd, *ld, *lcd, *f, *ext;
{
    char *p;

    (void)strcpy(newlcd, lcd);
    (void)strcat(newlcd, f);
    (void)strcpy(newf, ld);
    (void)strcat(newf, newlcd);
    if (access(newf, R_OK) != 0) {
	if (ext != NULL) {
	    (void)strcat(newf, ext);
	    if (access(newf, R_OK) != 0)
		return FALSE;
	} else
	    return FALSE;
    }
    if ((p = rindex(newlcd, '/')) != NULL)
	*(p+1) = '\0';
    else
	*newlcd = '\0';
    return TRUE;
}

/* newld <- copy of directory in path
 * newf, newlcd <- set by findsearchfile
 */
static
pathsearchfile(nextpath, path, newf, newlcd, newld, lcd, f, ext)
char **nextpath, *path;
char *newf, *newlcd, *newld, *lcd, *f, *ext;
{
    char *p, *d;

    for (; *path != '\0'; ) {
	for (; *path == PATH_SEP; path++)
	    ;
	for (p = path, d = newld; *p != PATH_SEP && *p != '\0'; )
	    *d++ = *p++;
	if (d == newld)
	    continue;
	if (*(d-1) != '/')
	    *d++ = '/';
	*d = '\0';
	if (findsearchfile(newf, newlcd, newld, lcd, f, ext)) {
	    *nextpath = p;
	    return TRUE;
	}
	if (*p == '\0')
	    break;
	path = p+1;
    }
    return FALSE;
}

searchfile(f, newf, nld, top, ext)
char *f, *newf;
struct libdir_body *nld;
BOOLEAN top;
char *ext;
{
    char *dfp, *lcd, *next, *p;

#ifdef DEBUG
    if (Debuguser)
	(void)fprintf(stderr, "search file %s in %s+%s\n",
		      f, libdir.dir, libdir.lcldir);
#endif
    if (strncmp(f, "//", 2) == 0) {
	f += 2;
	lcd = "";
	dfp = top ? dvi2lib : libdir.defpath;
    } else if (*f == '/'
#if defined(MSDOS) || defined(WIN32)
	       || (isalpha(*f) && *(f+1) == ':')
#endif
	       ) {
	p = rindex(f, '/');
#if defined(MSDOS) || defined(WIN32)
	if (p == NULL)
	    p = f+1;
#endif
	(void)strncpy(nld->dir, f, p+1-f);
	nld->dir[p+1-f] = '\0';
	nld->defpath = dvi2lib;
	return findsearchfile(newf, nld->lcldir, nld->dir, "", p+1, ext);
    } else if (top) {
	nld->defpath = dvi2lib;
	if (strncmp(f, "./", 2) == 0 || strncmp(f, "../", 3) == 0) {
	    p = rindex(f, '/');
	    (void)strncpy(nld->dir, f, p+1-f);
	    nld->dir[p+1-f] = '\0';
	    return findsearchfile(newf, nld->lcldir, nld->dir, "", p+1, ext);
	}
	if (pathsearchfile(&next, dvi2path, newf, nld->lcldir, nld->dir,
			   "", f, ext))
	    return TRUE;
	lcd = "";
	dfp = dvi2lib;
    } else {
	if (findsearchfile(newf, nld->lcldir,
			   libdir.dir, libdir.lcldir, f, ext)) {
	    (void)strcpy(nld->dir, libdir.dir);
	    nld->defpath = libdir.defpath;
	    return TRUE;
	}
	lcd = libdir.lcldir;
	dfp = libdir.defpath;
    }

#ifdef DEBUG
    if (Debuguser)
	(void)fprintf(stderr, "search file %s in lib %s+%s\n", f, dfp, lcd);
#endif
    if (pathsearchfile(&next, dfp, newf, nld->lcldir, nld->dir, lcd, f, ext)) {
	nld->defpath = next;
	return TRUE;
    }
    return FALSE;
}

#ifdef UNDEF
searchfiledir(f, ld, newf)
char *f;
struct libdir_body *ld;
char *newf;
{
    struct libdir_body newlibdir;	/* dummy */
    struct libdir save_libdir;
    int found;

    save_libdir = libdir;
    setlibdir(ld);
    found = searchfile(f, newf, &newlibdir, FALSE, (char *)NULL);
    libdir = save_libdir;
    return found;
}
#endif

void
skipline()
{
    for (; fdch != '\n' && fdch != EOF; fdch = getc(fdf))
	;
}

void
skipblanks0()
{
    int c;

    for (; fdch == ' ' || fdch == '\t' || fdch == '\\'; fdch = getc(fdf))
	if (fdch == '\\')
	    if ((c = getc(fdf)) != '\n') {
		(void)ungetc(c, fdf);
		break;
	    }
}

void
skipblanks()
{
    skipblanks0();
    if (fdch == '\n')
	Fatal("fontdesc: %s illegal line %d", fdname, fdline);
}

getfield(field)
char *field;
{
    char *fend;
    int c;

    skipblanks();
    for (fend = field+STRSIZE-1;
	 fdch != ' ' && fdch != '\t' && fdch != '\n' && fdch != EOF;
	 fdch = getc(fdf)) {
	if (fdch == '\\')
	    if ((c = getc(fdf)) != '\n') {
		(void)ungetc(c, fdf);
	    } else {
		fdch = ' ';
		break;
	    }
	if (field < fend)
	    *field++ = fdch;
	else
	    Fatal("fontdesc: field too long (%s line %d)", fdname, fdline);
    }
    *field = '\0';
}

getqfield0(field)
char *field;
{
    char *fend;
    int c;

    if (fdch == FDQUO) {
	*field++ = fdch;
	for (fend = field+STRSIZE-1;
	     (*field++ = fdch = getc(fdf)) != FDQUO && fdch != EOF; ) {
	    if (fdch == '\\')
		*(field-1) = getc(fdf);
	    if (field >= fend)
		Fatal("fontdesc: field too long (%s line %d)", fdname, fdline);
	}
	if (fdch == EOF)
	    Fatal("fontdesc: %c not closed (%s line %d)",
		  FDQUO, fdname, fdline);
	*field = '\0';
	fdch = getc(fdf);
    } else
	getfield(field);
}

getqfield(field)
char *field;
{
    skipblanks();
    getqfield0(field);
}

#ifdef UNDEF
getoqfield(field)
char *field;
{
    skipblanks0();
    if (fdch != '\n')
	getqfield0(field);
    else
	*field = '\0';
}
#endif

getlfield(field)
char *field;
{
    char *fend;
    int c;

    skipblanks();
    for (fend = field+STRSIZE-1; fdch != '\n' && fdch != EOF;
	 fdch = getc(fdf)) {
	if (fdch == '\\')
	    if ((c = getc(fdf)) != '\n') {
		(void)ungetc(c, fdf);
	    } else {
		fdch = ' ';
	    }
	if (field < fend)
	    *field++ = fdch;
	else
	    Fatal("fontdesc: field too long (%s line %d)", fdname, fdline);
    }
    *field = '\0';
}

struct confop skipcop = {
    "",
    skipline
};

struct confop *
findconfop(field)
char *field;
{
    struct confop **co;

    for (co = confops; *co != NULL; co++)
	if (STREQ((*co)->co_name, field))
	    return *co;
    Warning("fontdesc: %s illegal (%s line %d)", field, fdname, fdline);
    return &skipcop;
}

/*
 * configuration operations
 */

void getfontdesc();
struct confop fdcop = {
    "fontdesc",
    getfontdesc
};

void
getfontdesc()
{
    char field_file[PATHLEN];
    char path[PATHLEN];

    getfield(field_file);
    skipline();
    defexpand(path, field_file);
    read_fontdesc(path, FALSE);
}

void
arg_fontdesc(fdn)
char *fdn;
{
    char path[PATHLEN];

    defexpand(path, fdn);
    read_fontdesc(path, TRUE);
}

void getfdfont();
struct confop fontcop = {
    "font",
    getfdfont
};

void getfdvfont();
struct confop vfontcop = {
    "vfont",
    getfdvfont
};

struct fontdesc {
    struct fontop *fd_op;
    char *fd_spec;	/* specifier */ /* not used */
    int	fd_sub;		/* font substitution */
    struct funcfont *fd_path;	/* prototype path */
    struct fontdesc *fd_next;
};
static struct fontdesc *fontdescs = NULL;
static struct fontdesc **nextfd = &fontdescs;
static struct fontdesc *vfontdescs = NULL;
static struct fontdesc **nextvfd = &vfontdescs;

struct fontdesc *
getfontline()
{
    char field_type[STRSIZE];
    char field_spec[STRSIZE];
    char field_sub[STRSIZE];
    char field_path[STRSIZE];
    struct fontdesc *fd;
    struct fontop *fop;
    struct funcfont *ff;

    getfield(field_type);
    if ((fop = findfontop(field_type)) == NULL) {
	Warning("fontdesc: illegal font type %s (%s line %d)",
		field_type, fdname, fdline);
	skipline();
	return NULL;
    }
    getfield(field_spec);
    getfield(field_sub);
    getlfield(field_path);
    if (!(*fop->fo_init)(field_path, &ff)) {
	Warning("fontdesc: illegal font line (%s line %d)", fdname, fdline);
	return NULL;
    }
    fd = NEW(struct fontdesc, "fontdesc");
    fd->fd_op = fop;
    fd->fd_spec = strsave(field_spec);
    fd->fd_sub = atoi(field_sub);
    fd->fd_path = ff;
    fd->fd_next = NULL;
    return fd;
}

void
getfdfont()
{
    struct fontdesc *fd;

    if ((fd = getfontline()) != NULL) {
	*nextfd = fd;
	nextfd = &(fd->fd_next);
    }
}

void
getfdvfont()
{
    struct fontdesc *fd;

    if ((fd = getfontline()) != NULL) {
	*nextvfd = fd;
	nextvfd = &(fd->fd_next);
    }
}

struct fontop *
findfontop(type)
char *type;
{
    struct fontop **fo;
    
    for (fo = fontops; *fo != NULL; fo++)
	if (STREQ((*fo)->fo_type, type))
	    return *fo;
    return NULL;
}

pathtype_init(proto, ff)
char *proto;
struct funcfont **ff;
{
    char path[PATHLEN];

    defexpand(path, proto);
    *ff = (struct funcfont *)strsave(path);
    return TRUE;
}

void getdef();
struct confop defcop = {
    "define",
    getdef
};

struct definition {
    char *def_name;
    char *def_body;
    struct definition *def_next;
};
static struct definition *definitions = NULL;
static struct definition *arg_defs = NULL;

add_def0(var, val)
char *var, *val;
{
    struct definition *def;

    def = NEW(struct definition, "definition");
    def->def_name = var;
    def->def_body = val;
    def->def_next = definitions;
    definitions = def;
}

add_def(var, val)
char *var, *val;
{
    char path[PATHLEN];
    struct definition *def;

    def = NEW(struct definition, "definition");
    def->def_name = strsave(var);
    defexpand(path, val);
    def->def_body = strsave(path);
    def->def_next = definitions;
    definitions = def;
}

struct definition *
get_def(var, defs)
char *var;
struct definition *defs;
{
    struct definition *def;

    for (def = defs; def != NULL; def = def->def_next)
	if (STREQ(var, def->def_name))
	    return def;
    return NULL;
}

arg_define(def)
char *def;
{
    char *val;

    for (val = def; *val != '=' && *val != '\0'; val++)
	;
    if (*val == '=')
	*val++ = '\0';
    add_def(def, val);
    arg_defs = definitions;
}

void getdef()
{
    char field_name[STRSIZE];
    char field_body[STRSIZE];
    char path[PATHLEN];
    struct definition *def;

    getfield(field_name);
    getfield(field_body);
    skipline();
    if (get_def(field_name, arg_defs) == NULL)
	add_def(field_name, field_body);
}

char *
getdefbody(var)
char *var;
{
    struct definition *def;

    return (def = get_def(var, definitions)) != NULL ? def->def_body : "";
}

void
defexpand(path, proto)
char *path, *proto;
{
    char *p, *s, *t;
    char *pend;
    char dname[STRSIZE];

    for (p = path, s = proto, pend = path+PATHLEN-1; *s != '\0'; s++)
	if (*s == '$') {
	    if (*++s == '{') {
		for (t = dname, ++s; *s != '}' && *s != '\0'; s++, t++)
		    *t = *s;
		if (*s == '\0')
		    --s;	/* error */
	    } else {
		for (t = dname; isalnum(*s); s++, t++)
		    *t = *s;
		--s;
	    }
	    *t = '\0';
	    t = getdefbody(dname);
	    if (p+strlen(t) >= pend)
		Fatal("font path too long %s", proto);
	    (void)strcpy(p, t);
	    p += strlen(t);
	} else if (p < pend) {
	    *p++ = *s;
	} else
	    Fatal("font path too long %s", proto);
    *p = '\0';
}

/* dummy */
/* ARGSUSED */
void
add_include(f, top)
char *f;
BOOLEAN top;
{
}

/* dummy */
/* ARGSUSED */
void
add_setup(f, top)
char *f;
BOOLEAN top;
{
}

#ifdef UNDEF
void getsubst();
struct confop substcop = {
    "subst",
    getsubst
};

struct fontsubst {
    char *fs_font;
    int fs_len;
    int fs_reqmag;
    int fs_submag;
    struct fontsubst *fs_next;
};
static struct fontsubst *fontsubsts = NULL;
static struct fontsubst **nextfs = &fontsubsts;

void
getsubst()
{
    char field_font[STRSIZE];
    char field_reqmag[STRSIZE];
    char field_submag[STRSIZE];
    struct fontsubst *fs;;

    getfield(field_font);
    getfield(field_reqmag);
    getfield(field_submag);
    skipline();
    fs = NEW(struct fontsubst, "fontsubst");
    fs->fs_font = strsave(field_font);
    fs->fs_len = strlen(field_font);
    if (strcmp(field_reqmag, "%R") == 0)
	fs->fs_reqmag = resolution;
    else
	fs->fs_reqmag = atoi(field_reqmag);
    fs->fs_submag = atoi(field_submag);
    fs->fs_next = NULL;
    *nextfs = fs;
    nextfs = &(fs->fs_next);
}
#endif

void getreplfont();
struct confop replfcop = {
    "replfont",
    getreplfont
};

struct fontreplace {
    char *fr_replfont;
    char *fr_font;
    int fr_ds;
    int fr_fix;
    struct fontreplace *fr_next;
};
static struct fontreplace *fontreplaces = NULL;
static struct fontreplace **nextfr = &fontreplaces;

void
getreplfont()
{
    char field_replfont[STRSIZE];
    char field_font[STRSIZE];
    char field_par[STRSIZE];
    struct fontreplace *fr;
    char *c, *f;
    BOOLEAN fixs;
    float fx;

    getfield(field_replfont);
    getfield(field_font);
    getfield(field_par);
    skipline();
    fr = NEW(struct fontreplace, "fontreplace");
    fr->fr_replfont = strsave(field_replfont);
    fr->fr_font = strsave(field_font);
    for (c = field_par; *c != '\0' && *c != ','; c++)
	;
    fixs = *c == ',';
    *c = '\0';
    fr->fr_ds = atoi(field_par)<<16;
    fr->fr_fix = -1;
    while (fixs) {
	for (f = ++c; *c != '\0' && *c != '*'; c++)
	    ;
	fixs = *c == '*';
	*c = '\0';
	if (*f == 'f') {
	    if (fr->fr_fix >= 0)
		fr->fr_fix = scale_exact(fr->fr_fix, atoi(f+1));
	    else
		fr->fr_fix = atoi(f+1);
	} else {
	    (void)sscanf(f, "%f", &fx);
	    if (fr->fr_fix >= 0)
		fr->fr_fix = scale_exact(fr->fr_fix, (int)(fx*(float)(1<<20)));
	    else
		fr->fr_fix = (int)(fx*(float)(1<<20));
	}
    }
    fr->fr_next = NULL;
    *nextfr = fr;
    nextfr = &(fr->fr_next);
}

void getptex();
struct confop ptexcop = {
    "ptex",
    getptex
};

int dirmode = DIR_ELIM;
char *dir_spec_vert;
char *dir_spec_end;
int dir_spec_vert_len = 0;
int dir_spec_end_len = 0;
char ds_begin[STRSIZE+5];
char ds_end[STRSIZE+5];

#define	get_special(ds_p, ds_len, ds_buf)	\
	off = 5; \
	getqfield(ds_buf+off); \
	len = strlen(ds_buf+off); \
	if (*(ds_buf+off) == FDQUO) { \
	    off++; \
	    len -= 2; \
	} \
	n = inttob(k, len); \
	off -= n+1; \
	ds_buf[off] = XXX1+len/256; \
	strncpy(ds_buf+off+1, k, n); \
	ds_p = ds_buf+off; \
	ds_len = 1+n+len;

void
getptex()
{
    char field_mode[STRSIZE];
    int len, off, n;
    byte k[sizeof(int)];

    getfield(field_mode);
    if (STREQ(field_mode, "keep"))
	dirmode = DIR_KEEP;
    else if (STREQ(field_mode, "elim"))
	dirmode = DIR_ELIM;
    else if (STREQ(field_mode, "special"))
	dirmode = DIR_SPECIAL;
    else if (STREQ(field_mode, "ignore"))
	dirmode = DIR_IGNORE;
    else if (STREQ(field_mode, "mark"))
	dirmode = DIR_MARKLINE;
    else {
	Warning("fontdesc: illegal ptex %s (%s line %d)",
		field_mode, fdname, fdline);
	dirmode = DIR_ELIM;
    }
    if (dirmode == DIR_SPECIAL) {
	getfield(field_mode);
	if (STREQ(field_mode, "vert")) {
	    get_special(dir_spec_vert, dir_spec_vert_len, ds_begin);
	} else if (STREQ(field_mode, "end")) {
	    get_special(dir_spec_end, dir_spec_end_len, ds_end);
	}
    } else if (dirmode == DIR_MARKLINE) {
	getfield(field_mode);
	if (STREQ(field_mode, "char"))
	    dirmode = DIR_MARKCHAR;
    }
    skipline();
}

/*
 * initialize and fix some default values
 */
char *kpsevname = "kpse";

init_default(def_kpse)
char *def_kpse;
{
    add_def0(kpsevname, def_kpse);
}

fix_default(def_resolution)
int def_resolution;
{
    /* use resolution as drift!! */
    if (resolution <= 0)
	resolution = def_resolution;
}


/*
 * replace font
 */
replfont(n, s, rn, rd, rs)
char *n;
int s;
char *rn;
int *rd, *rs;
{
    struct fontreplace *fr;
    char *sb, *se;

    for (fr = fontreplaces; fr != NULL; fr = fr->fr_next)
	if (match_subf(fr->fr_replfont, n, FALSE, &sb, &se)) {
	    subst_subf(rn, fr->fr_font, sb, se);
	    *rd = fr->fr_ds;
	    if (fr->fr_fix < 0)
		*rs = s;
	    else
		*rs = scale_exact(fr->fr_fix, s);
	    return TRUE;
	}
    return FALSE;
}

/*
 * init_fontinfo
 */
init_finfo(fe, fonts)
struct font_entry *fe;
struct fontdesc *fonts;
{
    struct accarg acca;
    float rawmagfact, newmagfact;
    struct fontdesc *fd;
    int i, next;

    /*acca.rawmagfact = rawmagfact = newmagfact = dev_fontmag(fe);*/
    acca.pv_name = fe->n;
    /* We don't treat the case fe->a != 0 */

    acca.acc_mode = ACC_EXACT;
    /*acca.actmagfact = actfact(acca.rawmagfact);*/
    for (fd = fonts; fd != NULL; fd = fd->fd_next) {
	if ((*(fd->fd_op->fo_access))(fd->fd_path, fe, &acca)) {
#ifdef DEBUG
	    if (Debuguser)
		Warning("Font info for %s found", fe->n);
#endif
	    (*(fd->fd_op->fo_initfontinfo))(fe);
	    return TRUE;
	}
    }
    return FALSE;
}

void
init_fontinfo(fe)
struct font_entry *fe;
{
    void init_dvi_fontinfo();

    if (!init_finfo(fe, fontdescs)) {	/* if missing, pass through dvi  */
#ifdef DEBUG
	if (Debuguser)
	    Warning("Font info for %s not found, used unmodified", fe->n);
#endif
	init_dvi_fontinfo(fe);
    }
}

init_vfontinfo(fe)
struct font_entry *fe;
{
    return init_finfo(fe, vfontdescs);
}

/*
 * Turn a prototype path into a fullpath.
 */
void
pave(path, proto, acca)
char *path, *proto;
struct accarg *acca;
{
    char *p, *s, *t;
    char *pend;
    int len;
    char buf[32];
#ifdef MSDOS
    char *l, *b;
#endif

    for (p = path, s = proto, pend = path+PATHLEN-1; *s != '\0'; s++)
	if (*s == '%') {
	    switch (*++s) {
	    case 'f':
	    case 'n':
	    case 's':
#ifdef MSDOS
		len = strlen(t = acca->pv_name);
		if ((l = rindex(t, '.')) == NULL)
		    l = t+len;
		if (l-t > 8) {
		    if (G_longfontname) {
			(void)strncpy(buf, t, 4);
			(void)strncpy(buf+4, l-4, 4);
		    } else {
			(void)strncpy(buf, t, 8);
		    }
		    b = buf+8;
		} else {
		    (void)strncpy(buf, t, l-t);
		    b = buf+(l-t);
		}
		(void)strncpy(b, l, len-(l-t)+1);
		t = buf;
#else
		t = acca->pv_name;
#endif
		break;
	    case 'd':
	    case 'm':
		(void)sprintf(t = buf, "%d", acca->pv_mag);
		break;
	    case 'M':
		(void)sprintf(t = buf, "%f", acca->actmagfact);
		break;
	    case 'R':
		(void)sprintf(t = buf, "%d", resolution);
		break;
	    case 'F':
		t = acca->pv_fam;
		break;
	    case 'D':
		(void)sprintf(t = buf, "%d", acca->pv_ds);
		break;
	    case 'j':
		t = acca->pv_jsub;
		break;
	    default:
		*(t = buf) = *s;  *(t+1) = '\0';
		break;
	    }
	    if (p + (len = strlen(t)) <= pend) {
		(void)strncpy(p, t, len);
		p += len;
	    } else
		Fatal("font path too long %s", proto);
	} else if (p < pend) {
	    *p++ = *s;
	} else
	    Fatal("font path too long %s", proto);
    *p = '\0';
}

#ifdef KPATHSEA
static char pathk[PATHLEN], pathk0[PATHLEN], base[PATHLEN];

void
pavek(path, pathp, basep, proto, acca)
char *path, **pathp, **basep, *proto;
struct accarg *acca;
{
    char *p, *pthk;

    pave(pathk, proto, acca);
    if (strncmp(pathk, "//", 2) == 0) {
	(void)strcpy(pathk0, dvi2lib);
	(void)strcat(pathk0, "/");
	(void)strcat(pathk0, pathk+2);
	pthk = pathk0;
    } else 
	pthk = pathk;
    (void)strcpy(path, pthk);
    *pathp = pthk;
    for (p = pthk+strlen(pthk)-1; p >= pthk; --p)
	if (*p == '/' || *p == '}')
	    break;
    if (p < pthk) {
	*basep = pthk;
	*pathp = NULL;
    } else if (*++p != '\0') {
	strcpy(base, p);
	*basep = base;
	*p = '\0';
    } else {
	*basep = NULL;
    }
}
#endif
