/*
 *  TEX Device Driver  ver 2.02-2.32
 *  copyright(c) 1988, 1989 by TSG, 1990 by SHIMA
 *  1991 changed by T.Minagawa
 *
 *  init.c : initialize variables
 *      Apr. 29, 1989 : 1st edition
 *      Jun.  1, 1989 : 2nd edition
 *
 *      March, 1990   : Modified by SHIMA
 *  This module is a device-dependent one.
 *
 *  modified for non PC-9801 machines by sempa 1992
 *             14 June 1992 : modified for tpic by Oh-Yeah?
 *
 *  modified for Hires-9801 by OkI 21 June 1992
 *  modified for pTeX `tate' mode,  6 August 1992  by Naochan!.
 *  slightly modified for pTeX on LIPS3 by OkI 8 August 1992
 *
 *  modified for Minix-386 1992 by youchan
 *  modified for X-Window 1994 by M.M.U.
 */

#include "config.h"
#include "dd.h"
#include "err.h"
#include "dviread.h"
#include "device.h"
#include "option.h"
#include "version.h"
#include "vfont.h"

void get_config(DIMENSION*, int, char **);
void initialize(DVIFILE_INFO*, DIMENSION*);
static void read_post(DVIFILE_INFO*);
static void pixel_init(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 *);

#ifdef LBP
/* dummy function */
void p_out_char(PIXEL x, PIXEL y, FONT_INFO *f, uint n, PREAMBLE *p)
{
}

int d_download(FONT_INFO *f, int n)
{
    return(0);
}

KFONT *get_lbp_font(FONT_INFO *f)
{
    return((KFONT*)NULL);
}
#endif

/* size.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);

/* 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*);

/* vfont.c escpage.c Tomiie*/
#ifndef	NOTATEGAKI
int tategaki=0;
#endif

int test_flg = -1;
int prt_flag = 0;
static BOOL mag_half = FALSE;
static BOOL opt_mag = -1;
BOOL dvifile_page = FALSE;

static  int add_width;
static  int add_height;
static  int f_center;
static  int v_dx;
static  int v_dy;

int opt_x11_win_size=-1; /* default is -1 (auto detect) */

static  int vert_dpi;
static  int enlarge;

#ifndef NOTPIC
BOOL f_tpic_turn_on = TRUE; /* default is on */
#endif

#ifdef LIPS3
int  f_download = 0;
long cur_dsize = 0;
int  d_mincount;
#endif

#define CFG_PATH    "TEXCFG"
char    *cfg_path;

const char* const config_name = "dviout.cfg";
    /* 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 DVI PREVIEWER-32 "
    MACHINE VERSION;
const char* const title_copyright =
    "\nCopyright(C) 1988-89 by TSG, 90-91 by SHIMA,"
    "\n             1991-92 changed by Akiii, Oh-Yeah?, SOLITON, sempa, T.Minagawa"
    "\n             1992    changed by Naochan!, OkI, hero.h, Tomiie"
    "\n             1992    changed by obuk, youchan (32bit version)"
    "\n             1994    changed by M.M.U. (X-Window version)";

const char* const vfont_config = "dviout.vfn";
    /* vector font config file name */

extern char  prt_type;
extern BOOL  f_long_name;
extern BOOL  f_font_c;
extern char* goth;
extern char* sub_font;
extern char* fc_name;
extern char* k_dbl;
extern int   k_scale;
extern int   k_base;
extern int   x_shift;
extern int   y_shift;
extern int   s_max_width;
extern int   s_max_height;
extern int   f_search;
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.)
     */
extern char  ptex_mode;
    /* when `extended dvi file' encountered, this value is not zero.(pTeX)
     */
extern int  f_use_vfont;
extern char tmp_buf[];

#define BUFFER_NUM  5
#define CHAR_LIM    (0xff00/sizeof(PREAMBLE))

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


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 = {
    CRT_DPI,                    /* dpi */
    CRT_WIDTH, CRT_HEIGHT,      /* device width, height */
    0, 0,                       /* buffer width, height */
    DEF_MAG,                    /* mag */
    0, 0,                       /* text width, height */
    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 */
    0x80                        /* device type */
};

static ARG_TABLE option[] = {
    {"win",  INTEGER,   (void *)&(opt_x11_win_size),
	"window size for X-Window (0-4)"},
    {"mag",  INTEGER,    (void *)&opt_mag,
        "mag step (0-5)"},
    {"half", BOOLEAN,    (void *)&mag_half,
        "mag step (half)"},
    {"f",    INTEGER,    (void *)&test_flg,
        "test-flag"},
    {"dpi",  INTEGER,    (void *)&(dviout_dimension.dpi),
        "reset dpi"},
    {"DPI",  INTEGER,    (void *)&(vert_dpi),
        "vertical dpi"},
    {"e",    INTEGER,    (void *)&(enlarge),
        "enlarge*1000"},
    {"page", BOOLEAN,    (void *)&dvifile_page,
        "pages are dvifile-pages"},
    {"X",    INTEGER,    (void *)&(dviout_dimension.x_offset),
        "x-offset(pixel)"},
    {"Y",    INTEGER,    (void *)&(dviout_dimension.y_offset),
        "y-offset(pixel)"},
    {"w",    INTEGER,   (void *)&add_width,
        "add width(pixel)"},
    {"h",    INTEGER,   (void *)&add_height,
        "add length(pixel)"},
#ifndef NOTPIC /* this should be before "t" */
    {"tpic", BOOLEAN,   (void *)&f_tpic_turn_on,
        "Support tpic special [default +]"},
#endif
    {"r",    STRING,    (void *)&fc_name,
        "Save Font"},
    {"c",    BOOLEAN,   (void *)&f_font_c,
        "Check font matching"},
    {"F",    STRING,    (void *)&sub_font,
        "Font substiute"},
    {"L",    BOOLEAN,   (void *)&f_long_name,
        "cut center of long font names"},
    {"A",    INTEGER,   (void *)&f_search,
        "Font search"},
    {"K",    STRING,    (void *)&k_dbl,
        "Double size Kanji"},
    {"G",    STRING,    (void *)&goth,
        "Poor man's Kanji Gothic"},
    {"g",    BOOLEAN,   (void *)&use_lateral_kanji,
        "Use Lateral Kanji Font in pTeX `tate' mode"},
    {"base", BOOLEAN,   (void *)&draw_baseline,
        "draw the baseline"},
    {"box",  BOOLEAN,   (void *)&draw_boxpic,
        "draw boxes instead of characters"},
#ifndef NOVFONT
    {"vfn",  BOOLEAN,   (void *)&f_use_vfont,
        "Use Syotai Club's Font"},
#endif
    {"S",    INTEGER,   (void *)&k_scale,
        "Kanji scale*1000 (default 952)"},
    {"J",    INTEGER,   (void *)&k_base,
        "Kanji base line*1000 (default 0)"},
    {"W",    INTEGER,   (void *)&(s_max_width), 
        "V width(pixel)"},
    {"H",    INTEGER,   (void *)&(s_max_height), 
        "V height(pixel)"},
    {"P",    INTEGER,   (void *)&v_dx,
        "V x_offset(pixel)"},
    {"Q",    INTEGER,   (void *)&v_dy,
        "V y_offest(pixel)"},
    {"C",    BOOLEAN,   (void *)&(f_center),
        "V center"},
    {"=",    PROCEDURE, (void *)&opt_cfg,
        "configuration file"},
    {NULL}
};


void get_config(DIMENSION *dim, int argc, char **argv)
{
    int     i, l;
    char    real_name[MAXPATH], v_real_name[MAXPATH];
    char    *cfgpath;

    if ((cfgpath = getenv(CFG_PATH)) == NULL)
        cfgpath = CONFDIR;
    strncpy(real_name, cfgpath, MAXPATH-2);
    i = strlen(real_name);
    if (i > 0 && isalnum(real_name[i-1])) {
        real_name[i] = PATHCHAR;
        real_name[i+1] = '\0';
    }
    cfg_path = (char*)dup_string(real_name);
    strcpy(v_real_name, real_name);
    strncat(real_name, (char *)config_name, MAXPATH-1);
    strncat(v_real_name, (char *)vfont_config, MAXPATH-1);

    set_config(option, real_name);
    set_option(option, argc, argv);
#ifndef NOVFONT
    if (f_use_vfont && (0 != (l = get_vfont_name(v_real_name)))) {
        if (l > 0) {
            sprintf(tmp_buf,"[vfont] dviout.vfn/dviprt.vfn error.  line:%d\n", l);
            error(WARNING, tmp_buf);
        }
        else
            error(WARNING, "[vfont] Can't open dviout.vfn/dviprt.vfn file.");
    }
#endif
}

void initialize(DVIFILE_INFO *dvi, DIMENSION *dim)
{
    read_post(dvi);
    set_dimension(dvi, dim);
    make_font_list(dvi, dim);
    make_page_index(dvi, dim);
    pixel_init(dim);
    buffer_init();
    stack_init(dvi->stack_depth);

#ifndef NOTPIC
    if (f_tpic_turn_on) tpic_init(dim->buf_height);
        /* alloc y-bucket[vmax] and activate tpic interpretation */
#endif
}

/* optional configuration file */
static void opt_cfg(char *opt)
{
    set_config(option, opt);
}

void help_out(void)
{
    printf("usage : dviout [option(s)] dvifile [page(s) eg. 6-8 3+]\n\n");
    printf("options are as follows :\n");
    option_usage(option);
    printf("\noptions can be directed in %s\n", config_name);
    exit(0);
}

#define CM_INCH 2.54
    /* cm per inch */

static  int pres;

static void set_dimension(DVIFILE_INFO* dvi, DIMENSION* dim)
{
    static  int true_mag[] = { 1000, 1200, 1440, 1728, 2074, 2488 };
    ulong   num1, num2;
    long    num3;
    int     q;

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

    if (dim->dpi <= 0) error(ILLEGAL_ARGS, "dpi");
      dim->size_para = ((double)dvi->num *(double)dim->dpi*(double)dim->mag)/
     ((double)dvi->den*CM_INCH*100000000.0);

    if (vert_dpi == 0) vert_dpi = dim->dpi;
    set_convert(dim->size_para, dim->dpi, vert_dpi);
        /* set pixel<==>scaled-pt parameter */

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


#define END_DVI 223
#define ID      2
#define ID_PTEX 3

    /* id number for searching for postamble
     */

static void read_post(DVIFILE_INFO* dvi)
{
    long endofs;
    int code;
    
    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) {
            fprintf(stderr,"Extended DVI file encountered. Turn on pTeX mode.\n");
            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);
    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_short(dvi->file_ptr);
    dvi->total_page = read_short(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 ");
}


static void pixel_init(DIMENSION* dim)
{
    if (f_center) {
        x_shift = (s_max_width - dim->text_width)/2 + v_dx
            - dim->x_offset;
        y_shift = (s_max_height - dim->text_height)/2 + v_dy
            - dim->y_offset;
    }
    dim->text_width += dim->x_offset + add_width;
    dim->text_height += dim->y_offset + add_height;

    if (buffers[2].size == 0L ) {
        buffers[2].size  = ((dim->text_width+(HORI_DIVIDE-1)))/HORI_DIVIDE
            *(HORI_DIVIDE/8)*
            (((dim->text_height+(VERT_DIVIDE-1)))/VERT_DIVIDE*VERT_DIVIDE);
    }
    if (buffers[0].size <= 0x10000) buffers[0].size = 0x10000;
    dim->split = set_size(dim->text_width, dim->text_height,
         dim->max_width, dim->max_height,
         &dim->buf_width, &dim->buf_height);
}

static void make_page_index(DVIFILE_INFO* dvi, DIMENSION* dim)
{
    int i;
    long offset;
    
    if (dim->total_page <= 0)
        error(COMMAND_ERROR, "No pages in dvi-file");
    
    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 of file : init.c */
