/*
 *  TEX Device Driver  ver 2.02-
 *  (c) copyright 1988, 1989 by TSG, 1990-93 by SHIMA
 *
 *  main.c : MAIN MODULE
 *      Apr. 22, 1989 : 1st edition
 *      Jun.  1, 1989 : 2nd edition
 *
 *  1991 changed by hideki
 *	Modified for IBM-PC with DOS/V by SOLITON 12/10/1991
 *  This module becomes device-dependent which can be
 *  comment out by #undef IBMPC
 *	very slightly modified against warnings by Oh-Yeah? 25 May 1992
 *  modifed for LIPS3 by SHIMA 18 June 1992
 *  Modified for PC-9801 High-Resolution Mode by OKI 07/23/1992
 *	modified for LIPS3+ESC/Page by OkI & H.Tomiie 30 Sept. 1992
 *	slightly modified for JGfont(3D-Bezier) by Naochan! 12 Nov 1992
 */

#include <stdio.h>
#include <stdlib.h>
#define _DEF_STDIO_H_
#include <string.h>
#include <dos.h>
#include <dir.h>
#include <io.h>
#include <alloc.h>    /* H.senshu */
#define _DEF_STRING_H_
#include "dd.h"
#include "err.h"
#include "vfont.h"

#define OPTION_FLG    '-'
#define	EXTENSION_FLG '.'
#define	F_GOTH		1
char *const default_dvifile_ext = "dvi";

static int ctrl_c(void);
static void information_out(DIMENSION *);
static void dvifile_open(DVIFILE_INFO *, int, char **);
static void dvifile_close(DVIFILE_INFO *);
static char *name_link(char *, char *);
static void buffer_information(DIMENSION *);

#ifdef	SMALL
extern unsigned _heaplen = 25000;
#else
extern unsigned _heaplen = 40000;
#endif

extern int test_flg;

/* -f があるかどうか ( definition in init.c ) */
extern DIMENSION dviout_dimension;

/* name of the env-variable for pk-font path */

extern char *const title_name;
extern char *const title_comment;
extern char *const title_copyright;

extern int r_b_f_count;
extern int b_b_f_count;
extern int p_b_f_count;
extern int f_flush_pk;
extern uint num_char;

#ifdef	DOSV
extern int set_read_font(void);

#endif

uint resume_info;
int num_view_buf;
int ARGC;

#ifdef	PC9801
int num_view = -0x7fff;
#else
int num_view = -1;
#endif

#ifndef	NEMS
int f_EMS_pages = 0x800;
int	initialize_ems( int, int );
extern int total_EMS_page;
#endif
extern long view_buf_size;
extern BOOL f_wait;

/* init.c */
extern void get_config(int, char **);
extern void initialize(DVIFILE_INFO *, DIMENSION *);
void help_out(void);

BOOL f_resume;
extern char *resume_file;
static BOOL f_resume_file;

#ifdef HIRES98
extern int hireso;

#endif

/* putdvi.c */
void put_dvi(DVIFILE_INFO *, DIMENSION *, int, char **);
extern int current_page;

/* buffer.c */
char *marea(unsigned int);
ulong leftbuffer(void);
void save_fc(void);

/* err.c */
BOOL ask_retry(void);

/* fontdef.c */
char *get_font_name(FONT_INFO *);

#ifndef	NOVFONT
/* vfont.c */
V_JFM *get_vjfm(int);
extern V_FONT *vfont[];
#endif

static void exit_fn( void );
static int	c_break( void );
static void get_start_page( void );

DVIFILE_INFO dvifile;

void main(int argc, char **argv)
{
	int i;

	START(ctrl_c);

	ARGC = argc;
	printf("%s%s%s\n\n", title_name, title_comment, title_copyright);
	get_config(argc, argv);

	dvifile_open(&dvifile, argc, argv);

	ctrlbrk( c_break );
	atexit( exit_fn );
#ifndef	NEMS
	if( f_EMS_pages > 0 ) initialize_ems( 4, f_EMS_pages );
#endif
	initialize(&dvifile, &dviout_dimension);

	/* dviファイル名よりレジューム情報を作成 */
	if (resume_file != NULL && *resume_file != '-') {
		if (*resume_file == '+' || *resume_file == 0){
			for (i = strlen(dvifile.file_name) - 4; i >= 0; i--)
				resume_info += ((int)dvifile.file_name[i]<<(i&7));
			f_resume = TRUE;
		}
		else get_start_page();
	}

#if	defined(DOSV)
	if (set_read_proc()) {		/* 16x16dot フォントの読み込みルーチンの設定 */
		puts("Can't Use DBCS read routine in this system\n");
		puts("Please use command-line option \'-k\'.\n");
		exit(1);
	}
#endif
	if (test_flg) {
		put_dvi(&dvifile, &dviout_dimension, argc, argv);
		save_fc();
	}
	if (test_flg == 3)
		exit(0);
	information_out(&dviout_dimension);
	dvifile_close(&dvifile);

	buffer_information(&dviout_dimension);

	EXIT(0);
}

static int	c_break( void )
{
	return( 1 );
}

static void exit_fn( void )
{
	extern void release_ems (void);
	FILE *fp;

	if (f_resume_file && (fp = fopen(resume_file, "w")) != NULL){
		fprintf(fp, "%s %d\n", dvifile.file_name, current_page);
		fclose(fp);
	}
	release_ems();
}

int no_extension(char *name)
{
	int len, len0;

	len0 = ((len = strlen(name)) > 4) ? len - 4 : 0;
	while (--len >= len0) {
		if (name[len] == EXTENSION_FLG)
			return (0);
		else if (name[len] == '\\' || name[len] == '/')
			break;
	}
	return (1);
}

static int ctrl_c(void)
	/* Ctrl-C set up */
{
#if DEBUG & TRACE_LVL
	module_list_out();
#endif

	return (ask_retry());
}

static void get_start_page(void)
{
	FILE *fp;
	int ch;
	char *fname;

	f_resume_file = TRUE;
	if ((fp = fopen(resume_file, "r")) == NULL) return;
	for (fname = dvifile.file_name; *fname; fname++){
		if (fgetc(fp) != *fname) goto end;
	}
	if (fgetc(fp) == ' '){
		while((ch = fgetc(fp) - '0') >= 0 && ch <= 9)
			dviout_dimension.start_page = dviout_dimension.start_page*10 + ch;
	}
end:
	fclose(fp);
}

static void dvifile_open(DVIFILE_INFO *dvi, int argc, char **argv)
	/*  コマンドラインよりｄｖｉファイルをオープン
     *  拡張子(.dvi)も考慮する．
     */
{
	ENTER("dvifile_open");
	while (--argc) {
		if (**++argv != OPTION_FLG) {
			dvi->file_name = *argv;
			if (no_extension(*argv))
				dvi->file_name = name_link(*argv, default_dvifile_ext);

			while ((dvi->file_ptr = fopen(dvi->file_name, "rb")) == NULL) {
				f_wait = 0;
				error(NO_FILE, dvi->file_name);
			}
			END();
		}
	}
	help_out();
}

static void dvifile_close(DVIFILE_INFO *dvi)
	/* ｄｖｉファイルをクローズ
     */
{
	FONT_INFO *font;

	ENTER("dvifile_close");

	fclose(dvi->file_ptr);

	for (font = first_font_info; font; font = font->next_font) {
		if (font->font_type >= JIS_FONT) {
			if (font == font->k_top)
				close((font->ext.kdir)->fh);
		}
		else if (font->font_type >= PKD_FONT && font->ext.fh > 0)
			close(font->ext.fh);
	}

	END();
}

static char *
    name_link(char *base, char *ext)
	/* ベース名と，拡張子をくっつける．
     */
{
	char *name;
	int base_len;

	ENTER("name_link");

	base_len = strlen(base);
	name = marea(base_len + 5);
	strcpy(name, base);
	name[base_len] = EXTENSION_FLG;
	strcpy(name + base_len + 1, ext);
	RETURN(name);
}

static int open_num;
static void buffer_information(DIMENSION *dim)
	/* 最後に各バッファの使用状態が表示される */
{
	char	*s;
	long	size;

	if (test_flg == 2) {
		printf("\nflush = (Open %d, Bit %d, File %d, Raster %d)\n",
			   f_flush_pk, b_b_f_count, p_b_f_count, r_b_f_count);
		return;
	}
	printf("\nFiles open\t\t: flush%3d, total%7d files\n",
		   f_flush_pk, open_num + 1);
	printf("Bit map buffer\t\t: flush%3d, total%7ld bytes, used%7ld "
		   "split%3d\n",
		   b_b_f_count,
		   bitmap_buf_pointer->size,
		   (ulong)dim->buf_width / 8L * dim->buf_height,
		   dim->split);

	printf("Font file buffer\t: flush%3d, total%7lu bytes, used%7lu%s\n",
		   p_b_f_count, (ulong)pk_buf_pointer->size,
		   (ulong)((HUGE_BUF *)pk_buf_pointer->current
				   - (HUGE_BUF *)pk_buf_pointer->start),
#ifdef HIRES98
		   ((uint)FP_SEG(pk_buf_pointer->current) < 0xa800
			|| hireso == TRUE) ? "" : " in GVRAM");
#else
	   ((uint)FP_SEG(pk_buf_pointer->current) < 0xa800) ? "" : " in GVRAM");
#endif
	if( raster_buf_pointer->ems_bank < 0 )
		size = (ulong)((HUGE_BUF *)raster_buf_pointer->current
				- (HUGE_BUF *)raster_buf_pointer->start);
	else{
		size = raster_buf_pointer->size
		 + 0x4000L*(raster_buf_pointer->ems_bank - raster_buf_pointer->ems_top)
		 + (ulong)((HUGE_BUF *)raster_buf_pointer->current
				- (HUGE_BUF *)raster_buf_pointer->ems_start);
	}
	s = (raster_buf_pointer->ems_last==0)?"":"EMS";

	printf(
		"Expanded font buffer\t: flush%3d, total%7lu bytes, used%7lu #%u %s\n",
		   r_b_f_count, (ulong)raster_buf_pointer->size, size , num_char, s );

	if (num_view_buf > 0) {
		s = "Main RAM";
		if( num_view < 0 ) s = (num_view == -0x7fff )? "GVRAM":"EMS";
		printf("View Image buffer\t: number%2d, total%7lu bytes"
			   "\t\t    in %s\n",
			   num_view_buf, view_buf_size * num_view_buf, s );
	}

#ifndef	NEMS
	if (work_buf_pointer->size > 0 || total_EMS_page){
		printf(
			"Working buffer\t\t: EMS%5d  +  %9lu bytes "
			"(EMS: total %d pages)\n",
			max_user_page, (ulong)work_buf_pointer->size, total_EMS_page);
	}
#else
	if (work_buf_pointer->size > 0){
		printf(
			"Working buffer\t\t:%9lu bytes", (ulong)work_buf_pointer->size );
	}
#endif
	printf("Remaining memory\t:\t    local%7u bytes, far%8ld bytes\n",
		   coreleft(), leftbuffer());
}

#define	MAX_FOPEN	30
static void information_out(DIMENSION *dim)
	/* test-flag時には，これが表示される．
     */
{
	FONT_INFO *font;
	char *fname, *ftype;
	int font_num, f_kanji, i, fh;

#ifndef	NOVFONT
	int vchk_flg;

#endif
	V_JFM *vjfm;
	int f_open[MAX_FOPEN];

	ENTER("information_out");

	printf("\n");

#ifndef	NOVFONT
	vchk_flg =
#endif
		font_num = open_num = 0;
	for (i = 0; i < MAX_FOPEN; i++)
		f_open[i] = 0;
	for (font = first_font_info; font != NULL; font = font->next_font) {
		font_num++;
		if (test_flg == 0)
			continue;
		f_kanji = 0;
		ftype = "?";
		fname = "";
		switch (font->font_type) {

		  case (PK_FONT):
			  ftype = "PK";
			  break;

		  case (PKD_FONT):
			  ftype = "PKD";
			  goto jxl;

#ifdef VFD
		  case (VFD_FONT):
			  ftype = "VFD";
			  goto jxl;
#endif

		  case (JXL):
			  ftype = "JXL";
jxl:		  if (font->ext.fh > 0) {
				  fname = "+";
				  open_num++;
			  }
			  else
				  fname = "-";
			  break;

		  case (ROM_FONT):
			  ftype = "ROM";
			  f_kanji = 1;
			  break;
#ifndef	NOVFONT
#ifdef BEZIERFONT
		  case (JG_FONT):
#endif
		  case (ZS_FONT):
			  ftype = "Vec(**)";
			  vjfm = get_vjfm((font->ext.kdir)->fh);
			  ftype[4] = (char)vjfm->long_wide;
			  ftype[5] = (char)vjfm->slant;
			  fname = (font->ext.kdir)->name;
			  f_kanji = 1;
			  if (vchk_flg++ == 0) {
				  for (i = 0; i < MAX_VFONT; i++) {
					  if (vfont[i] != NULL &&
						  vfont[i]->status == V_OPEN)
						  open_num =
							  (vfont[i]->v_fh[1] == -1) ?
							  open_num + 1 : open_num + 2;
				  }
			  }
			  break;
#endif
#ifdef	LBP
		  case (JLBP):
			  ftype = "LBPfont";
			  f_kanji = 1;
			  goto kfont0;
#endif

		  case (JIS_FONT):
			  ftype = "";
kfont:			  if ((fh = font->ext.kdir->fh) != 0) {
				  for (i = 0; i < MAX_FOPEN; i++) {
					  if (f_open[i] == fh)
						  break;
					  else if (f_open[i] == 0) {
						  f_open[i] = fh;
						  open_num++;
						  break;
					  }
				  }
			  }
kfont0:		  fname = (font->ext.kdir)->name;
			  f_kanji = 1;
			  break;

		  case (JIS_PK):
			  ftype = "PK";
			  goto kfont;

		  case (JIS_PKH):
			  ftype = "PK/H";
			  goto kfont;

		  case (GAIJI):
			  ftype = "KG";
			  goto kfont;

		  case (PXL1001):
			  ftype = "PXL1001";
			  break;

		  case (PXL1002):
			  ftype = "PXL1002";
			  break;

		  case (PXL1003):
			  ftype = "PXL1003";
			  break;

		}
		if (test_flg == 2 || test_flg < 0)
			continue;
		printf("%5d: %s %s", font->font_code, get_font_name(font),
			   fname);
		if (f_kanji != 0) {
			printf("(%dx%d)", font->k_width, font->k_height);
			if (font->f_goth & K_DBL)
				printf("2");
			if (font->f_goth & F_GOTH)
				printf("G");
		}
		printf(" %s\n", ftype);
	}
	if (test_flg == 2 || test_flg < 0)
		END();
#ifdef	JAPANESE
	printf("\n使用フォント\t\t: 以上 %d個 (%d dpi)\n", font_num, dim->dpi);
	printf("magnification\t\t: %4d\n", dim->mag);
	printf("総ページ数\t\t: %4d\n", dim->total_page);
	printf("１ページ分割数\t\t: %4d\n\n", dim->split);
	printf("展開ビットマップサイズ\t: %d x %d dot\n", dim->buf_width,
		   dim->buf_height);
	printf("文書サイズ\t\t: %d x %d dot\n\n", dim->text_width,
		   dim->text_height);
#else
	printf("font : total %d (%d dpi)\n", font_num, dim->dpi);
	printf("mag  : %d\n", dim->mag);
	printf("page : %d\n", dim->total_page);
	printf("split: %d\n", dim->split);
	printf("buffer size : %d x %d\n", dim->buf_width, dim->buf_height);
	printf("text   size : %d x %d\n\n", dim->text_width, dim->text_height);
#endif
	END();
}
