/*  TEX Device Driver  ver 2.02-
 *  copyright(c) 1988, 1989 by TSG, 1990-1996 by SHIMA
 *  1991 changed by hideki
 *  1991 changed by T.Minagawa
 *
 *  init.c : initialize variables
 *      Apr. 29, 1989 : 1st edition
 *      Jun.  1, 1989 : 2nd edition
 *
 *  This module is a device-dependent one.
 *	modified for non PC-9801 by sempa 1992
 *             14 June 1992 : modified for tpic by Oh-Yeah?
 *
 *  modifed for LIPS3 by SHIMA, 30 June 1992
 *  modified for Hires-9801 by OkI 21 June 1992
 *  modified for pTeX `tate' mode,  6 August 1992  by Naochan!.
 *  slightly modified by OkI 8 August 1992 (pTeX & Hires & LIPS3)
 *  modified for ESC/Page by H.Tomiie, 20 August 1992
 *	modified for "-wait" option by sempa, 1 Sept 1992
 *	modified for LIPS3+ESC/Page by OkI & H.Tomiie 30 Sept. 1992
 *  slightly modified for NTTjTeX by Yakumo, 27 Nov. 1992
 *  slightly modified for NTTjTeX by Yakumo, 16 Dec. 1992
 *  modified for EMS by SHIMA, Dec 1992
 *  modified for LIPS Special commands  by Sadayuki Iwai 8 Nov. 1993
 */


#define	OFF_USG	4
#include <stdio.h>
#include <stdlib.h>

#ifndef   UNIX
#ifdef MSVC
#include "msvcdir.h"
#else
#include <dir.h>
#endif
#ifdef	GCC1
#include <djgppstd.h>
#else
#ifdef MSVC
#include <memory.h>
#include <malloc.h>
#else
#include <mem.h>
#include <alloc.h>
#endif
#endif
#include <io.h>
#endif

#include <string.h>
#include <ctype.h>

#include "dd.h"
#include "err.h"
#include "dviread.h"
#include "prtout.h"
#include "option.h"
#include "version.h"
#ifndef	NOVFONT
#include "vfont.h"
#endif
#include "inter.h"
#include "dviadd.h"
#ifdef	DVI_ADD
#include "sys/stat.h"
#include "tar.h"
#endif

void get_config(int, char **);
void initialize(DVIFILE_INFO *, DIMENSION *);

void end_config();
static void set_prt_type(DIMENSION *dim);
static int  read_post(DVIFILE_INFO *);
static void pixel_init(DVIFILE_INFO *, DIMENSION *);

/* static void set_mag( DIMENSION* ); */
static void set_dimension(DVIFILE_INFO *, DIMENSION *);
static void make_page_index(DVIFILE_INFO *, DIMENSION *);
static void youshi_size(char *);
static void option_usage(void);

/* main.c */
void Exit(int);
FILE *PushDVI(int);

/* err.c */
void more(void);

/* option.c */
int make_path(char *path, char *dir, char *name, char *ext);
void *show_option(ARG_TABLE *, int);
int length_to_sp(char *, SCALED_PT *);

/* size.c, prtsize.c */
void set_convert(SIZE_PARA, int, int);
PIXEL sptopixel(SCALED_PT);
PIXEL vtopixel(SCALED_PT);
int set_size(PIXEL, PIXEL, PIXEL, PIXEL, PIXEL *, PIXEL *);

/* fontdef.c */
void make_font_list(DVIFILE_INFO *, DIMENSION *);

/* buffer.c */
void buffer_init(void);
void *marea(int);
char *dup_string(char *);

/* decodepk.c */
void decode_init(void);

/* mult20.asm */
ulong mult20(ulong, ulong);

/* p_out.c */
void get_prt_ctl(char *fname);
#ifdef LBP
void set_LBP_prt_ctl(int hunit, int vunit);
#endif

/* stack.c */
void stack_init(int stack_max);

#ifndef NOTPIC
/* tpic.c */
void tpic_init(PIXEL buf_height);	/* alloc y-bucket[vmax] and activate */

#endif

/* vfont.c */
int get_vfont_name(char *cfg_name);

/* mwndproc.c */
void SetButton(void);

/* inter.c */
FILE *PushDVI(int);

#ifndef NOPSFRAG
void header_special_init(FILE *);
#endif

int f_init = INIT_ALL;
BOOL f_Expand;
int paper_type = SIZE_A4;
#ifdef	RAWOUT
BOOL f_dviprt = FALSE;
#endif

int ExpandGZ(char *, FILE **, char *);

/* vfont.c escpage.c 疑似縦書きスイッチ Tomiie*/
#ifndef	NOTATEGAKI
int tategaki = 0;
#endif

#ifndef NO_NTTRPL
/* NTTjTeX->ASCII日本語TeX font変換フラグ */
BOOL ntt_subst;
char *ntt_subst_fonts;

#endif

#ifndef NO_GENFONT
char *genfont_tmpl = NULL;
#endif

/* LBPプリンターが選ばれていることを示すフラグ */
BOOL f_lbp_prt;

static int opt_mag = -1;

static BOOL mag_half = FALSE;
/* -half があるかどうか */

int test_flg = -1;
/* -f があるかどうか */

BOOL dvifile_page = FALSE;

#ifdef	WIN32G
int f_scr_skip = 16;
#endif

/* pret.c */
BOOL LoadInit(BOOL);
#ifdef JDWN
extern DJTABLE* dj;
#endif

extern int length_to_dot(char *, int *, int);

int enlarge;
static char *ff_flg_str;

/* by K.Yoshizawa  Dec. 26, 1992 */
/* A4 :  210mm x 297mm */
#ifdef	WIN32G
BOOL   f_area = TRUE;			/* デフォルトのマージン */
#endif
static SCALED_PT OPW;
static SCALED_PT OPH;
	   SCALED_PT PW = MM_TO_SP(210);	/* 用紙の横幅 */
	   SCALED_PT PH = MM_TO_SP(297);	/* 用紙の縦幅 */
static SCALED_PT TM = -1L;				/* 用紙上端部のマージン */
static SCALED_PT BM = -1L;				/* 用紙下端部のマージン */
static SCALED_PT LM = -1L;				/* 用紙左端部のマージン */
static SCALED_PT RM = -1L;				/* 用紙右端部のマージン */
static SCALED_PT MW;					/* 印字可能域の最大横幅 */
static SCALED_PT MH;					/* 印字可能域の最大縦幅 */
SCALED_PT OX;						/* 横方向の原点の座標 */
SCALED_PT OY;						/* 縦方向の原点の座標 */
/* by K.Yoshizawa  Dec. 27, 1992 */
BOOL HC = FALSE;						/* 水平センタリング */
BOOL VC = FALSE;						/* 垂直センタリング */
SCALED_PT HS;							/* 水平センタリング後の移動 */
SCALED_PT VS;							/* 垂直センタリング後の移動 */
/* by K.Yoshizawa  Dec. 28, 1992 */
static int PF = 1;						/* 給紙位置 */

#ifdef	WIN32G
PIXEL	LeftMargine;
PIXEL	TopMargine;
PIXEL	RightMargine;
PIXEL	BottomMargine;

char *vfn_orgE = 
	"\n"
	"%version=2\n"
	"%vfont_list\n"
	"1,\042cmr10\042\n"
	"%jfm_list\n"
	"edefault,1,a,a,n,0;0;0,,1,0\n";
char *vfn_orgJ =
	"\n"
	"%version=2\n"
	"%vfont_list\n"
	"1,\042ＭＳ 明朝\042\n"
	"2,\042ＭＳ ゴシック\042\n"
	"3,\042@ＭＳ 明朝\042\n"
	"4,\042@ＭＳ ゴシック\042\n"
	"5,\042cmr10\042\n"
	"%jfm_list\n"
	"min,1,a,a,n,0;0;0,,1,0\n"
	"goth,2,a,a,n,0;0;0,,1,0\n"
	"tmin,3,a,a,n,0;0;0,,1,1\n"
	"tgoth,4,a,a,n,0;0;0,,1,1\n"
	"jis,1,a,a,n,0;0;0,,1,0\n"
	"jisg,2,a,a,n,0;0;0,,1,0\n"
	"default,1,a,b,n,0;0;0,,1,0\n"
	"tdefault,3,a,b,n,0;0;0,,1,1\n"
	"edefault,5,a,a,n,0;0;0,,1,0\n";
char *vfn_org =
	"\n"
	"%version=2\n";
#endif

#define	CFG_PATH	"TEXCFG"

#ifdef	UNIX
char	*cfg_path = 
# ifdef	CFGPATH
		CFGPATH;
# else
		"/usr/local/lib/texmf/";
# endif
#else
char far *cfg_path = NULL;	/* p_outでも参照するため，GROBALにした．
								get_configでfarmallocしている*/
#endif

static char progname[MAXPATH]			/* program name */
#ifdef	WIN32G
	 = "dviout";
#else
	 = "dviprt";		
static char inipath[MAX_PATH];
static int dviext;
#endif
static char config_name[MAXPATH];					/* config file name */
#ifndef	WIN32G
static char v_real_name[MAXPATH];					/* VFONT file name */
#else
static char *v_real_name;
#endif

char current_name[MAX_PATH];	/* original filename (may be foo.dvi.gz) */
char *current_name_pt = &current_name[0];

/* config file name */
const char *const pk_env_name = "TEXPK";

/* name of the env-variable for pk-font path */
const char *const title_name = "TeX PRINTER DRIVER "
MACHINE VERSION;

const char *const title_comment =
/*
#ifdef LBP
"("
#  ifdef LIPS3
"LIPSIII"
#   ifdef ESCPAGE
"&"
#   endif
#  endif
#  ifdef ESCPAGE
"ESC/Page"
#  endif
");";

#else
";";
#endif
*/
"";


const char *const title_copyright =
"\nCopyright(C) 1988-89 by TSG, 90-98 by SHIMA,"
#ifdef VFD
"\n\t     1991-98 changed by Akiii, hero.h, hideki, Naochan!, Oh-Yeah?, OkI,"
"\n\t\t     SOLITON, "
#else
"\n\t     1991-98 changed by Akiii, hero.h, Matsuda, Naochan!, Oh-Yeah?, OkI"
"\n\t\t"
#endif
#ifdef	LBP
		"SADA, "
#endif
		"SOLITON, sempa, T.Minagawa, Tomiie, "
#ifndef NOPS
		"T.Uchiyama, "
#endif
		"Yakumo\n\t\tYoshizawa, Asayama"
#ifdef DOSC
		", HARUYA"
#endif
#ifdef UNIX
		", Ohmori"
#endif
;

char *resume_file;
int org_mag;

#ifndef NOTPIC
int f_tpic_turn_on = 2;	/* default is spline */
#ifndef NOPS
BOOL f_gsize;
BOOL f_gow;
BOOL f_gclip = TRUE;
#ifdef	GIF
int	f_GIF;
#endif
char *gs_exe;
char *pbm_path;
#endif
#endif

#ifndef	UNIX
int	machine = -1; 	  /* 0: PC9801
						 1: DOS/V
						 2: J3100 */
#endif

extern int ARGC;
extern char prt_type;
extern int ff_flg;
extern int comp_type;
extern int f_wait;
extern PIXEL vert_divide;

void set_trans_jis(char *);
extern char ptex_mode;

#ifndef	NOVFONT
extern int f_use_vfont;
char *vfont_name;
void flush_vfont(void);
#  ifdef TTFONT
extern int f_use_ttf;
#  endif
#endif

#ifdef	HYPERTEX
void flush_hyper(void);
void clear_hyper_buf(void);
extern char base_href[];
#endif

#if	!defined(PC9801) || defined(DOSV)
extern char *pr_port_str;
#endif

extern BOOL f_rotate;

#ifdef LBP
extern int f_use_lfont;
extern int f_vh_ratio;
extern int f_copy;
extern int d_mincount;
extern char *youshi;
extern int k_base_l;	/* LBP 漢字ベース位置のファクター */
extern int k_scale_l;	/* LBP 漢字幅補正用のファクター */
extern int lbp_orig_dpi;	/* LBP本来の dpi 値デフォルト300 */
extern LBP_FUNC *lbpf;
extern BOOL f_lbp_comp;
extern int f_font_on_edge;	/* 紙面の縁のフォントも印刷する */
# ifdef	LIPS3
extern LBP_FUNC lips3_func;

# endif
# ifdef	ESCPAGE
extern LBP_FUNC escpage_func;

# endif
#else
char *youshi;
#endif

extern char *f_bmp;
#ifdef	FAX
extern char *f_fax;
#endif

#ifdef	FDOWN
#define		MAX_FONTDEF	6
extern int f_download;
extern int f_jdwn;
extern int f_cell;
extern long max_dsize;
extern char *font_def;
#endif

#ifdef	JDWN
extern int dj_min;
extern int dj_skip;
extern int f_gaiji;
extern uint dj_current;
#endif

#define	FAR_HEAP	0L
#define BUFFER_NUM	4

BUF_INFO buffers[BUFFER_NUM] =
{
	{NULL,NULL,NULL, DEF_RASTER_SIZE, 0},
	{NULL,NULL,NULL, DEF_PK_SIZE, 0},
	{NULL,NULL,NULL, DEF_BITMAP_SIZE, 0},
};

int org_bb_size = DEF_BITMAP_SIZE;

FONT_INFO *first_font_info = NULL;
FONT_INFO *font_info_root = NULL;

DIMENSION dviout_dimension =
{
	PRINTER_DPI,			/* dpi */
	0,						/* DPI */
	0, 0,					/* device width, height */
	0, 0,					/* output width, height */
	0, 0,					/* buffer width, height */
	0, 0,					/* text width, height */
	DEF_MAG,				/* mag */
	0, 						/* split */
	DEF_PRINT_DIR,			/* print direction */
	0,						/* convert parameter */
	0, 0,					/* x-offset, y-offset */
	0, 						/* offset of the page */
	0, 						/* total page */
	0, 0,					/* start page, end page */
	PRT_TYPE,				/* device type */
};

static char *pt_prt_type;

#include "prtinit.h"

void end_config(void)
{
	int l;

#ifndef	NOVFONT
	if(f_use_vfont == TRUE){
		if(!(f_init & INIT_VFONT) || vfont_name == NULL
		  || (*vfont_name <= ' ' && *vfont_name != '\n') )
			return;
		flush_vfont();
	}
#ifdef WIN32G
	v_real_name = vfont_name;
#endif
	f_use_vfont = FALSE;
	if (vfont_name != NULL && *vfont_name != '-') {
		f_init |= INIT_FONT;
		if (0 != (l = get_vfont_name(v_real_name))) {
			if (l > 0)
				error(WARNING,
					"[vfont] dviout.vfn/dviprt.vfn error(line:%d)", l);
			else
				error(WARNING,
					"[vfont] Can't open dviout.vfn/dviprt.vfn file");
			flush_vfont();
		}else
			f_use_vfont = TRUE;
	}
#endif
}

#ifndef	WIN32G
void get_config(int argc, char **argv)
{
	int i, l;
	char real_name[MAXPATH];
	char path_name[MAXPATH];
	char *cfgpath, *srcpath;

	strcpy(inipath, argv[0]);
	dviext=strlen(inipath)+1;
# ifdef	UNIX
	for(l = strlen(argv[0]); l >= 0; l-- )
		if(argv[0][l] == PATH_SEP) break;
	strcpy(config_name, argv[0] + l + 1);
	strcat(inipath, ".");
# else
	fnsplit(argv[0], real_name, v_real_name, config_name, path_name);
	if (memcmp(strlwr(config_name), "dvi", 3) == 0)
		strcpy(progname, config_name);
	dviext -= strlen(path_name);
# endif
	strcat(config_name, ".par");

	if ((cfgpath = getenv(CFG_PATH)) != NULL) {
		strncpy(path_name, cfgpath, MAXPATH - 2);
		i = strlen(path_name);
		if (isalnum(path_name[i - 1])) {
			path_name[i] = PATH_SEP;
			path_name[++i] = '\0';
		}
		cfg_path = dup_string(path_name);
	}
	else {
# ifdef	UNIX
		strcpy(path_name, cfg_path);
# else
		cfg_path = (char far *)"";
		path_name[0] = '\0';
# endif
	}
	strcpy(real_name, path_name);
	strcat(real_name, config_name);
	if (access(real_name, 0) == -1){
# ifndef GCC
		if ((srcpath = searchpath(config_name)) != NULL)
			strncpy(real_name, srcpath, MAXPATH - 2);
		else
# endif
			*real_name = 0;
	}
	if (*real_name) set_config(real_name);
	set_option(argc, argv);

#if	defined(PC9801) && defined(DOSV)
	if(machine < 0 || 
# ifdef J3100
	  machine > M_J31)
# else
	  machine > M_DOSV)
# endif
		error(ILLEGAL_ARGS, "  -hard=%d\n"
		"Indicate\t-hard=0[PC9801], 1[DOS/V], 2[J3100]\n",
		machine);
	machine = M_DOSV;
#endif

#ifndef	NOVFONT
	if (vfont_name != NULL && *vfont_name != '-') {
		make_path(real_name,
			NULL,
			(*vfont_name == 0 || *vfont_name == '+')?
#  ifdef WIN32G
			  "dviout"
#  else
			  "dviprt"
#  endif
			  :vfont_name, ".vfn");
		make_path(v_real_name, path_name, real_name, NULL);
# ifndef	GCC
		if (access(v_real_name, 0) == -1) {
			if ((srcpath = searchpath(real_name)) != NULL)
				strncpy(v_real_name, srcpath, MAXPATH - 2);
		}
# endif
	}
#endif
}

char *GetOutPath(char *ext)
{
	strcpy(inipath+dviext, ext);
	return &inipath[0];
}

#endif   /* End of #ifndef WIN32 */


void initialize(DVIFILE_INFO *dvi, DIMENSION *dim)
{
	if(!f_init || g_nErrorCode)		return;
	if(f_init & INIT_ENDCFG)	end_config();
	if((f_init & INIT_DVIREAD) && read_post(dvi))
								f_init |= INIT_METRIC;
	if(g_nErrorCode & FFE_DVI)		return;				/* Not DVI file */
	if(f_init & INIT_PRINTER)	set_prt_type(dim);
	if(f_init & INIT_NEWDIM)	set_dimension(dvi, dim);
	if(f_init & INIT_CHKFONT)	make_font_list(dvi, dim);
	if(g_nErrorCode)					return;
	if(f_init & INIT_DVIREAD){
								stack_init(dvi->stack_depth);
								make_page_index(dvi, dim);
	}
	if(f_init & INIT_PIXEL)		pixel_init(dvi, dim);
	if(f_init & INIT_BUFFER)	buffer_init();
	if(f_init & INIT_DECODE)	decode_init();
#ifndef NOTPIC
	if(f_init & (INIT_TPIC|INIT_BUFFER))
								tpic_init(f_tpic_turn_on?dim->buf_height:0);
#endif
#ifdef	HYPERTEX
	if(f_init & INIT_HYPER){
								flush_hyper();
								clear_hyper_buf();
	}
#endif
#ifdef	WIN32G
	if(f_init & INIT_BUTTON)	SetButton();
	if(f_init & INIT_BRIGHT)	SetBright();
	if(f_init & INIT_BMP)		SetBMP();
	ClearKeepBMP();
#endif
	if(!g_nErrorCode)
		f_init = 0;
}

/* set youshi size */
static void youshi_size(char *opt)
{
	int	ch;
	int pw, ph;

#ifdef	WIN32G
	if(f_FIT)
		return;
#endif
	ch = (*opt)?opt[1]:0;
	Free0(youshi);
	youshi = dup_string(opt);
#ifdef	WIN32G
	InitMenuItems();
#endif
	OPH = OPW = 0;
	switch(toupper(*opt)){
		case 'A':
			if (ch == '4'){
				PW = MM_TO_SP(210);
				PH = MM_TO_SP(297);
				paper_type = SIZE_A4;
			}
			else if (ch == '3'){
				PW = MM_TO_SP(297);
				PH = MM_TO_SP(420);
				paper_type = SIZE_A3;
			}
			else if (ch == '5'){
				PW = MM_TO_SP(148.5);
				PH = MM_TO_SP(210);
				paper_type = SIZE_A5;
			}
			else if (ch == '6'){
				PW = MM_TO_SP(105);
				PH = MM_TO_SP(148.5);
				paper_type = SIZE_A6;
			}
			else if (ch == '7'){
				PW = MM_TO_SP(74);
				PH = MM_TO_SP(105);
				paper_type = SIZE_A7;
			}
			goto skip_number;
		case 'B':
			if(ch && opt[2] == 'E')
				goto esize;
			if (ch == '4'){
				PW = MM_TO_SP(257);
				PH = MM_TO_SP(364);
				paper_type = SIZE_B4;
			}
			else if (ch == '5'){
				PW = MM_TO_SP(182);
				PH = MM_TO_SP(257);
				paper_type = SIZE_B5;
			}
			else if (ch == '3'){
				PW = MM_TO_SP(364);
				PH = MM_TO_SP(514);
				paper_type = SIZE_B3;
			}
			else if (ch == '6'){
				PW = MM_TO_SP(128.5);
				PH = MM_TO_SP(182);
				paper_type = SIZE_B6;
			}
			goto skip_number;
		case 'E':
esize:		if (ch == '4'){
				PW = MM_TO_SP(250);
				PH = MM_TO_SP(353);
				paper_type = SIZE_E4;
			}
			else if (ch == '5'){
				PW = MM_TO_SP(176);
				PH = MM_TO_SP(250);
				paper_type = SIZE_E5;
			}
			else if (ch == '3'){
				PW = MM_TO_SP(353);
				PH = MM_TO_SP(500);
				paper_type = SIZE_E3;
			}
			else if (ch == '6'){
				PW = MM_TO_SP(125);
				PH = MM_TO_SP(176);
				paper_type = SIZE_E6;
			}
			else if( memcmp(++opt, "xecutive", 8) == 0){
				opt += 8;
				PH = IN_TO_SP(10.5);
				PW = IN_TO_SP(7.25);
				paper_type = SIZE_EXECUTIVE;
				break;
			}
			goto skip_number;
		case 'S':
			if( memcmp(++opt, "VGA", 3) == 0){
				opt += 3;
				PW = IN_TO_SP(8);
				PH = IN_TO_SP(6);
				paper_type = SIZE_SVGA;
			}else if( memcmp(opt, "XGA", 3) == 0){
				opt += 3;
				PW = IN_TO_SP(12.8);
				PH = IN_TO_SP(10.24);
				paper_type = SIZE_SXGA;
			}else goto illegal;
			break;
		case 'X':
			if( memcmp(++opt, "GA", 2) == 0){
				opt += 2;
				PW = IN_TO_SP(10.24);
				PH = IN_TO_SP(7.68);
				paper_type = SIZE_XGA;
				break;
			}
			goto illegal;
		case 'U':
			if(memcmp(++opt, "VGA", 3) == 0){
				PW = IN_TO_SP(10.667);
				PH = IN_TO_SP(8);
				paper_type = SIZE_UVGA;
				opt += 3;
				break;
			}
			goto illegal;
		case 'J':
			if (ch == '1'){
				PW = MM_TO_SP(152);
				PH = MM_TO_SP(218);
				paper_type = SIZE_J1;
			}
			else if (ch == '2'){
				PW = MM_TO_SP(127);
				PH = MM_TO_SP(188);
				paper_type = SIZE_J2;
			}
			else if (ch == '3'){
				PW = MM_TO_SP(103);
				PH = MM_TO_SP(182);
				paper_type = SIZE_J3;
			}
			else if (ch == '4'){
				PW = MM_TO_SP(210);
				PH = MM_TO_SP(257);
				paper_type = SIZE_J4;
			}
			goto skip_number;
		case 'H':
			if( memcmp(++opt, "alfLetter", 9) == 0 )
			{
				opt += 9;
				PH = IN_TO_SP(8.5);
				PW = IN_TO_SP(5.5);
				paper_type = SIZE_HALFLETTER;
			}
			else
			{
				PW = MM_TO_SP(100);
				PH = MM_TO_SP(148);
				paper_type = SIZE_PCARD;
			}
			break;
		case 'G':
			if( memcmp(++opt, "ovLetter", 8) == 0 )
			{
				opt += 8;
				PH = IN_TO_SP(10.5);
				PW = IN_TO_SP(8);
				paper_type = SIZE_GOVLETTER;
			}
			else if( memcmp(opt, "ovLegal", 7) == 0 )
			{
				opt += 7;
				PH = IN_TO_SP(13);
				PW = IN_TO_SP(8.5);
				paper_type = SIZE_GOVLEGAL;
			}
			else goto illegal;
			break;
		case 'L':
			if(memcmp(++opt, "egal", 4) == 0){
				opt += 4;
				PH = IN_TO_SP(14);
				PW = IN_TO_SP(8.5);
				paper_type = SIZE_LEGAL;
			}
			else if(memcmp(opt, "etter", 5) == 0){
				opt += 5;
				PH = IN_TO_SP(11);
				PW = IN_TO_SP(8.5);
				paper_type = SIZE_LETTER;
			}
			else goto illegal;
			break;
		case 'F':
			paper_type = SIZE_USR;
			length_to_sp(++opt, &pw);
			do{
				if(!*opt)
					goto quit;
			}while(*++opt != ';' && *opt != ':');
			length_to_sp(++opt, &ph);
			opt += strlen(opt) - 1;
			if(pw <= 0 || ph <= 0){
				error(ILLEGAL_ARGS, "Zero paper size!");
			}else{
				PW = pw;
				PH = ph;
			}
			break;
		case 'T':
skip_number:
			while (isdigit(*++opt));
			break;
		default:
illegal:	error(ILLEGAL_ARGS,"%s in -y=", opt);
			break;
	}
	if(*opt=='J'||*opt=='E')
		opt++;
	switch(toupper(*opt)){
		case 'P':
#ifdef	WIN32G
			f_rotate = FALSE;
#else
			dviout_dimension.print_direction = HORIZONTAL;
#endif
			break;
		case 'L':
#ifdef	WIN32G
			f_rotate = TRUE;
#else
			dviout_dimension.print_direction = VERTICAL;
#endif
			break;
	}
quit:
	if(f_rotate == TRUE && paper_type == SIZE_USR){
		ch = PH;
		PH = PW;
		PW = ch;
	}
}

void GetPaperSize100(int *w, int *h)
{
	if(f_rotate){
		*h = (int)(SP_TO_MM(PW)*10 + .5);
		*w = (int)(SP_TO_MM(PH)*10 + .5);
	}
	else{
		*w = (int)(SP_TO_MM(PW)*10 + .5);
		*h = (int)(SP_TO_MM(PH)*10 + .5);
	}
}

static void set_prt_type(DIMENSION *dim)
{
	SCALED_PT len;
#ifdef LBP
	char *pt;
	int ch, num;
	int lbp_shift = 0;
#endif
	ff_flg = -1;
#ifdef	WIN32G
	if(f_scr_skip <= 0)
		f_scr_skip = 16;
//	if(f_scr_skip >= 64)
//		f_scr_skip = 64;
#endif
	f_lbp_prt = FALSE;
	len = 0;
	if(OPH)
		PH = OPH;
	else
		OPH = PH;
	if(OPW)
		PW = OPW;
	else
		OPW = PW;
#ifdef	FAX
	if (f_fax != NULL){
		vert_divide = 8;
		dim->prt_type = FAXFORM;
		if (pt_prt_type == NULL){
			if (dim->dpi == 0)
				dim->dpi = 200;
			goto escp1;
		}
	}
#endif
	if (pt_prt_type == NULL) goto escp;
	switch (*pt_prt_type | 0x20) {
escp:	case (T_ESC_P):
		case 0x20:
			dim->prt_type = ESC_P;
escp1:		if (dim->dpi == 0)
				dim->dpi = 180;
			break;

		case (T_PC_PR):
			dim->prt_type = PC_PR;
			if (dim->dpi == 0)
				dim->dpi = 160;
			break;

		case (T_PC_NM):
			dim->prt_type = PC_NM;
			goto escp1;

#ifdef	LIPS3
		case (T_LBP_LIPS3):
			dim->prt_type = LBP_LIPS3;
			lbpf = &lips3_func;
			f_lbp_prt = TRUE;
			len = MM_TO_SP(5);
			break;
#endif
#ifdef	ESCPAGE
		case (T_LBP_ESCPAGE):
			dim->prt_type = LBP_ESCPAGE;
			lbpf = &escpage_func;
			f_lbp_prt = TRUE;
			len = IN_TO_SP(0.2);
			break;
#endif
		case (T_PR_OTHER):
			dim->prt_type = PR_OTHER;
			get_prt_ctl(pt_prt_type + 1);
			if (dim->dpi == 0) {
				error(DIRECT, "Warning : Assume Printer DPI = 180\n\n");
				dim->dpi = 180;
			}
			break;

		default:
			error(ILLEGAL_ARGS, "-p=%s", pt_prt_type);
			break;
	}
	if (TM < 0){
#ifdef	LBP
		lbp_shift |= 1;
#endif
		TM = len;
	}
	if (RM < 0){
#ifdef	LBP
		lbp_shift |= 2;
#endif
		RM = len;
	}
	if (BM < 0) BM = len;
	if (LM < 0) LM = len;
#ifdef LBP
	f_download = 0;
	if (f_lbp_prt) {
		char *ext_cfg = NULL;
			/* default の minimal_unit, vertical_unit に対する倍率 */
		int hunit = 1, vunit = 1;

#if JGAIJI
		f_gaiji = 
#endif
#ifdef	JDWN
		f_jdwn = dj_current = 
#endif
		f_vh_ratio = f_cell = f_lbp_comp = lbp_orig_dpi = 0;
		k_scale_l = k_base_l = 10000;
#ifdef	JDWN
		dj_min = 64;
		dj_skip = 4;
#endif
		font_def = NULL;
		f_use_lfont = TRUE;
		f_font_on_edge = FALSE;
		f_download = 1;
		f_init |= INIT_PIXEL;
		if( *(pt = pt_prt_type + 1) && *pt < 0x40 ) pt++;
#ifdef	FDOWN
		max_dsize = 0x80000L;
#endif
		while ((ch = *pt++) != 0) {
			num = atoi(pt);
			switch (ch) {
			  case 'v':
				  f_vh_ratio = num;
				  if (f_vh_ratio == 0)
					  f_use_lfont = FALSE;
				  break;
			  case 'd':
# ifdef	FDOWN
				  max_dsize = 0x400L * num;
				  if (max_dsize <= 0)
					  f_download = 0;
# endif
				  break;
			  case 'r':
				  f_cell = 1;
				  break;
			  case 'j':
				  k_base_l = num;
				  break;
			  case 's':
				  k_scale_l = num;
				  break;
			  case 'D':
				  lbp_orig_dpi = num;
				  break;
			  case 'o':
				  ext_cfg = pt;
				  break;
			  case 'm':
				  d_mincount = num;
				  break;
			  case 'f':
				  if (font_def == NULL)
					  font_def = pt - 1;
				  break;
# ifdef	JDWN
#  ifdef JGAIJI
			  case 'g':
				  f_gaiji = f_jdwn = 1;
				  break;
#  endif
			  case 'k':
				  if(!tategaki){
					  f_jdwn = 1;
					  if(isdigit(*pt))
						  dj_min = 127 - num;
					  while(isdigit(*pt)) pt++;
					  if(*pt && isdigit(pt[1]))
					  dj_skip = atoi(++pt);
				  }
				  break;
# endif
			  case 'c':
				  f_lbp_comp = 1;
				  break;
			  case 'u':
				  /* minimal_unit や vertical_unit の option による変更 */
				  /* horizontal_unit は num, vertical は 8 bit. */
				  if (num > 0) hunit = num;	
				  /* horizontal_unit は -num, vertical は 24 bit. */
				  if (num < 0){
					  hunit = -num;
					  vunit = 3;
				  }
				  break;
			  case 'E':
				  /* LIPSで紙面の縁にかかると思われるフォントをVDで印字する
					 ことを強制する。*/
				  f_font_on_edge=TRUE;
				  break;
			}
			while (*pt != ';' && *pt != ':' && *pt)
				pt++;
			if (*pt)
				pt++;
		}
		/* LBP プリンタコードの初期化・変更 */
		/* まず `u' を考慮して default をセット */
		if(dim->prt_type == LBP_LIPS3){
			if(lbp_orig_dpi == 600)
				hunit = (hunit+1)&~1;
			else if(lbp_orig_dpi == 1200)
				hunit = (hunit+3)&~3;
			else if(lbp_orig_dpi != 300 && lbp_orig_dpi != 240)
				lbp_orig_dpi = 300;
		}
		set_LBP_prt_ctl(hunit, vunit);
		/* `o' が指定されていれば、これが優先になる。 */
		if (ext_cfg)
			get_prt_ctl(ext_cfg);

		if (f_vh_ratio < 200 || f_vh_ratio > 5000)
			f_vh_ratio = 1000;
		if (dim->dpi == 0)
			dim->dpi = (!lbp_orig_dpi)?300:lbp_orig_dpi;
		if (ff_flg_str != NULL)
			length_to_dot(ff_flg_str, &ff_flg, 0);
# ifdef	WIN32G
		dim->print_direction = HORIZONTAL;
		if(!f_rotate){
# else
		if (dim->print_direction == HORIZONTAL){
# endif
			if (dviout_dimension.max_width == 0)
				dviout_dimension.max_width = 2360;
			if (dviout_dimension.max_height == 0)
				dviout_dimension.max_height = 3387;
			goto def_tm0;
		}else{
# ifndef	WIN32G
			dim->print_direction = HORIZONTAL;
			f_rotate = TRUE;
			len = TM; TM = RM; RM = BM; BM = LM; LM = len;
			len = MH; MH = MW; MW = len;
# endif
			len = PH; PH = PW; PW = len;
			if (lbp_shift & 2) goto def_tm;
		}
def_tm0:
		if(lbp_shift & 1){			/* default TM */
def_tm:
# ifdef	ESCPAGE
				if (dim->prt_type == LBP_ESCPAGE)
						TM = IN_TO_SP(0.2);
				else
# endif
						TM = MM_TO_SP(5);
			if (dviout_dimension.max_width == 0)
				dviout_dimension.max_width = 3387;
			if (dviout_dimension.max_height == 0)
				dviout_dimension.max_height = 2360;
		}
		if (dim->DPI == 0 || !(f_init & INIT_VDPI))
			dim->DPI = dim->dpi;
		else
			f_init &= ~INIT_VDPI;
		return;
	}
	f_use_lfont = FALSE;
#endif /*LBP*/
	if (ff_flg_str != NULL){
		switch(*ff_flg_str){
			case '+':
					ff_flg = 1;
					break;
			case '2':
					ff_flg = 0;
		}
	}
	if (dim->DPI == 0 || !(f_init & INIT_VDPI))
		dim->DPI = dim->dpi;
	else
		f_init &= ~INIT_VDPI;
#ifdef	WIN32G
# ifdef	RAWOUT
	if(!f_dviprt)
		dim->print_direction = HORIZONTAL;
	else if(f_rotate){
		f_rotate = FALSE;
		dim->print_direction = VERTICAL;
	}
# endif
	if(	f_rotate == TRUE ){
		dim->print_direction = HORIZONTAL;
		len = PH; PH = PW; PW = len;
		if (dviout_dimension.max_width == 0)
			dviout_dimension.max_width = 11 * dim->dpi;
		if (dviout_dimension.max_height == 0)
			dviout_dimension.max_height = 8 * dim->DPI;
	}else
#endif
	{
		if (dviout_dimension.max_width == 0)
			dviout_dimension.max_width = 8 * dim->dpi;
		if (dviout_dimension.max_height == 0)
			dviout_dimension.max_height = 11 * dim->DPI;
	}
}

#ifdef	WIN32G
void Startvfn(void)
{
	vfn_org = (IsJapanese())?vfn_orgJ:vfn_orgE;
	if(!get_vfont_name(vfn_org))
		f_use_vfont = TRUE;
	f_init &= ~INIT_ENDCFG;
}

void ShowParameter(void)
{
	option_usage();
	error(DATATITLE, "List of Parameters");
}
#endif
static void option_usage(void)
{
	int	i;
	ARG_TABLE *tbl;

#define	lines		10

	tbl = (ARG_TABLE *)SetPara(NULL, GET_TOP);
	for (i = OFF_USG; tbl->option; i++, tbl++) {
		if (tbl->type < HIDDEN_BOOLEAN)
			error(C_MSG, "%s", (char *)show_option(tbl, 
#ifdef	WIN32G
			SHOW_OPTION ));
#else
			ARGC-1 ));
		if (i % lines == 0 && f_wait == 1) {
			more();
# if		defined(PC9801) && defined(DOSV) && defined(J3100)
			error(DIRECT, (machine==M_J31)?
				"\x1b[l" "\n" "\x1b[2A":"\n\x1b[2A");
# else
			error(DIRECT, "\n\x1b[2A");
# endif
		}
#endif
	}
}

void help_out(void)
{
	error(DIRECT, 
"usage : %s [option(s)] dvifile [page(s) eg. -4 7 . 9 12-14 20- @file]\n\n", 
		progname);

	option_usage();
#ifdef	JAPANESE
	error(DIRECT, 
	"\n上記オプションは、 parameter file <%s> で指定可能\ \n", config_name);
#else
	error(DIRECT, "\noptions can be directed in %s\n", config_name);
#endif
	EXIT(0);
}

#define CM_INCH 2.54
/* cm per inch */

static void set_dimension(DVIFILE_INFO *dvi, DIMENSION *dim)
	/* size_para, magnification, text_width, height の設定．
	 */
{
	static int true_mag[] =
	{1000, 1200, 1440, 1728, 2074, 2488, 2986, 3583, 4300, 5160};

	dim->mag = (int)dvi->mag;

	if (mag_half)
		dim->mag = 1095;		/* magstep half */
	else {
		if (opt_mag != -1)
			if (opt_mag >= 0 && opt_mag <= 9)
				dim->mag = true_mag[opt_mag];
			else if(opt_mag >= 500)
				dim->mag = opt_mag;
			else
				error(ILLEGAL_ARGS, "mag step over");
	}

	if (dim->dpi <= 0){
		error(ILLEGAL_ARGS, "dpi");
		dim->dpi = 300;
	}
#ifdef NOFLOAT
	dim->size_para = ROUND(((double)dvi->den * (CM_INCH * 100000000.0))/
	((double)dvi->num * (double)dim->dpi * (double)dim->mag));
#else
	dim->size_para = ((double)dvi->num * (double)dim->dpi * (double)dim->mag) /
		((double)dvi->den * CM_INCH * 100000000.0);
#endif
	if(enlarge != 0){
		if(enlarge < 300 || enlarge > 4000){
			error(ILLEGAL_ARGS, "-e should be 300-4000");
			enlarge = 0;
		}else if(enlarge == 1000)
			enlarge = 0;
		else
			dim->size_para = dim->size_para*1000/enlarge;
	}
	
	set_convert(dim->size_para, dim->dpi, dim->DPI);
	/* set pixel<==>scaled-pt parameter */

	dim->text_height = vtopixel(dvi->l + HEADER_DEPTH + FOOTER_DEPTH);
}

/*******************************************************
*
*				Embedded Files
*
********************************************************/
#ifdef	DVI_ADD
static char tmp_dir[MAXPATH];
static int tmp_path_len;
struct DVIADD *dviadd;
int num_add;

int GetAddTotal(void)
{
	return (num_add > 0)?num_add:0;
}

int GetAddMemory(char *name, char *buf, int size)
{
	FILE *fp;
	int i;

	for(i = 0; i < num_add; i++){
		if(!strcmp(name, dviadd[i].name)){
			if(size == 0)
				return dviadd[i].lod;
			else{
				if(size < 0 || size > dviadd[i].lod)
					size = dviadd[i].lod;
				fp =  PushDVI(1);
				if(fp == NULL)
					return -2;
				fseek(fp, dviadd[i].bod, SEEK_SET);
				for(i = 0; i < size; i++)
					buf[i] = read_byte(fp);
				PushDVI(-1);
				return size;
			}
		}
	}
	return -1;
}

char *GetAddName(int num)
{
	return (num >= num_add)?NULL:dviadd[num].name;
}

int GetAddSize(int num)
{
	return (num >= num_add)?(-1):dviadd[num].lod;
}

/*
 *	Get tempolary dir for dviout  ( + "\file.ext" is a file_name ) 
 */
char *GetTmpDir(void)
{
	char *s;

	if(!tmp_path_len){
		if( (s = getenv("TMP")) == NULL )
			s = getenv("TEMP");
		if(s == NULL)
			return NULL;
		strcpy(tmp_dir, s);
		sprintf(tmp_dir + strlen(tmp_dir), "\\dviout%d", DVIOUT_Count);
		tmp_path_len = strlen(tmp_dir);
		mkdir(tmp_dir);
	}else
		tmp_dir[tmp_path_len] = 0;
	return tmp_dir;
}

char *GetAddFile(char *name)
{
	FILE *fp, *fd;
	int i;

	for(i = 0; i < num_add; i++){
		if(!strcmp(name, dviadd[i].name)){
			if(GetTmpDir() == NULL)
				return NULL;
			sprintf(tmp_dir + tmp_path_len, "\\%s", dviadd[i].name);
			if(dviadd[i].flag & 1)
				return tmp_dir;
			if( (fp =  PushDVI(1)) == NULL || 
				(fd = fopenf(tmp_dir, "wb")) == NULL )
				return NULL;
			dviadd[i].flag |= 1;
			fseek(fp, dviadd[i].bod, SEEK_SET);
			for(i = dviadd[i].lod; i-- > 0;)
				putc(read_byte(fp), fd);
			fclose(fd);
			PushDVI(-1);
			return tmp_dir;
		}
	}
	return NULL;
}

FILE *OpenAddFile(char *name, char *mode)
{
	FILE *fp;

	if(!num_add)
		return NULL;
	GetAddFile(name);
	if(!tmp_path_len)
		return NULL;
	sprintf(tmp_dir + tmp_path_len, "\\%s", name);
	if( (fp = fopenf(tmp_dir, mode)) == NULL )
		return NULL;
	strcpy(name, tmp_dir);
	return fp;
}

#ifdef	WIN32
char *FindFirstW32(char *);
char *FindNextW32(void);
#endif

void DeleteAddFile(int mode, char *name)
{
	char *s;
	int	f_del;

	if(!tmp_path_len)
		return;
	f_del = 1;
	for(;;){
		sprintf(tmp_dir+tmp_path_len, "%c%s", PATH_SEP, "*.*");
		if( (s = FindFirstW32(tmp_dir)) == NULL )
			break;
rep:	strcpy(tmp_dir+tmp_path_len + 1, s);
		if(!strcmp(tmp_dir, name))
			f_del = 0;
		else 
			if(!unlink(tmp_dir))			/* delete a file */
				continue;
		if((s = FindNextW32()) == NULL)		/* no file remains */
			break;
		goto rep;
	}
	Free0(dviadd);
	dviadd = NULL;
	num_add = 0;
	FindFirstW32(NULL);
	if(mode && tmp_path_len && f_del){		/* delete %TEMP%\dviout? */
		tmp_dir[tmp_path_len] = 0;
		ToDviDir();
		rmdir(tmp_dir);
		tmp_path_len = 0;
	}
}

/******		.dvi.tar 	********/


int Current_DVI;
int Current_DVI_size;

static unsigned compsum(HEADER *block, int signed_char_type)
{
	int	i;
	unsigned sum;

	sum = 0;
	for (i = 0; i < NAMSIZ + 8 + 8 + 8 + 12 + 12; i++)
		sum += signed_char_type ? block->dummy[i]: (unsigned char) block->dummy[i];
	sum += ' ' * 8;
	for (i += 8; i < TBLOCK; i++)
		sum += signed_char_type ? block->dummy[i]: (unsigned char) block->dummy[i];
	return (sum);
}

static int eofblock(char *block)
{
	int n;

	for (n = TBLOCK; n; n--) {
		if (*block++)
			return (0);
	}
	return (1);
}

static char decode_dir_e(char *name, struct stat *p, HEADER *block, int mode)
{
	unsigned sum;

	p->st_mode = (unsigned short)strtol(block->dbuf.mode, NULL, 8);
	p->st_size = strtol(block->dbuf.size, NULL, 8);
	p->st_mtime = strtol(block->dbuf.mtime, NULL, 8);
	p->st_uid = strtol(block->dbuf.uid, NULL, 8);
	p->st_gid = strtol(block->dbuf.gid, NULL, 8);
	sum = strtol(block->dbuf.chksum, NULL, 8);
	strncpy(name, block->dbuf.name, 100);
	name[99] = '\0';
	if (sum != compsum(block, mode))
		return ('e');
	return (block->dbuf.typeflag);
}

static char decode_dir(char *name, struct stat *p, HEADER *block)
{
	char type;

	if ((type = decode_dir_e(name, p, block, 0)) == 'e')
		type = decode_dir_e(name, p, block, 1);
	return (type);
}

/*
 * Read [m-n] bytes from archive and set data address to *ptr
 */
static int read_arch(int n, char **ptr, FILE *fp)
{
	static int Left;
	static char *Ptr;
	static char Buff[TBLOCK];

	if(fp == NULL)
		return Left = 0;
	if (Left == 0){
		Left  = fread(Buff, 1, TBLOCK, fp);
		Ptr = Buff;
	}
	if (n < 0 || n > Left)
		n = Left;
	if (ptr)
		*ptr = Ptr;
	Ptr += n;
	Left -= n;
	return n;
}

static void skip_file(int Current_file_left, FILE *fp)
{
	int n, m;

	m = (int)(-Current_file_left & (TBLOCK - 1));
	while (Current_file_left > 0) {
		n = read_arch(Current_file_left, NULL, fp);
		if (n == 0)
			return;
		Current_file_left -= n;
	}
	while (m) {
		n = read_arch(m, NULL, fp);
		if (n == 0)
			return;
		m -= n;
	}
}


char *noabsolute(char *s, int mode)
{
	int m, n;

	if (*s && (!issjis1(*s) || !IsJapanese()) &&  s[1] == ':')
		s += 2;
	if (*s == '/' || *s == '\\')
		s++;
	m = n = 0;
	if(mode){
		while(s[n]){
			if(s[n] == '/' || s[n] == '\\')
				m = n+1;
			else if(IsJapanese() && issjis1(s[n]) && s[n+1])
				n++;
			n++;
		}
	}
	return s+m;
}

static void GettarDir(FILE *fp)
{
#define	MAX_ADD_BUF	0x8000

	struct stat statbuf;
	char namebuf[100];
	char *name;
	char type;
	HEADER *head;
	char *name_pt;

	dviadd = (struct DVIADD *)marea(MAX_ADD_BUF);
	name_pt = ((char *)dviadd) + (MAX_ADD_BUF-1);

	read_arch(0, 0, NULL);
	while (read_arch(TBLOCK, (char **)&head, fp) == TBLOCK) {
		if (eofblock(head->dummy))
			break;
		type = decode_dir(namebuf, &statbuf, head);
		name = noabsolute(namebuf, 1);

		switch (type) {
			case VOLTYPE:
			case MULTYPE:
				skip_file(statbuf.st_size, fp);
			case LNKTYPE:
			case SYMTYPE:
			case DIRTYPE:
				continue;
			case 'e':
				error(
#ifdef	WIN32G
					WARNING
#else
					FILE_FAULT
#endif
					, "Checksum Error of tar\n");
err:			DeleteAddFile(0, "");
				return;
			default:
				break;
		}
		if(*name){
			if(name_pt <= (char *)(dviadd+num_add+2)){
				error(
#ifdef	WIN32G
					WARNING
#else
					FILE_FAULT
#endif
					, "Too many files in tar\n");
				goto err;
			}
			name_pt -= strlen(name) + 1;
			dviadd[num_add].name = name_pt;
			strcpy(name_pt, name);
			dviadd[num_add].flag = 0;
			dviadd[num_add].bod = ftell(fp);
			dviadd[num_add++].lod = statbuf.st_size;
			skip_file(statbuf.st_size, fp);
		}
	}
}

void SearchDVI(char *name)
{
	int i, len;

	char s[0x100];

	strncpy(s, noabsolute(name, 1), 0x100);
	s[0xff] = 0;
	len = strlen(s);
	if(len > 4)
		s[len - 4] = 0;
	if(len > 8 && !strcmp(s+len - 8, ".dvi")){
		for(i = 0; i < num_add; i++){
			if(!strcmp(s, dviadd[i].name)){
				Current_DVI		 = dviadd[i].bod;
				Current_DVI_size = dviadd[i].lod;
				return;
			}
		}
	}
	ChooseTar();
}

#else	/* DVI_ADD */
#define	Current_DVI	0
#endif

#define	END_DVI	223
#define ID 2
#define ID_PTEX 3
/* id number for searching for postamble
	 */

static int read_post(DVIFILE_INFO *dvi)
	/* POSTAMBLEからのデータ読み出し．
	 */
{
	long endofs;
	int code, i;
	int f_new = 0;
	unsigned char ch;
#ifdef	DVI_ADD
	int	count;

	Current_DVI = 
#endif
	ptex_mode = 0;
	count = strlen(dvi->file_name);
	if(!tmp_path_len || strncmp(dvi->file_name, tmp_dir, tmp_path_len)){
		strncpy(current_name, dvi->file_name, MAXFILE);
		code = IsJapanese();
		current_name_pt = &current_name[0];
		for( i = 0; ; i++ ){
			ch = (unsigned char)(current_name[i]);
			if(!ch)
				break;
			if(code!=0&&issjis1(ch)){
				if(!current_name[++i])
					break;
				continue;
			}
			if( current_name[i] == PATH_SEP )
				current_name_pt = &current_name[i+1];
		}
	}
#ifdef	WIN32
	if(count > 3 && !stricmp(dvi->file_name + count - 3, ".gz"))
		ExpandGZ(dvi->file_name, &(dvi->file_ptr), "rb");
#endif

#ifdef	DVI_ADD
	DeleteAddFile(0, dvi->file_name);
#ifdef	USE_ETF
	FreeETF();
#endif
	if( ( count > 4 &&
			(  !stricmp(dvi->file_name + count - 4, ".tar")
			|| !stricmp(dvi->file_name + count - 4, ".dvz")) ) 
	  || (count > 7 && 
			(  !stricmp(dvi->file_name + count - 7, ".dvitar")
			|| !stricmp(dvi->file_name + count - 7, ".tar.gz")) ) ){
tar:	GettarDir(dvi->file_ptr);
		if(!num_add)
			goto err;
		SearchDVI(dvi->file_name);
		if(!Current_DVI){
# ifdef	WIN32G
				error(WARNING, "Cannot find DVI file in tar");
				goto err;
# else
			error(FILE_FAULT, "Cannot find DVI file in tar");
# endif
		}
		fseek(dvi->file_ptr, Current_DVI, SEEK_SET);
	}else
		num_add = -1;
#endif	// DVI_ADD
	if ((uchar)read_byte(dvi->file_ptr) != PRE ||
		(uchar)read_byte(dvi->file_ptr) != ID) {
#ifdef	DVI_ADD
		fseek(dvi->file_ptr, 0x100, SEEK_SET);
		fread(common_work,1, 8, dvi->file_ptr);
		if(!strncmp(common_work+1, "ustar", 5)){
			num_add = 0;
			fseek(dvi->file_ptr, 0, SEEK_SET);
			goto tar;
		}
#endif
#ifdef	WIN32G
		error(WARNING, "Not DVI file");
		goto err;
#else
		error(FILE_FAULT, "Not DVI file");
#endif
	}
#ifndef NOPSFRAG
	header_special_init(dvi->file_ptr);
#endif
	endofs = ((Current_DVI)?
		(Current_DVI + Current_DVI_size):filelength(fileno(dvi->file_ptr)))-3;
	for (; fseek(dvi->file_ptr, endofs, SEEK_SET),
		 (code = (uchar)read_byte(dvi->file_ptr)) != ID; endofs--)
		/* Search id number
			 */
		if (code == ID_PTEX) {
#ifdef	DEBUG1
			error(DIRECT, 
			  "Extended DVI file encountered. Turn on pTeX mode.\n");
#endif
			ptex_mode = 1;
			break;
		}
		else if (code != END_DVI){
#ifdef	WIN32G
			error(WARNING, "No ID");
			goto err;
#else
			error(FILE_FAULT, "No ID");
#endif
	}

	fseek(dvi->file_ptr, endofs - 4L, SEEK_SET);

	if ((dvi->post = read_long(dvi->file_ptr)) <= 0){
#ifdef	WIN32G
		error(WARNING, "Negative Pointer(POST)");
		goto err;
#else
		error(COMMAND_ERROR, "Negative Pointer(POST)");
#endif
	}
#ifdef	DVI_ADD
	dvi->post += Current_DVI;
#endif
	/* Read the position of POSTAMBLE */

#ifdef	DVI_ADD
	fseek(dvi->file_ptr, dvi->post - 8, SEEK_SET);
	endofs = read_long(dvi->file_ptr) + Current_DVI;
	if(read_long(dvi->file_ptr) == AdID){
		int bof, lof;
		char *s;

		fseek(dvi->file_ptr, endofs - 1, SEEK_SET);
		if(  (uchar)read_byte(dvi->file_ptr) != EOP
		  || (uchar)read_byte(dvi->file_ptr) != POST){
err_add:	num_add = -1;
			goto end_add;
		}
		fseek(dvi->file_ptr, dvi->post - 20, SEEK_SET);
		bof = read_long(dvi->file_ptr);
		lof = read_long(dvi->file_ptr) - bof;
#ifdef	WIN32G
		bof += Current_DVI;
#endif
		num_add = read_long(dvi->file_ptr);
		if(num_add <= 0 || lof <= 0)
			goto err_add;
		endofs = sizeof(struct DVIADD)*(num_add+1) + lof + 1;
		dviadd = (struct DVIADD *)marea(endofs);

		fseek(dvi->file_ptr, bof, SEEK_SET);
		dviadd[0].name = 
			s = ((char *)dviadd) + sizeof(struct DVIADD)*(num_add+1);
		for(code = count = 0; code < lof; code++){
			*s = (uchar)read_byte(dvi->file_ptr);
			if(!*s++){
				if(count++ >= num_add){
err_add1:			Free(dviadd);
					goto err_add;
				}
				if(count < num_add)
					dviadd[count].name = s;
				if(strstr(dviadd[count-1].name, "..\\"))	/* for seculity */
					dviadd[count-1].name[0] = 0;
			}
		}
		if(count != num_add)
			goto err_add1;
		*(((char *)dviadd) + endofs - 1) = 0;
		fseek(dvi->file_ptr, dvi->post - 8*num_add - 20, SEEK_SET );
		for(count = 0; count < num_add; count++){
			dviadd[count].bod = read_long(dvi->file_ptr);
			dviadd[count].lod = read_long(dvi->file_ptr);
			dviadd[count].flag = 0;
		}
#ifdef	USE_ETF
		LoadETF(NULL);
#endif
		LoadInit(TRUE);
end_add:
		fseek(dvi->file_ptr, dvi->post, SEEK_SET);
	}else
		LoadInit(FALSE);
#else
	fseek(dvi->file_ptr, dvi->post, SEEK_SET);
#endif	/* DVI_ADD */
	/* Set file-ptr at POSTAMBLE */
	if ((uchar)read_byte(dvi->file_ptr) != POST){
#ifdef	WIN32G
		error(WARNING, "No Postamble");
		goto err;
#else
		error(COMMAND_ERROR, "No Postamble");
#endif
	}

	if ((dvi->last_bop = read_long(dvi->file_ptr)) <= 0){
#ifdef	WIN32G
		error(WARNING, "Negative Pointer(Last BOP)");
		goto err;
#else
		error(COMMAND_ERROR, "Negative Pointer(Last BOP)");
#endif
	}
#ifdef	WIN32G
	dvi->last_bop += Current_DVI;
#endif
	code = read_long(dvi->file_ptr);
	if(dvi->num != code){
		dvi->num = code;
		f_new = 1;
	}
	code = read_long(dvi->file_ptr);
	if(dvi->den != code){
		dvi->den = code;
		f_new = 1;
	}
	code = read_long(dvi->file_ptr);
	if(org_mag != code){
		org_mag = dvi->mag = code;
		f_new = 1;
	}
	code = read_long(dvi->file_ptr);
	if(dvi->l != (SCALED_PT)code){
		dvi->l = (SCALED_PT)code;
		f_new = 1;
	}
	code = read_long(dvi->file_ptr);
	if(dvi->u != (SCALED_PT)code){
		dvi->u = (SCALED_PT)code;
		f_new = 1;
	}
	dvi->stack_depth = read_short(dvi->file_ptr);
	dvi->total_page = read_unsigned_short(dvi->file_ptr);

	if (dvi->num <= 0 || dvi->den <= 0 || dvi->mag <= 0){
#ifdef	WIN32G
		error(WARNING, "Reading Illegal Long");
		goto err;
#else
		error(COMMAND_ERROR, "Reading Illegal Long");
#endif
	}
	if (dvi->stack_depth < 0 || dvi->total_page <= 0){
#ifdef	WIN32G
		error(WARNING, "Reading Illegal Integer");
err:	g_nErrorCode = (g_nErrorCode & ~0xff)|FE_DVI|FFE_DVI;
#else
		error(COMMAND_ERROR, "Reading Illegal Integer");
#endif
	}
	return f_new;
}

static void calc_new_size_option(
 SCALED_PT lm, SCALED_PT tm, SCALED_PT rm, SCALED_PT bm,
 SCALED_PT mw, SCALED_PT mh,
 DVIFILE_INFO *dvi, DIMENSION *dim)
	/* Added by K.Yoshizawa  Dec. 26, 1992
	 * Modified by K.Yoshizawa  Dec. 31, 1992
	 */
{
	SCALED_PT w, h, LS;

/* ●ステップ１：給紙位置による補正 */

	/* 注：LS (プリンタの印字可能域の左端から用紙の左端までの距離)の扱い
	 *
	 * 本来であれば、LS ゼロでない場合は、各行のビットイメージをプリンタに
	 * 送出する前に、 LS をドット数に変換した距離だけ、プリンタのヘッドを
	 * 右に移動してやればよいはずである。
	 *
	 * しかし、プリンタによっては、それが難しいということなので、ビットマッ
	 * プ・バッファの幅を LS 分だけ広くとることで、対処している。省メモリと
	 * いう観点からは好ましくないが、暫定的措置として、こうしている。
	 */

	LS = 0;
	switch(PF) {
	case 1: /* 左端揃え給紙 */
		break;
	case 2: /* 中央揃え給紙 */
		if(mw > 0 && (f_init&INIT_MW)) {		/* 印字可能最大幅の指定ある時のみ、計算 */
			if (PW <= mw) {	/* 用紙幅の方が狭い：これが正常 */
				LS = (mw - PW) / 2;
			} else {		/* 印字可能最大幅の方が狭い */
				/* 左右に均等にマージンが指定されたものとみなし、あとは
				 * 左端揃えとして扱う */
				lm += (PW - mw) / 2;
				rm += (PW - mw) / 2;
			}
		}
		break;
	default:
		error(ILLEGAL_ARGS
#ifdef	JAPANESE
		, "-PF の値が異常"
#else
		, "-PF option value"
#endif
		, (long)PF);
		break;
	}

/* ●ステップ２：用紙のサイズから、その用紙での印字可能領域を計算 */

	w = PW - lm - rm; 	/* w はその用紙で印字すべき最大幅の暫定値 */
	h = PH - tm - bm;	/* h はその用紙で印字すべき最大長の暫定値 */

	if (mw>0 && (f_init&INIT_MW)) {		/* 印字可能域の最大幅の指定あるとき */
		if (w > mw) {	/* 中央揃え給紙の場合は常に偽のはず */
			rm += w - mw;/* 用紙が広すぎる：右マージンを増やす */
			w = mw;
		}
	} else {			/* 印字可能域の最大幅の指定無きとき */
		mw = w;			/* この幅まで印字できると仮定する */
	}

	if (mh > 0 && (f_init&INIT_MH)) {		/* 印字可能域の最大長の指定あるとき */
		if (h > mh) {
/*			bm += h - mh;  */ /* 用紙が長すぎる：下マージンを増やす */
			h = mh;
		}
	} else {			/* 印字可能域の最大長の指定無きとき */
		mh = h;			/* この長さまで印字できると仮定する */
	}
	/* この時点で、(w, h) はその用紙での印字可能領域のサイズとなっている */

	if (w <= 0 || h <= 0) {
		error(PROGRAM_STOP
#ifdef	JAPANESE
		, "印刷可能領域がありません：サイズ関係オプション要チェック"
#else
		, "No printable area! Please examine size options."
#endif
		);
	}

	/* dvi ファイルから読み取ったテキスト・サイズを元に設定した値
	 *（set_dimension() で設定）は無視して、設定しなおす。 */
	dim->text_width  = ROUND(SP_TO_IN(w + LS) * dim->dpi);
	dim->text_height = ROUND(SP_TO_IN(h) * dim->DPI);

/* ●ステップ３：続いて、オフセットの計算 */

	if (dim->print_direction == HORIZONTAL) {
		if (HC) {
			/* 水平方向にセンタリングする場合 (dvi->u : テキスト幅) */

			/* 用紙幅に対してセンタリングするバージョン */
			dim->x_offset
				= ROUND( SP_TO_IN( (PW - dvi->u)/2 - lm + HS + LS) * dim->dpi);
		} else {
			/* センタリングしない場合。
			 * この場合は、用紙上の原点の座標から、左マージンを除いた距離
			 * を x_offset とすればよい。これで、正しい位置に印字されるはず。
			 */
			dim->x_offset = ROUND((SP_TO_IN(OX - lm + LS) + 1) * dim->dpi);
		}

		if (VC) {
			/* 垂直方向にセンタリングする場合 (dvi->l : テキスト高) */

			/* 用紙長に対してセンタリングするバージョン */
			dim->y_offset
				= ROUND( SP_TO_IN( (PH - dvi->l)/2 - tm + VS) * dim->DPI);

		} else {
			dim->y_offset = ROUND((SP_TO_IN(OY - tm) + 1) * dim->DPI);
		}
	} else {
		/* i.e. dim->print_direction == VERTICAL
		 *
		 * 縦長に置いた用紙上に、90度回転した形で印刷するはず。
		 *
		 * この場合は、用紙右上（左上ではない！）に、dviファイルの原点が来る。
		 * この原点が、用紙右上を基点に (1in,1in) の位置に、（もし原点を移動
		 * したなら、縦置きで印刷した用紙を横長に眺めたとき、左上を基点にして
		 * (1in + OX, 1in + OY) の位置に来るように） [xy]_offset を調整しないと
		 * いけない。
		 *
		 * この時、[xy]_offset は dviファイルの座標系ではなく、用紙右上を基準
		 * とした座標系で指定する必要があることに注意。すなわち、x_offset は、
		 * 印字可能領域右端から原点までの距離である。また、y_offset は印字
		 * 可能領域上端から原点までの距離である。
		 *
		 * センタリングしない場合は、
		 * x_offset は、dviファイル原点のY座標から右マージンを除いた距離
		 * y_offset は、dviファイル原点のX座標から上マージンを除いた距離
		 * とすればよい。
		 */
		if (HC) {
			/* 水平方向にセンタリングする場合
			 * dviファイルの高さを使うことに注意  (dvi->l : テキスト高) */

			/* 用紙幅に対してセンタリングするバージョン */
			dim->x_offset
				= ROUND( SP_TO_IN( (PW - dvi->l)/2 - rm - HS) * dim->dpi);
		} else {
			dim->x_offset = ROUND((SP_TO_IN(OY - rm) + 1) * dim->dpi);
		}

		if (VC) {
			/* 垂直方向にセンタリングする場合 */

			/* 用紙長に対してセンタリングするバージョン */
			dim->y_offset
				= ROUND( SP_TO_IN( (PH - dvi->u)/2 - tm + VS) * dim->DPI);
		} else {
			dim->y_offset = ROUND((SP_TO_IN(OX - tm) + 1) * dim->DPI);
		}
	}

/* ●ステップ４：最大印字可能領域のドット数の設定 */

	/* dviprt only */
	dim->max_width  = ROUND(SP_TO_IN(mw) * dim->dpi);
	dim->max_height = ROUND(SP_TO_IN(mh) * dim->DPI);

}

static void pixel_init(DVIFILE_INFO *dvi, DIMENSION *dim)
	/* 表示枠の設定．
	 */
{
	long bb_size;
	PIXEL t_w, t_h;

#if	0
	if(bitmap_buf_pointer->size > org_bb_size)
		org_bb_size = bitmap_buf_pointer->size;
#endif
#ifdef RAWOUT
	if(f_dviprt == FALSE){
#endif
#ifdef	WIN32G
	calc_new_size_option(0, 0, 0, 0, (f_rotate)?MH:MW,(f_rotate)?MW:MH,
		dvi, dim);
	LeftMargine  = ROUND(SP_TO_IN((f_rotate)?TM:LM)*dim->dpi);
	if(LeftMargine < 0)
		LeftMargine = 0;
	TopMargine = ROUND(SP_TO_IN((f_rotate)?RM:TM)*dim->DPI);
	if(TopMargine < 0)
		TopMargine = 0;
	RightMargine  = ROUND(SP_TO_IN((f_rotate)?BM:RM)*dim->dpi);
	if(RightMargine < 0)
		RightMargine = 0;
	BottomMargine  = ROUND(SP_TO_IN((f_rotate)?LM:BM)*dim->DPI);
	if(BottomMargine < 0)
		BottomMargine = 0;
#endif
#ifdef RAWOUT
	}else
#endif
#if	defined(RAWOUT)||!defined(WIN32G)
	calc_new_size_option(LM ,TM, RM, BM, MW, MH, dvi, dim);
#endif
	t_w = dim->text_width;
	t_h = dim->text_height;
	bb_size = ((long)(t_w + (HORI_DIVIDE - 1))) / HORI_DIVIDE
			* (HORI_DIVIDE / 8) *
			(((long)(t_h + (vert_divide - 1))) / vert_divide * vert_divide);
#ifdef	JDWN
	if (f_download){
		if (f_jdwn && dj == NULL)
			dj = (void *)marea(0x4000L);
	}
	else f_jdwn = 0;
#endif
	if(bitmap_buf_pointer->size <= 0x8000L)
		bitmap_buf_pointer->size = 0x8000L;
	if(pk_buf_pointer->size <= 0x8000L)
		pk_buf_pointer->size = 0x8000L;
	if(raster_buf_pointer->size <= 0x8000L)
		raster_buf_pointer->size = 0x8000L;
	if(bb_size <= 0x2000) bb_size = 0x2000;
	if(bb_size < org_bb_size || f_bmp != NULL)
		bitmap_buf_pointer->size = bb_size;

	if (dim->print_direction == HORIZONTAL)
		dim->split = set_size(t_w, t_h, dim->max_width, dim->max_height,
						&dim->buf_width, &dim->buf_height);
	else{
		dim->split = set_size(t_w, t_h, dim->max_width, dim->max_height,
						&dim->buf_height, &dim->buf_width);
		dim->y_offset += dim->buf_height - t_w;
	}
}

static void make_page_index(DVIFILE_INFO *dvi, DIMENSION *dim)
{
	int i;
	long offset;

	Free0((void*)dim->page_index);

	dim->page_index =
		(PAGE_INDEX *)marea(sizeof(PAGE_INDEX) * (
			(dim->total_page = dvi->total_page) + 2));

	dim->max_nombre_page = 0;
	for (offset = dvi->last_bop, i = dvi->total_page; i > 0; i--) {
		fseek(dvi->file_ptr, offset, SEEK_SET);
		if ((uchar)read_byte(dvi->file_ptr) != BOP)
			error(COMMAND_ERROR, "No BOP command in page %d", i);

		dim->page_index[i].offset = offset;
		if((dim->page_index[i].number = read_long(dvi->file_ptr)) 
		  > dim->max_nombre_page)
			dim->max_nombre_page = dim->page_index[i].number;

		/* Read count[0] */
		fseek(dvi->file_ptr, 36L, SEEK_CUR);
		/* Skip other 'count' values */
		offset = read_long(dvi->file_ptr) + Current_DVI;
	}
#ifdef	HYPERTEX
	flush_hyper();
	base_href[0] = 0;
#endif
}

/* end of file : prtinit.c */
