/*
 *  TEX Device Driver  ver 2.02-
 *  copyright(c) 1988, 1989 by TSG, 1990-1993 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
 */


/*
#define	DEBUG	1
*/
#define	USER_EMS_PAGES	4

#include <stdio.h>
#include <stdlib.h>
#include <dir.h>
#include <mem.h>
#include <alloc.h>
#include <string.h>
#include <ctype.h>

#define _DEF_STDIO_H_
#include "dd.h"
#include "err.h"
#include "dviread.h"
#include "prtout.h"
#include "option.h"
#include "version.h"
#include "vfont.h"
#include "alloc.h"

void get_config(int, char **);
void initialize(DVIFILE_INFO *, DIMENSION *);

static void set_prt_type(DIMENSION *dim);
static void 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 ulong mult_long(ulong, ulong);
static void opt_cfg(char *);
static void youshi_size(char *);

/* option.c */
void set_option(ARG_TABLE *, int, char **);
void set_config(ARG_TABLE *, char *);
int make_path(char *path, char *dir, char *name, char *ext);

/* 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);
ulong leftbuffer(void);
char *marea(int);

/* 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);

/* 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

/* LBPプリンターが選ばれていることを示すフラグ */
BOOL f_lbp_prt;

int test_flg = -1;

/* -f があるかどうか */
static BOOL mag_half = FALSE;

/* -half があるかどうか */
static int opt_mag = -1;

/* -mag によって指定された数 */
static BOOL f_center = FALSE;

/* centering */
BOOL dvifile_page = FALSE;

#ifndef	NEMS
extern int system_EMS_end;
extern int max_user_page;
extern DJTABLE* dj;

int system_ems[] =
	{
		USER_EMS_PAGES,		/* user_ems */
		0,					/* for download table */
		-1
	};
#endif

#ifndef NNSZ
extern int length_to_dot(char *, int *, int);
#endif

int enlarge;
static int add_width;
static int add_height;
static char *ff_flg_str;

/* by K.Yoshizawa  Dec. 26, 1992 */
BOOL f_use_new_size_option = TRUE;
/* A4 :  210mm x 297mm */
static SCALED_PT PW = MM_TO_SP(210);	/* 用紙の横幅 */
static 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;					/* 印字可能域の最大縦幅 */
static SCALED_PT OX;					/* 横方向の原点の座標 */
static SCALED_PT OY;					/* 縦方向の原点の座標 */
/* by K.Yoshizawa  Dec. 27, 1992 */
static BOOL HC = FALSE;					/* 水平センタリング */
static BOOL VC = FALSE;					/* 垂直センタリング */
static SCALED_PT HS;					/* 水平センタリング後の移動 */
static SCALED_PT VS;					/* 垂直センタリング後の移動 */
/* by K.Yoshizawa  Dec. 28, 1992 */
static int PF = 1;						/* 給紙位置 */

#define	CFG_PATH	"TEXCFG"
char far *cfg_path = NULL;	/* p_outでも参照するため，GROBALにした．
                                get_configでfarmallocしている*/

char progname[9]     = "dviprt";		/* program name */
char config_name[13];					/* config file name */

/* 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-93 by SHIMA,"
#ifdef VFD
"\n\t     1991-93 changed by Akiii, hero.h, hideki, Naochan!, Oh-Yeah?, OkI,"
"\n\t\t     SOLITON, "
#else
"\n\t     1991-93 changed by Akiii, hero.h, Naochan!, Oh-Yeah?, OkI, SOLITON"
"\n\t\t     "
#endif
		"sempa, T.Minagawa, Tomiie, "
#ifndef NOPS
		"T.Uchiyama, "
#endif
		"Yakumo, Yoshizawa";

const char *const vfont_config = "dviprt.vfn";

/* vector font config file name */

long view_buf_size = 0x4000L;

char *resume_file;
BOOL f_max_bb;
int org_mag;

#ifndef NOTPIC
int f_tpic_turn_on = 1;	/* default is on */

#ifndef NOPS
extern int f_GS;
extern BOOL f_gbox;
extern BOOL f_gsize;
extern char *gs_exe;
extern char *pbm_path;
#ifdef	GIF
extern BOOL	f_GIF;
#endif
#endif

#endif
#ifdef HIRES98
int hireso = 0;	/* 0: normal, 1: high&interlace, 2: high & noninterlace */

#endif

extern char prt_type;
extern int ff_flg;
extern BOOL f_long_name;
extern BOOL f_font_c;
extern BOOL f_pause;
extern BOOL f_top_margin;
extern BOOL f_resize;
extern int k_scale;
extern int k_base;
extern int f_search;
extern int f_EMS_pages;
extern int total_EMS_page;
extern char *goth;
extern char *sub_font;
extern char *fc_name;
extern char *k_dbl;
extern char *k_16;
extern char *f_page_scroll;
extern char *f_out;
extern char *prt_initialize;
extern BOOL f_wait;
extern PIXEL vert_divide;

#ifdef VFD
extern BOOL tatevfd;

#endif

extern BOOL use_lateral_kanji;

/* using lateral Kanji Font for vertical writing (pTeX)
     */
extern BOOL draw_baseline;

/* [for hidden option-1 by Naochan!]
     * draw the baseline.
     */
extern BOOL draw_boxpic;

/* [for hidden option-2 by Naochan!]
     * typesetting with blank boxes (instead of normal characters.)
     */

void set_trans_jis(char *);
void use_romfont(char *);

extern char ptex_mode;

/* when `extended dvi file' encountered, this value is not zero.(pTeX)
     */
#ifndef	NOVFONT
extern int f_use_vfont;
static char *vfont_name;
#endif

#ifndef	PC9801
extern char *pr_port_str;

#endif

#ifdef LBP
extern int f_use_lfont;
extern int f_vh_ratio;
extern int f_rotate;
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 int 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

#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;
#endif

#define	FAR_HEAP	0L
#define BUFFER_NUM	4

BUF_INFO buffers[BUFFER_NUM] =
{
	{NULL,NULL,NULL, DEF_RASTER_SIZE, f_HUGE, -1,0,0,NULL,NULL},
	{NULL,NULL,NULL, DEF_PK_SIZE,     f_HUGE, -1,0,0,NULL,NULL},
	{NULL,NULL,NULL, DEF_BITMAP_SIZE, f_HUGE, -1,0,0,NULL,NULL},
	{NULL,NULL,NULL, DEF_WORK_SIZE,   f_HUGE, -1,0,0,NULL,NULL}
};

FONT_INFO *first_font_info = NULL;
FONT_INFO *font_info_root = NULL;

/*
BUF_INFO *raster_buf_pointer = &buffers[0];
BUF_INFO *pk_buf_pointer = &buffers[1];
BUF_INFO *bitmap_buf_pointer = &buffers[2];
*/

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.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;

static ARG_TABLE option[] =
{

#ifdef	JAPANESE
	{"mag", INTEGER, (void *)&opt_mag,
	 "mag step(0-9), mag(500-)"},
	{"half", BOOLEAN, (void *)&mag_half,
	 "\x09"   "half)"},
	{"br", LONGINT, (void *)&(buffers[0].size),
	 "展開フォント     バッファサイズ(byte単位)"},
	{"bf", LONGINT, (void *)&(buffers[1].size),
	 "フォントファイル" AsAbove},
	{"bb", LONGINT, (void *)&(buffers[2].size),
	 "展開ビットマップ" AsAbove},
	{"bw", LONGINT, (void *)&(buffers[3].size),
	 "ワーク用        " AsAbove},
#ifndef	NEMS
	{"EMS", INTEGER, (void *)&f_EMS_pages,
	 "EMSの使用ページ数(デフォルト 全部)"},
#endif
	{"f", INTEGER, (void *)&test_flg,
	 "情報表\示(0-3)"},
	{"wait", BOOLEAN, (void *)&f_wait,
	 "エラー時にキー入力を待つ"},
	{"dpi", INTEGER, (void *)&(dviout_dimension.dpi),
	 "dpi設定"},
	{"DPI", INTEGER, (void *)&(dviout_dimension.DPI),
	 "\03" "(縦方向)"},
	{"e", INTEGER, (void *)&(enlarge),
	 "拡大率(1000倍)"},
	{"page", BOOLEAN, (void *)&dvifile_page,
	 "オフセットページ指定"},
	{"nf", STRING, (void *)&ff_flg_str,
	 "改ページコード不使用(袋とじは 2)"
#ifdef	LBP
	 "\n\tLBPでは、袋とじの右ページの開始位置"
#endif
	},
	{"o", STRING, (void *)&f_page_scroll,
	 "出力ページ(r:reverse, e:even, o:odd)"},
	{"V", BOOLEAN, (void *)&(dviout_dimension.print_direction),
	 "90度回転"},
	{"X", INTEGER, (void *)&(dviout_dimension.x_offset),
	 "横方向位置調整    (ドット単位)"},
	{"Y", INTEGER, (void *)&(dviout_dimension.y_offset),
	 "縦" AsAbove},
	{"w", INTEGER, (void *)&add_width,
	 "横方向の幅" AsAbove},
	{"h", INTEGER, (void *)&add_height,
	 "縦" AsAbove},
	{"W", INTEGER, (void *)&(dviout_dimension.max_width),
	 "用紙の印字可能横幅" AsAbove},
	{"H", INTEGER, (void *)&(dviout_dimension.max_height),
	 "\x0e" "縦" AsAbove},
	{"M", BOOLEAN, (void *)&(f_max_bb),
	 "展開ビットマップを用紙印字可能サイズに"},
	{"T", BOOLEAN, (void *)&f_top_margin,
	 "単票用紙上空き修正"},
	{"C", BOOLEAN, (void *)&f_center,
	 "センタリング"},
#ifndef NOTPIC
	{"tpic", INTEGER, (void *)&f_tpic_turn_on,
	 "tpic special[0:ignore 1:Bezier(デフォルト)"
 #ifndef TPIC_NSPL
	 " 2:spline"
 #endif
	 "]"},
#endif
#ifndef NOPS
	{"GS", INTEGER, (void *)&f_GS,
	"Ghostscript[0:Off 1:On(default) 2:verbose 3:PBM 4:exact PBM 5:gssub]"},
#ifdef	GIF
	{"GIF", BOOLEAN, (void *)&f_GIF,
	"pbmrawの代わりにgifmonoを使う"},
#endif
	{"gsx", STRING, (void *)&gs_exe,
	"Ghostscript(デフォルト gs.exe)"},
	{"gdat", STRING, (void *)&pbm_path,
	"pbm/gifファイルのディレクトリ"},
	{"gbox", BOOLEAN, (void *)&f_gbox,
	"取り込み画像の枠表示"},
	{"gsize", BOOLEAN, (void *)&f_gsize,
	"\x0c"       "サイズ:mag込み"},
#endif
	{"r", STRING, (void *)&fc_name,
	 "フォントキャッシュのセーブ"},
	{"L", BOOLEAN, (void *)&f_long_name,
	 "長いフォント名の中央省略"},
	{"c", BOOLEAN, (void *)&f_font_c,
	 "フォントの整合性チェック"},
	{"F", STRING, (void *)&sub_font,
	 "代替フォント指定"},
	{"A", INTEGER, (void *)&f_search,
	 "フォントサーチ範囲拡大"},
	{"K", STRING, (void *)&k_dbl,
	 "倍角漢字指定"},
	{"G", STRING, (void *)&goth,
	 "ゴシック漢字指定"},
	{"S", INTEGER, (void *)&k_scale,
	 "漢字スケール(1000倍) 標準値 952"},
	{"g", BOOLEAN, (void *)&use_lateral_kanji,
	 "横書き用漢字フォントを使用(pTeX縦書きモード)"},
	{"JC", PROCEDURE, (void *)set_trans_jis,
	 "JIS文字コード変換"},
	{"romf", PROCEDURE, (void *)use_romfont,
	 "内蔵漢字フォントを使用するドット数(<max>[:<min>])"},
	{"k", STRING, (void *)&k_16,
	 "-romf= から除くドット数(<dot>:<dot>:...)"},
	{"varf", BOOLEAN, (void *)&f_resize,
	 "フォントをスケーラブルにする"},
	{"base", BOOLEAN, (void *)&draw_baseline,
	 "ベースラインを引く"},
	{"box", BOOLEAN, (void *)&draw_boxpic,
	 "文字の代わりに箱で組版"},
#ifndef	NOVFONT
	{"vfn", STRING, (void *)&vfont_name,
	 "書体倶楽部フォント"},
#endif
#ifndef NO_NTTRPL
	{"nttF", STRING, (void *)&ntt_subst_fonts,
	 "NTTjTeXでの非標準和文フォントの代替フォント指定"},
	{"ntt", BOOLEAN, (void *)&ntt_subst,
	 "\x07" "の和文フォントをアスキー日本語TeX用フォントで代用"},
#endif
	{"J", INTEGER, (void *)&k_base,
	 "漢字ベースライン(1000倍) 標準値 0"},
	{"y", PROCEDURE, (void *)&youshi_size,
	 "用紙の選択 [A3|A4|A5|B4|B5|H(葉書)"
#ifdef LBP
	"|F<width>[:<height>]|T<number>"
#else
    "[l]"
#endif
#ifdef LIPS3
	 "\n\t LIPS3   :[p(用紙縦)|l(用紙横)[0(自動)|1(手差し)|2(上段)|3(下段)]]"
#endif
#ifdef ESCPAGE
"\n\t ESC/Page:[p(用紙縦)|l(用紙横)[1(標準給紙)|2(ｵﾌﾟｼｮﾝ給紙)[:<ﾋﾞﾝ番号>]]]"
#endif
	"]"
	},
#ifdef LBP
	{"lc", INTEGER, (void *)&f_copy,
	 "LBPでのコピー枚数"},
#endif
#ifdef VFD
	{"RV", BOOLEAN, (void *)&tatevfd,
	 "vfdフォントの回転"},
#endif
#ifndef	NOTATEGAKI
	{"R", BOOLEAN, (void *)&tategaki,
#ifdef	LBP
	 "LBP内蔵, "
#endif
	 "書体倶楽部のフォントを90度回転"},
#endif
	{"O", STRING, (void *)&f_out,
	 "出力ファイル(!!!は頁番号)"},
	{"Z", BOOLEAN, (void *)&f_pause,
	 "１頁毎に一旦停止"},
	{"I", STRING, (void *)&prt_initialize,
	 "プリンタ初期化コード記述ファイル\n"},

	/* by K.Yoshizawa  Dec. 26, 1992 */
	{"newsize", BOOLEAN, (void*)&f_use_new_size_option,
	 "以下のサイズ・オプションを使用"},
	{"PW", LENGTH, (void*)&PW,
	"用紙の横幅 [デフォルト 210mm(A4)]"},
	{"PH", LENGTH, (void*)&PH,
	"\x06" "縦幅 [デフォルト 297" AsAbove},
	{"TM", LENGTH, (void*)&TM, "\x04" "上端の印字不可能域の幅"},
	{"BM", LENGTH, (void*)&BM, "\x04" "下" AsAbove},
	{"LM", LENGTH, (void*)&LM, "\x04" "左" AsAbove},
	{"RM", LENGTH, (void*)&RM, "\x04" "右" AsAbove},
	{"MW", LENGTH, (void*)&MW, "印字可能域の最大横幅"},
	{"MH", LENGTH, (void*)&MH, "\x10"          "縦" AsAbove},
	{"OX", LENGTH, (void*)&OX, "横方向の移動"},
	{"OY", LENGTH, (void*)&OY, "縦" AsAbove},

	/* by K.Yoshizawa  Dec. 27, 1992 */
	{"HC", BOOLEAN, (void*)&HC, "水平センタリング"},
	{"VC", BOOLEAN, (void*)&VC, "垂直" AsAbove},
	{"HS", LENGTH, (void*)&HS,  "水平センタリング後の移動"},
	{"VS", LENGTH, (void*)&VS,  "垂直" AsAbove},
	/* by K.Yoshizawa  Dec. 28, 1992 */
	{"PF", INTEGER, (void*)&PF, "給紙位置 [1:左端揃(デフォルト) 2:中央]\n"},
	{"=", PROCEDURE, (void *)opt_cfg, "パラメータファイル指定"},
#ifdef FAX
	{"FAX", STRING, (void *)&f_fax, "G3 FAX形式"},
#endif
	{"p", STRING, (void *)&pt_prt_type,
	 "プリンタの種類 e:ESC/P p:PC-PR n:NM o:other(default prtctl.cfg)"
#ifdef LBP
	 "\n\t"
#  ifdef LIPS3
	 "l:LIPS3 "
#  endif
#  ifdef ESCPAGE
	 "m:ESC/Page "
#  endif
	 "[v:字体縦横比 k:和文外字 d:download_size r:real_size"
	 "\n\tm:minimal_count f:font_def D:dpi j:baseline s:size_adj E:edge"
	 "\n\tu:minimal_unit c:compress o:other"
#endif
	},

#ifndef	PC9801	/* J-3100,AX,DOS/V */
	{"P", STRING, (void *)&pr_port_str,
	 "プリンタポートの指定, 0 for BIOS(default), 1〜4 for LPT1:〜LPT4:"},
#endif
#else
	{"mag", INTEGER, (void *)&opt_mag,
	 "mag step(0-9), mag(500-)"},
	{"half", BOOLEAN, (void *)&mag_half,
	 "\x09"  "half)"},
	{"br", LONGINT, (void *)&(buffers[0].size),
	 "raster buffer size"},
	{"bf", LONGINT, (void *)&(buffers[1].size),
	 "font  " AsAbove},
	{"bb", LONGINT, (void *)&(buffers[2].size),
	 "bitmap" AsAbove},
	{"bw", LONGINT, (void *)&(buffers[3].size),
	 "work  " AsAbove},
#ifndef	NEMS
	{"EMS", INTEGER, (void *)&f_EMS_pages,
	 "number of pages to use EMS(default all)"},
#endif
	{"f", INTEGER, (void *)&test_flg,
	 "test-flag(0-3)"},
	{"wait", BOOLEAN, (void *)&f_wait,
	 "wait for key-input when error occurs"},
	{"dpi", INTEGER, (void *)&(dviout_dimension.dpi),
	 "horizontal dpi"},
	{"DPI", INTEGER, (void *)&(dviout_dimension.DPI),
	 "vertical  " AsAbove},
	{"e", INTEGER, (void *)&(enlarge),
	 "enlarge*1000"},
	{"page", BOOLEAN, (void *)&dvifile_page,
	 "pages are dvifile-pages"},
	{"nf", STRING, (void *)&ff_flg_str,
	 "No use of form feed code"},
	{"o", STRING, (void *)&f_page_scroll,
	 "output (r:reverse, e:even pages, o:odd pages)"},
	{"V", BOOLEAN, (void *)&(dviout_dimension.print_direction),
	 "vertical-output"},
	{"X", INTEGER, (void *)&(dviout_dimension.x_offset),
	 "x-offset     (pixel)"},
	{"Y", INTEGER, (void *)&(dviout_dimension.y_offset),
	 "y" AsAbove},
	{"w", INTEGER, (void *)&add_width,
	 "add width" AsAbove},
	{"h", INTEGER, (void *)&add_height,
	 "\x04" "length" AsAbove},
	{"W", INTEGER, (void *)&(dviout_dimension.max_width),
	 "device width" AsAbove},
	{"H", INTEGER, (void *)&(dviout_dimension.max_height),
	 "\x07" "height" AsAbove},
	{"M", BOOLEAN, (void *)&(f_max_bb),
	 "use device size for bit map buffer"},
	{"T", BOOLEAN, (void *)&f_top_margin,
	 "correct Top margin for cut sheets"},
	{"C", BOOLEAN, (void *)&f_center,
	 "Centering"},
#ifndef NOTPIC
	{"tpic", INTEGER, (void *)&f_tpic_turn_on,
	 "tpic special(0:ignore 1:Bezier(default)"
 #ifndef TPIC_NSPL
	 " 2:spline"
 #endif
	 "]"},
#endif
#ifndef NOPS
	{"GS", INTEGER, (void *)&f_GS,
	"Ghostscript[0:Off 1:On(default) 2:verbose 3:PBM 4:exact PBM 5:gssub]"},
# ifdef	GIF
	{"GIF", BOOLEAN, (void *)&f_GIF,
	"use gifmono in place of pbmraw"},
# endif
	{"gsx", STRING, (void *)&gs_exe,
	"Ghostscript(default gs.exe)"},
	{"gdat", STRING, (void *)&pbm_path,
	"Directory of pbm/gif file"},
	{"gbox", BOOLEAN, (void *)&f_gbox,
	"draw frame for picture"},
	{"gsize", BOOLEAN, (void *)&f_gsize,
	 "picture size:include mag"},
#endif
	{"r", STRING, (void *)&fc_name,
	 "Save Font"},
	{"L", BOOLEAN, (void *)&f_long_name,
	 "cut center of long font names"},
	{"c", BOOLEAN, (void *)&f_font_c,
	 "Check font matching"},
	{"F", STRING, (void *)&sub_font,
	 "Font substitute"},
	{"A", INTEGER, (void *)&f_search,
	 "\x05" "search"},
	{"K", STRING, (void *)&k_dbl,
	 "Double size Kanji"},
	{"G", STRING, (void *)&goth,
	 "Gothic"},
	{"g", BOOLEAN, (void *)&use_lateral_kanji,
	 "Use Lateral Kanji Font in pTeX `tate' mode"},
	{"JC", PROCEDURE, (void *)set_trans_jis,
	 "translate JIS code"},
	{"romf", PROCEDURE, (void *)use_romfont,
	 "dots of using Kanji ROM Font(<max>[:<min>])"},
	{"k", STRING, (void *)&k_16,
	 "\x05" "not using Kanji ROM Font(<dot>:<dot>:...)"},
	{"varf", BOOLEAN, (void *)&f_resize,
	 "resize all fonts"},
	{"base", BOOLEAN, (void *)&draw_baseline,
	 "draw the baseline"},
	{"box", BOOLEAN, (void *)&draw_boxpic,
	 "typeset by boxes instead of characters"},
	{"vfn", STRING, (void *)&vfont_name,
	 "Syotai Club's Font"},
#ifndef NO_NTTRPL
	{"nttF", STRING, (void *)&ntt_subst_fonts,
	 "NTTjTeX Nonstandard Font substitute"},
	{"ntt", BOOLEAN, (void *)&ntt_subst,
	 "\x08" "Font substitute"},
#endif
	{"S", INTEGER, (void *)&k_scale,
	 "Kanji scale*1000 (default 952)"},
	{"J", INTEGER, (void *)&k_base,
	 "\x06" "base line*1000 (default 0)"},
	{"y", PROCEDURE, (void *)&youshi_size,
	 "Paper select [A3|A4|A5|B4|B5|H"
#ifdef LBP
	"|F<width>[:<height>]|T<number>"
#else
    "[l]"
#endif
#ifdef LIPS3
	 "\n\tLIPS3   :[p(port.)|l(land.)[<0(auto)|1(manual)|2(upper)|3(lower)>]]"
#endif
#ifdef ESCPAGE
	 "\n\tESC/Page:[p(port.)|l(land.)[1(normal)|2(option)[:bin]]]"
#endif
	 "]"
	},
#ifdef LBP
	{"lc", INTEGER, (void *)&f_copy,
	 "Number of copy by LBP"},
#endif
#ifdef VFD
	{"RV", BOOLEAN, (void *)&tatevfd,
	 "Rotate vfd font"},
#endif
#ifndef	NOTATEGAKI
	{"R", BOOLEAN, (void *)&tategaki,
	 "Font rotational printing with "
#ifdef	LBP
	 "LBP/"
#endif
	 "Zeit font"},
#endif
	{"O", STRING, (void *)&f_out,
	 "File output(!!! is replaced by page)"},
	{"Z", BOOLEAN, (void *)&f_pause,
	 "Pause for every page"},
	{"I", STRING, (void *)&prt_initialize,
	 "File with code intializing printer"},

	/* by K.Yoshizawa  Dec. 26, 1992 */
	{"newsize", BOOLEAN, (void*)&f_use_new_size_option,
	 "use the following size option"},
	{"PW", LENGTH, (void*)&PW,
	"paper width  [default 210mm(A4)]"},
	{"PH", LENGTH, (void*)&PH,
	"paper height [default 297mm(A4)]"},
	{"TM", LENGTH, (void*)&TM, "top    mechanical gap"},
	{"BM", LENGTH, (void*)&BM, "bottom" AsAbove},
	{"LM", LENGTH, (void*)&LM, "left  " AsAbove},
	{"RM", LENGTH, (void*)&RM, "right " AsAbove},
	{"MW", LENGTH, (void*)&MW, "max printable width"},
	{"MH", LENGTH, (void*)&MH, "\x0e"        "height"},
	{"OX", LENGTH, (void*)&OX, "horizontal move"},
	{"OY", LENGTH, (void*)&OY, "vertical  " AsAbove},
	/* by K.Yoshizawa  Dec. 27, 1992 */
	{"HC", BOOLEAN, (void*)&HC, "horizontal centering"},
	{"VC", BOOLEAN, (void*)&VC, "vertical  " AsAbove},
	{"HS", LENGTH, (void*)&HS, "horizontal shift after centering"},
	{"VS", LENGTH, (void*)&VS, "vertical  " AsAbove},
	/* by K.Yoshizawa  Dec. 28, 1992 */
	{"PF", INTEGER, (void*)&PF, 
		"paper feed position [1:left(default) 2:center]\n"},

	{"=", PROCEDURE, (void *)opt_cfg, "parameter file"},

#ifdef FAX
	{"FAX", STRING, (void *)&f_fax, "G3 FAX"},
#endif
	{"p", STRING, (void *)&pt_prt_type,
	 "type of printer e:ESC/P p:PC-PR n:NM o:other(default prtctl.cfg)"
#ifdef LBP
	 "\n\t"
#  ifdef LIPS3
	 "l:LIPS3 "
#  endif
#  ifdef ESCPAGE
	 "m:ESC/Page "
#  endif
	 "[v:font_aspect k:gaiji d:download_size r:real_size"
	 "\n\tm:minimal_count f:font_def D:dpi j:baseline s:size_adj E:edge"
	 "\n\tu:minimal_unit c:compress o:other"
#endif
	},

#ifndef	PC9801	/* J-3100,AX,DOS/V */
	{"P", STRING, (void *)&pr_port_str,
	 "Use Printer Port Directly, 0,1,..,4 for BIOS,LPT1,..,LPT4"},
#endif
#endif
	{NULL}
};

void get_config(int argc, char **argv)
{
	int i, l;
	char real_name[MAXPATH], v_real_name[MAXPATH];
	char path_name[MAXPATH];
	char *cfgpath, *srcpath;

	ENTER("get_config");

	fnsplit(argv[0], real_name, v_real_name, config_name, path_name);
	if (memcmp(strlwr(config_name), "dvi", 3) == 0)
		strcpy(progname, config_name);
	strcpy(config_name, progname);
	strcat(config_name, ".par");
	if (argc <= 1 ) return;

	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_name[++i] = '\0';
		}
		cfg_path = (char far *)farmalloc((long)i + 2L);

		/* p_out.cで使うのでコピー : strcpy(cfg_path, path_name); と同等 */
		{
			char *spt;
			char far *dpt;

			for (spt = path_name, dpt = cfg_path; (*dpt++ = *spt++) != 0;);
		}
	}
	else {
		cfg_path = (char far *)"";
		path_name[0] = '\0';
	}
	strcpy(real_name, path_name);
	strcat(real_name, config_name);

	if (access(real_name, 0) == -1){
		if ((srcpath = searchpath(config_name)) != NULL)
			strncpy(real_name, srcpath, MAXPATH - 2);
		else *real_name = 0;
	}
	if (*real_name) set_config(option, real_name);
	set_option(option, argc, argv);
#ifdef HIRES98
	/* PC9801 ハイレゾリューションモードの判定 */
	hireso = 0;					/* デフォルトはノーマルモード */
	if ((*(char far *)(0x00000501)) & 8) {
		/* システム共通域 0h:459h の ビット 3 でインターレースモードの調査 */
		hireso = ((*(char far *)(0x00000459)) & 8) ? 2 : 1;
		pk_buf_pointer->size = 0xffffL;
	}
	/* モード表示 */
#ifdef	DEBUG1
	switch (hireso) {
		  case 0:
			  fprintf(stderr, "\nNormal Mode\n");
			  break;
		  case 1:
			  fprintf(stderr, "\nHighReso. & Interlace\n");
			  break;
		  case 2:
			  fprintf(stderr, "\nHighReso. & Non-Interlace\n");
			  break;
	}
#endif
#endif
#ifndef	NOVFONT
	if (vfont_name != NULL && *vfont_name != '-') {
		f_use_vfont = TRUE;
		make_path(real_name,
			NULL,
			(*vfont_name == 0 || *vfont_name == '+')?"dviprt":vfont_name,
			".vfn");
		make_path(v_real_name, path_name, real_name, NULL);
		if (access(v_real_name, 0) == -1) {
			if ((srcpath = searchpath(real_name)) != NULL)
				strncpy(v_real_name, srcpath, MAXPATH - 2);
		}
		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");
			exit(-1);
		}
	}
#endif
	END();
}

void initialize(DVIFILE_INFO *dvi, DIMENSION *dim)
{
#ifndef NEMS
	int i, j;
#endif

	ENTER("initialize");
	read_post(dvi);
	set_prt_type(dim);
	set_dimension(dvi, dim);
	make_font_list(dvi, dim);
	make_page_index(dvi, dim);
	pixel_init(dvi, dim);
	buffer_init();
	stack_init(dvi->stack_depth);
	decode_init();

#ifndef NOTPIC
	if (f_tpic_turn_on)
		tpic_init(dim->buf_height);
	/* alloc y-bucket[vmax] and activate tpic interpretation */
#endif
#ifndef NEMS
	for (i = 0; system_ems[++i] != -1; ){
		if ((j = system_ems[i]) > 0){
			system_ems[i] = system_EMS_end;
			system_EMS_end += j;
			max_user_page -= j;
		}
		else system_ems[i] = -1;
	}
#endif

	END();
}

/* set youshi size */
static void youshi_size(char *opt)
{
	int	ch;

	ch = opt[1];
	youshi = (char*)dup_string(opt);
	switch(toupper(*opt)){
		case 'A':
			if (ch == '4'){
				PW = MM_TO_SP(210);
				PH = MM_TO_SP(297);
			}
		    else if (ch == '3'){
				PW = MM_TO_SP(297);
				PH = MM_TO_SP(420);
			}
			else if (ch == '5'){
				PW = MM_TO_SP(148.5);
				PH = MM_TO_SP(210);
			}
			goto skip_number;
		case 'B':
			if (ch == '4'){
				PW = MM_TO_SP(257);
				PH = MM_TO_SP(364);
			}
			else if (ch == '5'){
				PW = MM_TO_SP(182);
				PH = MM_TO_SP(257);
			}
			goto skip_number;
		case 'H':
			PW = MM_TO_SP(100);
			PH = MM_TO_SP(148);
			goto skip_number;
		case 'F':
			while (isdigit(*++opt));
			if (*opt != ':' && *opt !=';') break;
		case 'T':
skip_number:
			while (isdigit(*++opt));
			break;
		default:
			error(ILLEGAL_ARGS, opt);
			break;
	}
	switch(toupper(*opt)){
		case 'P':
			dviout_dimension.print_direction = HORIZONTAL;
			break;
		case 'L':
			dviout_dimension.print_direction = VERTICAL;
			break;
	}
}

static void set_prt_type(DIMENSION *dim)
{
	int ch;
	char *pt;
	SCALED_PT len;
#ifdef LBP
	int num;
	int lbp_shift = 0;

	f_lbp_prt = FALSE;
#endif
	len = 0;
#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):
			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) {
				fprintf(stderr, "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
	if (f_lbp_prt) {
		char *p;
		char *ext_cfg = NULL;
			/* default の minimal_unit, vertical_unit に対する倍率 */
		int hunit = 1, vunit = 1;

		f_use_lfont = TRUE;
		f_download = 1;
		if( *(pt = pt_prt_type + 1) && *pt < 0x40 ) pt++;
		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
			  case 'g':
				  f_gaiji = f_jdwn = 1;
				  break;
			  case 'k':
				  if(!tategaki){
					  f_jdwn = 1;
					  system_ems[1] = 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 をセット */
		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 == 0)?300:lbp_orig_dpi;

		if (ff_flg_str != NULL){
#ifndef NNSZ
			length_to_dot(ff_flg_str, &ff_flg, 0);
#else
			ff_flg = atoi(ff_flg_str);
#endif
		}
		if (dim->print_direction == HORIZONTAL){
			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{
			dim->print_direction = HORIZONTAL;
			f_rotate = TRUE;
			if (f_use_new_size_option){
				len = PH; PH = PW; PW = len;
				len = TM; TM = RM; RM = BM; BM = LM; LM = len;
				len = MH; MH = MW; MW = len;
				if (lbp_shift & 2) goto def_tm;
			}
			else{
def_tm0:		if(lbp_shift & 1){
def_tm:				if (dim->prt_type == LBP_ESCPAGE) TM = IN_TO_SP(0.2);
					else                              TM = MM_TO_SP(10.33);
				}
			}
			if (dviout_dimension.max_width == 0)
				dviout_dimension.max_width = 3387;
			if (dviout_dimension.max_height == 0)
				dviout_dimension.max_height = 2360;
		}
	}
	else
#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)
		dim->DPI = dim->dpi;
	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	FDOWN
	if (f_download)
		fc_name = NULL;
#endif
}

/* optional parameter file */
static void opt_cfg(char *opt)
{
	set_config(option, opt);
}

void help_out(void)
{
	ENTER("help_out");

	printf("usage : %s [option(s)] dvifile [page(s) eg. -4 7 9 12-14 20-]\n\n", progname);

#ifdef	JAPANESE
	option_usage(option);
	printf("\n上記オプションは、 parameter file <%s> で指定可能\ \n", config_name);
#else
	printf("options are as follows :\n");
	option_usage(option);
	printf("\noptions can be directed in %s\n", config_name);
#endif
	EXIT(0);
}

#define CM_INCH 2.54
/* cm per inch */

static int pres;
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};
#ifndef	USE_FLOAT
	ulong num1, num2;
	long num3;
	int q;
#endif

	ENTER("set_text_size");

	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");
	}

	dim->total_page = dvi->total_page;

	if (dim->dpi <= 0)
		error(ILLEGAL_ARGS, "dpi");
#ifdef	NOFLOAT
	num1 = mult_long((ulong)dvi->den, 254000000L);
	q = pres;

	num2 = mult_long((ulong)dvi->num, (ulong)dim->dpi);
	q -= pres;
	num2 = mult_long(num2, (ulong)dim->mag);
	q -= pres;

	num3 = 0;
	while (num1 >= num2) {
		num1 -= num2;
		num3++;
	}
	while (q-- >= 0) {
		num3 += num3;
		if ((num1 += num1) >= num2) {
			num1 -= num2;
			num3++;
		}
	}
	num3 >>= 1;
	if ((num3 & 1) != 0)
		num3++;
	if (enlarge != 0) {
		if (enlarge < 300 || enlarge > 4000)
			error(ILLEGAL_ARGS, "-e should be 300-4000");
		else {
			num3 = num3 * 1000 / enlarge;
		}
	}
	dim->size_para = num3;
#else
	dim->size_para = ((double)dvi->num * (double)dim->dpi * (double)dim->mag) /
		((double)dvi->den * CM_INCH * 100000000.0);
#endif
	set_convert(dim->size_para, dim->dpi, dim->DPI);
	/* set pixel<==>scaled-pt parameter */

	if ((dim->text_width = sptopixel(dvi->u)) == 0)
		f_max_bb = TRUE;
	dim->text_height = vtopixel(dvi->l + HEADER_DEPTH + FOOTER_DEPTH);

	if (f_center == TRUE) {
		if (dim->print_direction == HORIZONTAL) {
			if (dim->max_width > 0) {
				dim->x_offset += (dim->max_width - dim->text_width) / 2;
			}
			if (dim->max_height > 0) {
				dim->y_offset += (dim->max_height - dim->text_height) / 2;
			}
		}
		else {
			if (dim->max_width > 0) {
				dim->x_offset += (dim->max_width - dim->text_height) / 2;
			}
			if (dim->max_height > 0) {
				dim->y_offset += (dim->max_height - dim->text_width) / 2;
			}
		}
	}
	END();
}

#ifdef	NOFLOAT
static ulong mult_long(ulong num1, ulong num2)
{
	int i;

	if (num1 == 0 || num2 == 0) {
		pres = 0;
		return (0L);
	}
	i = 0;
	while (num1 >= 0x2000000L) {
		i++;
		num1 >>= 1;
	}
	while (num1 < 0x1000000L) {
		i--;
		num1 += num1;
	}
	while (num2 >= 0x2000000L) {
		i++;
		num2 >>= 1;
	}
	while (num2 < 0x1000000L) {
		i--;
		num2 += num2;
	}
	pres = i + 20;
	return (mult20(num1, num2));
}
#endif

#define	END_DVI	223
#define ID 2
#define ID_PTEX 3
/* id number for searching for postamble
     */

static void read_post(DVIFILE_INFO *dvi)
	/* POSTAMBLEからのデータ読み出し．
     */
{
	long endofs;
	int code;

	ENTER("read_post");

	if ((uchar)read_byte(dvi->file_ptr) != PRE ||
		(uchar)read_byte(dvi->file_ptr) != ID) {
		error(FILE_FAULT, "Not DVI file");
	}
	for (endofs = -3L; fseek(dvi->file_ptr, endofs, SEEK_END),
		 (code = (uchar)read_byte(dvi->file_ptr)) != ID; endofs--)
		/* Search id number
             */
		if (code == ID_PTEX) {
#ifdef	DEBUG1
			printf("Extended DVI file encountered. Turn on pTeX mode.\n");
#endif
			ptex_mode++;
			break;
		}
		else if (code == EOF || code != END_DVI)
			error(FILE_FAULT, "No ID");

	fseek(dvi->file_ptr, endofs - 4L, SEEK_END);
	if ((dvi->post = read_long(dvi->file_ptr)) <= 0)
		error(COMMAND_ERROR, "Negative Pointer(POST)");
	/* Read the position of POSTAMBLE */

	fseek(dvi->file_ptr, dvi->post, SEEK_SET);
	/* Set file-ptr at POSTAMBLE */

	if ((uchar)read_byte(dvi->file_ptr) != POST)
		error(COMMAND_ERROR, "No Postamble");

	if ((dvi->last_bop = read_long(dvi->file_ptr)) <= 0)
		error(COMMAND_ERROR, "Negative Pointer(Last BOP)");

	dvi->num = read_long(dvi->file_ptr);
	dvi->den = read_long(dvi->file_ptr);
	org_mag = dvi->mag = read_long(dvi->file_ptr);

	dvi->l = (SCALED_PT)read_long(dvi->file_ptr);
	dvi->u = (SCALED_PT)read_long(dvi->file_ptr);

	dvi->stack_depth = read_int(dvi->file_ptr);
	dvi->total_page = read_int(dvi->file_ptr);

	if (dvi->num <= 0 || dvi->den <= 0 || dvi->mag <= 0)
		error(COMMAND_ERROR, "Reading Illegal Long");

	if (dvi->stack_depth < 0 || dvi->total_page <= 0)
		error(COMMAND_ERROR, "Reading Illegal Integer");

	END();
}

static void calc_new_size_option(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) {		/* 印字可能最大幅の指定ある時のみ、計算 */
			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) {		/* 印字可能域の最大幅の指定あるとき */
		if (w > MW) {	/* 中央揃え給紙の場合は常に偽のはず */
			RM += w - MW;/* 用紙が広すぎる：右マージンを増やす */
			w = MW;
		}
	} else {			/* 印字可能域の最大幅の指定無きとき */
	 	MW = w;			/* この幅まで印字できると仮定する */
	}

	if (MH > 0) {		/* 印字可能域の最大長の指定あるとき */
		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);

			/* 印字可能幅に対してセンタリングするバージョン */
			/*dim->x_offset
				= ROUND( SP_TO_IN( (w - 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);

			/* 印字可能長に対してセンタリングするバージョン */
			/*dim->y_offset
				= ROUND( SP_TO_IN( (h - 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);

			/* 印字可能幅に対してセンタリングするバージョン */
			/*dim->x_offset
				= ROUND( SP_TO_IN( (w - 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);

			/* 印字可能長に対してセンタリングするバージョン */
			/*dim->y_offset
				= ROUND( SP_TO_IN( (h - 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 free_size, bb_size;
	int f_raster;
	PIXEL t_w, t_h;
#ifndef	NEMS
	int i, j, raster_page;
#endif

	ENTER("pixel_init");

	if (f_use_new_size_option) calc_new_size_option(dvi, dim);
	else{
		if (dim->print_direction == HORIZONTAL) {
			dim->text_width += dim->x_offset + add_width;
			dim->text_height += dim->y_offset + add_height;
			if (f_max_bb){
				if (dim->max_width  > 0) dim->text_width  = dim->max_width;
				if (dim->max_height > 0) dim->text_height = dim->max_height;
			}
		}
		else{
			dim->text_height += dim->x_offset + add_width;
			dim->text_width += dim->y_offset + add_height;
			if (f_max_bb){
				if (dim->max_height > 0) dim->text_width  = dim->max_height;
				if (dim->max_width > 0) dim->text_height = dim->max_width;
			}
			t_w = dim->text_height;
			t_h = dim->text_width;
			goto bb;
		}
	}
	t_w = dim->text_width;
	t_h = dim->text_height;
bb:	bb_size = ((long)(t_w + (HORI_DIVIDE - 1))) / HORI_DIVIDE
			* (HORI_DIVIDE / 8) *
			(((long)(t_h + (vert_divide - 1))) / vert_divide * vert_divide);
#ifndef	NEMS
 #ifdef FDOWN
	if (!f_download)
		system_ems[1] = f_jdwn = 0;
 #endif
	for (i = j = 0; system_ems[i] != -1; i++){
		if (j + system_ems[i] <= total_EMS_page) j += system_ems[i];
		else system_ems[i] = 0;
	}
 #ifdef	JDWN
	if (f_jdwn & system_ems[1] == 0)
		 dj = farmalloc(0x4000L);
	else dj = (DJTABLE*)pf_addr;
 #endif
	raster_page = ((total_EMS_page - j)/4)*4;
	if( raster_page > 0 ){
		buffers[0].type |= f_EMS;
		buffers[0].ems_last = raster_page;
	}
	else raster_page = 0;
#else
 #ifdef	FDOWN
	if (f_download) dj = farmalloc(0x4000L);
	else dj = (DJTABLE*)pf_addr;
 #endif
#endif
	if (buffers[0].size < 0) {
		f_raster = -1;
		buffers[0].size = -buffers[0].size;
	}
	else f_raster = (buffers[0].size == 0L)? 0:0x4000;

	free_size = (long)leftbuffer() - buffers[0].size - buffers[1].size
		- buffers[2].size - buffers[3].size - (FAR_HEAP + 0x100);

	if (buffers[2].size == 0L) {
		free_size -= (buffers[2].size = 80000L);
		if (free_size > 0) {
			if (f_raster - raster_page >= 0)
				buffers[0].size += (free_size >>= 1);
			buffers[2].size += free_size;
			if ((free_size = (buffers[2].size - bb_size)) <= 0) goto fr_0;
			buffers[2].size = bb_size;
		}else
fr_0:		free_size = 0;
	}
	if (buffers[0].size <= 0x2000 && !raster_page){
		buffers[0].size = 0x2000;
		buffers[2].size -= 0x2000;
	}
	if (bb_size > 0x2000 && buffers[2].size <= 0x2000){
		buffers[2].size = 0x2000;
		buffers[0].size -= 0x2000;
	}
	if (buffers[3].size < 0)
		buffers[3].size = (free_size >= 2048)? free_size:0;
	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;
	}
	END();
}

static void make_page_index(DVIFILE_INFO *dvi, DIMENSION *dim)
{
	int i;
	long offset;

	ENTER("make_page_index");

	dim->page_index =
		(PAGE_INDEX *)marea(sizeof(PAGE_INDEX) * (dvi->total_page + 1));

	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;
		dim->page_index[i].number = read_long(dvi->file_ptr);
		/* Read count[0] */
		fseek(dvi->file_ptr, 36L, SEEK_CUR);
		/* Skip other 'count' values */
		offset = read_long(dvi->file_ptr);
	}

	END();
}

/* end of file : prtinit.c */
