/*
 *  TEX Device Driver  ver 2.02-
 *  copyright(c) 1988, 1989 by TSG, 1990-93 by SHIMA
 *  1991 changed by hideki
 *  1991 changed by T.Minagawa
 *
 *  getfont.c : get unpacked font
 *
 *  Apr. 15, 1989 : first edition
 *  Jul.  2, 1989 : 2nd edition
 *	modified for non PC-9801 machines by sempa 1992
 *	very slightly modified against warnings by Oh-Yeah? 25 May 1992
 *  modifed for LIPS3 by SHIMA 30 June 1992
 *	modified for pTeX (tate mode) by Naochan! 6 August 1992
 *  slightly modified for pTeX on LIPS3 by OkI 8 August 1992
 *  modified  by Tomiie 20 August 1992
 *	modified for LIPS3+ESC/Page by OkI & H.Tomiie 30 Sept. 1992
 *  slightly modified for JGfont(3D-Bezier) by Naochan! 12 November 1992
 *  modified to use EMS by SHIMA 13 Dec 1992
 *  slightly modified for NTTjTeX by Yakumo 24 Dec. 1992
 *  modified to use font with magnification and reduction;
 *           by Yoshizawa, Matsuda, SHIMA, Naochan! 22 Feb. 1993
 */

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <io.h>
#include <mem.h>
#include <string.h>
#include <alloc.h>

#define _DEF_STDIO_H_
#include "dd.h"
#include "err.h"
#include "buffer.h"
#include "dviread.h"

#define	BIG_ZS	1

#ifdef	HIRES98
extern int hireso;
static	int char_size;
#define	CHAR_SIZE	char_size
#define	KCG_BUF		72
#else
#define	CHAR_SIZE	16
#define	KCG_BUF		32
#endif

#define PK_PRE		247
#define PK_ID		89
#define	PKD_ID		('p'+'k'+'d')
#define PK_POST		245
#define VFD_PRE		'v'
#define VFD_ID		('f'+'d')
#define VFDW_ID		((VFD_ID<<8)+VFD_PRE)

#define	PKW_ID		((PK_ID<<8)+PK_PRE)
#define	PKDW_ID		((PKD_ID<<8)+PK_PRE)
#define	PXL1001_ID	(3+(233<<8))
#define	PXL1002_ID	(3+(234<<8))
#define	PXL1003_ID	(3+(235<<8))
#define	JXL4_0_ID	(0x0100)
#define	JXL4_1_ID	(0x258B)
#define	JTFM_ID		(11<<8)
#define JTFMP_ID    (9<<8)		/* this definition is used in LBP.C, too */

#define	CRT_BIOS 0x18	/* PC9801 */

#define VIDEO_BIOS 0x10	/* IBMPC */

/* buffer.c */
char *marea(unsigned int);

 /* decodepk.c */
void decode_pk(BUFFER *, PREAMBLE *, int, FONT_INFO *);
void decode_jxl(BUFFER *, PREAMBLE *, int, FONT_INFO *);
void decode_vfn(int, BUFFER *, PREAMBLE *, FONT_INFO *);

 /* loadpk.c */
BUFFER *load_pk(const char *);
int ask_pk_buf(long);
void re_openf(FONT_INFO *);

 /* raster.c */
void raster_buf_alloc(PREAMBLE **, long);
void cut_raster(uint);
PREAMBLE *alloc_preamble(void);

 /* bitmap.c */
extern int f_shift_EMS;
BUFFER *rotate_raster(PREAMBLE *);

 /* sptopxl.asm  */
PIXEL sptopixel(SCALED_PT);
PIXEL vtopixel(SCALED_PT);

 /* mult20.asm */
SCALED_PT mult20(SCALED_PT, SCALED_PT);

 /* fontdef.c */
KFONT *open_kfont(FONT_INFO *, int, int, JFM_DATA *);
void open_pk(FONT_INFO *);
void open_jxl(FONT_INFO *);
void open_vf(FONT_INFO *);
int chk_goth(FONT_INFO *);

/* pret.c */
void rewrite_preamble_ptex(PREAMBLE *, uint );

#ifndef	NOVFONT
int chk_vfont_goth(FONT_INFO *);

#endif
char *get_font_name(FONT_INFO *);

 /* loadpk.c */
int file_read(int, BUFFER *, int);
FILE *fopenf(char *name, char *mode);

 /* vfont.c */
void get_vfont(int, PREAMBLE *, FONT_INFO *);

#ifdef BEZIERFONT
 /* jgfont.c */
void get_bezfont(int, PREAMBLE *, FONT_INFO *);

#endif

#ifdef	LBP
int search_djtable(uint code, uint font_code);
#endif

int k_scale = 952;
int k_base = 0;
int f_get_pk = 0;
int rom_base = -1;
BOOL f_font_c;

#if	defined(FDOWN) || defined(BIGFONT)
int f_assigned;
#endif

#ifdef	BIGFONT
static BUFFER *big_pk;
static FONT_INFO *big_font;
static PREAMBLE *big_preamble;
static int big_flag;
static int big_code;
static int f_big_same;
FILE *big_fp;

/* epsbox.c */
void name_pbm(char *);
#endif

extern char *goth;
extern int g_font;
extern CHAR_INFO *char_info_ptr;
extern int test_flg;
extern int r_b_f_count;
extern int enlarge;
extern char ptex_d;
extern BOOL f_resize;

#ifdef	FDOWN
extern int f_download;
extern uint dj_current;
extern int f_gaiji;
#endif

#ifdef DOSV
void read_font(int, int, int);
#endif

PREAMBLE *get_font(uint *, FONT_INFO *);
long jtfm_width(FONT_INFO *, int);
void set_trans_jis(char *);
uint trans_jis(uint);
static BUFFER *get_pk(int, FONT_INFO *, int *);
static int read_flag_byte(BUFFER **);
static PREAMBLE *set_preamble(BUFFER **, int, FONT_INFO *, int);
static void get_font16(int, PREAMBLE *);
static void get_kfont(int, PREAMBLE *, FONT_INFO *);
static void get_knjpk(int, PREAMBLE *, FONT_INFO *);
static void exp_1001(BUFFER *, PREAMBLE *, FONT_INFO *);
static void exp_1002(BUFFER *, PREAMBLE *, FONT_INFO *);
static void exp_1003(BUFFER *, PREAMBLE *, FONT_INFO *);
static void font_dbl(PREAMBLE *);
static BUFFER *get_pkd(FONT_INFO *, long, int *);
static BUFFER *get_jxl(long far *, FONT_INFO *, long, int *);
static void resize_getfont(PREAMBLE *, int, int);
static void rotate_getfont(PREAMBLE *);

#ifdef VFD
static BUFFER *get_vfd(FONT_INFO *, long, int);

#endif

#ifndef NO_NTTRPL
const long nttf_width[8] =
{0xec673L, 0xeddf1L, 0xe7439L, 0xe8fa2L,
 0xea58fL, 0xea58fL, 0xec673L, 0xef6d1L};
extern BOOL ntt_subst;
void unify_nttjfont(FONT_INFO *);
#endif

JFM_DATA *jfm_read(FONT_INFO *font, int char_code);

static void resizefont(uchar *, uint, uint, PREAMBLE *);
													/* ROM FONT の拡大縮小 */
#if DEBUG & MEM_CHK
static void _pkptrchk(BUFFER *);

#endif

#ifndef	NEMS
#define	MAX_PAGE	0x800

struct LOG_TO_PHYS_MAP {
	int	log;
	int	phys;
};

extern int f_cont_EMS;
extern struct LOG_TO_PHYS_MAP log_to_phys_map[];

#define	f_font_EMS	raster_buf_pointer->ems_last
#define	ems_page_top log_to_phys_map[0].log

int set_ems( int );
int copy_to_orig( uint s_seg, uint s_off, uint d_seg, uint d_off,
	long length );
int alloc_ems( int flag, int p0, int p1, int p2, int p3 );

void static get_ems( CHAR_INFO **font )
{
	uint page;

	if ((page = FP_SEG( *font )) >= MAX_PAGE) return;		/* not EMS */
	if (--page != ems_page_top || f_cont_EMS == 0)
		set_ems( page );
	((uint *)font)[1] = FP_SEG(pf_addr);
}

CHAR_INFO* expand_char_info_list( void )
{
	uint	off;

	if( raster_buf_pointer->ems_bank >= 0 ){
		off = (HUGE_BUF*)char_info_ptr - (HUGE_BUF*)pf_addr;
		return( MK_FP( raster_buf_pointer->ems_bank + 1, off ) );
	}
	else	return( char_info_ptr );
}
#else
#define	expand_char_info_list( )	char_info_ptr
#endif

struct TRANS_TABLE {
	int org;
	int new;
	char flag;
};

static struct TRANS_TABLE *trans_table;
static int total_trans;
#define	JIS_NO_TATE	2
#define	JIS_NO_YOKO	1

void set_trans_jis(char *pt)
{
	int i;
	total_trans = (int)strtol(pt, &pt, 0);
	trans_table = (void *)marea(total_trans*sizeof(struct TRANS_TABLE));
	pt++;

	for(i = 0; i < total_trans; i++){
		if(sscanf(pt, "%x=%x", &(trans_table[i].new), &(trans_table[i].org))
			!= 2 ) goto err;
		pt += 9;
		switch(*pt++){
			case 'y':
					trans_table[i].flag = JIS_NO_TATE;
					pt++;
					break;

			case 't':
					trans_table[i].flag = JIS_NO_YOKO;
					pt++;
					break;

			case  0 :
					if (i < total_trans - 1) goto err;
			case ':':
					trans_table[i].flag = 0;
					break;

			default:
err:		error(ILLEGAL_ARGS, "Bad parameter in -JC");
		}
	}
}


uint trans_jis(uint char_code)
{
	int i;
	struct TRANS_TABLE *pt_table;

	if(char_code > 0xff){
		for(i = 0, pt_table = trans_table; i++ < total_trans; pt_table++){
			if(pt_table->org == char_code && pt_table->flag != ptex_d + 1)
				return(pt_table->new);
		}
	}
	return(char_code);
}

PREAMBLE *get_font(uint *pt_code, FONT_INFO *font)
	/*  char_codeのフォントを得る．
     */
{
	PREAMBLE *preamble;
	BUFFER *pk;

	uint char_code, new_code;
	int flag_byte, flag_nf, n_flush;
	int new_width, new_height, f_modify;
	CHAR_INFO *char_info;
	CHAR_INFO *new_info;
	CHAR_INFO *kc_info;
	FONT_INFO *fontk;
	long	raster_size, tmp;
	struct TRANS_TABLE *pt_table;
#ifndef	NEMS
	CHAR_INFO *ems_info;
	int		ems_page;
	int		kc_ems_page;
#endif

#define	f_SIZE		1
#define	f_KSIZE		2
#define	f_ROTATE	4

	ENTER("get_font");
#if	defined(FDOWN) || defined(BIGFONT)
	f_assigned =
#endif
		flag_nf = 0;
	new_code = char_code = *pt_code;

#ifdef	LBP
	if(font->font_type == JLBP){
		*pt_code = trans_jis(char_code);
	}
 #ifdef	JDWN
	else if(f_download > 2 && dj_current > 0 &&
	  (font->font_type == JXL || font->font_type >= ROM_FONT) ){
		if (search_djtable(char_code, font->font_code))
			f_assigned = 2;
	}
 #endif
#endif
#ifdef	FDOWN
	if ((font->f_goth & F_DWN)
		&& ((font->d_flag[char_code >> 3] & (1 << (char_code & 7)))))
		f_assigned = 1;
#endif
	if ((char_info = font->char_info[char_code & (CHAR_ROOT - 1)]) != NULL) {
		/*  既に展開されたfontかどうか？
            	 */
#ifndef	NEMS
		ems_info = char_info;
 		get_ems( &ems_info );
		if (ems_info->code == char_code)
			RETURN(&(ems_info->pre));
#else
		if (char_info->code == char_code)
			RETURN(&(char_info->pre));
#endif
		for (;;) {
#ifndef	NEMS
			if (ems_info->code < char_code) {
				if (ems_info->next_char == NULL) {
					flag_nf = 1;
					break;
				}
				char_info = ems_info->next_char;
			}
			else {
				if (ems_info->former_char == NULL) {
					flag_nf = -1;
					break;
				}
				char_info = ems_info->former_char;
			}
			ems_info = char_info;
			get_ems( &ems_info );
			if( ems_info->code == char_code ) RETURN(&(ems_info->pre));
#else
			if (char_info->code < char_code) {
				if (char_info->next_char == NULL) {
					flag_nf = 1;
					break;
				}
				if ((char_info = char_info->next_char)->code == char_code)
					RETURN(&(char_info->pre));
			}
			else {
				if (char_info->former_char == NULL) {
					flag_nf = -1;
					break;
				}
				if ((char_info = char_info->former_char)->code == char_code)
					RETURN(&(char_info->pre));
			}
#endif
		}
	}
#ifndef	NEMS
	else{
		if( raster_buf_pointer->ems_bank >= 0 )
			set_ems( raster_buf_pointer->ems_top );
	}
#endif
	pk = get_pk(new_code = *pt_code = trans_jis(char_code), font, &flag_byte);
	n_flush = r_b_f_count;
	preamble = set_preamble(&pk, flag_byte, font, new_code);
	f_modify = 0;
#ifdef	LBP
	if (font->font_type == JLBP){
#ifndef	NEMS
		ems_page = ems_page_top;
#endif
		goto c_inf;
	}
#endif

	if (font->font_type >= JIS_FONT || font->font_type == ROM_FONT) {
#ifndef	NEMS
		ems_page = ems_page_top;
#endif
		for (fontk = font->k_top; fontk; fontk = fontk->k_next) {
			if (fontk == font
				|| (kc_info = fontk->char_info[char_code & (CHAR_ROOT - 1)])
				== NULL)
				continue;
#ifndef	NEMS
			for (;;) {
				get_ems( &kc_info );
				if(kc_info->code == char_code){
					if(ems_page != ems_page_top) break;
					preamble->raster = kc_info->pre.raster;
					goto c_inf;
				}
				if (kc_info->code < char_code) {
					if (kc_info->next_char == NULL)	  break;
					kc_info = kc_info->next_char;
				}else{
					if (kc_info->former_char == NULL) break;
					kc_info = kc_info->former_char;
				}
			}
#else
			if (kc_info->code == char_code) {
k_found:		preamble->raster = kc_info->pre.raster;
				goto c_inf;
			}
			for (;;) {
				if (kc_info->code < char_code) {
					if (kc_info->next_char == NULL)	break;
					if ((kc_info = kc_info->next_char)->code == char_code)
						goto k_found;
				}
				else {
					if (kc_info->former_char == NULL) break;
					if ((kc_info = kc_info->former_char)->code == char_code)
						goto k_found;
				}
			}
#endif
		}
#ifndef	NEMS
		if( raster_buf_pointer->ems_bank >= 0 )
			set_ems( raster_buf_pointer->ems_bank );
#endif
	}

	raster_size = (long)preamble->byte_width*preamble->height;
	if (ptex_d && font->font_type == JXL){
		f_modify |= f_ROTATE;
		tmp = (long)((preamble->height+7)/8)*preamble->width;
		if(tmp > raster_size) raster_size = tmp;
	}

	if (font->f_goth & K_SCALE){
		if (font->font_type > JXL){
			f_modify |= f_KSIZE;
			if ((font->f_goth & F_TATE) && !(preamble->rotate_ptex & 1)){
				new_width  = font->k_height;
				new_height = font->k_width;
			}
			else{
				new_width  = font->k_width;
				new_height = font->k_height;
			}
			tmp = (long)(new_width+7)/8*new_height;
			goto cmp_size;
		}
		else{
			preamble->pitch_offset 
						= ((long)preamble->pitch_offset*enlarge+500)/1000;
			preamble->depth_offset
						= ((long)preamble->depth_offset*enlarge+500)/1000;
			if(!(new_width  = ((long)preamble->width*enlarge+500)/1000))
				new_width = 1;
			if(!(new_height = ((long)preamble->height*enlarge+500)/1000))
				new_height = 1;
			if (new_width != preamble->width
			  || new_height != preamble->height){
				f_modify |= f_SIZE;
				if (enlarge > 1000){
					if(f_modify & f_ROTATE){
						tmp = (long)((new_height+7)/8) * new_width;
cmp_size:				if (tmp > raster_size) raster_size = tmp;
					}else
						raster_size = (long)((new_width+7)/8) * new_height;
				}
			}
		}
	}

#ifndef	BIGFONT
	if(raster_size > 0xffffL - 0x100
 #ifdef	FDOWN
 	&& !f_assigned
 #endif
	)	error(PROGRAM_STOP, "too big font");
#endif
#ifdef	BIGFONT
	if(raster_size > COMMON_SIZE && !f_assigned){
		if(raster_size > 0xffffL - 0x100
		  || (    (f_modify & (f_SIZE|f_KSIZE))
			       && (raster_size > 0xffffL - 0x800  ||
				    get_near_work(raster_size + 0x800) == NULL)
			  )
		){
			if(preamble->width > 8000)
				error(NO_MEMORY, "too big font");

			switch (font->font_type){
			  case (PKD_FONT):
			  case (PK_FONT):
			  case (JXL):
			  case (PXL1003):
			  case (ROM_FONT):
			  case (JIS_PK):
			  case (JIS_PKH):
			  case (GAIJI):
#if	BIG_ZS
#ifndef	NOVFONT
 #ifdef	BEZIERFONT
			  case (JG_FONT):
 #endif
			  case (ZS_FONT):
#endif
#endif
					f_assigned = (f_modify & (f_SIZE|f_KSIZE))? 3:4;
					big_pk = pk;
					big_preamble = preamble;
					big_flag = flag_byte;
					if (big_font == font && big_code == new_code){
						f_big_same = 1;
					}else{
						f_big_same = 0;
						big_font = font;
						big_code = new_code;
					}
					raster_buf_pointer->current = (BUFFER*)char_info_ptr;
					return(preamble);

			  default:
					error(PROGRAM_STOP, "too big font");
			}

		}
	}
#endif

	raster_buf_alloc(&preamble, raster_size);
#ifndef	NEMS
	ems_page = ems_page_top;
#endif
	switch (font->font_type) {
	  case (PKD_FONT):
	  case (PK_FONT):
		  decode_pk(pk, preamble, flag_byte, font);
		  /*  pk-fontの展開 */
		  goto c_inf;;
	  case (PXL1001):
		  exp_1001(pk, preamble, font);
		  goto c_inf;
	  case (PXL1002):
		  exp_1002(pk, preamble, font);
		  goto c_inf;
	  case (PXL1003):
		  exp_1003(pk, preamble, font);
		  goto c_inf;
	  case (JXL):
		  decode_jxl(pk, preamble, flag_byte, font);
		  goto c_inf;
#ifdef VFD
	  case (VFD_FONT):
		  decode_vfn(new_code, pk, preamble, font);
		  goto c_inf;
#endif
	  case (ROM_FONT):
		  get_font16(new_code, preamble);
		  break;
#ifndef	NOVFONT
#ifdef BEZIERFONT
	  case (JG_FONT):
#endif
	  case (ZS_FONT):
		  get_vfont(new_code, preamble, font);
		  break;
#endif
	  case (JIS_FONT):
		  get_kfont(new_code, preamble, font);
		  break;
	  case (JIS_PK):
	  case (JIS_PKH):
	  case (GAIJI):
		  get_knjpk(new_code, preamble, font);
		  break;
	}
	if (font->f_goth & K_DBL)
		font_dbl(preamble);
c_inf:
	if (f_modify){
		if (f_modify & f_ROTATE)
			rotate_getfont(preamble);
		if (f_modify & (f_KSIZE|f_SIZE))
			resize_getfont(preamble, new_width, new_height);
	}
	new_info = expand_char_info_list();
	/*  char_info-listに加える．*/
#ifndef	NEMS
	kc_info = new_info;
	get_ems( &kc_info );
	kc_info->code = char_code;
	kc_info->next_char = kc_info->former_char = NULL;
	if (flag_nf == 0 || n_flush != r_b_f_count )
		font->char_info[char_code & (CHAR_ROOT - 1)] = new_info;
	else{
		get_ems( &char_info );
		if (flag_nf > 0)
			char_info->next_char = new_info;
		else
			char_info->former_char = new_info;
	}
	if( ems_page != ems_page_top ) set_ems( ems_page );
#else
	new_info->code = char_code;
	new_info->next_char = new_info->former_char = NULL;
	if (flag_nf == 0 || n_flush != r_b_f_count )
		font->char_info[char_code & (CHAR_ROOT - 1)] = new_info;
	else if (flag_nf > 0)
		char_info->next_char = new_info;
	else
		char_info->former_char = new_info;
#endif
	RETURN(preamble);
}

static void font_dbl(PREAMBLE *preamble)
{
	uchar far *top;
	uint ch1, ch2;
	int lin, col, width;
	int off1, off2, i;

	width = (preamble->byte_width + 1) / 2;
	top = preamble->raster;
	off1 = ((preamble->height) / 2 - 1) * width;
	off2 = (preamble->height - 2) * preamble->byte_width;
	for (lin = (preamble->height) / 2 - 1; lin >= 0; lin--) {
		for (col = preamble->byte_width - 1; col >= 0; col--) {
			ch1 = top[off1 + col / 2];
			ch2 = 0;
			if (col & 1) {
				for (i = 1; i < 16; i += i) {
					ch2 >>= 2;
					if (ch1 & i)
						ch2 |= 0xc0;
				}
			}
			else {
				for (i = 16; i < 256; i += i) {
					ch2 >>= 2;
					if (ch1 & i)
						ch2 |= 0xc0;
				}
			}
			top[off2 + col] = top[off2 + preamble->byte_width + col] = ch2;
		}
		off1 -= width;
		off2 -= preamble->byte_width * 2;
	}
}

#ifdef	BIGFONT
int *get_bigfont(void)
{
#define	TMP_ROM_SIZE 96

#define	TMP_ZS_SIZE 512
#define	TMP_ZS_BUF	0x8000

	uint	i;
	uint size;
	uint b_width, b_height, old_width, old_height, t_width;
	BUFFER *zs_buf;
	static int	tmp[2];
#if	BIG_ZS
#ifndef	NOVFONT
	KFONT *kf;
#endif
#endif

	if (f_big_same)
		return &tmp[0];
	tmp[0] = tmp[1] = 100;
	name_pbm("bf$.pbm");
	b_width = big_preamble->width;
	b_height = big_preamble->height;
	t_width = 0;
	if (big_font->font_type == ROM_FONT)
			t_width = TMP_ROM_SIZE;
#if	BIG_ZS
#ifndef	NOVFONT
	else if (
 #ifdef	BEZIERFONT
		big_font->font_type == JG_FONT || 
 #endif
		big_font->font_type == ZS_FONT)
			t_width = TMP_ZS_SIZE;
#endif
#endif
	if (t_width){
		big_preamble->height = big_preamble->width = t_width;
		size = t_width * (big_preamble->byte_width = (t_width+7)/8);
	}
	if ((big_fp = fopenf(tmp_buf, "wb")) == NULL)
		error(PROGRAM_STOP, "can't open a file for big font");

								/* write the header of raw PBM file */
	fprintf(big_fp, "P4" "\12" "# %d:%04x" "\12" "%d %d\12",
		big_font->font_code, big_code,
		big_preamble->width, big_preamble->height);

	switch(big_font->font_type){
	  case (PKD_FONT):
	  case (PK_FONT):
			decode_pk(big_pk, big_preamble, big_flag, big_font);
resize:
			if (enlarge){
				tmp[0] = tmp[1] = (enlarge+5)/10;
				big_preamble->width  = (long)big_preamble->width*enlarge/1000;
				big_preamble->height = (long)big_preamble->height*enlarge/1000;
			}
			break;

	  case (JXL):
			decode_jxl(big_pk, big_preamble, big_flag, big_font);
			goto resize;

	  case (ROM_FONT):
			big_preamble->raster = (BUFFER*)tmp_buf;
			get_font16(big_code, big_preamble);
			for (i = 0; i < size; i++)
				putc(tmp_buf[i], big_fp);
			b_width = b_height = t_width;
			goto resizek;

#if	BIG_ZS
#ifndef	NOVFONT
 #ifdef	BEZIERFONT
	  case (JG_FONT):
 #endif
	  case (ZS_FONT):
			kf = big_font->ext.kdir;
			old_width = kf->width;
			old_height = kf->height;
			kf->height= kf->width = t_width;

			raster_buf_pointer->current += sizeof(CHAR_INFO);
			raster_buf_alloc(&big_preamble, TMP_ZS_BUF);
		  	get_vfont(big_code, big_preamble, big_font);

			kf->width = old_width;
			kf->height = old_height;
			zs_buf = big_preamble->raster;
			for (i = 0; i < size; i++)
				putc(zs_buf[i], big_fp);
			cut_raster(TMP_ZS_BUF + sizeof(CHAR_INFO));
			tmp[0] = ((long)b_width)*100/big_preamble->width;
			tmp[1] = ((long)b_height)*100/big_preamble->height;
			break;
#endif
#endif
	  case (JIS_PK):
	  case (JIS_PKH):
	  case (GAIJI):
			get_knjpk(big_code, big_preamble, big_font);
			if (big_font->f_goth & K_SCALE){
resizek:
				if (big_font->f_goth & F_TATE){
					old_width = big_font->k_height;
					old_height = big_font->k_width;
				}else{
					old_width = big_font->k_width;
					old_height = big_font->k_height;
				}
				tmp[0] =((long)(big_preamble->width=old_width))*100/b_width;
				tmp[1] =((long)(big_preamble->height=old_height))*100/b_height;
			}
			break;
	}
	fclose(big_fp);
	return &tmp[0];
}
#endif

static void exp_1001(BUFFER *pk, PREAMBLE *preamble, FONT_INFO *font)
{
	int i, j, k;
	BUFFER *dest;
	BUFFER *pkt;

	k = ((preamble->byte_width + 3) / 4) * 4;
	pk = font->pk + (uint)get_long(pk) * 4;
	dest = preamble->raster;
	for (i = preamble->height; i > 0; i--) {
		pkt = pk;
		for (j = preamble->byte_width; j > 0; j--) {
			*dest++ = *pkt++;
		}
		pk += k;
	}
}

static void exp_1002(BUFFER *pk, PREAMBLE *preamble, FONT_INFO *font)
{
	pk = font->pk + (uint)get_long(pk);

	movedata(FP_SEG(pk), FP_OFF(pk),
			 FP_SEG(preamble->raster), FP_OFF(preamble->raster),
			 preamble->byte_width * preamble->height);
}

static void exp_1003(BUFFER *pk, PREAMBLE *preamble, FONT_INFO *font)
{
	BUFFER *pkt;
	uchar flag;

	flag = *(pkt = font->pk + (uint)get_long(pk));
	if (flag & 64) {
#ifdef	BIGFONT
		if (f_assigned >= 3) 
			error(NO_MEMORY, "too big font without compression");
#endif
		movedata(FP_SEG(pkt), FP_OFF(pkt + 1),
				 FP_SEG(preamble->raster), FP_OFF(preamble->raster),
				 preamble->byte_width * preamble->height);
	}
	else {
		flag = ((flag << 4) & 0xff) + ((flag & 128) >> 4);
		decode_pk(pkt + 1, preamble, flag, font);
	}
}

static void rotate_getfont(PREAMBLE *preamble)
{
	BUFFER *buf;
	BUFFER *src_buf;
	int new_width, new_height, new_byte_width;
	long size;

	new_byte_width = ((new_width = preamble->height)+7)/8;
	new_height = preamble->width;
	size = (long)new_byte_width * new_height;
	src_buf = preamble->raster;

    buf = rotate_raster(preamble);
	if(f_shift_EMS & 0x4000){
		copy_to_orig(FP_SEG(buf), FP_OFF(buf),
			FP_SEG(src_buf), FP_OFF(src_buf), size);
		alloc_ems(-1, 0, 0, 0, 0);
	}else{
		movedata(FP_SEG(buf), FP_OFF(buf),
			FP_SEG(src_buf), FP_OFF(src_buf), size);
	}
	preamble->width  = new_width;
	preamble->height = new_height;
	preamble->byte_width = new_width;
}

static void resize_getfont(PREAMBLE *preamble, int width, int height)
{
	int src_width, src_height;
	uint size, new_size;
	uchar *src_buf;

	src_width = preamble->width;
	size = ((long)(src_width + 7)/8)*(src_height = preamble->height);
	if ((src_buf = (size <= COMMON_SIZE)?tmp_buf:get_near_work(size)) == NULL){
		error(WARNING, "No memory to resize font");
		return;
	}
	movedata(FP_SEG(preamble->raster), FP_OFF(preamble->raster),
		FP_SEG(src_buf), FP_OFF(src_buf), size);
	preamble->height = height;
	new_size = (preamble->byte_width = ((preamble->width = width) + 7)/8)
				* height;
	resizefont(src_buf, src_width, src_height, preamble);
	if (new_size < size) cut_raster(size - new_size);
}

static void get_kfont(int char_code, PREAMBLE *preamble, FONT_INFO *font)
{
	int sc;
	KFONT *kf;

	kf = font->ext.kdir;
	sc = (((uint)char_code >> 8) - 0x21) * 94;
	sc += ((char_code & 0xff) - 0x21);
	lseek(kf->fh, (long)sc * (long)(kf->size), SEEK_SET);
	file_read(kf->fh, preamble->raster, kf->size);
}

static void get_knjpk(int char_code, PREAMBLE *preamble, FONT_INFO *font)
{
	int sc;
	int pktype;
	int total;
	int *tbl;
	uint size;
	long seek_pt;
	long lsize;
	uchar temp[10];
	KFONT *kf;

	kf = font->ext.kdir;
	size = kf->size;
    lsize = kf->height*(long)((kf->width+7)/8);

	switch(font->font_type){
		case JIS_PK:
			pktype = 3;
			break;

		case JIS_PKH:
			pktype = 5;
			break;

		case GAIJI:
#ifdef	JDWN
			if (f_gaiji) return;
#endif
			pktype = 0;
			lseek(kf->fh, 32, SEEK_SET);
			for (sc = total = 0; sc <= total; sc++){
				if (!(sc & 0xff)){
					read(kf->fh, common_work, 0x200);
					tbl = (int*) common_work;
					if (!sc){
						total = *tbl++;
						continue;
					}
				}
				if (*tbl++ != char_code) continue;
				seek_pt = lsize*(sc - 1) + total*2 + 34;
				goto cpy;
			}
			error(FONT_MISMATCH, "%5d: %s %s(%XH)",
				  font->font_code, get_font_name(font),
				  font->ext.kdir->name, char_code);
	}
	sc = (((uint)char_code >> 8) - 0x21) * 94;
	sc += ((char_code & 0xff) - 0x21);
	lseek(kf->fh, (long)sc * pktype + 32, SEEK_SET);
	read(kf->fh, temp, 10);
	if (pktype == 3){
		seek_pt = (((long)(temp[0] & 0x3f)) << 16);
		seek_pt += (((long)(temp[1])) << 8) + temp[2];
	}else{
		seek_pt = *(long *)(temp+1);
		size = *(long *)(temp+6) - seek_pt;
	}
cpy:
	lseek(kf->fh, seek_pt, SEEK_SET);
	if ( (pktype == 3 && (temp[0] & 0x80) != 0)
	 ||  (pktype == 5 && (temp[0] & 0x0f) == 0x0f)
	 ||   pktype == 0 ){
#ifdef	BIGFONT
		if (f_assigned >= 3){
			while(lsize){
				size = (lsize > COMMON_SIZE)? COMMON_SIZE:lsize;
				read(kf->fh, common_work, size);
				fwrite(common_work, size, 1, big_fp);
				lsize -= size;
			}
		}
		else
#endif
		file_read(kf->fh, preamble->raster, size);
	}
	else{
		ask_pk_buf(lsize + 4);
		if (size) file_read(kf->fh, pk_buf_pointer->current, size);
		if (pktype == 3)
			decode_pk(pk_buf_pointer->current, preamble,
				(12 << 4) + ((temp[0] & 0x40) >> 3), font);
		else{
			*((long far *)(pk_buf_pointer->current + size)) = 0x0f0f0000L;
			decode_jxl(pk_buf_pointer->current, preamble, temp[0], font);
		}
	}
}

#ifdef	PC9801
static void get_font16(int char_code, PREAMBLE *preamble)
{
	union REGS regs;
	char char_buf[KCG_BUF + 2];
	int new_r_size;

#ifdef	HIRES98
	outportb(0x68, 11);
#else
	regs.x.ax = 0x1b01;
	int86(CRT_BIOS, &regs, &regs);
#endif

#ifdef	HIRES98
	if (hireso) {
		CHAR_SIZE = 24;
		regs.x.bx = FP_OFF(&(char_buf[2]));
		regs.h.ah = 0x1f;
	} else {
		CHAR_SIZE = 16;
		regs.x.bx = FP_SEG(&(char_buf[0]));
		regs.x.cx = FP_OFF(&(char_buf[0]));
		regs.h.ah = 0x14;
	}
	regs.x.dx = char_code;
#else
	regs.x.bx = FP_SEG(&(char_buf[0]));
	regs.x.cx = FP_OFF(&(char_buf[0]));
	regs.x.dx = char_code;
	regs.h.ah = 0x14;
#endif
	int86(CRT_BIOS, &regs, &regs);

	resizefont(&char_buf[2], CHAR_SIZE, CHAR_SIZE, preamble);

#ifdef	HIRES98
	outportb(0x68, 10);
#else
	regs.x.ax = 0x1b00;
	int86(CRT_BIOS, &regs, &regs);
#endif
}

#endif
#if	defined(J3100)
void get_font16(int char_code, PREAMBLE *preamble)
{
	union REGS regs;
	struct SREGS sregs;
    uchar *dst;
    uchar far *src;
    uchar font_buf[72];
    int i, ch_size, count;

    regs.h.ah = 3;			/* Get ROM KANJI font data */
	regs.x.dx = char_code;
	dst = font_buf;
    if (preamble->width <= CHAR_SIZE) {
		/* AL  0:Shift-JIS(16x16) 1:JIS(16x16) */
		/*     2:Shift-JIS(24x24) 3:JIS(24x24) */
    	ch_size = CHAR_SIZE;	/* default char size = 16 */
		regs.h.al = 1;
		int86x(0x60, &regs, &regs, &sregs);
		src = MK_FP(sregs.es, regs.x.si);
		for (i=0; i<32; i++)
			*dst++ = *src++;
    } else {
		/* AL  0:Shift-JIS(16x16) 1:JIS(16x16) */
		/*     2:Shift-JIS(24x24) 3:JIS(24x24) */
		ch_size = 24;			/* use 24x24 font */
		regs.h.al = 3;
		int86x(0x60, &regs, &regs, &sregs);
		src = MK_FP(sregs.es, regs.x.si);
		count = -(int)regs.x.si/4;
		/* Font data convert */
			for (i=0; i<24; i++) {
					/* 次の漢字ＲＯＭバンクを選択する		*/
					/* 93/03/11 (Thu) 18:06:40 by h.senshu	*/
					/* msu@mix 氏よりのアドバイスによる		*/
				if (i == count && i)
					 pokeb(0xe000, 0000, 0x80 | (regs.h.al + 1));
				*dst++ = *src++;
				*dst++ = *src++;
				*dst++ = *src++;
				src++;
		}
    }
	pokeb(0xe000, 0, regs.h.al | 0x80);
 	resizefont(font_buf, ch_size, ch_size, preamble);
}

#endif /* defined(J3100) */
#ifdef	AX
void get_font16(int char_code, PREAMBLE *preamble)
{
	union REGS regs;
	struct SREGS sregs;
	char b1[KCG_BUF], b2[KCG_BUF];
	int i, j, new_r_size;

	kgets(toSJISc(char_code), FP_SEG(&(b1[0])), FP_OFF(&(b1[0])));

	for (i = j = 0; i < 16; i++) {
		b2[j++] = b1[i];
		b2[j++] = b1[i + 16];
	}
	resizefont(b2, CHAR_SIZE, CHAR_SIZE, preamble);
}

#endif
#if	defined(DOSV)
void get_font16(int char_code, PREAMBLE *preamble)
{
	unsigned char char_buf[KCG_BUF];
	unsigned high = (0xff00 & char_code) >> 8, low = 0x00ff & char_code;
	int new_r_size;

	if (high & 1) {				/* JIS -> Shift JIS */
		if (low < 0x60)
			low += 0x1f;
		else
			low += 0x20;
	}
	else {
		low += 0x7e;
	}
	if (high < 0x5f)
		high = (high + 0xe1) >> 1;
	else
		high = (high + 0x161) >> 1;
	char_code = (high << 8) + low;
	read_font(char_code, FP_SEG(char_buf), FP_OFF(char_buf));
	resizefont(char_buf, CHAR_SIZE, CHAR_SIZE, preamble);
}

#endif

static BUFFER *get_pk(int char_code, FONT_INFO *font, int *flag_ptr)
	/*  char_codeのpk-fontを得る．pk-fontがloadされていないときは，
     *  loadする．pk-fontはシーケンシャルなので，char_codeの部分を
     *  サーチして，そのpointerを返す．
     */
{
	int flag_byte, tmp, width, total, i, pos;
	char isromfont;
	long base_ratio;	/* JFMより選られるベースラインの高さ */
	JFM_DATA *jtfm;
	long packet_length, id;
	SCALED_PT ptwork;

	/*  intで充分なのだが，一応longにしておく．*/
	BUFFER *pk;
	BUFFER *pk0;
	KFONT *kf;
	long far *jxl_info;
	uchar f_head[35];

	ENTER("get_pk");

	f_get_pk = 1;
	if (!font->pk) {
		/*  pk-fontがメモリー上に無かったら... */
		font->pk = load_pk(font->name);
		switch (*((int far *)font->pk)) {

		  case (0):
			  (HUGE_BUF *)pk =
				  (HUGE_BUF *)(pk_buf_pointer->current) - 6;
			  pos = get_int(pk);

			  tmp = *(((int far *)font->pk) + 1);
			  if (tmp == PXL1001_ID) {
				  font->font_type = PXL1001;
				  font->ext.dir = font->pk + pos * 4;
			  }
			  else {
				  if (tmp == PXL1002_ID) {
					  font->font_type = PXL1002;
					  font->ext.dir = font->pk + pos;
				  }
				  else {
					  if (tmp == PXL1003_ID) {
						  font->font_type = PXL1003;
						  font->ext.dir = font->pk + pos;
					  }
					  else
						  goto err_id;
				  }
			  }
			  (HUGE_BUF *)pk =
				  (HUGE_BUF *)(pk_buf_pointer->current) - 20;
			  goto checksum;

		  case (JXL4_0_ID):
			  if (*(((int far *)font->pk) + 1)
				  != JXL4_1_ID)
				  goto err_id;
			  pk = font->pk + 4;
			  font->font_type = JXL;
			  goto checksum;

		  case (JTFMP_ID):
			  font->f_goth |= F_TATE;
		  case (JTFM_ID):
			  if (font->font_type != UNKNOWN)
				  break;
			  /*jtfm = jfm_read( font, char_code );*/
			  jtfm = jfm_read(font, 0x3021);
			  width = sptopixel(mult20((id = jtfm->width),
									   font->size_para));
			  /*精度を落とさないように割り算. 0〜1000に変更*/
  			  base_ratio = (jtfm->depth) /
				  ((id = jtfm->depth + jtfm->height) >> 10);
			  base_ratio = (base_ratio * 1000L) >> 10;
			  ptwork = mult20(id, font->size_para / 250 * k_scale /4);
			  font->k_height = (font->f_goth & F_TATE)?
			  			sptopixel(ptwork) : vtopixel(ptwork);
			  width = sptopixel(mult20((id = jtfm->width),
									   font->size_para));

			  ptwork = mult20(id, font->size_para / 250 * k_scale);
			  font->k_width = (font->f_goth & F_TATE)?
			  			vtopixel(ptwork/4) : sptopixel(ptwork/4);
			  tmp = 0;
			  if(font->k_width < 3000){
				  if(( (font->f_goth & F_TATE)? 
					vtopixel(ptwork) : sptopixel(ptwork) ) % 4 < 2)
				  tmp = 1;
			  };
			  if (k_scale > 1000)
				  width = font->k_width;
			  kf = open_kfont(font, width, tmp, jtfm);
			  /* ↓bitmap font だった場合．．． */
			  if (font->font_type != ZS_FONT
#ifdef BEZIERFONT
				&& font->font_type != JG_FONT
#endif
#ifdef LBP
				&& font->font_type != JLBP
#endif
				&& font->font_type != ROM_FONT) {
				  lseek(kf->fh, 0L, SEEK_SET);
				  read(kf->fh, f_head, 35);
				  if ( *((uint *)f_head) == 0 && f_head[2] == PK_PRE){
					switch(f_head[3]){
						case 'K':
							tmp = 3;
							font->font_type = JIS_PK;
							break;

						case 'H':
							tmp = 5;
							font->font_type = JIS_PKH;
							break;

						case 'G':
							tmp = 0;
						  	font->font_type = GAIJI;
							break;

						default:
							goto jis_font;
				    }
					kf->width = f_head[4] + ((uint)(f_head[5]) << 8);
					kf->height = f_head[6] + ((uint)(f_head[7]) << 8);
					kf->size = (kf->width + 7) / 8 * kf->height;
					font->last = (!tmp)? 0x7fff:
						(((uint)f_head[33] << 8) + (uint)f_head[34] - 32)/tmp;
					if (tmp == 5) font->last--;
				  }
				  else {
jis_font:			  font->font_type = JIS_FONT;
					  font->last
						  = (int)(filelength(kf->fh) / kf->size);
				  }
				  font->last =
					  (((uint)font->last / 94) << 8)
					  + (font->last % 94) + 0x2120;
				  if (font->last < 0)
					  font->last = 0x7fff;
			  }
			  else {
				  /* (擬似)スケーラブルフォントの場合 */
				  font->last = 0x7e7e;
			  }
			  if (font->f_goth & (K_SCALE|K_SCALE2))
					tmp = font->k_height;
			  else	tmp = (font->f_goth & F_TATE)?kf->width:kf->height;

			  kf->base = (int)(((1000L - base_ratio
			  	  - ((font->f_goth & F_TATE)? 0 : k_base))
				  * (unsigned long) tmp + 500) / 1000L);
#ifdef LBP
			  if (font->font_type != JLBP)
#endif
			  {
				  font->ext.kdir = kf;
				  if (strstr(kf->name, goth) != NULL)
					  goto checkj;
#ifndef NOVFONT
				  if (font->font_type == ZS_FONT
#ifdef BEZIERFONT
					  || font->font_type == JG_FONT
#endif
					  ) {
					  switch (chk_vfont_goth(font)) {
						case 1:
							g_font = 0;
							break;
						case 2:
							(font->f_goth) |= (g_font = 1);
							break;
						default:
							(font->f_goth) |= (g_font = chk_goth(font));
					  }
				  }
				  else
					  (font->f_goth) |= (g_font = chk_goth(font));
#else
				  (font->f_goth) |= (g_font = chk_goth(font));
#endif
			  }
checkj:		  pk = font->pk + 28;
			  goto checksum;

		  case (PKDW_ID):
			  font->font_type = PKD_FONT;
			  goto check0;

		  case (PKW_ID):
			  font->font_type = PK_FONT;
check0:		  pk = font->pk;
			  pk += *((uchar far *)(pk + 2)) + 7;
checksum:	  if (f_font_c && (id = get_long(pk)) != 0
				  && font->c != 0 && font->c != id)
				  error(WARNING,
						"check sum doesn't match in Font%3d: "
						"dvi(%08lX) %s(%08lX)",
						font->font_code, font->c,
						(font->font_type >= ROM_FONT) ? "jfm" : "font", id);
			  break;
#ifdef VFD
		  case (VFDW_ID):
			  font->font_type = VFD_FONT;
			  pk = font->pk;
			  pk += *((uchar far *)(pk + 2)) + 7;
			  break;
#endif

		default:				/* */
err_id:		  error(UNPACK_ERROR, "Illegal font ID: %s(%04X)\nCheck TEXPK!",
					get_font_name(font), tmp);
		}
#ifndef NO_NTTRPL
		if (ntt_subst && (font->code_offset >= 0)) unify_nttjfont(font);
#endif
	}
  fcode:
	pk = font->pk;
	if (font->font_type >= ROM_FONT) {
		if (char_code < 0x2121 || char_code > font->last)
no_font:	error(FONT_MISMATCH, "%5d: %s %s(%XH)",
				  font->font_code, get_font_name(font),
				(font->font_type >= JIS_FONT) ? (font->ext.kdir)->name : "",
				  char_code);
		move_ptr(pk, 2);
		total = get_int(pk);	/* nt */
		move_ptr(pk, 2);
		tmp = get_int(pk);		/* lh */
		move_ptr(pk, (tmp + 5) << 2);
		pk0 = pk;
		while (total-- > 0) {
			if (char_code == get_int(pk))
				RETURN(pk);
			move_ptr(pk, 2);
		}
		if (font->font_type >= JIS_FONT && font->ext.kdir->fh < 0)
			re_openf(font);
		RETURN(pk0 + 2);
	}
#if DEBUG & MEM_CHK
	_ptrchk = _pkptrchk;		/* memory check用 */
#endif
	if (f_resize && enlarge && font->font_type <= JXL)
		font->f_goth |= K_SCALE;
	switch (font->font_type) {
	  case (PK_FONT):
		  move_ptr(pk, 2);
		  tmp = get_ubyte(pk);
		  move_ptr(pk, tmp + 16);
		  /* Skip specials, design size, check sum,
         	* hppp and vppp（とりあえずは，必要無いのでとばす．）
         	*/
		  for (;;) {
			  if ((flag_byte = read_flag_byte(&pk)) == PK_POST)
				  goto no_font;
			  switch (flag_byte & 7) {
				case 7:
					/* long-preamble */
					packet_length = get_long(pk);
					if (char_code == get_long(pk)) {
						*flag_ptr = flag_byte;
						RETURN(pk);
					}
					break;
				case 4:
				case 5:
				case 6:
					/* ex-short-preamble */
					packet_length =	/* ( ( flag_byte & 3 ) << 16 ) + 	*/
						get_int(pk);
					if (char_code == get_ubyte(pk)) {
						*flag_ptr = flag_byte;
						RETURN(pk);
					}
					break;
				default:
					/* short preamble */
					packet_length = ((flag_byte & 7) << 8) +
						get_ubyte(pk);
					if (char_code == get_ubyte(pk)) {
						*flag_ptr = flag_byte;
						RETURN(pk);
					}
					break;
			  }
			  move_ptr(pk, (int)packet_length);
		  }

	  case (PXL1001):
	  case (PXL1002):
	  case (PXL1003):
		  RETURN(font->ext.dir + (char_code << 4));

	  case (PKD_FONT):
		  if (font->ext.fh <= 0)
			  open_pk(font);
		  if ((tmp = char_code - *(font->pk + 4)) < 0
			  || char_code > *(font->pk + 6))
			  goto no_font;
		  pk = font->pk + (font->k_width + 3 * tmp);
		  if ((packet_length = get_mid(pk)) == 0L)
			  goto no_font;
		  RETURN(get_pkd(font, packet_length, flag_ptr));

#ifdef VFD
	  case (VFD_FONT):
		  if (font->ext.fh <= 0)
			  open_vf(font);
		  if ((tmp = char_code - *(font->pk + 4)) < 0
			  || char_code > *(font->pk + 6))
			  goto no_font;
		  pk = font->pk + (font->k_width + 5 * tmp);
		  if ((packet_length = get_mid(pk)) == 0L)
			  goto no_font;
		  if ((width = get_int(pk)) == 0)
			  goto no_font;
		  RETURN(get_vfd(font, packet_length, (width * 20 + 15) / 16 * 2));
#endif

	  case (JXL):
		  if (font->ext.fh <= 0)
			  open_jxl(font);
		  jxl_info = (long far *)(font->pk);
		  if (char_code < 0x3021) {
			  if (jxl_info[i = 13] == jxl_info[14])
				  goto no_font;
			  tmp = 0x21;
		  }
		  else if (char_code < 0x5021) {
			  if (jxl_info[i = 14] == 0)
				  goto no_font;
			  tmp = 0x30;
		  }
		  else {
			  if (jxl_info[i = 15] == 0)
				  goto no_font;
			  tmp = 0x50;
		  }
		  pos = ((char_code >> 8) - tmp) * 94 + (char_code & 0x7f) - 0x21;
		  RETURN(get_jxl(jxl_info, font, jxl_info[i] + (pos << 3), flag_ptr));
	}
	RETURN(NULL);
}

static BUFFER *get_jxl(long far * jxl_info, FONT_INFO *font, long pos, int *flag_ptr)
{
	int flag_s, fd;
	uchar tmp[8], tmp0[2];
	long pos_x, pos_y, pos_tfm, pos_raster, packet_length;
	BUFFER *pk;

	lseek(fd = font->ext.fh, pos, SEEK_SET);
	read(fd, &(tmp[0]), 8);

	pos_tfm = jxl_info[6] + ((uint)tmp[0] << 2);
	pos_x = jxl_info[8] + (((uint)tmp[4] << 8) + (uint)tmp[5]) * 6L;
	pos_y = jxl_info[10] + (((uint)tmp[6] << 8) + (uint)tmp[7]) * 6L;
	pos_raster = (((long)(tmp[1])) << 16) + (((long)(tmp[2])) << 8) + tmp[3];

	lseek(fd, pos_raster, SEEK_SET);
	read(fd, &(tmp[0]), 1);
	flag_s = ((*flag_ptr = tmp[0]) & 0x30) >> 4;
	if ((*flag_ptr & 0x0f) == 14) {
		lseek(fd, pos_x + 2, SEEK_SET);
		read(fd, &(tmp0[0]), 2);
		packet_length = (tmp0[0] << 8) + tmp0[1];
		lseek(fd, pos_y + 2, SEEK_SET);
		read(fd, &(tmp0[0]), 2);
		packet_length *= (tmp0[0] << 8) + tmp0[1];
		packet_length = (packet_length + 7) >> 3;
		lseek(fd, pos_raster + 1, SEEK_SET);
	}
	else {
		packet_length = 0;
		while (flag_s-- >= 0) {
			read(fd, &(tmp[0]), 1);
			packet_length = (packet_length << 8) + tmp[0];
		}
	}
	if (ask_pk_buf(packet_length) == FAILURE)
		error(UNPACK_ERROR,
			  "Too big raster in %s", get_font_name(font));
	file_read(fd, (pk = pk_buf_pointer->current) + 12, (int)packet_length);
	*((int far *)(&(pk[(int)packet_length + 12]))) = 0x0000;
	*((int far *)(&(pk[(int)packet_length + 14]))) = 0x0f0f;
	lseek(fd, pos_x, SEEK_SET);
	file_read(fd, pk, 4);
	lseek(fd, pos_y, SEEK_SET);
	file_read(fd, pk + 4, 4);
	lseek(fd, pos_tfm, SEEK_SET);
	file_read(fd, pk + 8, 4);

	return (pk);
}

BUFFER *get_pkd(FONT_INFO *font, long pos, int *flag_ptr)
{
	long packet_length;
	int fd, k;
	uchar tmpc;

	union NUM {
		long l;
		uint i;
		uchar ch[4];
	}
	num;

	lseek(fd = font->ext.fh, pos, SEEK_SET);
	read(fd, &tmpc, 1);
	*flag_ptr = tmpc;
	if ((tmpc &= 7) == 7)
		k = 3;
	else {
		if (tmpc > 3)
			k = 1;
		else
			k = 0;
	}
	while (k >= 0)
		read(fd, &(num.ch[k--]), 1);

	switch (tmpc) {

	  case 7:
		  packet_length = num.l;
		  read(fd, &num.l, 3);
		  break;

	  case 4:
	  case 6:
	  case 5:
		  packet_length = ((ulong)(tmpc & 3) << 16) + num.i;
		  break;

	  default:
		  packet_length = (tmpc << 8) + num.ch[0];
		  break;
	}
	read(fd, &num.l, 1);
	if (ask_pk_buf(packet_length) == FAILURE)
		error(UNPACK_ERROR, "Too big raster in %s", font->pk + 5);
	file_read(fd, pk_buf_pointer->current, (int)packet_length);
	return (pk_buf_pointer->current);
}

#ifdef VFD
BUFFER *get_vfd(FONT_INFO *font, long pos, int packet_length)
{
	int fd;

	lseek(fd = font->ext.fh, pos, SEEK_SET);

	if (ask_pk_buf(packet_length) == FAILURE)
		error(UNPACK_ERROR, "Too big vector in %s", font->pk + 5);
	file_read(fd, pk_buf_pointer->current, packet_length);
	return (pk_buf_pointer->current);
}

#endif

static int read_flag_byte(BUFFER **pk_ptr)
	/*  flag byte を読み出す．specialsのときはスキップする．
     */
{
	int flag_byte;
	BUFFER *pk;
	long tmp;

	ENTER("read_flag_byte");

	pk = *pk_ptr;
	flag_byte = get_ubyte(pk);
	while (flag_byte >= 240 && flag_byte != PK_POST) {
		/* Skip Specials
         */
		switch (flag_byte) {
		  case 240:
		  case 241:
		  case 242:
		  case 243:
			  for (tmp = 0; flag_byte >= 240; flag_byte--)
				  tmp = (tmp << 8) + get_ubyte(pk);

			  move_ptr(pk, (uint)tmp);
			  break;
		  case 244:
			  move_ptr(pk, 4);
			  break;
		  case 245:
		  case 246:
			  break;
		  default:
			  error(UNPACK_ERROR, "Unexpected %d!", flag_byte);
		}
		flag_byte = get_ubyte(pk);
	};

	*pk_ptr = pk;
	RETURN(flag_byte);
}

static PREAMBLE *set_preamble(BUFFER **pk_ptr, int flag_byte,
							  FONT_INFO *font, int char_code)
	/*  PREAMBLEを_raster_buf上に設定する．
     */
{
	PREAMBLE *preamble;
	BUFFER *pk;
	BUFFER *font_pk;
	int tmp, tmph, tmpw, fsc;
	PIXEL *ofs;

	ENTER("set_preamble");

	preamble = alloc_preamble();
	pk = *pk_ptr;
	fsc = 0;

	switch (font->font_type) {

	  case (ZS_FONT):
#ifdef BEZIERFONT
	  case (JG_FONT):
#endif
		fsc = 2;
	  case (ROM_FONT):
	  case (JIS_FONT):
	  case (JIS_PK):
	  case (JIS_PKH):
	  case (GAIJI):
	  case (JLBP):
		  /*preamble->pitch_offset = 0;*/
		  if ( font->f_goth & K_SCALE2 ){
			  tmpw = font->k_width;
			  tmph = font->k_height;
			  if ( font->f_goth & F_TATE ){
				tmp  = tmpw;
			  	tmpw = tmph;
				tmph = tmp;
			  }
			  fsc  = 2;
		  }
		  else{
			  tmpw = (font->ext.kdir)->width;
			  tmph = (font->ext.kdir)->height;
		  }
		  if ( font->f_goth & F_TATE ){
			  rewrite_preamble_ptex(preamble, char_code);
			  fsc |= (preamble->rotate_ptex & 1);
		  }
		  preamble->width = (fsc==3)?tmph:tmpw;
		  preamble->height = (fsc==3)?tmpw:tmph;
		  preamble->depth_offset = (font->ext.kdir)->base;
		  if (font->f_goth & K_DBL) {
			  preamble->width *= 2;
			  preamble->height *= 2;
			  preamble->depth_offset *= 2;
		  }
		  preamble->tfm_width =
			  mult20(jtfm_width(font, get_int(pk)), font->size_para);

		  if (font->f_goth & K_SCALE)
			  tmp = font->k_width;
		  else
			  tmp = (font->f_goth & F_TATE)?tmph:tmpw;

		  if ((tmp = tmp - sptopixel(preamble->tfm_width)) == 0) {
			  preamble->pitch_offset = 0;
		  }
		  else {
			  if (char_code <= 0x2125	/* 、。，．゛゜°′″*/
				  || (char_code <= 0x212c && char_code >= 0x212b)
				  || (char_code >= 0x216b && char_code <= 0x216d)) {
				  tmp = 0;
			  }
			  else if (char_code <= 0x215b && char_code >= 0x214a) {
				  if (char_code & 1)
					  tmp = 0;	/* カッコ閉じ */
			  }
			  else {
				  tmp /= 2;
			  }
			  preamble->pitch_offset = tmp;
		  }
		  break;

	  case (PK_FONT):
	  case (PKD_FONT):
		  switch (flag_byte & 7) {

			case 7:
				/* long format */
				preamble->tfm_width = mult20(get_long(pk), font->size_para);
				move_ptr(pk, 8);
				/* Skip hor_esc */
				preamble->width = (int)get_long(pk);
				preamble->height = (int)get_long(pk);
				preamble->pitch_offset = (int)get_long(pk);
				preamble->depth_offset = (int)get_long(pk);
				break;

			case 4:
			case 5:
			case 6:
				/* ex-short format */
				preamble->tfm_width = mult20(get_mid(pk), font->size_para);
				move_ptr(pk, 2);
				/* Skip hor_esc */
				preamble->width = get_int(pk);
				preamble->height = get_int(pk);
				preamble->pitch_offset = get_int(pk);
				preamble->depth_offset = get_int(pk);
				break;

			default:
				/* short format */
				preamble->tfm_width = mult20(get_mid(pk), font->size_para);
				move_ptr(pk, 1);
				/* Skip hor_esc */
				preamble->width = (int)get_ubyte(pk);
				preamble->height = (int)get_ubyte(pk);
				preamble->pitch_offset = (int)get_byte(pk);
				preamble->depth_offset = (int)get_byte(pk);
				break;
		  }
		  break;

#ifdef VFD
	  case (VFD_FONT):
		  font_pk = font->pk + font->k_width - 4;
		  preamble->tfm_width = mult20(get_long(font_pk), font->size_para);
		  preamble->width = sptopixel(preamble->tfm_width);
		  preamble->height = vtopixel(preamble->tfm_width);
		  preamble->pitch_offset = 0;
		  preamble->depth_offset = preamble->height * 4 / 5;
		  /* this value is ad hoc */
		  break;
#endif

	  case (JXL):
		  preamble->pitch_offset = get_int(pk);
		  preamble->width = get_int(pk);
		  preamble->depth_offset = get_int(pk);
		  preamble->height = get_int(pk);
#ifndef NO_NTTRPL
		  if (ntt_subst && (font->code_offset >= 0)) {
sub_ntt:	get_long(pk);
			preamble->tfm_width =
				mult20(nttf_width[font->pt_size], font->size_para);
			preamble->pitch_offset =
				(((font->f_goth & K_SCALE)?font->k_width:preamble->width)
					- sptopixel(preamble->tfm_width))/2;
		  }
		  else
#endif
		  preamble->tfm_width = mult20(get_long(pk), font->size_para);
		  break;

	  case (PXL1001):
	  case (PXL1002):
	  case (PXL1003):
		  preamble->width = get_int(pk);
		  preamble->height = get_int(pk);
		  preamble->pitch_offset = get_int(pk);
		  preamble->depth_offset = get_int(pk);
		  get_long(pk);
		  preamble->tfm_width = mult20(get_long(pk), font->size_para);
		  pk -= 8;
		  break;
	}
	preamble->byte_width = (preamble->width + 7) / 8;
	*pk_ptr = pk;

	if (!(fsc&1)){
		preamble->shift_up_ptex = preamble->shift_right_ptex = 0;
		preamble->rotate_ptex = 0;
	}

	RETURN(preamble);
}

long jtfm_width(FONT_INFO *font, int c_type)
{
	BUFFER *pk;
	int tmp, tmp1;

	ENTER("jtfm_width");

#ifndef NO_NTTRPL
	if (ntt_subst && (font->code_offset >= 0))
		RETURN(nttf_width[font->pt_size]);
#endif
	pk = font->pk + 2;
	tmp = get_int(pk);			/* nt */
	move_ptr(pk, 2);			/* lf */
	tmp += get_int(pk);			/* lh */
	move_ptr(pk, 2);			/* bc = 0 */
	tmp1 = get_int(pk);			/* ec */
	move_ptr(pk, (tmp + 4 + c_type) << 2);
	tmp += (int)get_byte(pk);	/* width_index */
	pk = font->pk;
	move_ptr(pk, (tmp + tmp1 + 8) << 2);

	RETURN(get_long(pk));

}

JFM_DATA *jfm_read(FONT_INFO *font, int char_code)
	/* read JFM files properly   21 July 1992, by Naochan! */
{
	static JFM_DATA jtfm;

	BUFFER *pk;
	int i, c_type;
	int tmp, tmp_w, w_to_h, h_to_d, d_to_i, tmp2, tmp3;
	int index_w, index_h, index_d, index_i, get_byte_tmp;
	int lh, nt, ec, nw, nh, nd;

	ENTER("jfm_read");

	pk = font->pk;
	tmp = get_int(pk);			/* id */
	jtfm.id = tmp;
	nt = get_int(pk);			/* nt */
	move_ptr(pk, 2);			/* skip lf  */
	lh = get_int(pk);			/* lh */
	move_ptr(pk, 2);			/* skip bc(=0) */
	ec = get_int(pk);			/* ec */
	nw = get_int(pk);			/* nw */
	nh = get_int(pk);			/* nh */
	nd = get_int(pk);			/* nd */

	move_ptr(pk, (lh + 3) << 2);/* set c_type */
	c_type = get_int(pk);
	for (i = 1; i < nt; i++) {
		tmp2 = get_int(pk);
		tmp3 = get_int(pk);
		if (char_code == tmp2) {
			c_type = tmp3;
			move_ptr(pk, (nt - i - 1) << 2);
			break;
		}
	}
	jtfm.char_type = c_type;

	move_ptr(pk, c_type << 2);
	index_w = (int)get_byte(pk);/*  width_index */
	get_byte_tmp = (int)get_byte(pk);
	index_h = (get_byte_tmp & 0x00F0) >> 4;	/* height_index */
	index_d = get_byte_tmp & 0x000F;	/*  depth_index */
	index_i = ((int)get_byte(pk) & 0x00FC) >> 2;	/* italic_index */

	tmp_w = (lh + nt + ec + index_w + 8) << 2;
	w_to_h = (nw - index_w + index_h - 1) << 2;
	h_to_d = (nh - index_h + index_d - 1) << 2;
	d_to_i = (nd - index_d + index_i - 1) << 2;

	pk = font->pk;				/* return to the home position */
	move_ptr(pk, tmp_w);
	jtfm.width = get_long(pk);
	move_ptr(pk, w_to_h);
	jtfm.height = get_long(pk);
	move_ptr(pk, h_to_d);
	jtfm.depth = get_long(pk);
	move_ptr(pk, d_to_i);
	jtfm.italic = get_long(pk);
#ifndef NO_NTTRPL
	if (ntt_subst && (font->code_offset >= 0))
		jtfm.width = jtfm.height = nttf_width[font->pt_size];
#endif

	RETURN(&jtfm);
}

#if DEBUG & MEM_CHK
static void _pkptrchk(BUFFER *ptr)
{
	if ((uchar huge *)ptr < (uchar huge *)(pk_buf_pointer->start)
		|| (uchar huge *)ptr >= (uchar huge *)(pk_buf_pointer->end))
		error(MEMORY_FAULT, "pk-buffer");
}

#endif

#ifdef AX
int toSJISc(jis)	/* JIS->SJIS */
	unsigned short jis;
{
	register unsigned short h, l;

	h = (jis >> 8) & 0xff;
	l = jis & 0xff;
	if (h & 1)
		l += 0x1f;
	else
		l += 0x7d;
	if (l >= 0x7f)
		l++;
	h = (h - 0x21 >> 1) + 0x81;
	if (h > 0x9f)
		h += 0x40;
	RETURN(h << 8 | l);
}

#endif

#ifndef NO_NTTRPL
void unify_nttjfont(FONT_INFO *font)
{
	FONT_INFO *dfont;
	for(dfont = first_font_info; dfont; dfont = dfont->next_font)
		if (dfont->family_code == font->family_code
				&& dfont->font_type == UNKNOWN) {
			dfont->font_type = font->font_type;
			dfont->f_goth = font->f_goth;
			dfont->pk = font->pk;
			dfont->k_width = font->k_width;
			dfont->k_height = font->k_height;
			dfont->last = font->last;
			dfont->ext = font->ext;
#ifdef	LBP
			dfont->lbp_font_inf = font->lbp_font_inf;
#endif
		}
}
#endif

static void resizefont(uchar *raster, uint src_x_dots, uint src_y_dots,
	PREAMBLE *preamble)
/*
 *  ROM FONT の拡大・縮小
 *
 * ●用法
 *
 * raster に格納されている ROM フォントを拡大／縮小して
 * preamble->raster にコピ−。
 *
 * フォントのサイズが 64KByte 以内であれば、フォントの縦横のサイズに
 * 制限はない(はずである)。
 * 
 * ●アルゴリズム
 * 
 * コピー元のフォントの各ドットがコピー先のどのドットにあたるか計算し
 * ながら、コピーする。
 * 
 * 縮小する場合は、コピー元の複数ドットがコピー先の１ドットに対応する。
 *（Naochan!氏の minifont 関数のアルゴリズム）
 * 
 * 逆に、拡大する場合は、コピー元の１ドットをコピー先の複数ドットに対
 * 応させる必要がある。そのために、元の１ドットを (dx0,dy0)-(dx1,dy1)
 * の範囲ドットに対応させるようになっている。
 * （吉澤氏の residebf.c のアルゴリズム）
 * 
 * フォントが、かすれたり、逆に潰れたりしないように、(dx0,dy0)-(dx1,
 * dy1)が他のドットとちょうど重ならない範囲となるように、少し工夫して
 * いる。(縮小する場合はどうしても重なってしまうが、拡大する場合は、
 * 重ならないはずである。)
 * 
 * 途中、(long) にキャストしているのは、16bit int のオーバー・フロー
 * を避けるためである。src_[xy]_dots / 2 を加算しているのは、四捨五入
 * のためである。
 *
 * この関数は、特別な作業領域を必要としない。また、スタック上に大きな
 * 作業配列をとるようなこともしてない。
 *
 * 拡大時に、線の太さが一定になるように、拡大前の１ドットが拡大後の何
 * ドットにあたるのかをあらかじめ計算している。（thick_[xy]） その際、
 * 隣接するドットとの間に隙間ができないように補正している。
 * （松田氏のアルゴリズム）
 * 
 * 若干の高速化とバグ修正を行った（SHIMA）
 *
 * ※このサブルーチンは、Naochan!によって Ver.2.38 からサポートされた
 *   ROMfont縮小ルーチン minifont()と、吉澤氏が作成した resizebf.c を
 *   融合し、書き直したものです。
 *
 */

{
#define CHK_DOT(x, y) (raster[((uint)y)*src_x_bytes + (((uint)x)>>3)] & row[(x)&7])
#define SET_DOT(x, y) (dst[((uint)y)*dst_x_bytes + (((uint)x)>>3)] |= row[(x)&7])

	static uchar row[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
	BUFFER *dst;
	BUFFER *d;
	uint n;
	uint src_x_bytes;			/* x-方向のバイト数			*/
	uint dst_byte_size;			/* フォント全体のバイト数	*/
	int  sx, sy;				/* コピー元のドット位置		*/
	int  dx, dy;				/* コピー先のドット位置		*/
	uint dx0, dy0, dx1, dy1;	/* コピー先のドット範囲		*/
	uint dst_x_bytes;			/* コピー先のバイト幅		*/
	uint dx0_m, dy0_m, dx1_m, dy1_m, dx1_p;	/* 計算用		*/
	uint thick_x, thick_y;		/* 線の太さ					*/
	uint tx_half, ty_half;      /* (thick_[xy] + 1)/ 2 の値 */
    int  sxd_m, syd_m, dxd_m, dyd_m;    /* 計算用 */
	int  f_now, f_left, f_up;	/* 拡大用のドット情報 　　　*/


	dst = preamble->raster;
	dst_byte_size = (dst_x_bytes = preamble->byte_width)
					* (dyd_m = preamble->height);
	if (!(sxd_m = src_x_dots) || !(syd_m = src_y_dots)) return;
	if ((dxd_m = preamble->width) == src_x_dots && dyd_m == src_y_dots) {
		/* サイズが同じ:単純コピーでよい。*/
		while (dst_byte_size-- > 0) *dst++ = *raster++;
		return;
	}
	/* コピー先をゼロ・クリア */
	for (d = dst, n = dst_byte_size; n > 0; n--) *d++ = 0;

	src_x_bytes = ((src_x_dots + 7) >> 3);

    if (dxd_m <= src_x_dots && dyd_m <= src_y_dots) {
        /* 縮小の場合はNaochan!のアルゴリズムで */

		if (sxd_m > 1){
 			sxd_m--;         			/* `src_x_dots' minus 1 */
			dxd_m--;					/* `dst_x_dots' minus 1 */
		}
	   	if (syd_m > 1){
			syd_m--;					/* `src_y_dots' minus 1 */
			dyd_m--;					/* `dst_y_dots' minus 1 */
		}

		f_up = ((long)src_y_dots*dyd_m + syd_m >= 0x8000L)?1:0;
		ty_half = syd_m >> 1;

        for (sx = 0; sx < src_x_dots; sx++) {
			dx = ( (long)sx * dxd_m + (sxd_m>>1) ) / sxd_m;
            for (sy = 0; sy < src_y_dots; sy++) {
                if (CHK_DOT(sx, sy)){
                    dy = (f_up)? ((long)sy * dyd_m + ty_half) / syd_m:
								 (sy * dyd_m + ty_half) / syd_m;
	                    SET_DOT(dx, dy);
                }
            }
        }
		return;
    }

	/* 拡大の場合は吉澤氏と松田氏のアルゴリズムで */
	/* 線の太さは拡大率を丸めたもの */
	thick_x = (dxd_m + src_x_dots/2) / src_x_dots;
	tx_half = ((thick_x + 1) >> 1);
	thick_y = (dyd_m + src_y_dots/2) / src_y_dots;
	ty_half = ((thick_y + 1) >> 1);

	if (sxd_m > 1) sxd_m--;		/* `src_x_dots' minus 1 */
	dxd_m -= thick_x;			/* `dst_x_dots' minus thick_x */
	if (syd_m > 1) syd_m--;		/* `src_y_dots' minus 1 */
	dyd_m -= thick_y;			/* `dst_y_dots' minus thick_y */

	for (sy = 0; sy < src_y_dots; sy++) {
		dy0 = ((long)sy * dyd_m + syd_m/2) / syd_m;
		dy1 = dy0 + thick_y;
        dy0_m = dy0 - ty_half;
        dy1_m = dy1 - ty_half;
		for (sx = f_left = 0; sx < src_x_dots; f_left = f_now, sx++) {
			if ((f_now = CHK_DOT(sx, sy)) != 0) {
				dx0 = ((long)sx * dxd_m + sxd_m/2) / sxd_m;
				dx1 = dx0 + thick_x;
				for (dy = dy0; dy < dy1; dy++) {
					for (dx = dx0; dx < dx1; dx++)
						SET_DOT(dx,dy);
				}
				/* 隙間補正(左) */
				if (f_left) {
					dx = dx0 - 1;
					for (dy = dy0; dy < dy1; dy++)
						SET_DOT(dx,dy);
				}
				/* 隙間補正(上) */
				if (sy > 0) {
					if ((f_up = CHK_DOT(sx, sy-1)) != 0) {
						dy = dy0 - 1;
						for (dx = dx0; dx < dx1; dx++)
							SET_DOT(dx,dy);
					}
					dx0_m = dx0 - tx_half;
					dx1_m = dx1 - tx_half;
					/* 隙間補正(左上) */
					if (sx > 0) {
						if (!f_up){
							if (!f_left && CHK_DOT(sx-1, sy-1)) {
								for (dy = dy0_m; dy < dy1_m; dy++) {
									for (dx = dx0_m; dx < dx1_m; dx++)
											SET_DOT(dx,dy);
								}
							}
						}else if (f_left && CHK_DOT(sx-1,sy-1))
							SET_DOT(dx0 - 1, dy0 - 1);
					}
					/* 隙間補正(右上) */
					if (!f_up && sx < src_x_dots - 1) {
						if (CHK_DOT(sx+1, sy-1) && !CHK_DOT(sx+1, sy)) {
			        		dx1_p = dx1 + tx_half;
							for (dy = dy0_m; dy < dy1_m; dy++) {
								for (dx = dx0 + tx_half; dx < dx1_p; dx++)
									SET_DOT(dx,dy);
							}
						}
					}
				}
			}
		}
	}
}
 /* end of file getfont.c */
