
/*
 *  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>
#define _DEF_STDIO_H_
#include <string.h>
#include <fcntl.h>
#include <dir.h>
#define _DEF_STRING_H_
#include "dd.h"
#include "err.h"
#include "dviread.h"
#include "vfont.h"

#ifdef	FLI
#include "flifont.h"
static char 
*accfli(char *fname, char *ptr_sp, char *ast, int reso, char *fontlib);
#endif	/* FLI */

#define READ_MODE   	0x04
#define	MAX_NAME_LEN	25
#define	MAX_SUB_LEN     15

					/* size of path name buffer tmp_buf[TMP_BUF_SIZE] */
#define TMP_BUF_SIZE    1500

#ifdef	HIRES98
extern int hireso;
static int rom_f_size;
#define	ROM_F_SIZE		rom_f_size
#else
#define	ROM_F_SIZE		16
#endif

#define DELIMITER   ';'
/* pathの区切り */

extern char *pk_env_name;

/* 環境変数名 */
char *pk_search_path = NULL;

/* 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

extern int test_flg;

char *k_16="";
BOOL f_long_name;
char *goth = "goth";
char *sub_font;
int f_search;
static int f_loop;
static int f_sub_font;
int f_use_vfont = FALSE;

#ifdef	LBP
int f_use_lfont = FALSE;

#endif

extern char ptex_mode;
int romfont_max = -1;	/* ROM FONT の拡大／縮小使用を許可するか */
int romfont_min;
BOOL f_resize;

struct FONT_ATR {
	/* font_defのパラメーター ; See "TeX:The program". */
	long k, c, s, d;
	int a, l;
	char *n;
};

struct finfo {
	char f_atrib;
	unsigned int f_time;
	unsigned int f_date;
	long f_size;
	char f_name[14];
	long f_pos;
};

#define	FINFO_SIZE	sizeof(struct finfo)

static int dpis, mags;

/* static double dpi, true_mag; */
/* dpi, mag */

/* standard library */
char *getenv(const char *);
int access(char *, int);

/* buffer.c */
char *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*);

char *k_dbl = "";
extern FONT_INFO *font_info_root;

static void font_define(int, FILE *);
static void make_font(struct FONT_ATR *);
static char *font_name_check(char *, uint, uint);

#define	store_font_name(x)	dup_string(x)
static char *str_fnt_nm(char *, char *, long, long);
static 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 *);
int accgth(char *fname, char *ptr_sp);
char *get_fontname(FONT_INFO *);

				/* devide tmp_buf */
#define	TMP_S			1800
#define	TMP_OLD			1830
#define	TMP_NEW			1860

#define	TMP_O_FONT		1900
#define	TMP_S_FONT		1920
#define	TMP_O_FIG		1940
#define	TMP_S_FIG		1960

#define	TMP_FONT_NAME	1980

/*
static char o_font[MAX_SUB_LEN];
static char s_font[MAX_SUB_LEN];
static char o_fig[MAX_SUB_LEN];
static char s_fig[MAX_SUB_LEN];
*/

#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)


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 char *ntt_sub(char *, FONT_INFO *, uint *, uint *);

#endif

void use_romfont(char *pt)
{
	if(sscanf(pt, "%d:%d", &romfont_max, &romfont_min) < 2 )
		romfont_max = atoi(pt);
}

char *to_font_name(char *name)
{
	if (*name == '*'){
		if(strchr(name += 9, ' ') == NULL)
			name[strlen(name)] = ' ';
	}
	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");

#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
			  "Set environment variable %s\n"
#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);

	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 */

#ifdef	HIRES98
	if (hireso) ROM_F_SIZE = 24;
	else        ROM_F_SIZE = 16;
#endif
	count = 0;
	strlwr(goth);
	while ((code = getc(dvi->file_ptr)) != POST_POST)
		if (code >= FNT_DEF_1 && code < FNT_DEF_1 + 4) {
			font_define(code, dvi->file_ptr);
			count++;
		}
		else if (code != NOP)
			error(COMMAND_ERROR, "code:%d", code);
#ifdef	FLI
	free_fli();
#endif	/* FLI */
	font_sort(count);
	END();
}

static void font_sort(int total)
{
	int i, j;

	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");

	}

	for (i = 1; i < total;) {
		j = i;
		while (i-- > 0 && font_adr[i]->font_code > font_adr[i + 1]->font_code) {
			font = font_adr[i];
			font_adr[i] = font_adr[i + 1];
			font_adr[i + 1] = font;
		}
		i = j + 1;
	}

	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 void font_define(int code, FILE * dvifile)
{
	int i, len, lenm;
	struct FONT_ATR font;
	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");

	tmp = read_str(dvifile, font.a + font.l);
	len = strlen(tmp);
	i = len;
	lenm = 8;
	while (--i >= 0) {
		if (tmp[i] == '.')
			lenm = 13;
		if (tmp[i] == ':' || tmp[i] == '\\')
			break;
	}
	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 - 5);
	if (len - i > lenm && f_long_name && i + lenm < MAX_NAME_LEN) {
		strcpy(tmp_name + i + 4, tmp + i + len - lenm + 4);
	}
	free(tmp);
	make_font(&font);

	END();
}

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);
		}
	}
}

static void make_font(struct FONT_ATR *atr)
	/* フォント表を作る
     */
{
	FONT_INFO *font;
	char *name, *path_name, *ptr;
	int i;
	uint fig, figl, fmags;
	ulong atr_s, atr_d, atr_t;
	static char null_name[1] =
	{0};
#ifndef NO_NTTRPL
	FONT_INFO *ifont;
#endif

	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)
				error(PROGRAM_STOP, "Twice fnt_def");
		/* ２度定義しているか？
                     */

		/* 空いているなら */
		font = font->next_font = font_info_alloc();
	}

	font->font_code = (int)atr->k;
	/* フォント番号をセット
         */

	atr_t = (ulong)dpis *(ulong)mags;

	if (atr->s == atr->d) {
		atr_s = atr_t;
		atr_d = 100;
		i = 1;
	}
	else {
		atr_s = atr->s;
		atr_d = atr->d;
		while (atr_d > 6000L) {
			atr_s >>= 1;
			atr_d >>= 1;
		}
		fig = (uint)((atr_s * 1000 + (atr_d >> 1)) / atr_d);
		if (atr_d > 2000L) atr_s /= 4;
		else atr_d *= 4;
		atr_s *= atr_t / 25L;
		i = 2;
	}
	for (fmags = mags; i > 0; i--) {
		if (fmags == 1095)
			atr_s += atr_s / 2460;	/* 1095.4451... */
		else if (fmags == 2074)
			atr_s -= atr_s / 5183;	/* 2073.6		*/
		else if (fmags == 2488)
			atr_s += atr_s / 7775;	/* 2488.32		*/
		fmags = fig;
	}
	/*
	 *	解像度の算出、atr_s の値は fig*atr_d*100
	 *	3000L < atr->d <=  6000L
	 *	dpi < 60000 ( => dpi*100 < 6000000L => dpi*atr_d*10 < 2^(32) )
	 *	dpis =  100, mags = 1000 -> dpis*mags/25 =  10000L
	 *	dpis = 4000, mags = 1000 -> dpis*mags/25 = 400000L
	 */
	fig = (uint)((atr_d * 5 + atr_s) / (atr_d * 10));
	figl = (uint)((atr_d + atr_s) / (atr_d * 2));
	name = atr->n;
#ifndef NO_NTTRPL
	if (ntt_subst)
		name = ntt_sub(name, font, &fig, &figl);
#endif
  again:
	if ((path_name = font_name_check(name, fig, figl)) != NULL)
		goto exist;
	if (sub_font != NULL) {
		f_sub_font++;
		ptr = sub_font;
		do {
			ptr = next_top(&(s_font[0]), ptr);
			ptr = next_top(&(s_fig[0]), ptr);
			ptr = next_top(&(o_font[0]), ptr);
			ptr = next_top(&(o_fig[0]), ptr);
			if ((path_name = font_name_check(name, fig, figl)) != NULL) {
				f_sub_font = 0;
				goto exist;
			}
		} while (*ptr != 0);
	}
	if (f_sub_font < 2) {
		printf("\n%s.%03u(%03u):\n", name, fig, figl);
		f_sub_font = 2;
		goto again;
	}
	if (test_flg != 0)
		error(NO_FONT, "Any of the above.");
	test_flg = f_sub_font = 0;
	path_name = null_name;
  exist:
	font->name = path_name;
	if (test_flg == 0) {
		printf("%3d%9s.%03u(%4u): %s\n", font->font_code, name, fig, figl,
			   get_font_name(font));
	}
	font->size_para = atr->s;
	font->c = atr->c;
	font->font_type = UNKNOWN;
	font->f_goth = 0;
	font->next_font = font->before_font = font->after_font = NULL;
	font->pk = font->ext.dir = NULL;
	for (i = 0; i < CHAR_ROOT + 2; i++)
		font->char_info[i] = NULL;
#ifndef NO_NTTRPL
	if (ntt_subst && (font->code_offset >= 0)) {
		font->family_code = font->font_code;
		for (ifont = first_font_info; ifont != font; ifont = ifont->next_font)
			if (!strcmp(ifont->name,font->name)
					&& ifont->size_para == font->size_para) {
				font->family_code = ifont->family_code;
				break;
			}
	}
#endif
	END();
}

int chk_goth(FONT_INFO *font)
{
	int offset;

	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;
	}
	if (strstr(font->name + offset, goth) == NULL)
		RETURN(0);
	RETURN(1);
}

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 = '*';
	*((long *)(ptr1 + 1)) = pos;
	*((long *)(ptr1 + 5)) = size;
	strcpy(ptr1 + 9, name);
	strcpy(ptr1 + 10 + len, ptr_sp + 1);
	RETURN(ptr);
}

#define FIG_COLUMN      8

static 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;

	char fig_str[FIG_COLUMN], figl_str[FIG_COLUMN];
	char *tmp;
#ifdef	FLI
	char *flib;
#endif	/* FLI */

	ENTER("font_name_check");

	if((path0 = getenv(pk_env_name)) == NULL)
		path0 = pk_search_path;

	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++;
			tmp = tmp_buf;
			path = path0;
			token_exist = copy_token(&tmp, &path, DELIMITER);
			if(!*tmp_buf) continue;
			*tmp = '\0';
			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(tmp_buf,
											 (*s_font != 0) ? s_font : name,
											(*s_fig != 0) ? s_fig : fig_str,
										  (*s_fig != 0) ? s_fig : figl_str);
			}
			else
				number_exist =
					fill_name_and_fig(tmp_buf, name, fig_str, figl_str);
			if (f_sub_font >= 2) {
				printf("Searched %s\n", tmp_buf);
				goto loop;
			}
			if ((ptr_sp = strchr(tmp_buf, ' ')) == NULL) {
				if (access(tmp_buf, READ_MODE) != FAILURE)
					RETURN(store_font_name(tmp_buf));
			}
			else {
#ifdef	FLI
				if (fli_search_path && (tmp = strchr(tmp_buf, '*')) != NULL) {
					flib = strdup(fli_search_path);
					tmp = accfli(tmp_buf, ptr_sp, tmp, figl, flib);
					free(flib);
					if (tmp) return tmp;
				} else
#endif	/* FLI */
				if (accgth(tmp_buf, ptr_sp) != FAILURE)
					RETURN(str_fnt_nm(tmp_buf, ptr_sp, fpos, fsize));
			}
		  loop:if (!number_exist)
				break;
		}
		path0 = path;
	} while (token_exist);
	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;
/*
	static char font_name[10];
 */
#define	font_name	(tmp_buf+TMP_FONT_NAME)

	ENTER("get_fontname");

	if (*(tmp = fontc->name) == '*')
		tmp += strlen(tmp + 9) + 10;
	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) < 9) {
			for (ch = 0; ch <= widthm; ch++)
				font_name[ch] = tmp[width0 + ch];
			font_name[ch] = 0;
		}
	}
	RETURN(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 *tmp, *path, *path0, *pt;
	int ch, 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;
	int width_tmp;

	ENTER("open_kfont");

	dif = loop = f_dbl = 0;
	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;
	if (maxwidth >= ROM_F_SIZE){
		sprintf(fig_str, "%d", ROM_F_SIZE);
		width0 = (strstr(k_16, fig_str) == NULL) ? ROM_F_SIZE : ROM_F_SIZE - 1;
	}
	else
		width0 = 0;

#ifndef	NOVFONT
	if (f_use_vfont) {
		kf = get_vfont_list(fontc, name);
		if (kf != NULL)
			RETURN(kf);
	}
#endif

#ifdef	LBP
	if (f_use_lfont) {
		kf = get_lbp_font(fontc, jfm);
		if (kf != NULL)
			RETURN(kf);
	}
#endif

	/* 要求された大きさが romfont_min romfont_max の範囲に有り、
	 * -k により pk 使用が指定されていない場合には、ROM FONT を拡大／縮小
	 * して使用する。適当な pk を探し、見つからなければやはり ROM FONT を
	 * 使用する。
	 * -romf 無しでは romfont_min == -1 となる。
	 */
	width_tmp = *wdthp;
	if (width_tmp <= romfont_max && width_tmp >= romfont_min){
		sprintf(fig_str, "%d", width_tmp);
		if ((pt = strstr(k_16, fig_str)) == NULL
		|| *(pt - 1) != DELIMITER
		|| *(pt + strlen(fig_str)) != DELIMITER){
			fontc->f_goth |= K_SCALE2;
			goto rom_font;
		}
	}

  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 {
				tmp = tmp_buf;
				path = path0;
				token_exist = copy_token(&tmp, &path, DELIMITER);
				if(!*tmp_buf) continue;
				*tmp = '\0';
				fill_name_and_fig(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(tmp_buf, O_RDONLY | O_BINARY)) != -1)
					goto exit;
				path0 = path;
			} while (token_exist);
		}
		if (f_dbl == 0) {
			if (!(width & 1)
				&& (pt = strstr(k_dbl, fig_str)) != NULL
				&& *(pt - 1) == DELIMITER
				&& *(pt + strlen(fig_str)) == DELIMITER) {
				f_dbl = K_DBL;
				if (width == 2 * ROM_F_SIZE && k_16 == "") {
rom_dbl:			if (!f_resize) fontc->f_goth |= K_DBL;
					goto rom_font;
				}
				widthm = width / 2;
				goto repdbl;
			}
		}
		else {
			if (width == 2 * ROM_F_SIZE)
				goto rom_dbl;
		}
next:	if (!loop)
			dif = (dif < dir) ? 1 - dif : -dif - 1;
	}
	if (loop++ == 0 && *wdthp < ROM_F_SIZE) {
		width = *wdthp + 1;
		dif = 1;
		maxwidth = width0 = (k_16 == "") ? ROM_F_SIZE : ROM_F_SIZE + 1;
		goto rep;
	}
rom_font:					/* use ROM FONT */
	width = width_tmp;
	/* width = fontc->k_width; 要求されたフォントの大きさ
       * -romf=xx の xx が ROM_F_SIZE より大きければxxを修正
       */
	if ((width > romfont_max || width < romfont_min) && !f_resize)
		width = ROM_F_SIZE;
	fontc->font_type = ROM_FONT;
	if (fontc->k_top == NULL) {
		for (font = first_font_info; font != NULL; font = font->next_font) {
			if (font->font_type == ROM_FONT
				&& (font->f_goth & K_DBL) == f_dbl
				&& font->ext.kdir != NULL
				&& font->ext.kdir->width == width
				&& !f_resize
				&& !(font->f_goth & K_SCALE2)
				) {
				for (fontk = font; fontk->k_next; fontk = fontk->k_next);
				fontk->k_next = fontc;
				fontc->k_top = fontk->k_top;
				RETURN(dup_kf(fontk->ext.kdir));
			}
		}
		fontc->k_top = fontc;
	}
	/* kfont構造体を新たに確保 */
	kf = (KFONT *)marea(KFONT_SIZE);
	kf->name = (char *)NULL;	/*漢字フォントファイル名無し*/
	fh = NULL;					/*ファイルハンドル無し*/
	goto exit1;

exit:						/* define Kanji Font file */
	kf = (KFONT *)marea(KFONT_SIZE);
	kf->name = (char *)dup_string(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;
exit1:
	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);
}

int accgth(char *fname, char *ptr_sp)
{
	int stat, f_num;
	FILE *fp;
	long start;
	char gth_buf[FINFO_SIZE];
	struct finfo *finfo;
	struct FARDIR {
		char f_name[10];
		long f_time;
		long f_size;
		long f_pos;
	}
	fardir;
	char *p;
#ifdef	FLI
	char *q;
	int len;
#endif	/* FLI */

	*ptr_sp = '\0';
	finfo = (struct finfo *)gth_buf;
	if ((fp = fopen(fname, "rb")) == NULL) {
		goto non_exist1;
	}
	p = ptr_sp + 1;
#ifdef	FLI
	q = strchr(p, '.');
	if ((len = q ? q - p : strlen(p)) > 8) 
		strcpy(p + 8, p + len);
#endif	/* FLI */
	fread(gth_buf, FINFO_SIZE, 1, fp);
	if (strcmp(gth_buf + 8, "gather") == 0)
		goto exist;
	fseek(fp, -8L, SEEK_END);
	f_num = read_int(fp);
	start = read_long(fp);
	if (read_int(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 = fardir.f_size;
			fpos = fardir.f_pos;
			goto accend;
		}
		if (stat > 0)
			break;
	}
	goto non_exist;

  exist:
	strupr(p);
	start = *((long *)(gth_buf));
	f_num = *((int *)(gth_buf + 4));
	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 = finfo->f_size;
			fpos = finfo->f_pos;
			strlwr(p);
		  accend:fclose(fp);
			return (NOTHING);
		}
		if (stat > 0)
			break;
	}
  non_exist:{
	};
	fclose(fp);
  non_exist1:{
	};
	*ptr_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 = ' ';
	return NULL;
}
#endif	/* FLI */

static BOOL copy_token(char **dst_ptr, char **src_ptr, int delim)
{
	char *src;
	char *dst;

	src = *src_ptr;
	dst = *dst_ptr;

	while (*src != '\0' && *src != delim)
		*dst++ = *src++;

	*src_ptr = src + 1;
	*dst_ptr = dst;

	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'
#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;
	BOOL f_num = FALSE;

	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 (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");
				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] == GTH_FLG) {
				len--;
				strdel(tmp, FLG_LEN);
				if (strchr(buf, '.') == NULL
					|| strchr(buf, '.') > tmp - 1) {
					strins(tmp, ".gth ");
					tmp += 4;
				}
				else {
					strins(tmp, " ");
				}
			}
#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
				error(ILLEGAL_ARGS, "%%%c in TEXPK or TEXKNJ", tmp[1]);
		}
		else
			tmp++;
	}
	return (f_num);
}

/* NTTjTeX -> アスキー日本語TeX font 変換 */
#ifndef NO_NTTRPL

static char *ntt_sub(char *name, FONT_INFO *font, uint *fig, uint *figl)
{
#if 1
	struct NTT_TBL {
		int	type;
		int off;
	};
	#define	mk_int(x,y)	((x)+((y)<<8))
	#define	SIZE_NTT_TBL	7

	static struct NTT_TBL ntt_tbl[] = {
		{mk_int('r','a'), 0x2420},
		{mk_int('t','a'), 0x2520},
		{mk_int('m','a'), 0x2300},
		{mk_int('s','y'), 0x2120},
		{mk_int('e','k'), 0x2620},
		{mk_int('a','n'), 0x2720},
		{mk_int('e','n'), 0x2820},
	};
#endif
	char *pt;
	int i, type;
/*
	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] = NULL;
	font->code_offset = -1;
	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(new, pt);
			pt = next_top(old, pt);
			for (i = 0; old[i] == name[i]; ++i);
			if (old[i] == NULL && name[i] == 'j') {
				strcpy(s, new);
				break;
			}
		} while (*pt != 0);
	}
	if (s[0] != NULL) {
		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 < 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 s;
		}
		type = *((int*)pt);
		for (i = 0; i < SIZE_NTT_TBL; i++){
			if (ntt_tbl[i].type == type){
				font->code_offset = ntt_tbl[i].off;
				return s;
			}
		}
	}
	return name;
}

#endif
/* end of file : fontdef.c */
