/*
 *  TEX Device Driver  ver 2.02-
 *  copyright(c) 1988, 1989 by TSG, 1990-93 by SHIMA
 *  1990 changed by M.Watanabe
 *  1991 changed by hideki
 *  1991 changed by T.Minagawa
 *
 *  fontdef.c : module to make font information list
 *
 *  Jul.  1, 1989 : 3rd edition
 *  very slightly modified against warnings by Oh-Yeah? 25 May 1992
 *  modifed for LIPS3 by SHIMA 30 June 1992
 *  modified by Naochan! 6 August 1992
 *  slightly modified for LIPS3&ESC/Page by OkI 8 August 1992
 *  slightly modified for JGfont(3D-Bezier) by Naochan! 12 Nov 1992
 *  slightly modified by Yakumo 27 Nov 1992
 *  slightly modified for NTTjTeX by Yakumo 20 Dec. 1992
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#define	MULTI_ROOT 1

#ifdef  UNIX
#include <unistd.h>
#else
#include <io.h>
#ifdef MSVC
#include "msvcdir.h"
#else
#include <dir.h>
#endif
#include <process.h>
# if defined(GCC1)||defined(WIN32C)||defined(SLEEP)
#include <dos.h>
# endif
#endif
#include <ctype.h>

#include "dd.h"
#include "err.h"
#include "dviread.h"
#include "vfont.h"
#include "option.h"
#include "inter.h"
#include "help_id.h"

#ifdef	UNIX
#define	STR_PATH_SEP	"/"
#define	STR_DELIM		":"
#else
#define	STR_PATH_SEP	"\\"
#define	STR_DELIM		";"
#endif

#define	CHAR_SP	'\t'
#define	STR_SP	"\t"

/* option.c */
int make_path(char *, char *, char *, char *);

#if	defined(GCC1) && !defined(UNIX)
struct find_t {
	char     reserved[21];      /* Microsoft reserved - do not change */
	char     attrib;            /* attribute byte for matched file */
	unsigned wr_time;           /* time of last write to file */
	unsigned wr_date;           /* date of last write to file */
	long     size;              /* size of file */
	char     name[13];          /* asciiz name of matched file */
};
#define	_A_SUBDIR	0x10
#endif

#ifdef	FLI
#include "flifont.h"
static char 
*accfli(char *fname, char *ptr_sp, char *ast, int reso, char *fontlib);
#endif	/* FLI */

#ifndef NO_GENFONT
/* Please comment out the next line, if don't use (near) METAFONT routine. */
/* #define INTEGER_CALC */
static FILE *genfntfp = NULL;
extern char *genfont_tmpl;
void CutLast(char *src);
char * genfont_main(char *, ulong, ulong, uint, uint, uint);
static void genfont_init(void);
static void genfont_out(FILE *, int);
static void genfont_proc(FILE *, char *, long, long);
static void free_tmpl(void);
#ifdef INTEGER_CALC
# define KETA 5
 static long ftolong(float);
 static long quotient(long, long);
#endif
static int extra_size;
static BOOL genflag;
static BOOL f_tfm2ttf;
static char *gentmp;
static char *genfnt;
static char *genmode;
static char *extramode;
static char *fntname;

static struct gen_tmpl {
	char *line;
	struct gen_tmpl *next;
} *root_tmpl[] = {NULL, NULL, NULL};

#endif

/* err.c */
extern int f_wait;

/* buffer.c */
void font_flush(void);

/* prtinit.c */
FILE *OpenAddFile(char *, char *);

# ifndef NOVFONT
/* vfont.c */
char *check_ftt(char *);
BOOL check_vjfm(char *);
char *check_myftt(char *, int);
# endif

#ifdef	USE_ETF
BOOL IsETF(FONT_INFO *, char *, int);
#endif

#ifdef	WIN32G
#define	MIKTEX	1

void DisplayMessage(char *);
char *FindNextW32(void);
char *FindFirstW32(char *);
void ShowWinHelp(int);

#ifdef	MIKTEX
int ReadRegString(char *, int, char *, char *, int);
#define	REG_MIKTEX	"SOFTWARE\\Mik\\MikTeX\\CurrentVersion\\MiKTeX"
static char *miktexpk_org = 
	"^r\\tfm\\\\^s^tfm;^r\\pk\\\\dpi^d\\^s.pk;"
	"^r\\vf\\\\^s.vf;^r\\ovf\\\\^s.ovf;^r\\tfm\\\\^s.tfm";
#endif

#endif


char *texpk_org = 
	"^r\\tfm\\\\^s^tfm;^r\\pk\\\\^s.^dpk;"
	"^r\\vf\\\\^s.vf;^r\\ovf\\\\^s.ovf;^r\\tfm\\\\^s.tfm";

#ifdef	USE_WINAPI
extern f_osversion;
int WinMinExecute(char **, int, BOOL);
#endif

#define READ_MODE   	0x04
#define	MAX_SUB_LEN     16

					/* size of path name buffer tmp_buf[TMP_BUF_SIZE] */
#define TMP_BUF_SIZE    1500

#define	ROM_F_SIZE		16

#ifdef	GCC
#define FIG_COLUMN      16
#else
#define FIG_COLUMN      8
#endif

extern char *pk_env_name;

/* 環境変数名 */
char *pk_search_path = NULL;
char *root_search_path;
char *font_search_path;
char *font_root_path;
char *new_tfm_search_path;
extern char *subfont_path;
extern char *new_subfont_path;

/* opt file で設定された pk ファイルのパス */
char *pkd_search_path = NULL;

/* opt file で設定された pkd ファイルのパス */
char *knj_search_path = NULL;

/* opt file で設定された KANJI pk ファイルのパス */

#ifdef VFD
char *vfd_search_path = NULL;

/* cfg file で設定された vfd ファイルのパス */
#endif

#ifdef FLI
char *fli_search_path = NULL;

/* cfg file で設定された fli ファイルのパス */
#endif

#ifdef TTFONT
char *tfm_search_path = NULL;

/* cfg file で設定された tfm ファイルのパス(CM-TT font で使用) */
#endif

extern int test_flg;
extern int f_init;

int f_long_name = 2;
char *goth;
char *sub_font;
int	f_sub_blank;
int f_search;
static int f_loop = 3;
static int f_sub_font;
static int f_sub_warn;
static unsigned char f_checkerror = 0;
int f_use_vfont = FALSE;

#ifdef	LBP
int f_use_lfont = FALSE;

#endif

static int romfont_max = -1;	/* ROM FONT の拡大／縮小使用を許可するか */
BOOL f_resize;
BOOL f_kakuto;

struct FONT_ATR {
	/* font_defのパラメーター ; See "TeX:The program". */
	long k, c, s, d;
	int a, l;
	char *n;
};

struct finfo {
	char  f_atrib;
	uchar f_time[2];
	uchar f_date[2];
	uchar f_size[4];
	char  f_name[14];
	uchar f_pos[4];
};

#define	FINFO_SIZE	sizeof(struct finfo)

/*		Reserve font files corresponding to fonts		*/
#define	PACKNAME		1				/*	Set 0 for debug */
#define	MAX_FCASH		400
#define	MAX_FCASH_REV	16

char tmp_tfm[MAXFILE+2];
static int dpis, mags;
int texpk_pos;
uchar *path_font;
uchar *path_cash;
int	f_path_cash;
int fcash_size;
int fcash_rev;
int fcash_ver;
int fcash_dev;
BOOL f_ondemand = TRUE;

/* static double dpi, true_mag; */
/* dpi, mag */

/* standard library */
char *getenv(const char *);

/* buffer.c */
void *marea(unsigned int);
char *dup_string(char *);
FONT_INFO *font_info_alloc(void);

/* loadpk.c  */
int openf(char *, int);

/* vfont.c */
KFONT *get_vfont_list(FONT_INFO *, char *);

/* lbp.c */
KFONT *get_lbp_font(FONT_INFO *, JFM_DATA*);

/* loadpk.c */
uchar *IsInnerJFM(char *);

char *k_dbl;
extern FONT_INFO *font_info_root;

static int font_define(int, FILE *, int);
static void make_font(struct FONT_ATR *, int);
void resolve_font(FONT_INFO *);

#if defined(GCC1) && !defined(UNIX)
static int findfirstdir(char *, struct find_t *);
static int findnextdir(struct find_t *);
#endif

int  my_access(char *, int);
static int  font_access(char *, int, int);
BOOL kpse_search(char *, char *);
char *font_name_check(char *, uint, uint);

#define	store_font_name(x)	dup_string(x)
static char *str_fnt_nm(char *, char *, long, long);
BOOL copy_token(char *, char **, int);

/* static int token_last( char* ); */
static BOOL fill_name_and_fig(char *, char *, char *, char *);
static void strdel(char *, int);
static void strins(char *, char *);
static int accgth(char *fname, char *ptr_sp);
char *get_fontname(FONT_INFO *);

#if defined(GCC1) || defined(UNIX) || defined(MSVC)
char *stpcpy(char *dest, const char *src)
{
	strcpy(dest,src);
	return dest + strlen(dest);
}
#endif

#if defined(UNIX) && !defined(HAVE_MEMMOVE)
void memmove(char *d, char *s, int len)
{
	if(d < s){
		while(len-- > 0)
			*d++ = *s++;
	}else{
		while(len-- > 0)
			d[len] = s[len];
	}
}
#endif

				/* devide tmp_buf */
#define	MAX_N_FIG		20
#ifdef	GCC
#define	TMP_S			3000
#else
#define	TMPS			2000
#endif
#define	TMP_OLD			(TMP_S+MAX_NAME_LEN)
#define	TMP_NEW			(TMP_S+2*MAX_NAME_LEN)

#define	TMP_O_FONT		(TMP_S+3*MAX_NAME_LEN)
#define	TMP_S_FONT		(TMP_S+4*MAX_NAME_LEN)
#define	TMP_O_FIG		(TMP_S+5*MAX_NAME_LEN)
#define	TMP_S_FIG		(TMP_O_FIG+MAX_N_FIG)
#define	TMP_SS_FIG		(TMP_O_FIG+2*MAX_N_FIG)

#define	TMP_FONT_NAME	(TMP_O_FIG+3*MAX_N_FIG)

#define	o_font	(tmp_buf + TMP_O_FONT)
#define	s_font	(tmp_buf + TMP_S_FONT)
#define	o_fig	(tmp_buf + TMP_O_FIG)
#define	s_fig	(tmp_buf + TMP_S_FIG)
#define	ss_fig	(tmp_buf + TMP_SS_FIG)

#if defined(GCC1) && !defined(UNIX)
/* used in kpse_search */
#define	TMP_KPSE		1500
#define	tmp_front	((char *)(tmp_buf + TMP_KPSE))
#define	tmp_rear	((char *)(tmp_buf + TMP_KPSE + 80))
#define	direc		((struct find_t *)(tmp_buf + TMP_KPSE + 160))
#elif defined(USE_WINAPI) || defined(UNIX)
#define	TMP_KPSE		(TMP_SS_FIG+MAX_NAME_LEN)
#define	tmp_front	((char *)(tmp_buf + TMP_KPSE))
#define	tmp_rear	((char *)(tmp_buf + TMP_KPSE + MAXPATH + 0x20))

void FlushAllFindDir(void);
char *FindNextDir(int level);
char *FindFirstDir(char *name, int level);
#endif

static long fsize, fpos;

static void make_font_tree(FONT_INFO **, int, int, int);
static void font_sort(int);

#ifndef NO_NTTRPL
extern BOOL ntt_subst;
extern char *ntt_subst_fonts;
static int get_fname_off(char *);
static char *ntt_sub(char *, FONT_INFO *, uint *, uint *);

#endif
#ifdef TTFONT
extern int f_use_ttf;
#endif
#ifdef VIRTUALFONT
extern BOOL f_use_virtualfont;
#endif

#ifndef	UNIX
BOOL IsTopChar(char *s, char *t)
{
	if(!IsJapanese())
		return TRUE;
	while(*s && s < t){
		if(issjis1(*s))
			s++;
		s++;
	}
	return (s==t);
}

char *StrStr(char *s, char *t)
{
	char *u;

	while((u = strstr(s, t)) != NULL){
		if(IsTopChar(s, u))
			return u;
		s = u+1;
	}
	return NULL;
}
#endif

int kpse_find(char *buf, char *kpse, char *fname)
{
	int len;
	char path[1024], *dir, *tmp, *tmpp;
	BOOL token_exist;

	dir = kpse;
	do {
		token_exist = copy_token(path, &dir, DELIMITER);
		strcat(path, fname);
		if(root_search_path != NULL){
			len = strlen(root_search_path);
			tmp = path;
			while( (tmpp = StrStr(tmp, "^r")) != NULL
				|| (tmpp = StrStr(tmp, "%r")) != NULL){
				tmp = tmpp;
				memmove(tmp, tmp + 2, strlen(tmp));
				memmove(tmp + len, tmp, strlen(tmp) + 1);
				memcpy(tmp, root_search_path, len);
				tmp += len;
			}
		}
#if	!defined(GCC) || defined(USE_WINAPI) || defined(UNIX)
		if(  path[0] == '\\' && path[1] == '\\' && !access(path, 0)){
found:		if(strlen(path) < MAXPATH){
				strcpy(buf, path);
				return TRUE;
			}
			return FALSE;
		}
		if (kpse_search(path, "\\\\") == FALSE){
			if(  path[0] == '/' && path[1] == '/' && !access(path, 0))
				goto found;
			kpse_search(path, "//");
		}
		do { 
#endif
			if (!access(path, 0))
				goto found;
#if	!defined(GCC) || defined(USE_WINAPI) || defined(UNIX)
		} while (kpse_search(path, NULL));
#endif
	} while (token_exist);
	return FALSE;
}

/*
			Expand  TEXROOT  for  TEXPK, TEXFONTS, TEXSUBF
 */
int resolve_font_root_path(void)
{
	#define	MAXSEARCH	0x2000
	int count;
	char *rep, *r, *dtop, *dend, *dp, *stop, *sr, *sp, *ttop;

	Free0(font_root_path);
	Free0(font_search_path);
	Free0(new_tfm_search_path);
#ifdef	USE_SUBFONT
	Free0(new_subfont_path);
#endif
	new_subfont_path = new_tfm_search_path = NULL;

	if((rep = root_search_path) != NULL){
#ifndef	UNIX
		if(IsJapanese()){
			while(*rep && *rep != DELIMITER){
				if(issjis1(*rep) && *(rep+1))
					rep++;
				rep++;
			}
		}else
#endif
		{
			while(*rep && *rep != DELIMITER)
				rep++;
		}
	}
	if((stop = getenv(pk_env_name)) == NULL)
		stop = pk_search_path;
	if((ttop = getenv("TEXFONTS")) == NULL)
		ttop = tfm_search_path;

	if(!rep || !*rep || !stop){
		font_root_path = (char *)dup_string(root_search_path);
		if(!rep || !stop){
			font_search_path = (char *)dup_string(stop);
			new_tfm_search_path = (char *)dup_string(ttop);
			new_subfont_path = (char *)dup_string(subfont_path);
			return 0;
		}
	}else{
		*rep = 0;
		font_root_path = (char *)dup_string(root_search_path);
		*rep++ = DELIMITER;
	}
	count = ttop?strlen(ttop):0;
	if(subfont_path)
		count += strlen(subfont_path);
	dtop = (char*)marea(MAXSEARCH+strlen(rep)+strlen(stop)+count+4);
	dend = dtop + MAXSEARCH;
	for(dp = dtop, count = 0; count++ < 
#ifdef	USE_SUBFONT
		3
#else
		2
#endif
	; ){
		for(sr = (sp = stop) - 1, r = rep; ;){
			while(*sp){			/* check ^r */
				if((*sp == '^' || *sp == '%') && *(sp+1) == 'r'){
					sr = sp;
					break;
				}
				sp++;
			}
			if(dp >= dend)					/* too long */
er:				error(PROGRAM_STOP, "Too long TEXROOT/TEXPK");
			for(r = root_search_path; *r; ){
				if(dp != dtop)
					*dp++ = DELIMITER;			/* put separater */

				sp = stop;						/* copy top */
				if(sr >= stop){
					while(sp < sr)
						*dp++ = *sp++;

					while(*r && *r != DELIMITER){		/* replace ^r */
#ifndef	UNIX
						if(issjis1(*r) && *(r+1) && IsJapanese())
							*dp++ = *r++;
#endif
						*dp++ = *r++;
					}
					if(*r == DELIMITER)
						r++;
					sp += 2;
				}
				while(*sp && *sp != DELIMITER){		/* copy tail */
#ifndef	UNIX
					if(issjis1(*r) && *(r+1) && IsJapanese())
						*dp++ = *r++;
#endif
					*dp++ = *sp++;
				}
				if(dp >= dend)						/* too long */
					goto er;
				if(sr < stop)
					break;
			}
			if(!*sp){
				*dp = 0;
				break;
			}
			stop = sp + 1;
		}
		SimplifyFname(dtop);
		switch(count){
			case 1:
				font_search_path = dup_string(dtop);
				if(ttop == NULL){
					count++;
					goto nxt;
				}
				stop = ttop;
				break;
			case 2:
				new_tfm_search_path = dup_string(dtop);
nxt:			if(!subfont_path)
					count = 10;
				else
					stop = subfont_path;
				break;
			case 3:
				new_subfont_path = dup_string(dtop);
			default:
				break;
		}
	}
	Free0(dtop);
	return *rep?1:0;
}

/*
  path_cash[] = 
  TEXROOT \0
  TEXPK   \0
  length  count  position  ^s d1 d2 \0  replace \0
  length  count  position  ^s d1 d2 \0  replace \0
  ...
  \0
 */
int get_path_cash(void)
{
	char *path0, *tmp;

	if(f_path_cash == 1){
		if(root_search_path != NULL){
			if(strcmp(path_cash, root_search_path))
				goto no_cash;
			tmp = path_cash + strlen(path_cash) + 1;
		}else
			tmp = path_cash + 1;
		if((path0 = getenv(pk_env_name)) == NULL)
			path0 = pk_search_path;
		if(strcmp(tmp,  path0))
			goto no_cash;
		path_font = tmp + strlen(tmp) + 1;
		f_path_cash = 2;
	}else if(f_path_cash <= 0)
no_cash:
		return 0;
	return 1;
}

static int pack_name(char *buf, char *name, int dpi)
{
#if	PACKNAME
	static int def_dpi[] = 
	{96, 115, 118, 129, 142, 160, 170, 180, 192, 197, 200, 204, 216, 240, 288, 
	300, 320, 329, 360, 384, 394, 400, 432, 438, 480, 518, 600, 622, 657, 720, 
	746, 788, 864, 32000};		/* def_dpi[15] = 300 */
	int	len = 0;
	int i, j;

	switch(*name){
		case 'c':
			if(name[1] == 'm'){
				if(name[2] >= 'b' && name[2] <= 'v'){	/* cmb ... cmv */
					*buf = name[2] - ('b' - 1);			/* 1 to 19 */
					len = 3;
				}else{
					*buf = 20;							/* 20  cm.. */
					len = 2;
				}
			}
			break;
		case 'e':
			if(name[1] == 'u'){
				*buf = 21;								/* 21  eu.. */
				len = 2;
			}
			break;
		case 'g':
			if(name[1] == 'o' && name[2] == 't' && name[3] == 'h'){
				*buf = 22;								/* 22  goth.. */
				len = 4;
			}
			break;
		case 'l':
			if(name[1] == 'i' && name[2] == 'n' && name[3] == 'e'){
				*buf = 23;								/* 23  line.. */
				len = 4;
			}else if(!strlcmp(name+1, "circle")){
				*buf = 24;								/* 24  lcircle.. */
				len = 7;
			}else if(name[1] == 'o' && name[2] == 'g' && name[3] == 'o'){
				*buf = 25;								/* 25  logo.. */
				len = 4;
			}
			break;
		case 'm':
			if(name[1] == 's'){
				if(name[2] == 'a' && name[3] == 'm'){
					*buf = 26;							/* 26  masm.. */
					len = 4;
				}else if(name[2] == 'b' && name[3] == 'm'){
					*buf = 27;							/* 27  masb.. */
					len = 4;
				}else{
					*buf = 28;							/* 28  ms.. */
					len = 2;
				}
			}else if(name[1] == 'i' && name[2] == 'n'){
				*buf = 29;								/* 29  min.. */
				len = 3;
			}else if(name[1] == 'a' && name[2] == 'n'){	/* min.. */
				*buf = 30;								/* 30  man.. */
				len = 3;
			}
			break;
		case 'w':
			if(name[1] == 'n' && name[2] == 'c' && name[3] == 'y'){
				*buf = 31;								/* 31  wncy.. */
				len = 4;
			}
			break;
	}
	i = (len)?0:-1;
	while( (buf[++i] = name[len++]) != 0);
	if(i >= 2 && buf[i-2] == '1' && buf[i-1] <= '9' && buf[i-1] >= '0'){
		buf[i-2] = buf[i-1] - ('0' - 1);
		buf[--i] = 0;
	}
	if(dpi < 32000){
		for(j = (dpi>=300)?0:15; def_dpi[j++] < dpi; );
		if(def_dpi[j-1] == dpi){
			buf[i++] = j;
			goto quit;
		}
	}
	buf[i++] = dpi/255 + 64;
	buf[i++] = dpi%255 + 1;
quit:
	buf[i] = 0;
	return i;
#else
	sprintf(buf, "%s.%d", name, dpi);
	return strlen(buf);
#endif
}

static char *check_path_cash(char *name, int fig)
{
	int i;
	char *tmp;
	if(!get_path_cash())
		goto no_cash;
	pack_name(tmp_buf, name, fig);
	for(i = 0, tmp = path_font; *tmp && i++ < MAX_FCASH; tmp += *(uchar *)tmp){
		if(!strcmp(tmp+3, tmp_buf))
			return(tmp);
	}
no_cash:
	return NULL;
}

char *get_old_path(int pos, char *replace)
{
	int i, j;
	char path[MAXPATH], *dir;
	BOOL token_exist;

	if(pos < 0)
		return "";
	dir = font_search_path;
	do{
		token_exist = copy_token(path, &dir, DELIMITER);
	}while(token_exist && pos-- > 0);
	fill_name_and_fig(path, "^s", "^d", "^l");
	for(j=1; path[j]; j++){
		if(path[j] == '/'){
			if(path[j+1] == '/')
				break;
		}
		else if(path[j] == '\\'){
			if(path[j+1] == '\\')
				break;
		}
	}
	for(i=0; i <= j; i++)
		((char *)tmp_buf)[i] = path[i];
	if(!path[j])
		goto quit;
	if(!*replace)
		j++;
	strcpy(stpcpy((char *)tmp_buf + i, replace), path + j + 1);
quit:
	return (char *)tmp_buf;
}

static char *get_kpse_replace(FONT_INFO *font)
{
	int	i, j, k, len, len2;
	char path[MAXPATH], path2[MAXPATH];
	char *dir, *name;
	char fig_str[FIG_COLUMN], figl_str[FIG_COLUMN];
	BOOL token_exist;

	name = font->name;
	j = font->texpk_pos;
	if(*name == '*' || font->n[MAX_NAME_LEN-1] != ' ' || j < 0)
		return NULL;
	dir = font_search_path;
	do{
		token_exist = copy_token(path, &dir, DELIMITER);
	}while(token_exist && j-- > 0);
	fill_name_and_fig(path, "^s", "^d", "^l");
	for(j=1; path[j]; j++){
		if(path[j] == '/'){
			if(path[j+1] == '/')
				break;
		}
		else if(path[j] == '\\'){
			if(path[j+1] == '\\')
				break;
		}
	}
	if(path[j]){
		strcpy(path2, path + j + 1);
		path[j+1] = 0;
	}else
		path2[0] = 0;
	len = strlen(name);
	for (i = j = 0; i < 3; i++) {
		sprintf(fig_str, "%u", font->dpi + j);
		sprintf(figl_str, "%u", font->dpi*5 + j);
			j = -j;
			if (j >= 0)
				j++;
		strcpy(tmp_buf, path);
		fill_name_and_fig(tmp_buf, font->n, fig_str, figl_str);
		for(k = 0; ((char *)tmp_buf)[k]; k++){
			if(((char*)tmp_buf)[k] != name[k])
				goto cont;
		}
		if(*path2){
			strcpy((char *)tmp_buf + 0x200, path2);
			fill_name_and_fig(tmp_buf + 0x200, font->n, fig_str, figl_str);	
			len2 = len - strlen((char *)tmp_buf + 0x200);
			if(len2 < k-1 || strcmp((char *)tmp_buf + 0x200, name + len2) )
				goto cont;
		}else
			len2 = 0;
		for(len=0; len+k < len2; len++)
			((char *)tmp_buf)[len]  = name[len+k];
		((char *)tmp_buf)[len] = 0;
			return (char *)tmp_buf;
cont:	;
	}
	return NULL;
}

#ifdef	WIN32G
char *path_cash_info(void)
{
	int count, top, last;
	char *tmp;

	count = 0;
	for(tmp = path_font; tmp && *tmp; tmp += *(uchar *)tmp){
		if(!count++)
			top = *((uchar *)tmp + 1);
		last = *((uchar *)tmp + 1);
	}
	if(count)
		sprintf(common_work, "total %d (%d - %d)", count, top, last);
	else
		common_work[0] = 0;
	return common_work;
}

void keep_font_path(void)
{
#define	DEPTH_COUNT	3

	int i, j, k, count, new_count, len;
	char *tmp, *buf, *pt, *dir;
	FONT_INFO *font;
	unsigned char *fc[MAX_FCASH+512];
	unsigned char *f_rep[MAX_FCASH];
#ifdef	VIRTUALFONT
	FONT_INFO *lf;
#else
	#define	lf	font
#endif
	if(f_path_cash < 0){
		KeepPathCash(NULL, 0);
		return;
	}
	if(first_font_info == NULL)
		return;
	if(f_path_cash == 1 || (f_path_cash && !get_path_cash()) )
		return;
	buf = pt = (char*)marea(0x4000);
	count = new_count = 0;
	if(f_path_cash == 2){
		for(tmp = path_font; *tmp; tmp += *(uchar *)tmp){
			fc[count++] = tmp;
			j = *((uchar *)tmp + 1);
			*((uchar *)tmp + 1) = j*15/16;		/* decrease count */
		}
	}
	for (font = first_font_info; font; font = font->next_font){
#ifdef	VIRTUALFONT
		for(i = 0, lf = font;
			lf != NULL && count < MAX_FCASH + 512 && i++ < 256; ){
#endif
			if(  lf->font_type <= UNRESOLVE
			  || lf->n[MAX_NAME_LEN-1] != ' '		/* substituted font */
			  || lf->name[0] == '<' )				/* inner jfm */
				goto cnt;
			if(lf->texpk_pos == -1){				/* use cash */
				tmp = check_path_cash(lf->n, lf->dpi);
				if(tmp != NULL)
					*((uchar *)tmp + 1) += 0x10;
			}else{
				tmp = get_kpse_replace(lf);
				if(tmp == NULL)
					goto cnt;
				*((uchar *)pt + 1) = 0x40;
				*((uchar *)pt + 2) = lf->texpk_pos;
				len = pack_name(pt + 3, lf->n, lf->dpi) + 4;
				len = stpcpy(pt + len, tmp) - pt + 1;
				*(uchar *)pt = len;
				fc[count++] = pt;
				new_count++;
				pt += len;
				if(pt - buf > 0x3e00)
					goto over;
			}
cnt:
#ifdef	VIRTUALFONT
			if(font->font_type != VIRTUAL_FONT)
				break;
			if(lf==font){
				if(i > DEPTH_COUNT)
					break;
				lf = lf->ext.local_font;
			}else
				lf = lf->next_font;
		}
#endif
	;}
over:
	pt = tmp_buf;
	if(!new_count && fcash_rev < MAX_FCASH_REV)
		goto freq;
	len = 0;
	for(k = count - 1; k >= 0; k = j){		/* sort by frequency */
		j = -1;
		for(i = 1; i <= k; i++){
			if(*((uchar *)(fc[i-1] + 1)) < *((uchar *)(fc[i] + 1))){
				len++;
				j = i-1;
				tmp = fc[j];
				fc[j] = fc[i];
				fc[i] = tmp;
			}
		}
	}
	if(!len && !new_count){				/* same entry and order */
		fcash_rev = 0;
		goto freq;
	}
	if((dir = getenv(pk_env_name)) == NULL)
		dir = pk_search_path;
	if(root_search_path != NULL)
		pt = stpcpy(pt, root_search_path) + 1;
	else
		*pt++ = 0;
	pt = stpcpy(pt, dir) + 1;
#if	1
	f_rep[0] = pt - 1;
	k = 1;
	if(count > MAX_FCASH)
		count = MAX_FCASH;
	for(i = 0; i < count; i++){
		tmp = fc[i] + strlen(fc[i] + 3) + 4;
		for(j = 0; j < k; j++){
			if(!strcmp(f_rep[j], tmp)){
				*tmp = j;
				goto find;
			}
		}
		f_rep[k] = pt;
		pt = stpcpy(pt, tmp) + 1;
		if((*tmp = k++) == 255){
			count = i;
			break;
		}
find:	;	/* the same string exists */
	}
	/*	k: number of inserted strings */
	/*  *(fc[i] + 2): position in TEXPK */
	for( i = fcash_dev = 0; i < count; i++){
		if(*(fc[i] + 2) > fcash_dev)
			fcash_dev = *(fc[i] + 2);
	}
	fcash_ver = FCASH_VERSION+1;
	if((++fcash_dev)*k >= 256){
		fcash_ver--;
		fcash_dev = 0;
	}
	*pt++ = 0;
	for(i = 0; i < count && pt - tmp_buf < COMMON_SIZE - 0x200; i++){
		j = *(fc[i] + 2);
		tmp = fc[i] + 3;
		while( (*pt++ = *tmp++) != 0);
		if(fcash_dev){
			*pt++ = j + fcash_dev*(*tmp);
		}else{
			*pt++ = j;
			*pt++ = *tmp;
		}
	}
	count = i;
#endif
	*pt++ = 0;
	KeepPathCash(tmp_buf, fcash_size = pt - tmp_buf);
freq:
	pt = tmp_buf;
	*pt++ = fcash_ver;					/* version */
	*pt++ = fcash_rev + 1;
	*pt++ = fcash_size & 0xff;
	*pt++ = fcash_size >> 8;
	*pt++ = count & 0xff;
	*pt++ = count >> 8;
	if(fcash_ver == FCASH_VERSION+1)
		*pt++ = fcash_dev;
	for(i = 0; i < count; ){
		*pt = *(((uchar *)(fc[i++]))+1);
		pt++;
	}
	Free0(buf);
	KeepPathCash(tmp_buf, tmp_buf - pt);
}
#endif


char *to_font_name(char *name)
{
	static char font_name[256];
	int	i, j;
	
	if(name==NULL)
		return "?";
	if(*name == '*'){
		name += 9;
		for(i = j = 0; i < 255; i++){
			if(!(font_name[i] = name[i])){
				if(j++ > 0)
					break;
				font_name[i] = ' ';
			}
		}
		return &font_name[0];
	}
	else return name;
}

char *get_font_name(FONT_INFO *font)
{
	ENTER("get_font_name");

	RETURN(to_font_name(font->name));
}

void make_font_list(DVIFILE_INFO *dvi, DIMENSION *dimension)
	/* DIMENSIONのデータに基づき，font-listの作成
	 */
{
	int code, count;

#ifdef	FLI
	char *fontlib;
	extern void free_fli();
#endif	/* FLI */

	ENTER("make_font_list");
	if(!f_sub_warn)
		f_sub_warn = f_wait;
#if 1
	if (first_font_info != NULL) {
		if(dpis == dimension->dpi && mags == dimension->mag
			&& (f_init & (INIT_CHKFONT|INIT_F_BUF|INIT_R_BUF|INIT_FLSHFONT))
				== INIT_CHKFONT){
			while (1){
				if ((code = getc(dvi->file_ptr)) == POST_POST)
					return;
				if (code >= FNT_DEF_1 && code < FNT_DEF_1 + 4) {
					if(font_define(code, dvi->file_ptr, 1) != 0)
						break;
				}
				else if (code != NOP)
					error(COMMAND_ERROR, "code:%d", code);
			}
		}
		font_flush();
	}
#else
	if (first_font_info != NULL)
		font_flush();
#endif

#ifdef	FLI
	if ((fontlib = getenv("TEXFLI")) != NULL) fli_search_path = fontlib;
#endif	/* FLI */

	if (pk_search_path == NULL && getenv(pk_env_name) == NULL){
		error(ILLEGAL_ARGS,
#ifdef	JAPANESE
			  "環境変数 または パラメータ・ファイルで %s を設定して下さい．\n"
#else
# ifdef WIN32G
			  "Set environment variable %s (Option ->Setup Parameters->Font)\n"
# else
			  "Set environment variable %s\n"
# endif
#endif
			  "\nExample: set %s=b:^d\\^s.^d;dpi^d^g^s.pk;"
			  "b:\\font\\^l.far^g^s;b:^l\\^s.pxl\n"
			  "\t ^d: dpi number\n\t ^l: dpi number x 5\n"
			  "\t ^s: font name\n\t ^g: GTH/far file",
			  pk_env_name, pk_env_name);
		g_nErrorCode = FE_NOFONT;
		return;
	}
	resolve_font_root_path();
	dpis = dimension->dpi;
	mags = dimension->mag;
	f_loop = 3;
	if (f_search > 0)
		f_loop += f_search;
	/*  true_mag = ((double)dimension->mag) / 1000.0;	*/
	/* DIMENSIONでは1000倍の値が入っている．*/
	fseek(dvi->file_ptr, dvi->post + 29, SEEK_SET);
	/*  set file-ptr to first font_def */
	count = 0;
	while ((code = getc(dvi->file_ptr)) != POST_POST && !g_nErrorCode)
		if (code >= FNT_DEF_1 && code < FNT_DEF_1 + 4) {
			font_define(code, dvi->file_ptr, 0);
			count++;
		}
		else if (code != NOP)
			error(COMMAND_ERROR, "code:%d", code);
#ifdef	FLI
	free_fli();
#endif	/* FLI */
#ifndef NO_GENFONT
	if (genfntfp != NULL) {
		genfont_out(genfntfp, 2);
		fclose(genfntfp);
		genfntfp = NULL;
		free_tmpl();
	}
#endif
	if(!g_nErrorCode)
		font_sort(count);
	END();
}

static int font_comp(FONT_INFO **arg1, FONT_INFO **arg2)
{
	return	(*arg1)->font_code - (*arg2)->font_code;
}

static void font_sort(int total)
{
	int i;

	FONT_INFO **font_adr;
	FONT_INFO *font;

	ENTER("font_sort");

	font_adr = (FONT_INFO **)(marea(sizeof(FONT_INFO *) * total));

	font = first_font_info;
	for (i = total - 1; i >= 0; i--) {
		font_adr[i] = font;
		font = font->next_font;
		if ((i == 0 && font != NULL) || (i > 0 && font == NULL))
			error(PROGRAM_STOP, "Making font table");

	}
	qsort(font_adr, total, sizeof(FONT_INFO *), (COMP)font_comp);
	i = (total - 1) >> 1;
	font_info_root = font_adr[i];
	make_font_tree(font_adr, i, 0, total - 1);
	Free(font_adr);
	END();
}

static void make_font_tree(FONT_INFO **font_adr,
						   int now, int before, int after)
{
	int current;

	ENTER("make_font_tree");

	if (before < now) {
		current = before + ((now - before) >> 1);
		font_adr[now]->before_font = font_adr[current];
		make_font_tree(font_adr, current, before, now - 1);
	}
	if (now < after) {
		current = now + ((after - now + 1) >> 1);
		font_adr[now]->after_font = font_adr[current];
		make_font_tree(font_adr, current, now + 1, after);
	}
	END();
}

static int font_define(int code, FILE * dvifile, int mode)
{
	int i, len;
#ifndef	UNIX
	int lenm;
#endif
	struct FONT_ATR font;
	FONT_INFO *f;
	char *tmp, tmp_name[MAX_NAME_LEN];

	ENTER("font_define");
	font.k = read_n(dvifile, code - FNT_DEF_1 + 1);
	font.c = read_long(dvifile);
	font.s = read_long(dvifile);
	font.d = read_long(dvifile);
	font.a = read_byte(dvifile);
	font.l = read_byte(dvifile);
	font.n = tmp_name;

	if (font.a == EOF || font.l == EOF){
		error(FILE_FAULT, "DVI file");
		g_nErrorCode = FE_NOFONT;
		return -1;
	}
	tmp = read_str(dvifile, font.a + font.l);

	len = strlen(tmp);

#ifdef	DBGPO
	error(14, "%s:%d\n", tmp, len);
#endif

	i = len;
#ifndef	UNIX
	lenm = 8;
#endif
	while (--i >= 0) {
#ifndef UNIX
		if (tmp[i] == '.')
			lenm = 13;
#endif
		if (tmp[i] == ':' || tmp[i] == '\\' || tmp[i] == '/')
			break;
	}
#ifdef	UNIX
	i++;
	strncpy(tmp_name, tmp, MAX_NAME_LEN);
#else
	if (len - ++i > lenm && !f_long_name
# ifdef FLI
		&& fli_search_path == NULL
# endif /* FLI */
	)
	tmp[i + lenm] = '\0';
	strncpy(tmp_name, tmp, MAX_NAME_LEN);
	if (f_long_name == 1 && len - i > lenm && i + lenm < MAX_NAME_LEN)
		strcpy(tmp_name + i + 4, tmp + i + len - lenm + 4);
#endif
	if(mode == 1){
		Free(tmp);
		for (f = font_info_root; f != NULL;) {
			if (f->font_code == font.k){
				return (f->size_para == font.s
				  && f->des_para == font.d
				  && f->c == font.c
				  && strcmp(&(f->n[0]), font.n) == 0)?
				  0:1;
			}
			f = (f->font_code < font.k) ? f->after_font : f->before_font;
		}
		return -1;
	}
#ifndef NO_GENFONT
	fntname = &tmp[i];
#endif
	make_font(&font, 0);
	Free(tmp);
	return 0;
}

static char *
	next_top(char *dest, char *org)
{
	int i, ch;

	ENTER("next_top");

	for (i = 0;; i++) {
		ch = *org++;
		if (i < MAX_SUB_LEN - 1)
			*dest++ = ch;
		if (ch == 0)
			return (org - 1);
		if (ch == '.' || ch == '=' || ch == ';') {
			*(dest - 1) = 0;
			RETURN(org);
		}
	}
}

#ifdef	WIN32G

#if 1
static void keep_guess(char *type, char *guess, char mode, char *path, 
	char *name)
{
	char fullpath[MAXPATH+64];
	char msg[0x400];
	int len;

	if(mode == 32 && (*type & 24))		/* jfm  &&  fond dpi or dpi^1.2 */
		return;
	strcpy(fullpath, path);
	len = strlen(fullpath);
	strcpy(fullpath + len - 3, name);
	if(*type & mode){		/* duplication */
		sprintf(msg, "Use\n  (Y) %s\nin place of\n  (N) %s", 
			guess, fullpath);
		if(AskYes(msg, "duplication"))
			return;
	}
	*type |= mode;
	strcpy(guess, fullpath);
}

static BOOL AskDirectry(char *path)
{
	char msg[MAXPATH+256];

	sprintf(msg, "Do you include the font directory which contains "
				"the following font?\n%s\n", path);
	return AskYes(msg, "special fonts");
}

#define	MAXGUESS	40

#ifdef	UNIX
static char *KPSE_REP = "public/cm:public/latex:ams/symbols:ams/extracm";
#else
static char *KPSE_REP = "public\\cm;public\\latex;ams\\symbols;ams\\extracm";
#endif


static void keep_gth(char *guess, char *path, char *name, char *dpistr)
{
	char fullpath[MAXPATH], *s, *t;

	strcpy(fullpath, path);
	s = fullpath + strlen(fullpath) - 3;
	strcpy(s, name);
	t = StrStr(s, dpistr);
	strcpy(t, "^d");
	strcpy(t + 2, name + (t-s) + strlen(dpistr));
	if(strlen(guess) + strlen(fullpath) < 1020)
		return;
	s = strstr(guess, fullpath);
	if( s != NULL ){
		if(   s == guess
		 || (*(s-1) == DELIMITER && *(s + strlen(fullpath) - 1) == DELIMITER) )
		return;
	}
	strcat(guess, fullpath);
	strcat(guess, STR_DELIM);
}

/*
	 path    = "/usr/local/share/texmf/fonts/pk/cx/public/cm/^s.^dpk";
	 cut[]   = "/public/cm/";    		<- get from  KPSE_REP
 ->  
	 path1[] = "/usr/local/share/texmf/fonts/pk/cx/";
	 path2[] = "/^s.^dpk";
	 path    = "/usr/local/share/texmf/fonts/pk/cx//^s.^dpk";
	 check     "/usr/local/share/texmf/fonts/pk/cx/..../^s.^dpk";
 */


static char *set_kpse(char *pt)
{
	int	i, j, k, ch, count, len;
	char *path[2*MAXGUESS];
	char cut[MAXPATH];
	char path1[MAXPATH];
	char *pt_kpse, *s, *t, *r, *path2;

	for(count = i = 0, s = pt; *s && count < 2*MAXGUESS; s++){
		if(!i){
			path[count++] = s;
			i = 1;
		}
		if(*s == DELIMITER)
			*s = i = 0;
	}

	for(ch = 1, pt_kpse = KPSE_REP; ch; ){
		s = cut;
		*s++ = PATH_SEP;
		while( (ch=(*s++ = *pt_kpse++)) != 0 && ch != DELIMITER);
		*(s-1) = PATH_SEP;
		*s = 0;
		for(i = 0; i < count; i++){
			if(strstr(path[i], cut) == NULL)
				continue;
			strcpy(path1, path[i]);
			r = strstr(path1, cut);
			if(  StrStr(path1, "^d") == NULL
			  || StrStr(path1, STR_PATH_SEP STR_PATH_SEP) != NULL
			  || !strcmp(path1 + strlen(path1) - 4, ".tfm") )
				continue;
			*(r+1) = 0;
			path2 = r + strlen(cut) - 1;
			sprintf(path[i], "%s%s", path1, path2);
			len = strlen(path[i]);
			for(j = 0; j < count; j++){
				if(j == i || strlcmp(path[j], path1))
					continue;
				k = strlen(path[j]);
				if(k >= len-1 
				  && !strcmp(path[j] + strlen(path[j]) - strlen(path2), path2))
					path[j][0] = 0;
			}
		}
	}
	for(i = j = 0, s = pt; i < count; ){
		t = path[i++];
		if(*t){
			if(j++ != 0)
				*s++ = DELIMITER;
			while((*s++ = *t++) != 0);
				--s;
		}
	}
	return(s);
}

#ifdef	MIKTEX
static BOOL ReadMikTeX(void)
{
	char *s, *d;
	int res;

	res = ReadRegString(tmp_buf + 0x1000, 0x800, 
	  REG_MIKTEX, "TEXMF Root Directories", 1);
	if(!res)
		res = ReadRegString(tmp_buf + 0x1000, 0x800, 
		  REG_MIKTEX, "TEXMF Root Directories", 2);
	if(res <= 0 || !AskYes(	"MikTeX is detected\n"
			"Do you use its setting?\n"
			"(See On-line Help to arrange the automatic setting)", 
			"TeX environment"))
		return FALSE;

	tmp_buf[0x17ff] = 0;
	s = tmp_buf + 0x1000;
	d = tmp_buf + 0x1800;
	while(*s){
		if(*s == ';'){
			strcpy(d, "\\fonts");
			d += 6;
		}
		*d++ = *s++;
	}
	strcpy(d, "\\fonts");
	sprintf(tmp_buf, "TEXROOT=%s\nTEXPK=%s\n", tmp_buf + 0x1800, miktexpk_org);
	return TRUE;
}
#endif

void GuessFont(char *dir, char *efont, char *jfont, int dpi)
{
	int  i, j, k, type, len, max_guess, ans;
	BOOL token_exist;
	char *free_top, *s, *t, *r, *u, *v, *get_buf, *org_dir;
	char *pt_texpk;
	char *allfont[MAXGUESS];
	char guess_font[2][MAXGUESS][MAXPATH];
	char guess_gth[1024];
	char font_type[MAXGUESS]; /*   1: jfont       2: cut last  4: cut center */
							  /*   8: found dpi  16: found dpi^1.2 */
							  /*  32: jfm */
							  /*  64: ^d + ^d */
							  /* 128: done by dpi & dpi^1.2 */
	unsigned char same_len[2][MAXGUESS];
	char dpistr[4][16];
	char path[MAXPATH], path1[MAXPATH], path2[MAXPATH];
	char tmp_name[MAXPATH];

#ifdef	MIKTEX
	if(ReadMikTeX())
		return;
#endif
	type = IsJapanese();

	/* Check environment variables TEXMFMAIN and TEXMF */
	ans = 0;	// 1:TEXMFMAIN    2:TEXMF    4:ptex
	if(getenv("TEXMFMAIN") != NULL){
		strcpy(path, getenv("TEXMFMAIN"));
		ans = 1;
	}
	if(getenv("TEXMF") != NULL){
		strcpy(path, getenv("TEXMF"));
		ans |= 2;
	}
	if(ans){
		if(ans == 3){
			error(WARNING, 
				type?
					"環境変数 TEXMF と TEXMFMAIN の両方が"
					"定義されています!\n":
					"The environments TEXMF and TEXMFMAIN are"
					" simultaneousely defined!");
			goto def0;
		}
		s = dup_string(path);
		chg_pathsep(s, PATH_SEP);
		goto ptex;
	}
#ifndef UNIX
	if(access("c:\\usr\\local\\bin\\ptex.exe", 0) == 0
		&& access("c:\\usr\\local\\share\\texmf\\web2c\\texmf.cnf", 0) == 0){
			strcpy(path, "c:\\usr\\local\\share\\texmf");
			ans |= 4;
	}else
#endif
	{
		t = getenv("PATH");
		if(t == NULL)
			goto def0;
		s = dup_string(t);
ptex:	for(i=j=0, k=1; k; i++, j++){
			k = path[j] = s[i];
			if(type && issjis1(s[i]) && s[i+1]){
				path[++j] = s[++i];
				continue;
			}
			if(!k || k == ';'){
				path[j] = 0;
				if(ans & 3){
					if(j <= 12 || stricmp(path+j-12, "\\share\\texmf"))
						goto cnt;
					else
						j -= 8;
				}else if(j <= 4 || stricmp(path+j-4, "\\bin"))
					goto cnt;
				strcpy(path+j-3, "bin\\ptex.exe");
				if(access(path, 0) == 0){
					strcpy(path+j-3, "share\\texmf\\web2c\\texmf.cnf");
					if(access(path, 0) == 0){
						path[j+8] = 0;
						GSPN(path, path1);		// short pathname
						strcpy(path, path1);
						ans |= 4;
						break;
					}
				}
cnt:			j = -1;
			}
		}
		Free(s);
	}
	if((ans & 4) &&  AskYes(
		type?
			"標準的な日本語TeX環境が検知されました．\n"
			"それに合った標準設定を選択します．":
			"The Standard Installation of ptex is detected.\n"
			"Use the default setting for the installation?",
		type?
			"TeXの環境":
			"TeX environment") ){
		f_kakuto = TRUE;
		if(ans & 3)
ret:		strcpy(path, "^T");
		sprintf(tmp_buf, "TEXROOT=%s\\fonts\nTEXPK=%s\n", path, texpk_org);
		return;
	}
def0:
	if(!AskYes(
		type?
			"(Y)es: DISK内のTeX環境から設定する．\n"
			"(N)o:  デフォルト値を用いる．":
			"(Y)es: Guess TEXROOT/TEXPK/L from fonts in DISK\n"
			"(N)o:  Set default values for TEXROOT/TEXPK/L",
		type?
			"パラメータ TEXROOT/TEXPK/L の推測":
			"Examine Fonts")){
		if(!(ans & 3)){
			error(WARNING, 
				type?
					"デフォルト値が決定できません!\n"
					"環境変数からの推測が不可能です．":
					"The default values are uncertain!\n"
					"Cannot guess from the environments variables.");
		}
		goto ret;
	}

	free_top = get_buf = (char *)marea(0x1000);
	s = efont;
	guess_gth[0] = 0;
	org_dir = dir;

	for(i = 0; i < 4; i++){					/* set string of dpi's */
		switch(i){
			case 0:	j = dpi; break;
			case 1: j = dpi * 5; break;
			case 2: j = (dpi * 12 + 5)/10; break;
			case 3: j = (dpi * 60 + 5)/10; break;
		}
		sprintf(dpistr[i], "%d", j);
	}

	for(max_guess = j = 0; ; ){
		strcpy(free_top, s);
		allfont[max_guess] = free_top;
		if( (len = strlen(s)) > 32)
			break;
		free_top += len + 2;
		font_type[max_guess] = j;
		if(++max_guess >= MAXGUESS)
			break;
		if(   len > 8
		  && (!strcmp(s, "lcircle10") || !strcmp(s, "lcirclew10")) ){
			strcpy(free_top, s);
			allfont[max_guess] = free_top;
			free_top[8] = 0;
			font_type[max_guess] = j|2;
			free_top += 10;
			if(++max_guess >= MAXGUESS)
				break;

			strcpy(free_top, s);
			for(i = 4; i <= 8; i++)
				free_top[i] = free_top[i + len - 8];
			allfont[max_guess] = free_top;
			font_type[max_guess] = j|4;
			free_top += 10;
			if(++max_guess >= MAXGUESS)
				break;
		}
		s += len+1;
		if(!*s){
			if(j++)
				break;
			s = jfont;
		}
	}
	for(i = 0; i < max_guess; i++){
		strlwr(allfont[i]);
		strcat(allfont[i], ".");
	}
	do{
		token_exist = copy_token(path, &dir, ';');
		sprintf(tmp_buf, "Searching fonts in %s", path);
		DisplayMessage(tmp_buf);
		strcat(path, STR_PATH_SEP STR_PATH_SEP "*.*");
		if (kpse_search(path, STR_PATH_SEP STR_PATH_SEP) == FALSE)
			continue;
		do{ 
			for(s = FindFirstW32(path); s; s = FindNextW32()){
				if((len = strlen(s)) < 4)
					continue;
				strlwr(s=strcpy(tmp_name, s));
				t = s + len - 2;
				if(!strcmp(t, "pk")){
					type = 0;
check_pk:			for(i = 0; i < max_guess; i++){
						r = allfont[i];
						for(j = 0; ;j++){
							if(!s[j])
								goto skip;
							if(s[j] != r[j] )
								break;
						}
						if(r[j])
							continue;
											/* found font */
						if(type == 2){			/* jfm */
							if(font_type[i] & 1)
								keep_guess(
									&font_type[i], guess_font[0][i],
									32, path, s);
							goto skip;
						}						/* pk or pxl */
						for(k = 0; k < 4; k+=2){
							if(( u = StrStr(path, dpistr[k+type]) ) != NULL){
																/* in dir? */
								if( u == path
								  || isdigit(*(u-1))
								  || isdigit(*(u+strlen(dpistr[k+type]))) )
									u = NULL;
							}
							v = StrStr(s+j, dpistr[k+type]);	/* in name? */
							if(    v != s+j
							  || len != strlen(dpistr[k+type]) + strlen(r)
									 + type + 2 )
								v = NULL;
							if(v == NULL && len != strlen(r) + type + 2)
								u = NULL;
							if(u != NULL || v != NULL){
								keep_guess(
									&font_type[i], guess_font[k>>1][i],
									(k & 2)?16:8, path, s);
								break;
							}
						}
					}
				}else if(!strcmp(t-1, "pxl")){
					type = 1;
					goto check_pk;
				}else if(!strcmp(t-2, ".tfm")){
					type = 2;
					goto check_pk;
				}else if(!strcmp(t-2, ".gth")){
					for(k = 0; k < 4; k+=2){
						if( StrStr(s, dpistr[k]) != NULL )
							keep_gth(guess_gth, path, s, dpistr[k]);
					}
				}
			}
skip:	;
		}while (kpse_search(path, NULL));
	}while(token_exist);

	for(i = 0; i < max_guess; i++){
		for(k = 0 ; k < 2; k++){		/* set ^s */
			switch(k){
				case 0:
					s = (font_type[i] & 40)?guess_font[0][i]:NULL;
						break;
				case 1:
					s = (font_type[i] & 16)?guess_font[1][i]:NULL;
						break;
			}
			if(s){
				len = strlen(s);
				while(s[--len] != '.');
				strcpy(path, s+len);
				while(s[--len] != '\\' && len > 0);
				strcpy(s+len+1, "^s");
				strcat(s, path);
			}else
				guess_font[k][i][0] = 0;
		}
			/* guess  ^d  by comparing  dpi  and  dpi^1.2 */
		if(!(len = strlen(guess_font[1][i])))
			continue;
		if( guess_font[1][i][len-1] == 'k' && (font_type[i] & 8)){	/* <- pk */
			type = 0;
cmp:		s = guess_font[1][i];									/* <- pxl */
			strcpy(tmp_buf, s);
			while( (s = StrStr(s+1, dpistr[type+2])) != NULL){
				len = s - guess_font[1][i];
				for(k=0; dpistr[type][k]; k++){
					if(dpistr[type][k] != guess_font[0][i][len+k])
						goto skip2;
				}
				strcpy(path, s + strlen(dpistr[type+2]));
				s[0] = '^';
				s[1] = (type)?'l':'d';
				strcpy(s+2, path);
				s = guess_font[0][i]+len;
				strcpy(path, s + strlen(dpistr[type]));
				s[0] = '^';
				s[1] = (type)?'l':'d';
				strcpy(s+2, path);
				if(font_type[i] & 128)
					font_type[i] |= 64;
				else
					font_type[i] |= 128;
skip2:	;
			}
			if( (font_type[i] & 64)
			  && !strcmp(guess_font[0][i], guess_font[1][i]) ){
				guess_font[1][i][0] = 0;
				strcpy(guess_font[1][i]+1, tmp_buf);
			}
		}else if(guess_font[1][i][len-1] == 'l'){			/* pxl */
			len = strlen(guess_font[0][i]);
			if(len && guess_font[0][i][len-1] == 'l')
				goto cmp;
		}
	}
								/* set ^d for the remaining */
	for(i = 0; i < max_guess; i++){
		if(font_type[i] & 64){
			s = guess_font[1][i] + 1;
			k = 2;
			goto set_d;
		}
		if(font_type[i] & 128)
			continue;
		for(k = 0; k < 4; k += 2){
			s = guess_font[k/2][i];
set_d:		if(!(len = strlen(s)))
				continue;
			if(s[len-1] == 'k')
				type = 0;
			else if(s[len-1] == 'l')
				type = 1;
			else
				continue;
			do{
				s = StrStr(s+1, dpistr[type+k]);
			}while(StrStr(s+1, dpistr[type+k]) != NULL);
			strcpy(path, s + strlen(dpistr[type+k]));
			s[0] = '^';
			s[1] = (type)?'l':'d';
			strcpy(s+2, path);
		}
	}
						/* erase the duplicated TEXPK's */
	for(i = 0; i < max_guess; i++){
		for(k = 0; k < 2; k++){
			s = guess_font[k][i];
			if(!*s)
				continue;
			if(k==0 && !strcmp(s, guess_font[1][i]))
				guess_font[1][i][0] = 0;
			for(j = i+1; j < max_guess; j++){
				if(!strcmp(s, guess_font[0][j]))
					guess_font[0][j][0] = 0;
				if(!strcmp(s, guess_font[1][j]))
					guess_font[1][j][0] = 0;
			}
		}
	}
#ifdef	USE_WINFONT
						/* search TrueType if the top font is not found */
	if(  guess_font[0][0][0] == 0
	  && check_wintt(efont) != NULL
	  && ((s = getenv("TEXMFMAIN")) != NULL || (s = getenv("TEXMF")) != NULL)
	){
		sprintf(guess_font[0][0], 
			"%s" STR_PATH_SEP "fonts" STR_PATH_SEP STR_PATH_SEP "^s.tfm"
			, s);
		i=0;
		while((k = (uchar)(guess_font[0][0][i++])) != 0){
			if(issjis1(k) && IsJapanese()){
				i++;
				continue;
			}
#ifdef	UNIX
			if(k=='\\')
				guess_font[0][0][i-1] = PATH_SEP;
#else
			if(k=='/')
				guess_font[0][0][i-1] = PATH_SEP;
#endif
		}
	}
#endif
						/* calculate the same heads */
	s = guess_font[0][0];
	if(IsJapanese()){
		for(i=type=0; s[i]; i++)
			if(issjis1((uchar)(s[i])))
				type=1;
	}
	same_len[0][0] = len = 0;
	for(i=0; i < max_guess; i++){
		for(k=0; k < 2; k++){
			if(!i && !k)
				continue;
			t = guess_font[k][i];
			if(!type)
				for(j=0; tolower(s[j]) == tolower(t[j]) && s[j] != '^'; j++);
			else
				for(j=0; s[j] == t[j] && s[j] != '^'; j++);
			while(s[j] != PATH_SEP && j > 0)
				j--;
			if(s[j-1] == PATH_SEP)
				j--;
			same_len[k][i] = j;
			if(j > len)
				len = j;
		}
	}
					/* determine the common top */
	type = k = 0;
	while(len > 2){
		j = 0;
		for(i=0; i < max_guess; i++){
			if(same_len[0][i] >= len)
				j += len-2;
			if(same_len[0][i] >= len)
				j += len-2;
		}
		if(j >= k){
			type = len;
			k = j;
		}
		len--;
	}
	for(i=0; i < type; i++){
		path[i] = guess_font[0][0][i];
	}
	path[i] = 0;
									/* define TEXROOT */
	free_top = (char *)tmp_buf;
	if(type){
		if(SetPath(path2, "^T")){
			for(i = 0; ; i++){
				if(!path2[i]){
					sprintf(free_top, "TEXROOT=^T%s\n", path+i);
					goto endtexpk;
				}else if(tolower(path2[i]) != tolower(path[i]))
					break;
			}
		}
		sprintf(free_top, "TEXROOT=%s\n", path);
endtexpk:
		free_top += strlen(free_top);
	}
									/* define TEXPK for pk, jxl4, jfm */
	strcpy(free_top, "TEXPK=");
	free_top+=6;
	pt_texpk = free_top;
	if(type <= 2)
		type = 200;
	same_len[0][0] = 100;
	for(i=0; i < max_guess; i++){
		for(k=0; k < 2; k++){
			s = guess_font[k][i];
			if(!*s)
				continue;
			if(same_len[k][i] >= type)
				sprintf(free_top, "^r%s" STR_DELIM, s+type);
			else
				sprintf(free_top, "%s" STR_DELIM, s);
			if(i == 0 && k == 0){
				r = path2;
				*r++ = PATH_SEP;
				t = KPSE_REP;
				while( (*r = *t++) != 0 && *r != DELIMITER) r++;
				*r = PATH_SEP;
				*(r+1) = 0;
				r = StrStr(free_top, path2);
				if(r){
					for(u = path1, v = free_top; v <= r; *u++ = *v++);
					*u = 0;
					v = r + strlen(u = path2) - 1;
					while((*u++ = *v++) != 0);
					if(path2[0])
						*(u-2) = 0;
				}else
					path1[0] = path2[0] = 0;
			}
			free_top += strlen(free_top);
		}
	}
						/* search other directries containing  ^s.^dpk */
	r = guess_font[0][MAXGUESS-4];
	t = guess_font[0][MAXGUESS-3];
	u = guess_font[0][MAXGUESS-2];
	v = guess_font[0][MAXGUESS-1];
	dir = org_dir;

	do{
		token_exist = copy_token(r, &dir, ';');
		sprintf(t, "Searching extra fonts in %s", r);
		DisplayMessage(t);
		sprintf(t, STR_PATH_SEP STR_PATH_SEP "*.%spk", dpistr[0] );
		strcat(r, t);
		len = strlen(dpistr[0]) + 4;
		if (kpse_search(r, STR_PATH_SEP STR_PATH_SEP) == FALSE)
			continue;
		do{
			if((s = FindFirstW32(r)) != NULL){
				strlwr(s = strcpy(tmp_name, s));
				j = strlen(s) - len + 1;
				if(j <= 0 || strcmp(s+j, t+3))
					continue;
				strcpy(u, r);
				strcpy(u + strlen(u) - len, s);
				strcpy(v, r);
				strcpy(v + strlen(v) - len, "^s.^dpk");
				for(i=0; path[i] && path[i] == v[i]; i++);
				if(!path[i] && i > 2){
					v[0] = '^';
					v[1] = 'r';
					for(j=2; v[i]; )
						v[j++] = v[i++];
/*					v[j++] = ';'; */
					v[j] = 0;
				}
				if(   (s = StrStr(tmp_buf, v)) != NULL
				   && s > tmp_buf
				   && (*(s-1) == '=' || *(s-1) == DELIMITER) )
					continue;					/* already found */
				if(  path1[0] && !strlcmp(v, path1)
				  && StrStr(v, path2) ==  v + strlen(v) - strlen(path2))
					continue;
				for(i=0; i<max_guess; i++){
					if( (font_type[i] & 64)
					  && !(strcmp(guess_font[1][i]+1, v)) )
					break;
				}
				if(i == max_guess && AskDirectry(u)){
					if(*(free_top-1) != '=' && *(free_top-1) != DELIMITER)
						*free_top++ = DELIMITER;
					free_top = stpcpy(free_top, v);
				}
			}
		}while(kpse_search(r, NULL));
	}while(token_exist);
	FlushAllFindDir();

	free_top = set_kpse(pt_texpk);
	if(*(free_top-1) != DELIMITER)
		*free_top++ = DELIMITER;
											/* define TEXPK for  GTH */
	type = 0;
	if(guess_gth[0]){
		for(i=0; path[i] && path[i] == guess_gth[i]; i++);
		if(path[i])
			strcpy(free_top, guess_gth);
		else
			sprintf(free_top, "^r%s", guess_gth+i);
		type |= 6;
		free_top += strlen(free_top);
	}
	if(*(free_top-1) != DELIMITER)
		*free_top++ = DELIMITER;
	if(!strlcmp(path1, "^r")){
		strcpy(path2, path);
		strcat(path2, path1 + 2);
		if( (r = StrStr(path2, 
				STR_PATH_SEP "texmf" STR_PATH_SEP "fonts" 
				STR_PATH_SEP "pk" STR_PATH_SEP)
			) != NULL){
			for(i=0; i < 2; i++){
				strcpy(r + 13, 
				(i)?"vf" STR_PATH_SEP STR_PATH_SEP "^s.vf"
				   : "pk" STR_PATH_SEP "modeless" STR_PATH_SEP STR_PATH_SEP
					 "^s.^dpk;");
				if(!strlcmp(path2, path)){
					strcpy(free_top, "^r");
					strcpy(free_top + 2, path2 + strlen(path));
				}else
					strcpy(free_top, path2);
				free_top += strlen(free_top);
			}
		}
	}
	if(get_buf == free_top)
		get_buf[0] = 0;
	else{
		s = strstr(get_buf, "TEXPK=^r\\tfm\\^s.tfm;");
		if(s){
			s[15] = '^';
			strcpy(free_top, "^r\\tfm\\^s.tfm");
			free_top += 13;
		}
		if(*(free_top-1) != DELIMITER)
			free_top++;
		*(free_top-1) = '\n';
		*free_top = 0;
	}

	for(i=0; i < max_guess; i++)
		type |= font_type[i] & 6;
	if(type){
		sprintf(free_top, "F=%s%s",
			((type&2)&&(type&56))?
				"lcircle1.=lcircle10.;lcirclew.=lcirclew10.;":"",
			((type&4)&&(type&56))?
				"lcirle10.=lcircle10.;lcirew10.=lcirclew10.;":"");
		free_top += strlen(free_top) - 1;
		strcpy(free_top, "\n");
	}
	Free(get_buf);
}
#endif

static char *checkjfmid(char *dir)
{
	char path[MAXPATH], *name;
	FILE *fp;
	int id, pos;

	strcpy(path, dir);
	pos = strlen(path) - 5;
	while(pos >= 0
	  && path[pos] != '\\' && path[pos] != '/' && path[pos] != ':')
		pos--;
	pos++;
	for(name = FindFirstW32(dir); name; name = FindNextW32()){
		strncpy(path + pos, name, MAXPATH - 1 - pos );
		if((fp = fopenf(path, "rb")) == NULL)
			continue;
		if(fgetc(fp) != 0 || ((id = fgetc(fp)) != 11 && id != 9) ){
			path[strlen(path) - 4] = 0;
			if(check_wintt(path + pos) == NULL){
				fclose(fp);
				return name;
			}
		}
		fclose(fp);
	}
	return NULL;
}
#endif

int my_access(char *path, int mode)
{
	char tmp[MAXPATH+32];

	SetPath(tmp, path);
	return access(tmp, mode);
}

static int font_access(char *path, int mode, int type)
{
	uchar ctmp[2];
	int fd, pos, top, pos2, res2;

	if(my_access(path, mode) == FAILURE)
		return FAILURE;
	pos = strlen(path) - 4;
	if(pos > 0 && !strcmp(path + pos, ".tfm")){
		if(!tmp_tfm[0])
			strcpy(tmp_tfm+1, path); 
		fd = openf(path, O_RDONLY | O_BINARY);
		read(fd, &ctmp[0], 2);
		close(fd);
		for(top = pos - 1; top >= 0; top--){
			if(path[top] == '\\' || path[top] == '/' || path[top] == ':')
				break;
		}
		top++;
		fd = ctmp[0] + (ctmp[1]<<8);
		if(fd == (9<<8) || fd == (11<<8)){	 /* (jfm yoko) || (jfm tate) */
			if(!tmp_tfm[0])
				tmp_tfm[0] = 'j';
			path[pos] = 0;
			if(f_tfm2ttf){					/* ^s^tfm */
				fd = check_wintt(path + top);
				if(!fd){
					res2 = 0;
					pos2 = strlen(path + top);
					while(--pos2>0 && 
					  path[top+pos2] >= '0' && path[top+pos2] <= '9'){
						res2 = path[top+pos2];
					}
					if(res2){
						path[top+pos2+1] = 0;
						fd = check_vjfm(path + top);
						path[top+pos2+1] = res2;
					}
				}
			}else
				fd = strcmp(check_ftt(path + top), "-");
		}else{
			if(!tmp_tfm[0])
				tmp_tfm[0] = 't';
#ifdef	USE_WINFONT
			if(!type)
				return FAILURE;
			path[pos] = 0;
			fd = check_wintt(path + top);

			if(!fd){
				char *ttf;

				ttf = check_myftt(path + top, 0);
				if(*ttf && my_access(ttf, mode) != FAILURE){
					strcpy(path, ttf);
					return NOTHING;
				}
			}
#else
			return FAILURE;
#endif
		}
		path[pos] = '.';
		if(!fd)
			return FAILURE;
	}
	return NOTHING;
}

#ifdef	WIN32G
char *checkjfm(char *dir)
{
	char *tmp;
	int i;
	int pos = 0;

	while(dir[pos]){
		i = pos;
		while((tmp_buf[pos - i] = dir[pos]) != 0){
			if(dir[pos++] == ';'){
				tmp_buf[pos - i] = 0;
				break;
			}
		}
		if(pos - i < 5 || strcmpi(tmp_buf + pos - i - 4, ".tfm") != 0)
			continue;
		fill_name_and_fig((char *)tmp_buf, "*", "1", "1");
		if (tmp_buf[0] == '\\' && tmp_buf[1] == '\\'
		  && my_access(tmp_buf, READ_MODE) != FAILURE)
			goto dup_path;
		if (kpse_search(tmp_buf, "\\\\") == FALSE){
			if(  tmp_buf[0] == '/' && tmp_buf[1] == '/' 
			  && (tmp = checkjfmid(tmp_buf)) != NULL )
				goto dup_path;
			kpse_search(tmp_buf, "//");
		}
		do { 
			if ( (tmp = checkjfmid(tmp_buf)) != NULL){
dup_path:		strcpy(o_font, dir + i);
				for(i = 0; o_font[i]; i++){
					if(o_font[i] == ';')
						o_font[i] = 0;
				}
				sprintf(tmp_buf,
					"TEXPK(%s) corresponds to\n"
					" %s, which is not a jfm file!\n"
					"TEXPK may be wrong.\n",
					o_font, tmp);
				return tmp_buf;
			}
		}while (kpse_search(tmp_buf, NULL));
	}
	return NULL;
}
#endif

void SetFontDPI(FONT_INFO *font)
{
	int	cmd;
	uint fig=0, fmags;
	ulong atrs, atrd, atrt;
	double magsize;

	/* calculate font dpi (from fontdef.c) */
	atrt = (ulong)dpis *(ulong)mags;
	if (font->size_para == font->des_para) {
		atrs = atrt;
		atrd = 100;
		cmd = 1;
	} else {
		atrs = font->size_para;
		atrd = font->des_para;
		while (atrd > 6000L) {
			atrs >>= 1;
			atrd >>= 1;
		}
		fig = (uint)((atrs * 1000 + (atrd >> 1)) / atrd);
		if (atrd > 2000L) atrs /= 4;
		else atrd *= 4;
		atrs *= atrt / 25L;
		cmd = 2;
	}
	for (fmags = mags; cmd > 0; cmd--) {
		if (fmags == 1095)
			atrs += atrs / 2460;	/* 1095.4451... */
		else if (fmags == 2074)
			atrs -= atrs / 5183;	/* 2073.6		*/
		else if (fmags == 2488)
			atrs += atrs / 7775;	/* 2488.32		*/
		fmags = fig;
	}
/*
	set the same dpi as fdpi in genfont_proc() (--ak 2010-03-09)
*/
	magsize = (double)((long)((double)font->size_para/font->des_para*mags*100. + 0.5));
	magsize *= 1.0e-5;
	font->dpi = (int)(magsize*dpis + 0.5);
/*
	font->dpi = (uint)((atrd * 5 + atrs) / (atrd * 10));
*/
	font->sdpi = (uint)((atrd + atrs) / (atrd * 2));
	font->code_offset = -1;

	font->n[MAX_NAME_LEN-1] = ' ';
	font->pk = font->vjfm = font->name = NULL;
	font->next_font = font->before_font = font->after_font = NULL;
	for(cmd = 0; cmd < CHAR_ROOT; cmd++)
		font->char_info[cmd] = NULL;
}

static void make_font(struct FONT_ATR *atr, int mode)
	/* フォント表を作る
	 */
{
	FONT_INFO *font;
	char *name;

	ENTER("make_font");

	if (first_font_info == NULL)
		font = first_font_info = font_info_alloc();
	else {
		for (font = first_font_info; font->next_font; font = font->next_font)
			/* フォントリスト内をサーチ
			 */
			if (font->font_code == atr->k){
				if(mode == -1)
					return;
				else
		/* ２度定義しているか？	*/
					error(PROGRAM_STOP, "Twice fnt_def");
			}
		/* 空いているなら */
		font = font->next_font = font_info_alloc();
	}

	/* フォント番号をセット */
	font->font_code = (int)atr->k;
	font->size_para = atr->s;
	font->des_para = atr->d;
	SetFontDPI(font);
	name = atr->n;
	font->f_goth = (*name=='t' || *name=='T')?F_TOPT:0;
	font->c = atr->c;
	strncpy(&(font->n[0]), atr->n, MAX_NAME_LEN-2);
	font->ext.dir = NULL;
	font->font_type = ONDEMAND;
#ifdef	USE_SUBFONT
	font->sfd_id = -1;
#endif
	if(!f_ondemand)
		resolve_font(font);
}

BOOL ExecBatch(char *fname, int mode)
{
	int i;
	FILE *fa, *fb;
	char fbname[MAXFILE+4];

	if(!mode){
		SetPath(fbname, "^?\\gs_tmp.bat");
		if(!(fb = fopenf(fbname, "wt"))){
			fname = fbname;
			goto err;
		}
		fputs(fname, fb);
		goto exe;
	}

	if(!fname || (fa = fopenf(fname, "rt")) == NULL){
err:	error(WARNING, "Cannot make %s", fname?fname:"batch file");
		return FALSE;
	}
	strcpy(fbname, fname);
	strcpy(fbname + strlen(fbname) - 4, "$.bat");
	if((fb = fopenf(fbname, "wt")) == NULL){
		fname = fbname;
		goto err;
	}
	while((i = getc(fa)) != EOF)
		putc(i, fb);
	fclose(fa);
exe:
	fputs("\nPause to keep the above message by Cut & Paste!", fb);
	fclose(fb);
	system(fbname);
	unlink(fbname);
	return TRUE;
}

void resolve_font(FONT_INFO *font)
{
	char *path_name, *ptr, *dir, *tmp, *tmpp;
	char name[0x100];

	int i, mode;
	uint fig, figl;
	BOOL token_exist, f_create;
#ifndef NO_NTTRPL
	FONT_INFO *ifont;
#endif

	if(font == NULL){
		f_checkerror = 0;
		return;
	}
	if(font->font_type != ONDEMAND && font->font_type != ONDEMAND2)
		return;
	tmp_tfm[0] = 0;
	strcpy(name, font->n);
	fig = font->dpi;
	figl = font->sdpi;
	font->sdpi = font->dpi;
	mode = font->font_type;
	font->font_type = UNKNOWN;
#ifndef NO_NTTRPL
	if (ntt_subst && mode == ONDEMAND) {
		strcpy(name, ntt_sub(name, font, &fig, &figl));
		font->f_goth = (*name=='t' || *name=='T')?F_TOPT:0;
		if (font->code_offset >= 0) {
			i = strlen(name);
			font->family_code = font->font_code;
			for (ifont=first_font_info; ifont!=font; ifont=ifont->next_font){
				if (ifont->font_type == ONDEMAND)
					resolve_font(ifont);
				if (!strncmp(ifont->name + get_fname_off(ifont->name), name, i)
						&& ifont->size_para == font->size_para) {
					font->family_code = ifont->family_code;
					path_name = dup_string(ifont->name);
					goto exist;
				}
			}
		}
	}
#endif
#ifdef	USE_ETF
	if(IsETF(font, name, fig)){
		path_name = dup_string(
			(font->font_type == UNKNOWN)?"<ETF.tfm":"<ETF");
		texpk_pos = -1;
		if(font->etf_type == PK_FONT && font->sdpi != font->dpi)
			font->n[MAX_NAME_LEN-1] = '+';
		goto exist;
	}
#endif
	if(IsInnerJFM(name)){
		path_name = (char *)marea(strlen(name) + 6);
		sprintf(path_name, "<%s.tfm", name);
		texpk_pos = -1;
		goto exist;
	}
again:
	if ((path_name = font_name_check(name, fig, figl)) != NULL)
		goto exist;
	f_create = FALSE;

	if (sub_font != NULL && *sub_font) {
		if(!f_sub_font++){
			if(f_sub_warn == 2)
				error(DATALOG, "Substitute font for %s at %d dpi", name, fig);
			else if(f_sub_warn == 1){
				 switch(error(ASK, 
					  "Substitute font for %s at %d dpi", name, fig)){
					  case 0:	/* ignore */
							f_sub_warn = 2;
							break;
					  case 1:	/* retry */
							break;
					  case 2:	/* abort */
							goto sub_skip;
				 }
		   }
		}
		ptr = sub_font;
		do {
			ptr = next_top((char *)&(s_font[0]), ptr);
			ptr = next_top((char *)&(s_fig[0]), ptr);
			ptr = next_top((char *)&(o_font[0]), ptr);
			ptr = next_top((char *)&(o_fig[0]), ptr);
			if(*s_fig == '!'){
				sprintf(&(s_fig[0]), "%d", dpis);
				sprintf(&(ss_fig[0]), "%d", dpis*5);
			}else if(*s_fig == 't'){

/* 	substitute by ^s.tfm  */
				dir = new_tfm_search_path?new_tfm_search_path:"";
				do {
					token_exist = copy_token((char *)tmp_buf, &dir, DELIMITER);
					make_path(tmp_buf, tmp_buf, name, ".tfm");
					if(root_search_path != NULL){
						i = strlen(root_search_path);
						tmp = tmp_buf;
						while( (tmpp = StrStr(tmp, "^r")) != NULL
						  ||   (tmpp = StrStr(tmp, "%r")) != NULL ){
							tmp = tmpp;
							memmove(tmp, tmp + 2, strlen(tmp));
							memmove(tmp + i, tmp, strlen(tmp) + 1);
							memcpy(tmp, root_search_path, i);
							tmp += i;
						}
					}

#if defined(UNIX)||defined(USE_WINAPI)
					if (tmp_buf[0] == '\\' && tmp_buf[1] == '\\'
					  && my_access(tmp_buf, READ_MODE) != FAILURE)
						goto dup_path;
					if (kpse_search(tmp_buf, "\\\\") == FALSE){
						if(  tmp_buf[0] == '/' && tmp_buf[1] == '/' 
						  && my_access(tmp_buf, READ_MODE) != FAILURE )
							goto dup_path;
						kpse_search(tmp_buf, "//");
					}
					do { 
#endif
						if (my_access(tmp_buf, READ_MODE) != FAILURE){
dup_path:					path_name = dup_string(tmp_buf);
							goto exist;
						}
#if	defined(UNIX)||defined(USE_WINAPI)
					} while (kpse_search(tmp_buf, NULL));
#endif
				} while (token_exist);
				continue;
/* end of substitution by ^s.tfm */

			}else
				strcpy(ss_fig, s_fig);
			if ((path_name = font_name_check(name, fig, figl)) != NULL)
				goto exist;
		} while (*ptr != 0);
	}
sub_skip:
	if (f_sub_font < 2) {
		error(C_MSG, "\n%s.%03u(%03u):\n", name, fig, figl);
		f_sub_font = 2;
		goto again;
	}
	if (test_flg != 0
#ifndef NO_GENFONT
		&& (genfont_tmpl == NULL || !*genfont_tmpl)
#endif
		){
		error(NO_FONT, "Any of the above%s.", 
			tmp_tfm[0]?" execpt for .tfm file":"");
		if(mode == ONDEMAND)
			g_nErrorCode = FE_NOFONT;
		goto skip;
	}
#ifndef NO_GENFONT
	if (genfont_tmpl && *genfont_tmpl) {
		if(f_checkerror & 1)
			goto skip0;
		f_create = TRUE;
		path_name = genfont_main(font->n, font->des_para, font->size_para, 
			fig, figl, dpis);
		if (path_name != NULL) goto exist;
skip0:	if(mode == ONDEMAND)
			g_nErrorCode = FE_NOFONT;
		if(f_checkerror & 1)
			goto skip;
		if (genfntfp == NULL) { /* make gen_font.bat */
			if ((genfntfp=fopenf(genfnt,"w")) == NULL){
#ifdef	WIN32G
				error(ERRPAUSE, "Cant't make fnt-batch file:%s",
					genfnt);
				goto skip;
#else
				error(PROGRAM_STOP, "Can't make fnt-batch file:%s",
					genfnt);
#endif
			}
			genfont_out(genfntfp, 0);
		}
		genfont_proc(genfntfp, font->n, font->des_para, font->size_para);
	}
#endif

skip:
#ifndef	WIN32
	test_flg = 0;
#endif
	font->font_type = UNRESOLVE;
	error(C_MSG, "Searched the above");
	error(DATATITLE, "Cannot resolve Fonts");
#ifdef  WIN32G
	if(g_nErrorCode && !(f_checkerror & 6) && f_ondemand == TRUE){
		if(!f_checkerror)
			ShowWinHelp(IDH_QE10);
		if(f_create){
			switch(error(ASK, 
//						"Terminate Automatic Font Generation?"
				"(A)bort Automatic Font Generation for this file?\n"
				"(R)etry it for the investigation by executing GEN_TMP.BAT?\n"
				"(I)gnore this font?")){
					case 0:	/* ignore */
							break;
					case 1:	/* retry */
							ExecBatch(gentmp, 1);
							break;
					case 2:	/* abort */
						f_checkerror |= 1;
			}
		}
	}
	if(f_create)
		f_checkerror += 2;
#endif
	if(g_nErrorCode){
		if(!f_ondemand){
			font->next_font = NULL;
			font->name = dup_string("");
#ifdef	USE_WINAPI
			FlushAllFindDir();
#endif
			return;
		}
		path_name = dup_string(tmp_tfm[0]?(tmp_tfm+1):"<<jis.tfm");
		if(tmp_tfm[0] == 't')
			font->font_type = SUBTFM;
		else{
			font->font_type = SUBJFM;
			font->last = 0x7fffffff;
		}
		font->n[MAX_NAME_LEN-1] = 't';
		g_nErrorCode = 0;
	}else
		path_name = dup_string("");
exist:
#ifdef	USE_WINAPI
	FlushAllFindDir();
#endif
	font->name = path_name;
	if (test_flg == 0)
		error(C_MSG, "%3d%9s.%03u(%4u): %s\n", font->font_code, name, 
			fig, figl, get_font_name(font));

	font->texpk_pos = texpk_pos;
	if(f_sub_font == 1){
		if(*s_fig == 't'){
			font->font_type = SUBTFM;
			i = 't';
		}else {
			if((i = atoi(s_fig)) > 0)
				font->sdpi = i;
			switch(f_sub_blank){
				case 0: i = '*'; break;
				case 1: i = '!'; break;
				case 2: i = '#'; break;
				case 3: i = '+'; break;
				default: i = '?';
			}
		}
		font->n[MAX_NAME_LEN-1] = i;
		f_sub_font = 0;
	}
	END();
}

int chk_goth(FONT_INFO *font)
{
	int offset;
	BOOL token_exist;
	char *ptgoth, key_goth[0x100];

	ENTER("chk_goth");

	if (*goth == 0)
		return (0);

	if (*(font->name) == '*') {
		offset = 9;
		offset += strlen((font->name) + 9) + 1;
	}
	else {
		offset = strlen(font->name) - 13;
		if (offset < 0)
			offset = 0;
	}
	ptgoth = goth;
	if(strlen(goth) < 0x100){
		do{
			token_exist = copy_token(key_goth, &ptgoth, ';');
			if (*ptgoth && StrStr(font->name + offset, key_goth))
				RETURN(1);
		}while(token_exist);
	}
	RETURN(0);
}

static char *
	str_fnt_nm(char *name, char *ptr_sp, long pos, long size)
{
	int len;
	char *ptr, *ptr1;

	ENTER("str_fnt_nm");
	len = strlen(name);

	ptr = ptr1 = (char *)marea(len + strlen(ptr_sp + 1) + (1 + 2 * 4 + 1 + 1));
	*ptr1 = '*';
	save_long((uchar *)(ptr1 + 1), pos);
	save_long((uchar *)(ptr1 + 5), size);
	strcpy(ptr1 + 9, name);
	strcpy(ptr1 + 10 + len, ptr_sp + 1);
	RETURN(ptr);
}

#if defined(GCC1) && !defined(UNIX)
/*
 *  kpathsea like recursive search
 */

static int findfirstdir(char *name, struct find_t *d)
{
	int r;

	r=_dos_findfirst(name, _A_SUBDIR, d);
	while (!r&&((*((*d).name)=='.')||!((*d).attrib&_A_SUBDIR)))
		r=_dos_findnext(d);
	return r;
}

static int findnextdir(struct find_t *d)
{
	int r;

	do	r=_dos_findnext(d);
	while (!r&&((*((*d).name)=='.')||!((*d).attrib&_A_SUBDIR)));
	return r;
}
#endif

#if	defined(USE_WINAPI)||defined(UNIX)
BOOL kpse_search(char *path, char *sep)	
{
	static BOOL search;
	char *found;
	static char *dirname[MAX_KPS_DEPTH];
	static char *sep_pos[MAX_KPS_DEPTH+1];
	static int ins_ptr[MAX_KPS_DEPTH];
	static int level, pt;
	char *ins_pos;

	if (sep != NULL) {		/* initialize */
		if ((ins_pos = StrStr(path+2, sep)) != NULL) {
			search = TRUE;
			*ins_pos = '\0';
			SetPath(tmp_front, path);
			dirname[level = 0] = tmp_front + strlen(tmp_front);
			strcpy(tmp_rear, ins_pos + 1);
			sep_pos[0] = ins_pos = tmp_rear;
			for(pt = 1; pt < MAX_KPS_DEPTH; pt++){
				if ((ins_pos = StrStr(ins_pos, sep)) == NULL){
					sep_pos[pt] = NULL;
					break;
				}
				*ins_pos++ = 0;
				sep_pos[pt] = ins_pos;
			}
			ins_ptr[0] = 0;
			goto add;
		} else {
			search = FALSE;
		}
	} else {
		if (search == TRUE) {
			while(1){
				if(level >= MAX_KPS_DEPTH-2)
					found = NULL;
				else if(ins_ptr[level] == ins_ptr[level+1])
					found = FindNextDir(level);
				else{
#ifdef	UNIX
					*dirname[level] = 0;
#else
					strcpy(dirname[level], "\\*.*");
#endif
					found = FindFirstDir(tmp_front, level);
				}
				if(found != NULL)
					break;
				if(--level < 0){
					search = FALSE;
					break;
				 }
			}
			if (search == TRUE) {
				dirname[level + 1] =
					stpcpy(dirname[level] + 1, found);
#ifdef	UNIX
				dirname[level][0] = PATH_SEP;
#endif
				ins_ptr[level+1] = ins_ptr[level];
				level++;
add:			while(sep_pos[ins_ptr[level]] != NULL 
				  && level < MAX_KPS_DEPTH - 1){
					dirname[level + 1] = 
						stpcpy(dirname[level], sep_pos[ins_ptr[level]]);
					ins_ptr[level + 1] = ins_ptr[level] + 1;
					level++;
				}
				level--;
				strncpy(path, tmp_front, MAXPATH);
			}
		}
	}
/*
	if(search == TRUE)
		error(C_MSG, "%d:%s\n", level, path);
*/
	return(search);
}

#else
#if	defined(GCC1)
BOOL kpse_search(char *path, char *sep)	
{ 
	static BOOL search;
#ifdef	WIN32
	static char *dirname[9];
#else
	BOOL notfound;
	static char *dirname[4];
#endif
	static int level;
	char *ins_pos;

	if (sep != NULL) {		/* initialize */
		if ((ins_pos = StrStr(path, sep)) != NULL) {
			search = TRUE;
			*ins_pos = '\0';
			dirname[level = 0] = stpcpy(tmp_front, path);
			strcpy(tmp_rear, ins_pos + 1);
			strcpy(ins_pos, tmp_rear);
		} else {
			search = FALSE;
		}
	} else {
		if (search == TRUE) {
			strcat(dirname[0], "\\*.*");
#ifdef	WIN32
			found = (level < 8)? FindFirstDir(tmp_front, level):NULL;
			while(found == NULL)
#else
			notfound = (level < 3)? findfirstdir(tmp_front, &direc[level]) : 1;
			while(notfond)
#endif
			{
				if (--level < 0) {
					search = FALSE;
					break;
				}
#ifdef	WIN32
				found = FindNextDir(level);
#else
				notfound = findnextdir(&direc[level]);
#endif
			}
			if (search == TRUE) {
				dirname[level + 1] =
					stpcpy(dirname[level] + 1, 
#ifdef	WIN32
					found
#else
					direc[level].name
#endif
					);
				level++;
				strcpy(path, tmp_front);
				strcat(path, tmp_rear);
			}
/*		error(14, "[%s][%s][%s][%s]", found, dirname[level-1], tmp_front, tmp_rear); */
		}
	}
	return (search);
}
#endif
#endif

char *
	font_name_check(char *name, uint fig, uint figl)
	/* 環境変数で指定されたPATHで，FILEがあるかどうかを調べる．
	 * あったら，そのFull-Path-Nameを返す．ないときはNULL
	 */
{
	char *path, *path0, *ptr_sp;
	BOOL token_exist, number_exist;
	int i, j, type;
	char msg[512];

	char fig_str[FIG_COLUMN], figl_str[FIG_COLUMN];
/*	char fig_str_sub[FIG_COLUMN], figl_str_sub[FIG_COLUMN]; */
	char *tmp;
#ifdef	FLI
	char *flib;
#endif	/* FLI */

	ENTER("font_name_check");

	type = (f_use_ttf && (fig >= f_use_ttf))?1:0;
	if((tmp = check_path_cash(name, fig)) != NULL){
		strcpy((char *)tmp_buf + 0x200, 
		  get_old_path( *((uchar *)tmp+2), tmp + strlen(tmp + 3) + 4 ));
		SetPath(tmp_buf + 0x200, tmp_buf + 0x200);
		texpk_pos = -1;
		for (i = j = 0; i < f_loop; i++) {
			sprintf(fig_str, "%u", fig + j);
			sprintf(figl_str, "%u", figl + j);
			j = -j;
			if (j >= 0)
				j++;
			strcpy(tmp_buf, (char *)tmp_buf + 0x200);
			fill_name_and_fig((char *)tmp_buf, name, fig_str, figl_str);
			if(font_access(tmp_buf, READ_MODE, type) != FAILURE)
				goto dup_path;
		}
#ifdef	WIN32G
		KeepPathCash(NULL, 0);
#endif
		Free0(path_cash);
		path_cash = NULL;
		f_path_cash = -1;
	}
#ifdef	WIN32G
		if(!b_presentation_mode){
			sprintf(msg, "Searching font %s(%d dpi)", name, fig);
			DisplayMessage(msg);
		}
#endif
	path0 = font_search_path;
	texpk_pos = 0;
	do {
		/* この下で３回調べているのは，計算の誤差が出るためである．*/
		for (i = j = 0; i < f_loop; i++) {
			sprintf(fig_str, "%u", fig + j);
			sprintf(figl_str, "%u", figl + j);
			j = -j;
			if (j >= 0)
				j++;
			path = path0;
			token_exist = copy_token((char *)tmp_buf, &path, DELIMITER);
			if(!*tmp_buf) continue;
			if (f_sub_font & 1) {
				if (*o_font != 0 && strcmp(o_font, name) != 0)
					continue;
				if (*o_fig != 0) {
					if (strcmp(o_fig, fig_str) != 0 &&
						strcmp(o_fig, figl_str) != 0)
						continue;
				}
				number_exist = fill_name_and_fig((char *)tmp_buf,
					(*s_font != 0) ? (char *)s_font : name,
					(*s_fig != 0) ? (char *)s_fig : fig_str,
					(*s_fig != 0) ? (char *)ss_fig : figl_str);
			}
			else{
				number_exist =
					fill_name_and_fig((char *)tmp_buf, name, fig_str, figl_str);
			}
#ifdef TTFONT
			if (f_use_ttf <= 0) {
				tmp = strrchr(tmp_buf, '.');
				if (tmp > (char*)tmp_buf && strcmpi(tmp, ".ttf") == 0)
					goto loop;
			}
#endif
#ifdef VIRTUALFONT
			if (f_use_virtualfont != TRUE) {
				tmp = strrchr(tmp_buf, '.');
				if (tmp > (char*)tmp_buf && strcmpi(tmp, ".vf") == 0)
					goto loop;
			}
#endif
			if (f_sub_font >= 2) {
				error(C_MSG, "Searched %s\n", tmp_buf);
				goto loop;
			}
#ifdef DVI_ADD
			if ( tmp_buf[0] == '^' && tmp_buf[1] == 'F' &&
				(tmp_buf[2] == '\\' || tmp_buf[2] == '/') ){
			char *t_path;
				if( (t_path = GetAddFile(tmp_buf+3)) != NULL){
					f_fkeep = FALSE;
#ifdef	WIN32G
					DisplayMessage(NULL);
#endif
					RETURN((char *)store_font_name(t_path));
				}
			}
#endif
#if	defined(UNIX)||defined(USE_WINAPI)

			if (tmp_buf[0] == '\\' && tmp_buf[1] == '\\'
			  && font_access(tmp_buf, READ_MODE, type) != FAILURE)
				goto dup_path;
			if (kpse_search(tmp_buf, "\\\\") == FALSE){
				if(  tmp_buf[0] == '/' && tmp_buf[1] == '/'
				  && font_access(tmp_buf, READ_MODE, type) != FAILURE )
					goto dup_path;
				kpse_search(tmp_buf, "//");
			}
			do { 
#endif
				if ((ptr_sp = strchr(tmp_buf, CHAR_SP)) == NULL) {
					if (font_access(tmp_buf, READ_MODE, type) != FAILURE){
dup_path:
#ifdef	WIN32G
						DisplayMessage(NULL);
#endif
						RETURN((char *)store_font_name(tmp_buf));
					}
				}
				else 
#ifdef	FLI
				if (fli_search_path && (tmp = strchr(tmp_buf, '*')) != NULL) {
					flib = dup_string(fli_search_path);
					tmp = accfli((char *)tmp_buf, ptr_sp, tmp, figl, flib);
					Free(flib);
					if (tmp) return tmp;
				} else
#endif	/* FLI */
				if (accgth((char *)tmp_buf, ptr_sp) != FAILURE){
#ifdef	WIN32G
					DisplayMessage(NULL);
#endif
					RETURN(str_fnt_nm((char *)tmp_buf, ptr_sp, fpos, fsize));
				}
#if	defined(UNIX)||defined(USE_WINAPI)
			} while (kpse_search(tmp_buf, NULL));
#endif
loop:		if (!number_exist)
				break;
		}
		path0 = path;
		texpk_pos++;
	} while (token_exist);
#ifdef	WIN32G
	DisplayMessage(NULL);
#endif
	RETURN(NULL);
}

void open_jxl(FONT_INFO *font)
{
	ENTER("open_jxl");

	if ((font->ext.fh = openf(font->name, O_RDONLY | O_BINARY)) < 0)
		error(FILE_FAULT, "Cannot re_open JXL file %s", font->name);
	END();
}

#ifdef VFD
void open_vf(FONT_INFO *font)
{
	int i;
	char *dir;
	char fname[100];
	BUFFER *ptr;

	font->k_width = font->pk[2] + (3 + 4);
	ptr = font->pk + 7;
	i = 0;

	if ((dir = getenv("TEXVFD")) == NULL &&
		(dir = vfd_search_path) == NULL)
		*fname = 0;
	else {
		for (; i < 99; i++)
			if ((fname[i] = dir[i]) == 0)
				break;
	}
	while (i < 100) {
		if ((fname[i++] = *ptr++) == 0)
			break;
	}
	if ((font->ext.fh = openf(fname, O_RDONLY | O_BINARY)) > 0)
		return;
	error(NO_FILE, "VFN file %s", fname);
}

#endif

void open_pk(FONT_INFO *font)
{
	int i;
	char *dir;
	char fname[100];
	BUFFER *ptr;

	ENTER("open_pk");

	font->k_width = font->pk[2] + (3 + 16);
	ptr = font->pk + 7;
	i = 0;
	if ((dir = getenv("TEXPKD")) == NULL &&
		(dir = pkd_search_path) == NULL)
		*fname = 0;
	else {
		for (; i < 99; i++)
			if ((fname[i] = dir[i]) == 0)
				break;
	}
	while (i < 100) {
		if ((fname[i++] = *ptr++) == 0)
			break;
	}
	if ((font->ext.fh = openf(fname, O_RDONLY | O_BINARY)) > 0)
		END();
	error(NO_FILE, "PK file %s", fname);
}

char *
	get_fontname(FONT_INFO *fontc)
{
	char *tmp;
	int ch, width, width0, widthm;
#ifdef	USE_ETF
	char etfbuf[0x80];
#endif
#define	font_name	(tmp_buf+TMP_FONT_NAME)

	ENTER("get_fontname");

	if (*(tmp = fontc->name) == '*')
		tmp += strlen(tmp + 9) + 10;
	else if(*tmp == '<'){
		tmp++;
#ifdef	USE_ETF
		if(!strcmp(tmp, "ETF.tfm"))
			sprintf(tmp = etfbuf, ":%s.tfm", fontc->n);
#endif
	}
	width = strlen(tmp) - 4;
	font_name[0] = 0;
	if (tmp[width--] == '.') {
		while ((ch = tmp[width]) >= '0' && ch <= '9' && width > 0)
			width--;
		for (width0 = width; width0 >= 0; width0--) {
			if ((ch = tmp[width0]) == '\\' || ch == '/' || ch == ':' || ch == 0) {
				break;
			}
		}
		width0++;
		if ((widthm = width - width0) <= MAX_NAME_LEN) {
			for (ch = 0; ch <= widthm; ch++)
				font_name[ch] = tmp[width0 + ch];
			font_name[ch] = 0;
		}
	}
	RETURN((char *)font_name);
}


KFONT *
	dup_kf(KFONT *kfo)
{
	KFONT *kf;

	kf = (KFONT *)marea(KFONT_SIZE);
	kf->width = kfo->width;
	kf->height = kfo->height;
	kf->size = kfo->size;
	kf->base = kfo->base;
	kf->fh = kfo->fh;
	kf->name = kfo->name;
	return (kf);
}

KFONT *
	open_kfont(FONT_INFO *fontc, int maxwidth, int dir, JFM_DATA *jfm)
{
	char *path, *path0, *pt;
	int width, width0, widthm, fh, dif, f_dbl, loop, far *wdthp;
	char fig_str[FIG_COLUMN];
	char *name;
	KFONT *kf;
	FONT_INFO *font;
	FONT_INFO *fontk;
	BOOL token_exist;

	ENTER("open_kfont");

	dif = loop = f_dbl = 0;
#ifndef	WIN32
	get_near_work(0);
#endif
	name = get_fontname(fontc);
	wdthp = (fontc->f_goth & F_TATE)?&(fontc->k_height):&(fontc->k_width);

	width = *wdthp;
	if (f_resize && maxwidth < 512) maxwidth = 512;
	width0 = 0;
#ifdef	LBP
	if (f_use_lfont) {
		kf = get_lbp_font(fontc, jfm);
		if (kf != NULL)
			RETURN(kf);
	}
#endif

#ifndef	NOVFONT
	if (f_use_vfont) {
		kf = get_vfont_list(fontc, name);
		if (kf != NULL)
			RETURN(kf);
	}
#endif

	/* 要求された大きさが romfont_min romfont_max の範囲に有り、
	 * -k により pk 使用が指定されていない場合には、ROM FONT を拡大／縮小
	 * して使用する。適当な pk を探し、見つからなければやはり ROM FONT を
	 * 使用する。
	 * -romf 無しでは romfont_min == -1 となる。
	 */

rep:							/* search kanji font file */
	for (; width != width0; width += dif) {
		if (width > maxwidth)
			goto next;
		f_dbl = 0;
		widthm = width;
repdbl:						/* search again */
		sprintf(fig_str, "%d", widthm);
		if ((path0 = getenv("TEXKNJ")) != NULL ||
			(path0 = knj_search_path) != NULL) {
			do {
				path = path0;
				token_exist = copy_token((char *)tmp_buf, &path, DELIMITER);
				if(!*tmp_buf) continue;
				fill_name_and_fig((char *)tmp_buf, name, fig_str, "");

				for (font = first_font_info; font != NULL; font = font->next_font) {
					if ((font->font_type > ROM_FONT)
						&& font->ext.kdir != NULL
						&& strcmp((font->ext.kdir)->name, tmp_buf) == 0) {
						if ((font->f_goth & K_DBL) == f_dbl && !f_resize){
							if (fontc->k_top == NULL) {
								for (fontk = font;
									 fontk->k_next; fontk = fontk->k_next);
								fontk->k_next = fontc;
								fontc->k_top = fontk->k_top;
							}
							fontc->f_goth |= f_dbl;
							RETURN(dup_kf(font->ext.kdir));;
						}
						fh = (font->ext.kdir)->fh;
						goto exit;
					}
				}
				if ((fh = openf((char *)tmp_buf, O_RDONLY | O_BINARY)) != -1)
					goto exit;
				path0 = path;
			} while (token_exist);
		}
		if (f_dbl == 0) {
			if (!(width & 1) && k_dbl != NULL
				&& (pt = StrStr(k_dbl, fig_str)) != NULL
				&& *(pt - 1) == DELIMITER
				&& *(pt + strlen(fig_str)) == DELIMITER) {
				f_dbl = K_DBL;
				widthm = width / 2;
				goto repdbl;
			}
		}
next:	if (!loop)
			dif = (dif < dir) ? 1 - dif : -dif - 1;
	}
	if (loop++ == 0 && (*wdthp < ROM_F_SIZE || romfont_max == 0)) {
		width = *wdthp + 1;
		width0 = width + 128;
		dif = 1;
		maxwidth = width0;
		goto rep;	
	}
							/* use ROM FONT */
	error(FONT_MISMATCH, 
		"This document requires a Japanese Font but "
		"Can't find Kanji FONT(%d)\n",
		*wdthp);

exit:						/* define Kanji Font file */
	kf = (KFONT *)marea(KFONT_SIZE);
	kf->name = (char *)dup_string((char *)tmp_buf);
	if (f_dbl == K_DBL) {
		if (!f_resize) fontc->f_goth |= K_DBL;
		width >>= 1;
	}
	if (fontc->k_top == NULL)
		fontc->k_top = fontc;
	if (f_resize) fontc->f_goth |=
		((fontc->font_type == ROM_FONT)?K_SCALE2:K_SCALE);
	kf->height = kf->width = width;
	kf->size = (width + 7) / 8 * kf->height;
	kf->fh = fh;
	RETURN(kf);
}

static int accgth(char *fname, char *ptr_sp)
{
	int stat, f_num, len;
	FILE *fp;
	long start;
	char gth_buf[FINFO_SIZE];
	struct finfo *finfo;
	struct FARDIR {
		char  f_name[10];
		uchar f_time[4];
		uchar f_size[4];
		uchar f_pos[4];
	}
	fardir;
	char *p, *q;

	*ptr_sp = '\0';
	finfo = (struct finfo *)gth_buf;
	if ((fp = fopenf(fname, "rb")) == NULL)
		goto non_exist1;
	p = ptr_sp + 1;
	q = strchr(p, '.');
	if ((len = q ? q - p : strlen(p)) > 8) 
		strcpy(p + 8, p + len);
	fread(gth_buf, FINFO_SIZE, 1, fp);
	if (strcmp(gth_buf + 8, "gather") == 0)
		goto exist;
	fseek(fp, -8L, SEEK_END);
	f_num = read_short(fp);
	start = read_long(fp);
	if (read_short(fp) != (int)('f' + 'o' + 'n' + 't' + 'a' + 'r' + 'c' + 'h' + 'i' + 'v' + 'e'))
		goto non_exist;

	fseek(fp, start, SEEK_SET);
	strlwr(p);
	while (f_num-- > 0) {
		fread((char *)(&fardir), sizeof(fardir), 1, fp);
		if ((stat = strcmp(fardir.f_name, p)) == 0) {
			fsize = long_int(fardir.f_size);
			fpos = long_int(fardir.f_pos);
			goto accend;
		}
		if (stat > 0)
			break;
	}
	goto non_exist;

exist:
	strupr(p);

	start = long_int((uchar *)gth_buf);
	f_num = ((uchar *)gth_buf)[4] + (((int)((uchar *)gth_buf)[5]) << 8);

	fseek(fp, start, SEEK_SET);
	while (f_num-- > 0) {
		fread(gth_buf, FINFO_SIZE, 1, fp);
		if ((stat = strcmp(finfo->f_name, p)) == 0) {
			fsize = long_int(finfo->f_size);
			fpos = long_int(finfo->f_pos);
			strlwr(p);
accend:		fclose(fp);
			return (NOTHING);
		}
		if (stat > 0)
			break;
	}
non_exist:
	fclose(fp);
non_exist1:
	*ptr_sp = CHAR_SP;
	return (FAILURE);
}

#ifdef	FLI
static char 
*accfli(char *fname, char *ptr_sp, char *ast, int reso, char *fontlib)
{
	char fnbuf[128];
	char *p, *q, *s;
	struct FNT *fnt;
	extern struct FNT *search_fli(char *, char *, int);

	*ptr_sp = '\0';
	strcpy(fnbuf, fname);
	s = fnbuf + (ast - fname);
	ast++;
	for (p = fontlib; *p;) {
		q = strchr(p, DELIMITER);
		if (q) *q++ = '\0';
		strcpy(s, p);
		strcat(s, ast);
		p = q;
		if ((fnt = search_fli(fnbuf, ptr_sp + 1, reso)) != NULL) {
			return str_fnt_nm(fnbuf, ptr_sp, fnt -> fontpos, fnt -> fontlen);
		}
	}
	*ptr_sp = CHAR_SP;
	return NULL;
}
#endif	/* FLI */

BOOL copy_token(char *dst, char **src_ptr, int delim)
{
	char *src;

	src = *src_ptr;

	while (*src != '\0' && *src != delim)
		*dst++ = *src++;

	*src_ptr = src + 1;
	*dst = '\0';

	return (*src != '\0');
}

/* static int token_last( char* token ) */
/* 文字列の最後の文字
	 */
/*
{
	if ( ! *token )
		return( '\0' );

	while( *++token )
		;

	return( *(token - 1) );
}
*/

static void strdel(char *line, int num)
{
	int len;

	len = strlen(line);
	if (len < num)
		return;

	memmove(line, line + num, len + 1);
	/* don't forget delimiter '\0'... */
}

static void strins(char *line, char *token)
{
	int len, token_len;

	len = strlen(line);
	token_len = strlen(token);
	memmove(line + token_len, line, len + 1);
	memcpy(line, token, token_len);
}

#define FLG_LEN         2
#define FLG_HEAD        '%'
#define	FLG_HEAD2		'^'
#define NAME_FLG        's'
#define FIG_FLG         'd'
#define FIGL_FLG        'l'
#define	GTH_FLG			'g'
#define	PATH_FLG		'r'
#define FLG_TFM			't'
#ifdef	FLI
#define	FLI_FLG			'f'
#endif	/* FLI */

static BOOL fill_name_and_fig(char *buf, char *fname, char *fig, char *figl)
{
	char *tmp;
	int len, name_len, fig_len, figl_len, root_len;
	BOOL f_num = FALSE;

	f_tfm2ttf = 0;
	len = strlen(buf);
	name_len = strlen(fname);
	fig_len = strlen(fig);
	figl_len = strlen(figl);

	for (tmp = buf; *tmp;) {
		if ((*tmp == FLG_HEAD || *tmp == FLG_HEAD2)
#if	defined(USE_WINAPI)||defined(UNIX)
		 && tmp[1] != 'x' 
		 && tmp[1] != 'T' 
# ifdef	USE_WINAPI
		 && tmp[1] != 'w'
# endif
# ifdef	DVI_ADD
		 && tmp[1] != 'F'
# endif
#endif
		 ) {
			if (tmp[1] == NAME_FLG) {
				len = len - FLG_LEN + name_len;
				if (len >= TMP_BUF_SIZE){
p_over:				error(ILLEGAL_ARGS, "Path name buffer is out of range");
					return FALSE;
				}
				strdel(tmp, FLG_LEN);
				strins(tmp, fname);
				tmp += name_len;
			}
			else if (tmp[1] == FIG_FLG) {
				f_num = TRUE;
				len = len - FLG_LEN + fig_len;
				if (len >= TMP_BUF_SIZE)
					goto p_over;
				strdel(tmp, FLG_LEN);
				strins(tmp, fig);
				tmp += fig_len;
			}
			else if (tmp[1] == FIGL_FLG) {
				f_num = TRUE;
				len = len - FLG_LEN + figl_len;
				if (len >= TMP_BUF_SIZE)
					goto p_over;
				strdel(tmp, FLG_LEN);
				strins(tmp, figl);
				tmp += figl_len;
			}
			else if (tmp[1] == PATH_FLG){
				root_len = (root_search_path == NULL)?
					0:strlen(root_search_path);
				len = len - FLG_LEN + root_len;
				strdel(tmp, FLG_LEN);
				if(root_len){
					strins(tmp, root_search_path);
					tmp += root_len;
				}
			}
			else if (tmp[1] == GTH_FLG) {
				len--;
				strdel(tmp, FLG_LEN);
				if (strchr(buf, '.') == NULL
					|| strchr(buf, '.') > tmp - 1) {
					strins(tmp, ".gth" STR_SP );
					tmp += 4;
				}
				else {
					strins(tmp, STR_SP);
				}
			}
#ifdef	FLI
			else if (tmp[1] == FLI_FLG) {
				len--;
				strdel(tmp, FLG_LEN);
				strins(tmp, "*");
			}
#endif	/* FLI */
			else if (tmp[1] == tmp[0]) {
				len--;
				strdel(tmp, 1);
				tmp++;
			}
			else if (tmp[1] == FLG_TFM){
				f_tfm2ttf = TRUE;
				*tmp = '.';
			}
			else{
				error(ILLEGAL_ARGS, "%%%c or ^%c in TEXPK or TEXKNJ", 
					tmp[1], tmp[1]);
				return FALSE;
			}
		}
		else
			tmp++;
	}
	SetPath(buf, buf);
	return (f_num);
}

/* NTTjTeX -> アスキー日本語TeX font 変換 */
#ifndef NO_NTTRPL
static int get_fname_off(char *name)
{
	int i;
	if (name == NULL) return 0;
	if (*name == '*')
		for(i=9;name[i]!=CHAR_SP;++i) {
			if (name[i]=='\0') break;
		}
	else {
		for(i=strlen(name)-1;i>=0;--i)
			if (name[i]==PATH_SEP) break;
	}
	return ++i;
}

static char *ntt_sub(char *name, FONT_INFO *font, uint *fig, uint *figl)
{
#if 1
	struct NTT_TBL {
		char type[2];
		int off;
	};
#	define	SIZE_NTT_TBL	7

	static struct NTT_TBL ntt_tbl[] = {
		{{'r','a'}, 0x2420},
		{{'t','a'}, 0x2520},
		{{'m','a'}, 0x2300},
		{{'s','y'}, 0x2120},
		{{'e','k'}, 0x2620},
		{{'a','n'}, 0x2720},
		{{'e','n'}, 0x2820},
	};
#endif
	char *pt;
	int i;
/*
	static char s[MAX_NAME_LEN], old[MAX_NAME_LEN], new[MAX_NAME_LEN];
*/
#	define	s	(tmp_buf + TMP_S)
#	define	old	(tmp_buf + TMP_OLD)
#	define	new	(tmp_buf + TMP_NEW)

	s[0] = 0;
	if ((*name == 'd' && *(name + 2) == 'j') || *(name + 1) == 'j') {
		if (*(name + 1) == 'm' || *name == 'm')
			strcpy(s, "min");
		else if (*(name + 1) == 'g' || *name == 'b')
			strcpy(s, "goth");
	}
	if (ntt_subst_fonts != NULL) {
		pt = ntt_subst_fonts;
		do {
			pt = next_top((char *)new, pt);
			pt = next_top((char *)old, pt);
			for (i = 0; old[i] == name[i]; ++i);
			if (old[i] == 0 && name[i] == 'j') {
				strcpy(s, new);
				break;
			}
		} while (*pt != 0);
	}
	if (s[0] != 0) {
		pt = name + strlen(name) - 1;
		if (*pt >= '0' && *pt <= '9') {
			if (*(pt - 1) >= '0' && *(pt - 1) <= '9')
				--pt;
			strcat(s, pt);
			font->pt_size = atoi(pt) - 6;
			if (font->pt_size == 6) {
				*fig += *fig/5;
				*figl += *figl/5;
				*(s+strlen(s)-1) = '0';
			}
			else if (font->pt_size == 11)
				font->pt_size = 7;
			else if (font->pt_size == 14)
				font->pt_size = 8;
			else if (font->pt_size < 0 || font->pt_size > 6)
				font->pt_size = 4;
			--pt;
		}
		else {
			font->pt_size = 4;
			strcat(s,"10");
		}
		--pt;
		if (*pt == 'k'){
			font->code_offset = ((*(pt + 1) - 'a') << 8);
			return (char *)s;
		}
		for (i = 0; i < SIZE_NTT_TBL; i++){
			if (ntt_tbl[i].type[0] == pt[0]
			  && ntt_tbl[i].type[1] == pt[1]){
				font->code_offset = ntt_tbl[i].off;
				return (char *)s;
			}
		}
	}
	return name;
}

#endif
#ifndef NO_GENFONT
void CutLast(char *src)
{
	int len;

	if(	  src != NULL
	  && (len = strlen(src)) > 0
	  &&  src[len-1] <= 0x20 )
	src[len-1] = 0;
}


char *GetCommandResult(char *cmd, int mode)
{
	char path[MAX_PATH], buf[0x1000];
	char *argv[5];
	FILE *fp;

	argv[0] = (f_osversion<0)?"command.com":"cmd.exe";
	argv[1] = "/c";
	argv[2] = cmd;
	strcpy(path, ">\"");
	SetPath(path+2, "^?\\$.txt");
	strcat(path, "\"");
	argv[3] = path;
	argv[4] = NULL;
	path[strlen(path)-1] = 0;
	if(!WinMinExecute(argv, 0, TRUE) || (fp = fopenf(path+2,"r")) == NULL)
		return NULL;
	buf[0x0fff] = buf[0] = 0;
	if(mode)
		fread(buf, 1, 0x0fff, fp);
	else
		fgets(buf, 0x0fff, fp);
	fclose(fp);
	unlink(path+2);
	if(!*buf)
		return NULL;
	return dup_string(buf);
}

char *genfont_main(char *name, ulong atrd, ulong atrs,
				  uint fig, uint figl, uint dpi)
{
	char *path_name;
	int i, ch;
	FILE *gentmpfp;

	if (root_tmpl[0] == NULL)
		genfont_init();
	if (!genflag) return (NULL);
	/* make and run gen_tmp.bat */
	if ((gentmpfp = fopen(gentmp,"w"))==NULL)
		error(PROGRAM_STOP, 
			"Can't make tmp-batch file: %s\n"
			"Check environment variables TMP and TEMP", 
			gentmp);
	genfont_out(gentmpfp, 0);
	genfont_proc(gentmpfp, name, atrd, atrs);
	genfont_out(gentmpfp, 2);
	fclose(gentmpfp);
	f_sub_font = 0;
#ifdef	USE_WINAPI
	{
		char *argv[4];
		char msg[512];
		char cmd[512];

#ifdef	WIN32G
		sprintf(msg, "Creating font: %s %d/%ddpi", name, fig, dpi);
		DisplayMessage(msg);
#else
		fprintf(stderr, "Creating font: %s %d/%ddpi", name, fig, dpi);
#endif
		if(*genfont_tmpl == '`' || *genfont_tmpl == '!'){
			for(i=0; i < 254; i++){
				if((msg[i] = genfont_tmpl[i+1]) <= 0x20){
					i++;
					break;
				}
			}
			msg[i] = 0;
			gentmpfp = fopen(gentmp, "r");
			for(i = 0; i < 510; i++){
				if((ch = fgetc(gentmpfp)) < ' ' || ch == EOF)
					break;
				cmd[i] = ch;
			}
			fclose(gentmpfp);
			cmd[i] = 0;
			argv[0] = &cmd[0];
			argv[1] = NULL;
			if(  access(msg, READ_MODE) != FAILURE
			  && WinMinExecute(argv,0,(*genfont_tmpl=='`')) ) goto chk;
			argv[0] = (f_osversion<0)?"command.com":"cmd.exe";
			argv[1] = "/c";
			argv[2] = &cmd[0];
			argv[3] = NULL;
			if(WinMinExecute(argv, 0, (*genfont_tmpl=='`'))) goto chk;	
		}
		argv[0] = (f_osversion<0)?"command.com":"cmd.exe";
		argv[1] = "/c";
		argv[2] = gentmp;
		argv[3] = NULL;
		strcpy(msg, gentmp);
		i = strlen(msg) - 3;
		if(i >= 0){
			strcpy(msg + i, "pif");
			if(access(msg, READ_MODE) != FAILURE)
				remove(msg);
		}
		if(WinMinExecute(argv, 0,TRUE)) goto chk;
	}
#endif
	if (!system(gentmp)){
chk:	for(i = 2; i > 0; i--){
			if((path_name = font_name_check(name, fig, figl)) != NULL
			  || f_checkerror)
				break;
#ifdef	USE_WINAPI
			sleep0(500);
#else
			sleep(1);
#endif
		}
	}
#ifdef	WIN32G
	DisplayMessage(NULL);
#endif
	if (i > 0) return (path_name);
	return (NULL);
}

/* read and store the template file for auto-font-generation */
static void genfont_init(void)
{
	FILE *tmpl;
	struct gen_tmpl *cur_tmpl[3];
	int i, part, tmp_dpi, len;
	char tmp_path[MAXPATH];

	if (*genfont_tmpl != '`' && (tmpl=fopenf(genfont_tmpl, "r")) == NULL)
		error(PROGRAM_STOP, "Can't open template file:%s", genfont_tmpl);
	for(part=0; part<3;++part) {
		cur_tmpl[part] = root_tmpl[part]
			= (struct gen_tmpl *)marea(sizeof(struct gen_tmpl));
		cur_tmpl[part]->next = NULL;
	}
	Free0(gentmp);
	if(!SetPath(tmp_path, "^?"))
		*tmp_path = 0;
	len = strlen( tmp_path );
	if( len > 0 && tmp_path[len-1] != PATH_SEP ){
		tmp_path[len] = PATH_SEP;
		tmp_path[len+1] = 0;
	}
	strcat(tmp_path, "GEN_TMP.BAT");
	gentmp = dup_string(tmp_path);
	Free0(genfnt);
	genfnt = dup_string("GEN_FONT.BAT");
	genflag = TRUE;
	extra_size = 0;

	if(*genfont_tmpl == '`'){
		cur_tmpl[1]->line = dup_string(genfont_tmpl+1);
		cur_tmpl[1]->next = (struct gen_tmpl *)marea(sizeof(struct gen_tmpl));
		cur_tmpl[1] = cur_tmpl[1]->next;
		cur_tmpl[1]->next = NULL;
		return;
	}

	part = -1;
	while(fgets(tmp_buf, 1024, tmpl) != NULL) {
		if (*tmp_buf != '#' || *(tmp_buf+1) == '!') {
			if (strncmp(tmp_buf, "%1st", 4) == 0) part = 0;
			else if (strncmp(tmp_buf, "%2nd", 4) == 0) part = 1;
			else if (strncmp(tmp_buf, "%3rd", 4) == 0) part = 2;
			else if (part < 0) {
					if (strncmp(tmp_buf, "mode_name=", 10) == 0) {
						for( i=10; tmp_buf[i]>='0' && tmp_buf[i]<='9'; ++i) ;
						if (tmp_buf[i]==':') {
							tmp_buf[i] = NULL;
							if ((tmp_dpi=atoi(&tmp_buf[10])) == dpis) {
								Free0(genmode);
								genmode = dup_string((char *)&tmp_buf[i+1]);
								CutLast(genmode);
							}
							if (tmp_dpi == extra_size) {
								Free0(extramode);
								extramode = dup_string((char *)&tmp_buf[i+1]);
								CutLast(extramode);
							}
						}
						else error(PROGRAM_STOP, "Illegal mode in template:%s",
							genfont_tmpl);
					}
					else if (strncmp(tmp_buf, "extra_size=", 11) == 0) {
						extra_size = atoi(&tmp_buf[11]);
					}
					else if (strncmp(tmp_buf, "auto=", 5) == 0) {
						if (tmp_buf[5] == 'n' || tmp_buf[5] == 'N')
							genflag = FALSE;
					}
					else if (strncmp(tmp_buf, "gen_tmp=", 8) == 0) {
						Free(gentmp);
						gentmp = dup_string((char *)&tmp_buf[8]);
						CutLast(gentmp);
					}
					else if (strncmp(tmp_buf, "gen_font=", 9) == 0) {
						Free(genfnt);
						genfnt = dup_string((char *)&tmp_buf[9]);
						CutLast(genfnt);
					}
					else error(PROGRAM_STOP, "Illegal statement in template:%s",
						genfont_tmpl);
				}
			else {
					cur_tmpl[part]->line = dup_string((char *)tmp_buf);
					cur_tmpl[part]->next = (struct gen_tmpl *)marea(sizeof(struct gen_tmpl));
					cur_tmpl[part] = cur_tmpl[part]->next;
					cur_tmpl[part]->next = NULL;
			}
		}
	}
	fclose(tmpl);
}

/* write statements to the batch file */
static void genfont_out(FILE *fp, int part)
{
	struct gen_tmpl *cur_tmpl;
	for(cur_tmpl=root_tmpl[part];cur_tmpl->next!=NULL;cur_tmpl=cur_tmpl->next)
		fputs(cur_tmpl->line, fp);
}

/* replace ^? and write statements to the batch file */
static void genfont_proc(FILE *fp, char *name, long atrd, long atrs)
{
	char *ss;
	struct gen_tmpl *cur_tmpl;
	float magsize;
	int fdpi, extra_fdpi, tmp;
#ifdef INTEGER_CALC
	long scmag;
	magsize = (float)((long)((float)atrs/atrd*mags*100. + 0.5)) * 1.e-5;
	scmag = ftolong(magsize);
	fdpi = (int)quotient(quotient(scmag*dpis,4736286L), 59429463L);
	extra_fdpi = (int)quotient(quotient(scmag*extra_size,4736286L), 59429463L);
#else
	magsize = (float)((long)((float)atrs/atrd*mags*100. + 0.5)) * 1.e-5;
	fdpi = (int)(magsize*dpis + 0.5);
	extra_fdpi = (int)(magsize*extra_size + 0.5);
#endif
	for(cur_tmpl=root_tmpl[1]; cur_tmpl->next!=NULL; cur_tmpl=cur_tmpl->next) {
		for(ss = cur_tmpl->line; *ss; ++ss)
			if (*ss == '^')
				switch(*(++ss)) {
					case 's':
						fprintf(fp, "%s", name);
						break;
					case 'm':
						fprintf(fp, "%.5f", magsize);
						break;
					case 'M':
						if(fdpi > dpis){
							tmp = fdpi/dpis;
							fprintf(fp, "%d+%d/%d", tmp, fdpi - tmp*dpis, dpis);
						}else
							fprintf(fp, "%d/%d", fdpi, dpis);
						break;
					case 'd':
						fprintf(fp, "%d", fdpi);
						break;
					case 'D':
						fprintf(fp, "%d", dpis);
						break;
					case 'e':
						fprintf(fp, "%d", extra_fdpi);
						break;
					case 'n':
						if(genmode==NULL)
							error(WARNING, "mode_name is undefined!");
						else
							fprintf(fp, "%s", genmode);
						break;
					case 'N':
						fprintf(fp, "%s", extramode);
						break;
					case '^':
						fputc('^', fp);
						break;
			} else fputc(*ss, fp);
	}
}

static void free_tmpl(void)
{
	struct gen_tmpl *c_tmpl, *cc_tmpl;
	int i;
	for(i=0;i<3;++i)
		for(c_tmpl=root_tmpl[i];c_tmpl->next!=NULL;) {
			cc_tmpl = c_tmpl->next;
			Free(c_tmpl->line);
			Free(c_tmpl);
			c_tmpl = cc_tmpl;
		}
	root_tmpl[0] = root_tmpl[1] = root_tmpl[2] = NULL;
}

#ifdef INTEGER_CALC
static long ftolong(float x)
{
	int dig[KETA];
	int i;
	float xtmp = x;
	long a = 0;
	xtmp -= (float)((int)xtmp);
	for(i=0;i<KETA;++i) {
		xtmp *= 10.;
		dig[i] = (int)xtmp;
		xtmp -= (float)dig[i];
	}
	i = KETA;
	while(i > 0) /* round_decimal */
		a = (a + dig[--i] * 131072L) / 10;
	return ((long)x * 65536L + ((a + 1)>>1));
}

static long quotient(long p , long q) /*make_scaled [2^16*p/q+0.5]*/
{
	long r = p;
	long f;
	long n;
	long becareful;
	n = r / q;
	r %= q;
	n = (n - 1) * 65536L;
	f = 1;
	while (!(f >= 65536L)) {
		becareful = r - q;
		r += becareful;
		if (r >= 0)
			f += f + 1;
		else {
			f += f;
			r += q;
		}
	}
	becareful = r - q;
	if (becareful + r >= 0)
		++f;
	return(n + f);
}
#endif /* end of INTEGER_CALC */
#endif
/* end of file : fontdef.c */
