
/*******************************************************/
/* tex4ht.c                                  v alpha.8 */
/* Copyright (C) 1996--98 Eitan M. Gurari              */
/*                                                     */
/* Permission is granted to use and copy this package, */
/* but not to sell any part of it without the author's */
/* written permission.  This notice must remain in any */
/* copy or derivative, and binary forms must reproduce */
/* the above copyright notice.                         */
/*                                                     */
/* gurari@cis.ohio-state.edu                           */
/* http://www.cis.ohio-state.edu/~gurari               */
/* ftp.cis.ohio-state.edu : pub/tex/osu/gurari         */
/*******************************************************/

/* **********************************************
    Compiler options                            *
    (uncommented | command line)                *
------------------------------------------------*
        Clasic C (CC)             default
#define ANSI                      ansi-c, c++
#define DOS_C
*************************************************
    Tex4ht variables                            *
    (uncommented | command line)                *
----------------------------------------------- */

#ifndef MAXFONTS
#define MAXFONTS 255
#endif


#ifndef LGFNT
#define LGFNT "Font(\"%s\",\"%s\",\"%d\")\n"
#endif


#ifndef LGCLS
#define LGCLS "Font_Class(%d,\"%s\"): %s\n"
#endif


#ifndef LGPIC
#define LGPIC "--- needs --- %%1.idv[%%2] ==> %%3 ---\n%"
#endif


#ifndef LGSEP
#define LGSEP "--- characters ---\n"
#endif


#ifndef LGTYP
#define LGTYP ".gif"
#endif


#ifndef ENVFILE

#endif


#ifndef TFMDIR

#endif


#ifndef HTFDIR

#endif


/* ******************************************** */
#ifdef MSVC_1_52_DOS_LIB
#define  MSVC_1_52_DOS
#endif
#ifdef MSVC_1_52_DOS
#define DOS
#define NOSUBDIR
#endif
#ifdef MSVC_1_52_DOS_LIB
#undef NOSUBDIR
#endif
#ifdef DOS_C
#define DOS
#endif
#ifdef DOS
#define DOS_WIN32
#endif
#ifdef WIN32
#define DOS_WIN32
#endif

#ifdef KPATHSEA
#ifdef WIN32
#define KWIN32
#endif
#endif



#include <stdio.h>   
#include <stdlib.h>  


#ifdef DOS
#include <string.h>
#endif


#ifdef KPATHSEA
#include <kpathsea/config.h>
#include <kpathsea/c-errno.h>
#include <kpathsea/c-ctype.h>
#include <kpathsea/c-fopen.h>
#include <kpathsea/c-pathmx.h>
#include <kpathsea/proginit.h>
#include <kpathsea/tex-file.h>
#include <kpathsea/tex-make.h>
#include <signal.h>
#if !defined(_AMIGA) && !defined(WIN32)
#include <sys/time.h>
#endif
#include <fcntl.h>
#include <setjmp.h>
#endif 


#ifdef WIN32
#include <string.h>
#include <windows.h>
#endif


#include <limits.h> 


#include <signal.h>


#ifndef F_OK
#ifdef DOS_WIN32
#define  F_OK 0               
#endif
#ifndef DOS_WIN32
#include <unistd.h>
#endif
#endif


#ifdef DOS_WIN32
#include <io.h>
#endif


#include <sys/stat.h>




#ifndef WIN32


#ifndef MSVC_1_52_DOS
#include  <dirent.h>

#endif

#endif





#ifdef KPATHSEA
#ifndef HAVE_STRCHR
#define  strchr  index
#endif
#ifndef HAVE_STRRCHR
#define  strrchr  rindex
#endif
#endif 


#ifdef DOS
#define HTM
#endif




#ifdef DOS
#define PROTOTYP
#endif
#ifdef ANSI
#define PROTOTYP
#endif
#ifdef KWIN32
#define PROTOTYP
#endif





#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif


#if INT_MAX < 2147483647L  
#define LONG L
#endif


#ifdef LONG
#define INTEGER long
#else
#define INTEGER int
#endif


#define m_alloc(typ,n) (typ *) malloc_chk((int) ((n) * sizeof(typ)))


#define IGNORED void


struct files_rec{
  FILE* file;
  char* name;
  struct files_rec *next, *prev;
};


#define gif_open  span_open
#define gif_alt   span_name
#define gif_class span_size
#define gif_size  span_mag
#define gif_mag   span_ord
#define gif_ord   span_ch
#define gif_end   end_span


#define HEIGHT 120


#define NULL_MAP (struct map_line_type*) 0


#define XRESOLUTION MARGINSP
#ifdef LONG
#define YRESOLUTION 786432L
#else
#define YRESOLUTION 786432
#endif


#define MAX_MAP_LINE 500


#define idv_int(val)     int_to_dvi((long int) val,4)


#define get_dec(n)    ((double)n / (double)(1L<<20))


#define new_font   font_tbl[font_tbl_size]


#ifdef LONG
#define MARGINSP 344061L        
#else
#define MARGINSP 344061
#endif


#define ignore_ch 0


#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef BOOL
#define BOOL int
#endif


#define GIF_I      "-%x%s"
#define GIF_II  "-%x-%x%s"
#define GIF_VII       "%s"


#ifdef HTM
#define DOS_GIF_FILE
#endif


#define BASE  36


#define store_bit_I(ch,i)  ch[(i)/8]|=(1<<((i)%8));
#define store_bit_Z(ch,i)  ch[(i)/8]&=~(1<<((i)%8))
#define add_bit(ch,i,b)   ch[(i)/8] |= ((b) << ((i)%8))
#define get_bit(ch,i)     ((ch[i/8] >> (i%8)) & 1)


#ifndef MAXFDIRS
#define MAXFDIRS 100
#endif


#ifndef  S_ISDIR
#define S_ISDIR(M)  ((M & _S_IFMT)==_S_IFDIR)   
#endif

#ifndef _S_IFDIR
#define _S_IFDIR S_IFDIR
#endif

#ifndef _S_IFMT
#define _S_IFMT S_IFMT
#endif


#ifdef DOS_WIN32
#define LSTAT stat
#else
#define LSTAT lstat
#endif
#define STSTAT stat


#define get_unt(n)  fget_unt(dvi_file,n)


#define get_int(n)  fget_int(dvi_file,n)


#define eq_str(x,y) (!strcmp(x,y))


#define bad_arg            err_i(0)
#define bad_in_file(name)   err_i_str(1,name)
#define bad_out_file(name)  err_i_str(2,name)
#define bad_special(name)   warn_i_str(3,name)
#define bad_mem             err_i(4)
#define bad_char(chr)       err_i_int(5,chr)
#define bad_dvi             err_i(7)


#ifdef DOS_WIN32
#define READ_BIN_FLAGS "rb"
#define READ_TEXT_FLAGS "r"
#define WRITE_BIN_FLAGS "wb"
#define WRITE_TEXT_FLAGS "w"
#else
#define READ_BIN_FLAGS "r"
#define READ_TEXT_FLAGS "r"
#define WRITE_BIN_FLAGS "w"
#define WRITE_TEXT_FLAGS "w"
#endif


#ifdef PROTOTYP
#define VOID void
#define ARG_I(x) x
#define ARG_II(x,y) x,y
#define ARG_III(x,y,z) x,y,z
#define ARG_IV(x,y,z,w) x,y,z,w
#else
#define VOID
#define ARG_I(x)
#define ARG_II(x,y)
#define ARG_III(x,y,z)
#define ARG_IV(x,y,z,w)
#endif



struct count_rec{
   char* str;
   int i, depth, max;
   int* stack;
   struct count_rec* next;
};


struct ch_map_rec{
  char* line;
  int max, chars;
};


struct stack_entry{
  long  int x_val, y_val;
  INTEGER dx_1, dx_2, dy_1, dy_2;
  BOOL text_on;
  
int stack_id;
struct group_info* begin;
char *end;


};


struct group_info{
  int stack_id;
  char *info;
  struct group_info* next;
};


struct font_entry {
 INTEGER num;
 INTEGER scale;
 INTEGER design_sz;
 
INTEGER mag;


 
char *family_name, *font_size;


 
 INTEGER design_pt;     
 int char_f, char_l;    
 char *char_wi;
 char *char_hidp;
 int  wtbl_n;
 int  htbl_n;
 int  dtbl_n;
 INTEGER  *wtbl;              
 INTEGER  *htbl;              
 INTEGER  *dtbl;              
 INTEGER  word_sp;            
 INTEGER  it;                 
 INTEGER  ex;                 


 
char *name, *gif_on, *ch_str;
unsigned char **str, *ch, *gif1;


};


struct html_font_rec{  char* name;
                       int   i;     };


#ifdef DOS_GIF_FILE
struct gif_file_rec{
    char                code[4];
    char                *name;
    struct gif_file_rec *next;     };
#endif


struct cache_font_rec{  char* dir;
                        struct cache_font_rec* next;     };



#ifdef WIN32
static char dirname[MAX_PATH];
#endif


FILE*  dot_file;


char *out_dir = "";


FILE* dvi_file;


char* job_name;
int   job_name_n;


FILE *out_file  = (FILE *) 0,
     *root_file = (FILE *) 0,
     *cur_o_file;


int  stack_len;


long int x_val = 0, max_x_val = -10000,
     max_y_val = 0, prev_y_val = 0;


BOOL text_on = FALSE;


INTEGER dx_1 = 0, dx_2 = 0;


INTEGER  dy_1 = 0, dy_2 = 0;
long int y_val = 0;


int cur_fnt;  


char special_hd[10];


BOOL nomargin = FALSE;


struct files_rec *opened_files = (struct files_rec *) 0, *p;


struct count_rec *counter = (struct count_rec *) 0;


int    pause_style = 0, default_font = -1, base_font_size=6533;
BOOL
  span_name_on = FALSE,
  span_on = FALSE;


char *  img_src;


char *  img_alt;


BOOL not_notify = FALSE;


char * span_name[256], * span_open[256], * span_size[256],
     * span_mag[256],  * span_ch[256],   * end_span[256],
     * span_ord[256],  * gif_id[256];
char class_on[32];


BOOL in_trace_char = FALSE, block_start = FALSE;
BOOL trace_dvi = FALSE;
char trace_dvi_del[256]     = "<!-- DVI ",
     end_trace_dvi_del[256] = "\n-->";
int push_depth=0, push_id=0, push_st[256];


BOOL start_span = FALSE, in_span_ch = FALSE;


struct ch_map_rec  ch_map[HEIGHT];
  int max_map_line, min_map_line;


BOOL ch_map_flag = FALSE;


INTEGER xresolution, yresolution;


char ok_map = TRUE;


int prevcol = -1, prevrow;
double prev_x;


BOOL  dvi_flag = FALSE;
FILE *idv_file;


FILE*  log_file;


INTEGER mid_page_y, mid_page_x;


int page_n,  file_n;


int stack_n = 0;
struct stack_entry* stack;


BOOL group_dvi = FALSE;


BOOL pos_dvi = FALSE;
char   *pos_body,     * pos_text,     * pos_line,
       *end_pos_body, * end_pos_text;
double   pos_x_A, pos_x_B, pos_y_C, pos_y_D;
long int base_pos_x, base_pos_y, min_pos_x,
         max_pos_x, min_pos_y, max_pos_y;


struct font_entry*  font_tbl;
int font_tbl_size = 0;


char*  new_font_name;


char *lg_font_fmt = NULL;


double word_sp   = 999999.0, margin_sp;


unsigned  char  null_str = '\0';    


BOOL verb_ch = FALSE;


char *class_fmt = NULL;


char *font_gif = NULL;


char *begin_char_gif = NULL;


char *gif = NULL;


#ifdef DOS_GIF_FILE
struct gif_file_rec *   gif_file = (struct gif_file_rec *) 0;
#endif


#ifdef DOS_GIF_FILE
char xeh[]="0123456789abcdefghijklmnopqrstuvxyz";
#endif


BOOL gif_ch = TRUE;
int design_ch = 0;


char  *fontdir[MAXFDIRS];
int fontdir_count = 0;


struct cache_font_rec *cache_font,  *cur_cache_font;


BOOL special_on = FALSE;


char *warn_err_mssg[]={ 
"improper command line\ntex4ht in-name[.dvi]\n\
   [-ttfm-font-dir]...\n\
   [-ihtf-font-dir]\n\
   [-eenv-dir]\n\
   [-dout-dir]\n\
   [-oout-name[.html]]\n",                            
"Can't find/open file `%s'\n",                       
"Can't open output file for `%s'\n",                 
"Can't close file `%s' (file is not open)\n",        
"Insufficient memory\n",                              
"Bad character code: %d\n",                           
"Can't find font number %d\n",                        
"Improper dvi file\n",                                
"Improper op while scanning font defs in postamble\n",
"Problem with command line\n",                        
"Font definition repeated in postamble\n",            
"Empty entry in font environment variable\n",         
"Can't access directory `%s\n'",                     
"Too many directories in font environment variable\n",
"Missing fonts, can't proceed\n",                     
"Invalid header in file `%s'\n",                     
"Checksum inconsistent\n",                            
"MAXFONTS too small: %d\n",                           
"Improper signature at end of file `%s.htf'\n",      
"Improper signature at start of file `%s.htf'\n",    
"Improper file `%s.htf'\n",                          
"Couldn't find font `%s.htf' (char codes: ",        
"File `%s.htf' starts/ends with character code %d (instead of %d)\n",
"Implementation problem\n",                           
"Improper groups in \\special{t4ht+}... idv[%d]\n",   
"Too many characters (> %d) for map line: `%c'\n",   
"Extra characters in \\special(t4ht%c...",            
"Page break within a ch map/picture\n",               
"Char code >255 in htf file: %d\n",                   
"Improper char for code in htf file: %c\n",           

"Illegal storage address\n", 
"Floating-point\n",          
"Interrupt with Cntr-C\n",   

                           
#ifdef DOS_WIN32
"%c-script too long in tex4ht.env \n",                
#else
"%c-script too long in tex4ht.env (.tex4ht)\n",       
#endif
"Too many rows (> %d) for map: `%c'\n",              
"More than 255 strings in font\n",                    
"\\special{t4ht;%c...}?\n",                           
"\\special{t4ht;|%s}?\n",                             
"missing %s\n",                                       
"\\special{t4ht\"...%s}?\n",                          
"system error 40\n",                                  

 "" };


char warning[] = "--- warning --- ";



#ifdef WIN32
BOOL sigint_handler(DWORD)
#endif


void

#ifdef WIN32
__cdecl
#endif


sig_err(ARG_I(int));


void* malloc_chk(ARG_I(int));


void* r_alloc(ARG_II(void *, size_t));


void strct( ARG_II(char *, char *) );


FILE* open_html_file( ARG_I(char*) );


INTEGER insert_ch( ARG_I(int) );


void try_new_line( ARG_I(void) );


void rule_x( ARG_I(BOOL) );


INTEGER move_x( ARG_I(register INTEGER) );


INTEGER move_y( ARG_I(register INTEGER) );


BOOL tex4ht_special( ARG_II( int*, long int*) );


void init_ch_map( ARG_I(void) );


void insert_ch_map( ARG_II(char,BOOL) );


void dump_ch_map( ARG_I(void) );


void  set_loc( ARG_II(int, long int) );


void idv_char( ARG_I(int) );


void cond_idv_char( ARG_I(int) );


void idv_copy( ARG_I(void) );


void cond_idv_int( ARG_II(long int, int) );


void  int_to_dvi( ARG_II(long int, int) );


void cond_string( ARG_II(int, int) );


INTEGER advance_idv_page( ARG_II( INTEGER,char*) );


void store_mv( ARG_II( int, INTEGER) );


void push_stack( ARG_I(void) );


void pop_stack( ARG_I(void) );


double pos_dbl( ARG_I(long int *) );


int search_font_tbl( ARG_I(int) );


int get_html_ch( ARG_I(FILE*) );


INTEGER get_html_file_id( ARG_IV(FILE*, int, int, int) );


void notify_class_info( ARG_I(int) );


void script( ARG_IV(char *, char *, int, char *) );


#ifdef DOS_GIF_FILE
void  dos_gif_file( ARG_III(char *, int, int) );
#endif


void put_alt_ch( ARG_II( int, BOOL) );


char* get_script( ARG_III(char *, char *, int) );


BOOL com_dir( ARG_I(char*) );


FILE*  search_in_dot_file( ARG_III( int, char *, char *) );


FILE* search_file( ARG_III(char *, char *, char *) );


FILE* search_file_ext( ARG_III(char *, char *, char *) );


BOOL search_dot_file( ARG_I( int) );


void put_char( ARG_I(int) );


void print_f( ARG_I(char*) );


int get_char( ARG_I(void) );


int get_noop( ARG_I(void) );


long fget_unt( ARG_II(FILE*, int) );


long fget_int( ARG_II(FILE *, int) );


long cond_int( ARG_I(register  INTEGER) );


void warn_i( ARG_I(int) );


void warn_i_int( ARG_II(int,int) );


void warn_i_int_2( ARG_III(int,int,int) );


void warn_i_str( ARG_II(int,char *) );


void err_i( ARG_I(int) );


void err_i_int( ARG_II(int,int) );


void err_i_str( ARG_II(int,char *) );



#ifdef WIN32
BOOL sigint_handler(DWORD dwCtrlType)
{
  err_i(32);
  return FALSE;      /* return value obligatory */
}
#endif



void

#ifdef WIN32
__cdecl
#endif


sig_err
#ifdef ANSI
#define SEP ,
(  int s
)
#undef SEP
#else
#define SEP ;
(s)  int s
;
#undef SEP
#endif
{
  (void) signal(s,SIG_IGN);  
  switch( s ){
#ifdef SIGSEGV
    case SIGSEGV: err_i(30);
#endif
    case SIGFPE : err_i(31);
#if defined(SIGINT) && !defined(WIN32)
    case SIGINT : err_i(32);
#endif
  } }



void* malloc_chk
#ifdef ANSI
#define SEP ,
( int n
)
#undef SEP
#else
#define SEP ;
( n ) int n
;
#undef SEP
#endif
{      void* p;
   if((p = (void *) malloc( (size_t) n)) == NULL ) bad_mem;
   return p;
}



void* r_alloc
#ifdef ANSI
#define SEP ,
(
      void   *q SEP 
      size_t  n
)
#undef SEP
#else
#define SEP ;
( q, n )
      void   *q SEP 
      size_t  n
;
#undef SEP
#endif
{    void*   p;
   if((p = (void *) realloc( q, (size_t) n)) == NULL) bad_mem;
   return p;
}



void strct
#ifdef ANSI
#define SEP ,
(
     char * str1 SEP 
     char * str2

)
#undef SEP
#else
#define SEP ;
( str1, str2 )
     char * str1 SEP 
     char * str2

;
#undef SEP
#endif
{   char * ch;
   ch = str1 + (int) strlen(str1);
   (IGNORED) strcpy( ch, str2 );
}


 FILE* open_html_file
#ifdef ANSI
#define SEP ,
(
     char* name
)
#undef SEP
#else
#define SEP ;
(name)
     char* name
;
#undef SEP
#endif
{   FILE* file;
     char* str;
  str = m_alloc(char, (int) strlen(name) + (int) strlen( out_dir ) + 1);
  (IGNORED) strcpy(str, out_dir);
  (IGNORED) strcpy(str+(int) strlen(out_dir), name);
  (IGNORED) printf(" file %s\n", str);
  if( (file = fopen(str, WRITE_TEXT_FLAGS)) == NULL )  bad_in_file(str);
  free((void *)  str);
  return file;
}


  INTEGER insert_ch
#ifdef ANSI
#define SEP ,
(    int ch
)
#undef SEP
#else
#define SEP ;
(ch)    int ch
;
#undef SEP
#endif
{
   try_new_line();
   

if( span_on && (default_font != font_tbl[cur_fnt].num) ){
  if( !ch_map_flag && start_span ){
    if( span_name_on ){
       if( *span_open[0] )
           (IGNORED) fprintf(cur_o_file, span_open[0]);
       if( *span_name[0] ) (IGNORED) fprintf(cur_o_file,
            span_name[0], font_tbl[cur_fnt].family_name);
       if( *span_size[0] ) (IGNORED) fprintf(cur_o_file,
            span_size[0], font_tbl[cur_fnt].font_size);
       if( *span_mag[0]  && (font_tbl[cur_fnt].mag != 100))
           (IGNORED) fprintf(cur_o_file,
                       span_mag[0], font_tbl[cur_fnt].mag);
       if( *span_ch[0] )
           (IGNORED) fprintf(cur_o_file, span_ch[0]);
    }
    start_span = FALSE;
  }
}

 
if( trace_dvi ){
   if( !ch_map_flag ){
     (IGNORED) fprintf(cur_o_file,
         block_start? "%sCH %s %d B%s" : "%sCH %s %d%s",
         trace_dvi_del, font_tbl[cur_fnt].name, ch, end_trace_dvi_del);
   }
   block_start = FALSE;
}

 
if( pos_dvi && *pos_text ){       long int d;
  (IGNORED) fprintf(cur_o_file, pos_text,
       pos_x_A * (x_val - base_pos_x) + pos_x_B,
       pos_y_C * (y_val - base_pos_y) + pos_y_D);
  if( x_val < min_pos_x )                       min_pos_x = x_val;
  if( (d = x_val + 
(int)(
(double) *(font_tbl[cur_fnt].wtbl
                 +  (int) (
*(font_tbl[cur_fnt].char_wi +  (int)
   ( ch - font_tbl[cur_fnt].char_f)% 256)

))
   / (double) (1L<<20)
   * (double) font_tbl[cur_fnt].scale

)

)  > max_pos_x ) max_pos_x = d;
  if( (d = y_val - 
(int)(
(double) *(font_tbl[cur_fnt].htbl
                 +  (int) (
( *(font_tbl[cur_fnt].char_hidp +  (int)
   ( ch - font_tbl[cur_fnt].char_f)% 256)
  >>  4
) & 0x0F

))
   / (double) (1L<<20)
   * (double) font_tbl[cur_fnt].scale

)

) < min_pos_y ) min_pos_y = d;
  if( (d = y_val + 
(int)(
(double) *(font_tbl[cur_fnt].dtbl
                 +  (int) (
( *(font_tbl[cur_fnt].char_hidp +  (int)
   ( ch - font_tbl[cur_fnt].char_f)% 256)
) & 0x0F

))
   / (double) (1L<<20)
   * (double) font_tbl[cur_fnt].scale

)

)  > max_pos_y ) max_pos_y = d;
}


if( verb_ch ) (IGNORED) putc( ch, cur_o_file );
else
{     int gif_flag, chr, r_ch;
      BOOL  ch_str_flag;
  r_ch = ch - font_tbl[cur_fnt].char_f;
  chr=*(font_tbl[cur_fnt].ch + r_ch);
  gif_flag = font_tbl[cur_fnt].gif1[r_ch];
  ch_str_flag = get_bit( font_tbl[cur_fnt].ch_str, r_ch);
  if( (gif_flag % 2) || ch_str_flag ){      design_ch = ch;
              { 
      char  str[256], *p;
      BOOL sv;
      int mag;
sv = special_on;   special_on = TRUE;
if( gif_ch && (gif_flag % 2) ){
   if( !gif_open[gif_flag] ){
     
(IGNORED) sprintf(str,
   "\\special{t4ht;|%d...} for char %d in font %s.htf",
   gif_flag, ch,font_tbl[cur_fnt].name
  );
warn_i_str(38,str);


gif_open[gif_flag] = m_alloc(char,
   
26

);
(IGNORED) strcpy(gif_open[gif_flag],
  
"<IMG SRC=\"+\"ALT=\"+++++\">+"

);
gif_alt[gif_flag] = gif_open[gif_flag]+11;
  *(gif_alt[gif_flag] - 1) = '\0';
gif_class[gif_flag] = gif_open[gif_flag]+18;
  *(gif_class[gif_flag] - 1) = '\0';
gif_size[gif_flag] = gif_open[gif_flag]+19;
  *(gif_size[gif_flag] - 1) = '\0';
gif_mag[gif_flag] = gif_open[gif_flag]+20;
  *(gif_mag[gif_flag] - 1) = '\0';
gif_ord[gif_flag] = gif_open[gif_flag]+21;
  *(gif_ord[gif_flag] - 1) = '\0';
gif_end[gif_flag] = gif_open[gif_flag]+22;
  *(gif_end[gif_flag] - 1) = '\0';
gif_id[gif_flag] = gif_open[gif_flag]+25;
  *(gif_id[gif_flag] - 1) = '\0';


   } else if( !get_bit( class_on, gif_flag ) ) {
      notify_class_info(gif_flag);
      store_bit_I( class_on, gif_flag );
   }
   
if( *(p = gif_open[gif_flag]) ){
   print_f(p); strcpy(str, font_tbl[cur_fnt].name);
   mag = (int) ((double) font_tbl[cur_fnt].scale /
                font_tbl[cur_fnt].design_sz  * 10 );
   
#ifndef DOS_GIF_FILE
print_f(font_tbl[cur_fnt].name);
if( mag == 10 )  (IGNORED) sprintf(str, GIF_I,   design_ch, gif);
else             (IGNORED) sprintf(str, GIF_II,  mag, design_ch, gif);
#endif


#ifdef DOS_GIF_FILE
dos_gif_file(str, mag, design_ch);
print_f(str);
(IGNORED) sprintf(str, GIF_VII, gif);
#endif


   print_f(str);
   add_bit( font_tbl[cur_fnt].gif_on, r_ch, 1 );
}


   
if( *(p = gif_alt[gif_flag]) ){
   print_f(p);  put_alt_ch(chr,ch_str_flag);
}


   
if( *(p = gif_class[gif_flag] ) ){
  (IGNORED) fprintf(cur_o_file, p,
                   font_tbl[cur_fnt].family_name);  }


   
if( *(p = gif_size[gif_flag]) ){
   (IGNORED) fprintf(cur_o_file, p,
                   font_tbl[cur_fnt].font_size);  }


   
if(   *(p = gif_mag[gif_flag])
   && (font_tbl[cur_fnt].mag != 100) ){
  (IGNORED) fprintf(cur_o_file, p, font_tbl[cur_fnt].mag);
}


   
if( *(p = gif_ord[gif_flag]) ){
  (IGNORED) fprintf(cur_o_file, p, ch);
}


   
if( *(p = gif_end[gif_flag]) ){ print_f( p ); }


} else  { 
if( !gif_flag  || ch_map_flag ) { put_alt_ch(chr,ch_str_flag);  }
else{ 

if( gif_flag && !get_bit( class_on, gif_flag ) ) {
  notify_class_info(gif_flag);
  store_bit_I( class_on, gif_flag );
}



if( *span_open[gif_flag] ){
   print_f( span_open[gif_flag] );
}



if( *span_name[gif_flag] ){
  (IGNORED) fprintf(cur_o_file, span_name[gif_flag],
                        font_tbl[cur_fnt].family_name);
}



if( *span_size[gif_flag] ){
  (IGNORED) fprintf(cur_o_file, span_size[gif_flag],
                        font_tbl[cur_fnt].font_size);
}



if( *span_mag[gif_flag] ){
  (IGNORED) fprintf(cur_o_file, span_mag[gif_flag],
                        font_tbl[cur_fnt].mag);
}



if( *span_ord[gif_flag] ){
  (IGNORED) fprintf(cur_o_file, span_ord[gif_flag], chr);
}



if( *span_ch[gif_flag] ){
  print_f( span_ch[gif_flag] );
}


put_alt_ch(chr,ch_str_flag);

if( *end_span[gif_flag] ){
   print_f( end_span[gif_flag] );
}



 }

 }
special_on = sv;

 } design_ch = 0;    }
  else if( !ch_str_flag ) { 
if( !gif_flag || ch_map_flag ) { put_char(chr);  }
else{ 

if( gif_flag && !get_bit( class_on, gif_flag ) ) {
  notify_class_info(gif_flag);
  store_bit_I( class_on, gif_flag );
}



if( *span_open[gif_flag] ){
   print_f( span_open[gif_flag] );
}



if( *span_name[gif_flag] ){
  (IGNORED) fprintf(cur_o_file, span_name[gif_flag],
                        font_tbl[cur_fnt].family_name);
}



if( *span_size[gif_flag] ){
  (IGNORED) fprintf(cur_o_file, span_size[gif_flag],
                        font_tbl[cur_fnt].font_size);
}



if( *span_mag[gif_flag] ){
  (IGNORED) fprintf(cur_o_file, span_mag[gif_flag],
                        font_tbl[cur_fnt].mag);
}



if( *span_ord[gif_flag] ){
  (IGNORED) fprintf(cur_o_file, span_ord[gif_flag], chr);
}



if( *span_ch[gif_flag] ){
  print_f( span_ch[gif_flag] );
}


put_char(chr);

if( *end_span[gif_flag] ){
   print_f( end_span[gif_flag] );
}



 }

 }
}

if( pos_dvi ){
   print_f(end_pos_text);
}

 
if( trace_dvi && !ch_map_flag ){
   (IGNORED) fprintf(cur_o_file, "%sHC%s",
         trace_dvi_del, end_trace_dvi_del);
}

 


   text_on = TRUE;
   
{
  return (INTEGER)(
      (double) *(font_tbl[cur_fnt].wtbl +
                 (int) 
*(font_tbl[cur_fnt].char_wi +
       (ch - font_tbl[cur_fnt].char_f)% 256)

)
      / (double) (1L<<20)
      * (double) font_tbl[cur_fnt].scale
  );  }


}


void try_new_line(VOID)
{        long int  v;
         double    dy;
   if( !text_on && (y_val > max_y_val) ){
      put_char('\n');  max_x_val = -10000;
      prev_y_val = max_y_val  = stack_n? y_val : 0;
   }else{
      v = y_val - prev_y_val;
      dy = 1.7 * (double) font_tbl[cur_fnt].ex
               / (double) (1L<<20)
               * (double) font_tbl[cur_fnt].scale;
      if( v > dy ){ put_char('\n');   max_x_val = x_val;
                    prev_y_val = stack_n? y_val : 0;
      }else if( v < -(dy / 1.4) ) prev_y_val = stack_n? y_val : 0;
}  }


  void rule_x
#ifdef ANSI
#define SEP ,
(
      BOOL  tag
)
#undef SEP
#else
#define SEP ;
( tag )
      BOOL  tag
;
#undef SEP
#endif
{    long i, right, up;
   up = (INTEGER) get_int(4);
   right = (INTEGER) get_int(4);
   if( ch_map_flag ){ 
   long int  sv_x_val, sv_y_val, sv_right, sv;
   int  ch;
sv_x_val = x_val;
sv_y_val = y_val;
sv_right = right;
y_val-=up;
if( right < 0 ){ x_val += right;  right = -right; }
if( up < 0 ){ y_val += up;  up = -up; }
ch = ( (right > xresolution) &&  (up > yresolution) ) ?
       
3
 :  ( ( right > up )? 
1
 : 
2
 );
right += x_val;
up    += sv = y_val;
for( ; x_val < right; x_val += xresolution )
  for( y_val = sv ; y_val < up;  y_val += yresolution )
     insert_ch_map((char) ch, FALSE);
x_val = sv_x_val;
y_val = sv_y_val;
if( sv_x_val + sv_right > max_x_val ) max_x_val = sv_x_val + sv_right;
if( 
tag
 ) x_val += sv_right;

 }
   else if( pos_dvi ){
      
         long int d;
if( (up > 0) && (right > 0) && *pos_line ){
   (IGNORED) fprintf(cur_o_file, pos_line,
        pos_x_A * (x_val - base_pos_x) + pos_x_B,
        pos_y_C * (y_val - up/2 - base_pos_y) + pos_y_D,
        pos_x_A * right + pos_x_B,
        pos_y_C * up + pos_y_D);
   if( x_val < min_pos_x )           min_pos_x = x_val;
   if( (d = x_val + right) > max_pos_x ) max_pos_x = d;
   if( (d = y_val - up) < min_pos_y ) min_pos_y = d;
   if( y_val > max_pos_y )           max_pos_y = y_val;
}


      if( tag ) x_val += right;
   } else if(  (x_val + right)  >  max_x_val ){
      if( max_x_val == -10000) max_x_val=0;
      i =  (INTEGER) (  (double) (x_val + right - max_x_val)
                      /         (text_on? word_sp : margin_sp)
                      +         0.5 );
      if( i && !text_on )  try_new_line();
      while( i-- ) { text_on=TRUE;  put_char('_'); }
      max_x_val = x_val + right;
      if( tag ) x_val += right;
}  }


 INTEGER move_x
#ifdef ANSI
#define SEP ,
(
      register INTEGER  d
)
#undef SEP
#else
#define SEP ;
( d )
      register INTEGER  d
;
#undef SEP
#endif
{    register long     i, dx;
   if(  (x_val += d)  >  max_x_val ){
     if( max_x_val == -10000) max_x_val=0;
     i =  (INTEGER) (  (double) (dx = x_val - max_x_val)
                 /         (text_on? word_sp : margin_sp)
                 +         0.5 );
     if( !i ) i = dx>99999L;
     while( i-- )     { text_on=TRUE;  put_char(' '); }
     max_x_val = x_val;
   }
   return  d;
}



INTEGER move_y
#ifdef ANSI
#define SEP ,
( register INTEGER d
)
#undef SEP
#else
#define SEP ;
( d ) register INTEGER d
;
#undef SEP
#endif
{  y_val += d;
   return  d;
}



BOOL tex4ht_special
#ifdef ANSI
#define SEP ,
(
    int      *chr SEP 
    long int *special_n

)
#undef SEP
#else
#define SEP ;
( chr, special_n)
    int      *chr SEP 
    long int *special_n

;
#undef SEP
#endif
{  BOOL     tex4ht;
    int      i;
    long unsigned N;
  tex4ht = FALSE;
  
*special_n = (long int) (N = get_unt(*chr - 
239 
 + 1));
for(i=4; i--; ){
  special_hd[i] = (unsigned char) (N & 0xFF);
  N = N >> 8; }


  if( *special_n > 4 ){
    for(i=4; i<9; i++)   special_hd[i]=get_char();
    special_hd[9]='\0';
    
tex4ht =           (special_hd[4] == 't') || (special_hd[4] == 'T');
tex4ht = tex4ht &&  special_hd[5] == '4';
tex4ht = tex4ht && ((special_hd[6] == 'h') || (special_hd[6] == 'H'));
tex4ht = tex4ht && ((special_hd[7] == 't') || (special_hd[7] == 'T'));


    *chr = special_hd[8];
    tex4ht = tex4ht && ( (*chr == '=') || (*chr == '<') ||
        (*chr == ';') || (*chr == '>') || (*chr == '@') ||
        (*chr == ':') || (*chr == '"') || (*chr == '~') ||
        (*chr == '|') || (*chr == '+') || (*chr == '!') );
    *special_n -= 5;  }
  else{ special_hd[4]='\0'; }
  return  tex4ht;
}


void init_ch_map(VOID)
{   int i;
  for( i=0; i<HEIGHT; i++ ){
    ch_map[i].max = 0;  ch_map[i].chars = 0;  ch_map[i].line = NULL;  }
  max_map_line = -1;
  min_map_line = HEIGHT;
}



void insert_ch_map
#ifdef ANSI
#define SEP ,
(
       char ch SEP 
       BOOL 
tag


)
#undef SEP
#else
#define SEP ;
( ch, 
tag
 )
       char ch SEP 
       BOOL 
tag


;
#undef SEP
#endif
{     int row, col;
   
{          double x;
   row = (int) ( (double) y_val / (double) yresolution + 0.5);
   if( row >= HEIGHT ){
     if( ok_map ){ warn_i_int_2( 34, row, ch); ok_map = FALSE; }
     return; }
   x = (x_val>0? x_val : 0.0 ) / (double) xresolution + 0.75;
   col = (int) x;
   if( (ch > ' ') && (ch != '-') && (ch != '|') ){
      if( row == prevrow ){
         if( (col == prevcol + 1) && (x > prev_x + 0.5) )
            insert_ch_map(' ', TRUE);
         else if( (col > prevcol + 1) && (x < prev_x+0.2)  )
            col = prevcol + 1;
      }else  prevrow = -1;
      prev_x = x
             + (
(double) *(font_tbl[cur_fnt].wtbl
                 +  (int) (
*(font_tbl[cur_fnt].char_wi +  (int)
   ( (design_ch? design_ch : ch) - font_tbl[cur_fnt].char_f)% 256)

))
   / (double) (1L<<20)
   * (double) font_tbl[cur_fnt].scale

)
             / (double) xresolution;
      prevcol = col;
   }else  prevrow = -1;
   prevrow = row;
}


   if(ch != 10)
      if( (ch_map[row].max > MAX_MAP_LINE) || (col > MAX_MAP_LINE) ){
        if( ok_map ){ warn_i_int_2( 25, MAX_MAP_LINE, ch);
                      ok_map = FALSE; }
      }else{  
         if( row < min_map_line ) min_map_line = row;
         if( row > max_map_line ) max_map_line = row;
         if( ch_map[row].max ){ 
    int   n;
    char* p;
if( ch_map[row].chars > col ){
      
if( 
tag
 ){
   if(   *(ch_map[row].line + ch_map[row].max - 1)
      ||  (ch_map[row].chars - col == 1)  ){ 
ch_map[row].max += 5;
ch_map[row].line = (char *)
   r_alloc((void *) ch_map[row].line,
           (size_t) ch_map[row].max + 1 );
for( n = 0; n<5; n++ )
   *(ch_map[row].line + ch_map[row].max - n) = 0;
ch_map[row].chars += 5;

 }
   col = (ch_map[row].chars--) - col;
   p = ch_map[row].line + ch_map[row].max;
   while( col ){                     unsigned char temp_ch;
     if( ((unsigned char) (*p)) < 
4
 ) col--;
       temp_ch = *(--p);  *(p+1) = temp_ch;  }
} else {
   col = ch_map[row].chars - col;
   p = ch_map[row].line + ch_map[row].max;
   while( col ){
     if( ((unsigned char) (*p)) < 
4
 ) col--;  p--;  }
}
*(++p) = ch;

 }
else{ 
n = (col - ch_map[row].chars + 8) / 5 * 5;
ch_map[row].chars += n - 
tag
;
ch_map[row].max += n;
ch_map[row].line = (char *)
    r_alloc((void *) ch_map[row].line,
            (size_t) ch_map[row].max + 1);
while( n-- )  *(ch_map[row].line + ch_map[row].max - n) = 0;
*(ch_map[row].line + ch_map[row].max
         - (ch_map[row].chars - col) + !
tag
 ) = ch;

 }

 }
         else { 
   int   n;
   char* p;
ch_map[row].chars = (n = (col + 2 + 5) / 5 * 5) - 
tag
;
ch_map[row].max =  n - 1;
ch_map[row].line = p = m_alloc(char, n);
while( n-- ){ *(p++) = 0; }
*(ch_map[row].line + col) = ch;

 }
}     }


void dump_ch_map(VOID)
{     int   n, i, min, k, extra_sp;
      char  *p;
      
  
{    int   max;
   min = 100; max = 0;
   for( i=min_map_line; i<=max_map_line; i++ ){
     p = ch_map[i].line;
     n = ch_map[i].max;  if( max < n )  max = n;
     k = 0;  while( n-- ){ if(*(p++)) break;  k++; }
     if( ch_map[i].max && (k < min) ) min = k;        }
   if( (max < 78) && !nomargin ) min = 0;
}


  for( i=min_map_line; i<=max_map_line; i++ ){
    p = ch_map[i].line;  k = min;    extra_sp = 0;
    n = ch_map[i].max;   
{     char  *s;
   s = p + n;
   while( n && !(*s) && !(*(s-1)) ){  n--; s--; }
   if( n && !(*s) && (((unsigned char) *(s-1)) < 
4
) ) n--;
}


    while( 1 + n-- ){
      if( --k < 0 ){
        if( extra_sp && (((unsigned char) *p)     < 
4
)
                     && (((unsigned char) *(p+1)) < 
4
) )
          extra_sp--;
        else   switch( *p ){ 
           case 0: { put_char(' '); break; }
    case 
1
: { put_char('-'); break; }
    case 
2
: { put_char('|'); break; }
case 
3
: { put_char('#'); break; }
         case ' ': { extra_sp++; }
          default: { 
    BOOL    tag;
    INTEGER count;
tag = TRUE;   count = 0;
do{   if( *p == '<' )       tag   = FALSE;
      else  if( *p == '>' ) tag   = TRUE;
            else           count += tag;
      put_char( *p ); n--;
}while( ((unsigned char) *(++p)) >= 
4
 );
if( !count ){ n++; p--; }

  break; }

 }
      }
      p++;  }
    if( ch_map[i].max )  free((void *)  ch_map[i].line );
    if( i<max_map_line )  put_char('\n');
  }
  nomargin = FALSE;
}



void  set_loc
#ifdef ANSI
#define SEP ,
(
          int op SEP 
   long   int d

)
#undef SEP
#else
#define SEP ;
( op, d )
          int op SEP 
   long   int d

;
#undef SEP
#endif
{
   idv_char( op + 3 );  int_to_dvi( d, 4 ); file_n += 5;
}



void idv_char
#ifdef ANSI
#define SEP ,
(         int  n
)
#undef SEP
#else
#define SEP ;
( n )         int  n
;
#undef SEP
#endif
{ (IGNORED) putc( n, idv_file ); }



void cond_idv_char
#ifdef ANSI
#define SEP ,
(         int  n
)
#undef SEP
#else
#define SEP ;
( n )         int  n
;
#undef SEP
#endif
{
   if( dvi_flag ){  (IGNORED) putc( n, idv_file );  file_n++;  }
}


void idv_copy(  VOID )
{  idv_char( get_char() );  file_n++;  }



void cond_idv_int
#ifdef ANSI
#define SEP ,
(  long   int val SEP 
                             int n
)
#undef SEP
#else
#define SEP ;
( val, n )  long   int val SEP 
                             int n
;
#undef SEP
#endif
{
  if( dvi_flag ){  int_to_dvi((long int)  val, n );   file_n += n;  }
}



void  int_to_dvi
#ifdef ANSI
#define SEP ,
(  long int val SEP 
                                int n

)
#undef SEP
#else
#define SEP ;
( val, n )  long int val SEP 
                                int n

;
#undef SEP
#endif
{         unsigned char ch2, ch3, ch4;
  ch4 = (unsigned char) (val & 0xFF);   val = val >> 8;
  ch3 = (unsigned char) (val & 0xFF);   val = val >> 8;
  ch2 = (unsigned char) (val & 0xFF);   val = val >> 8;
  switch( n ){
    case 4: idv_char( (int) val );
    case 3: idv_char( ch2 );
    case 2: idv_char( ch3 );
    case 1: idv_char( ch4 ); }

}



void cond_string
#ifdef ANSI
#define SEP ,
(           int  ch SEP  int n

)
#undef SEP
#else
#define SEP ;
(ch, n)           int  ch SEP  int n

;
#undef SEP
#endif
{  cond_idv_char( ch );
   while( n-- )  cond_idv_char( get_char() );
}



INTEGER advance_idv_page
#ifdef ANSI
#define SEP ,
(  INTEGER    bop_addr SEP 
                                            char*  cur_font

)
#undef SEP
#else
#define SEP ;
( bop_addr, cur_font )  INTEGER    bop_addr SEP 
                                            char*  cur_font

;
#undef SEP
#endif
{                                           int    i;
   if( page_n++ ){
     idv_char(
142 
);  file_n++;
     idv_char(
140 
);      file_n++;
     idv_char( 
139 
 );
     idv_int( page_n );  for( i=36; i--; ) idv_char( 0);
     idv_int( bop_addr );  bop_addr = file_n;  file_n += 45;
     idv_char(
141 
);  file_n++;
     for( i=1; i<=cur_font[0]; i++ ){
        idv_char( cur_font[i] );   file_n++;
   } }
   
store_mv(
151 
, dx_1);
store_mv(
156 
, dx_2);
store_mv(
165 
, dy_1);
store_mv(
170 
, dy_2);


   return  bop_addr;
}



void store_mv
#ifdef ANSI
#define SEP ,
(  int op SEP   INTEGER d

)
#undef SEP
#else
#define SEP ;
(op, d)  int op SEP   INTEGER d

;
#undef SEP
#endif
{
   cond_idv_char(op);  idv_int( (INTEGER) -d);
   cond_idv_char(op);  idv_int( (INTEGER)  d);  file_n += 8;
}


void push_stack(VOID)
{
   stack[stack_n].x_val = x_val;
   stack[stack_n].dx_1  = dx_1;
   stack[stack_n].dx_2  = dx_2;
   stack[stack_n].y_val = y_val;
   stack[stack_n].dy_1  = dy_1;
   stack[stack_n].dy_2  = dy_2;
   stack_n++;
if( stack_n > 
((int) stack_len + 1)

 ){
  warn_i(40);
}
}


void pop_stack(VOID)
{
   --stack_n;
   x_val = stack[stack_n].x_val;
   dx_1  = stack[stack_n].dx_1;
   dx_2  = stack[stack_n].dx_2;
   y_val = stack[stack_n].y_val;
   dy_1  = stack[stack_n].dy_1;
   dy_2  = stack[stack_n].dy_2;
}



double pos_dbl
#ifdef ANSI
#define SEP ,
(       long  int *  special_n
)
#undef SEP
#else
#define SEP ;
( special_n )       long  int *  special_n
;
#undef SEP
#endif
{
                char ch;
                double v;
                int d;
  v = 0.0; d = 10;
  while(  --(*special_n) > 0 ){
    ch = get_char();
    if( ('0' <= ch ) && (ch <= '9' ) ){
       v += (double) (ch -'0') / d;  d *= 10; }
    else break;
  }
  return v;
}



int search_font_tbl
#ifdef ANSI
#define SEP ,
(
        int cur_fnt
)
#undef SEP
#else
#define SEP ;
( cur_fnt )
        int cur_fnt
;
#undef SEP
#endif
{      int i;
   for( i=0; i<font_tbl_size; i++)
     if( font_tbl[i].num == cur_fnt )  return i;
   warn_i_int( 6,cur_fnt );
   return 0;
}



int get_html_ch
#ifdef ANSI
#define SEP ,
(   FILE*  file

)
#undef SEP
#else
#define SEP ;
( file )   FILE*  file

;
#undef SEP
#endif
{                        int ch;
  if( (ch = (int) getc(file)) < 0 ) {
     
{       int i, j, ch, chr;
  (IGNORED) fseek(file, 0L, 0);
  i=-1; j=0;
  while( (ch = getc(file)) >=0  ){
    if( !j ){  chr = ch; }
    j += ch==chr;
    (IGNORED)  putc(ch,stderr);
    if( ch == '\n' ){
       if( (i>-1 ) && (j<4) ) printf("missing delimiter \n");
       (IGNORED) fprintf(stderr,"%d:  ",++i);
       j=0;
} } }


     err_i_str(20, new_font_name);
  }
  return ch;
}



 INTEGER get_html_file_id
#ifdef ANSI
#define SEP ,
(
                            FILE* file SEP 
                            int first SEP  int last SEP  int n

)
#undef SEP
#else
#define SEP ;
(file, first, last, n)
                            FILE* file SEP 
                            int first SEP  int last SEP  int n

;
#undef SEP
#endif
{                          int ch, i, bound, cnt;
                            INTEGER  diff;
                            char* name;
   name = new_font_name;
   while( *name == (ch = get_html_ch(file)) )  name++;
   if( (*name != '\0') || (ch != ' ') )  warn_i_str(n, name);
   bound = first;  diff = 0;
   for( cnt = 0; cnt < 2; cnt++ ){
      while( ch == ' ' )  ch = get_html_ch(file);
      i = 0;
      while( (ch >= '0') && (ch <= '9') ){
         i = i * 10 + ch - '0';  ch = get_html_ch(file);  }
      if( i != bound ){
         
(IGNORED) fprintf(stderr,warning);
(IGNORED) fprintf(stderr,warn_err_mssg[22]

, new_font_name, i, bound);
         diff = diff * 1000 + i - bound;    }
      bound = last;  }
   while( ch != '\n' ) ch = get_html_ch(file);
   return diff;
}



void notify_class_info
#ifdef ANSI
#define SEP ,
(   int gif_flag
)
#undef SEP
#else
#define SEP ;
( gif_flag )   int gif_flag
;
#undef SEP
#endif
{                        char str[256], *p;
   str[0] = '\0';
   if( *(p = gif_open[gif_flag] ) ) (IGNORED) strct(str,p);
   if( *(p = gif_alt[gif_flag] ) ) (IGNORED) strct(str,p);
   if( *(p = gif_class[gif_flag] ) ) (IGNORED) strct(str,p);
   if( *(p = gif_size[gif_flag] ) ) (IGNORED) strct(str,p);
   if( *(p = gif_mag[gif_flag] ) ) (IGNORED) strct(str,p);
   if( *(p = gif_ord[gif_flag] ) ) (IGNORED) strct(str,p);
   if( *(p = gif_end[gif_flag] ) ) (IGNORED) strct(str,p);
   p = str;
   while( *p ){
     if( *p == '\n' ) *p = ' ';
     p++;
   }
   (IGNORED) fprintf(log_file, class_fmt,
      gif_flag,
      gif_id[gif_flag]? gif_id[gif_flag] : "",
      str);
}



void script
#ifdef ANSI
#define SEP ,
(
      char *templt SEP 
      char *job SEP 
      int  page SEP 
      char *font

)
#undef SEP
#else
#define SEP ;
(templt, job, page, font)
      char *templt SEP 
      char *job SEP 
      int  page SEP 
      char *font

;
#undef SEP
#endif
{    char *ch, *p;
      char fmt[256];
   job[ (int) strlen(job) - 1 ] ='\0';
   p = ch = templt;
   while( TRUE ){
     if( *ch == '%' ){
       
*ch = '\0';  (IGNORED) fprintf(log_file, "%s", p);
*(ch++) = '%';


       
p=fmt;  *(p++) = '%';
if( *ch == '\0' ){ job[ (int) strlen(job) ] ='.';  return; }
while( *ch != '%' ){  *(p++) = *(ch ++);  }
*(p+1) = '\0';


       switch( *(++ch) ){
          case '1':{ *p = 's';
                     (IGNORED) fprintf(log_file, fmt, job);  break;}
          case '2':{ *p = 'd';
                     (IGNORED) fprintf(log_file, fmt, page); break;}
          case '3':{ *p = 's';
                     (IGNORED) fprintf(log_file, fmt, font); break;}
          case '%':{ *p = 'c';
                     (IGNORED) fprintf(log_file, fmt, '%');  break;}
           default:{ job[ (int) strlen(job) ] ='.';         return;}
       }
       p = ++ch;
     }else ch++;
} }


#ifdef DOS_GIF_FILE

void  dos_gif_file
#ifdef ANSI
#define SEP ,
(
        char *str SEP 
        int  mag SEP 
        int  design_ch

)
#undef SEP
#else
#define SEP ;
(str, mag, design_ch)
        char *str SEP 
        int  mag SEP 
        int  design_ch

;
#undef SEP
#endif
{      int  n, m, i;
        struct gif_file_rec * p, * q;
        char *ch;
  m = n = (int) strlen(str);
  if( n > 4 ){
    
if( (p = gif_file) != NULL ){
  while( TRUE ){
    if( eq_str( str, p->name ) ) break;
    if( (p = p->next) == gif_file ){ p = NULL;  break; }
} }


    if( p == NULL ){ 
p =  m_alloc(struct gif_file_rec, 1);

for(i=str[n]; n; ){ i+=str[--n];  if( i > (INT_MAX / 8) ) i/=2; }
if( (n=i % BASE) <10 ) n+= 10 + i%(BASE-20);
*(ch = p->code)= n; n += i;
ch[1]          = n%BASE; n += i;
ch[2]          = n%BASE; n += i;
ch[3]          = n%BASE;



if( gif_file ){
   q = gif_file->next;
   while( TRUE ){
     if( (*(q->code) == *ch)   && (*(q->code+1) == ch[1]) &&
         (*(q->code) == ch[2]) && (*(q->code+2) == ch[3])  ){
        ch[3] ++;  ch[2] += ch[3]/ BASE;  ch[3] = ch[3] % BASE;
                   ch[1] += ch[2]/ BASE;  ch[2] = ch[2] % BASE;
                                          ch[1] = ch[1] % BASE;
        q = gif_file;
     } else if( q == gif_file ) break;
     q = q->next;
}  }


printf("\nRenaming `%s____.gif' to `%c%c%c%c____.gif'\n", str,
          xeh[ch[0]], xeh[ch[1]], xeh[ch[2]], xeh[ch[3]]);
p->name = m_alloc(char,m+1);
strcpy( p->name, str );
if( gif_file ){  p->next = gif_file->next;   gif_file->next = p;  }
          else   p->next = p;

 }
    gif_file = p;
    for( n=0; n<4; n++ )   str[n] = xeh[*(p->code + n)];
  }
  str[n++] = xeh[mag<16? 0: mag / 16];
  str[n++] = xeh[mag % 16];
  str[n++] = xeh[design_ch<16? 0: design_ch / 16];
  str[n++] = xeh[design_ch % 16];
  str[n] = '\0';
}
#endif



void  put_alt_ch
#ifdef ANSI
#define SEP ,
(
      int  chr SEP 
      BOOL ch_str_flag
)
#undef SEP
#else
#define SEP ;
(chr,ch_str_flag)
      int  chr SEP 
      BOOL ch_str_flag
;
#undef SEP
#endif
{
   if( !ch_str_flag ) put_char( chr );
   else if( chr > 0 ){ 
    unsigned char * p;
p = font_tbl[cur_fnt].str[chr-1];
if( gif_ch )  print_f( (char *) p );  
else while( *p ){
  switch( *p ){
    case '<':  { while( *p && (*p != '>') )  p++;  break; }
    case '>':
    case '"':  { p++;  break; }
    default:   { put_char( (int) *p  ) ; p++; }
} }

 }
}


#ifdef DOS_WIN32


char *get_env_dir
#ifdef ANSI
#define SEP ,
(
      char *progname

)
#undef SEP
#else
#define SEP ;
(char)
      char *progname

;
#undef SEP
#endif
{    int  i;
      char *p;
  if(! progname || ! *progname)  return NULL;  
  i = (int) strlen(progname);
  while(progname[--i] != '.' && i > 0) ;   
  if(i == 0)  return NULL;                       
  p = (char *) malloc(i+5);
  if(p == NULL)  return NULL;     
  strncpy(p, progname, i+1);                         
  strcpy(&p[i+1],"env");                       
  return p;
}


#endif



char* get_script
#ifdef ANSI
#define SEP ,
(
     char * name SEP 
     char * inln SEP 
     int x

)
#undef SEP
#else
#define SEP ;
(name, inln,x)
     char * name SEP 
     char * inln SEP 
     int x

;
#undef SEP
#endif
{
   if( !name )
   {                char  str[256], *ch;
      (IGNORED) fseek(dot_file, 0L, 
0
);
      if( search_dot_file( x ) ){
           
ch = str;  str[254] = '\0';
do{
  while((*(ch++) = (int) getc(dot_file)) != '\n'){
    if( *(ch-1) == -1 ){ *(ch-1)='\n';  break; }
    if( str[254] ){ warn_i_int(33, x);  break; }
  }
}while( (int) getc(dot_file) == x );
*ch = '\0';


      } else  strcpy(str, inln);
      ch = m_alloc(char, (int) strlen(str)+2);
      strcpy(ch, str);
      return ch;
   }else return name;
}


 BOOL com_dir
#ifdef ANSI
#define SEP ,
(
     char* p
)
#undef SEP
#else
#define SEP ;
(p)
     char* p
;
#undef SEP
#endif
{   int i;   char   str[256];
  (IGNORED) strcpy( str, p+2 );
  i = (int) strlen(str) - 1;
  if( str[i] == '!' )  str[i] = '\0';
  if( !access(str,F_OK) ) return TRUE;
  warn_i_str(12,p+2);     return FALSE;
}



FILE*  search_in_dot_file
#ifdef ANSI
#define SEP ,
(     int   typ SEP 
                                                 char  *name SEP 
                                                 char  *flags

)
#undef SEP
#else
#define SEP ;
( typ, name, flags)     int   typ SEP 
                                                 char  *name SEP 
                                                 char  *flags

;
#undef SEP
#endif
{                                         char  *ch, dir[256];
                                          FILE* file;
   (IGNORED) fseek(dot_file, 0L, 
0
);
   while( search_dot_file( typ ) ){
      ch = dir;
      while((*(ch++) = (int) getc(dot_file)) > ' ');
      *(ch-1) = '\0';
      if( (file = search_file(name, dir, flags)) != NULL )
        return file;
   }
   return NULL;
}



FILE* search_file
#ifdef ANSI
#define SEP ,
(
     char   *name SEP 
     char   *dir SEP 
     char   *flags

)
#undef SEP
#else
#define SEP ;
( name, dir, flags )
     char   *name SEP 
     char   *dir SEP 
     char   *flags

;
#undef SEP
#endif
{   FILE*  file;
     char     str[256];
     int i;
     BOOL subs;
  
if( (file = fopen(name, flags)) != NULL ){
   (IGNORED) printf("(%s)\n", name);
   return file; }


      (IGNORED) strcpy(str, dir);
      i = (int) strlen(str) - 1;
      subs = str[i] == '!';
      if( subs )  str[i] = '\0';  else i++;
  
(IGNORED) strct(str,name);
if( (file = fopen(str, flags)) != NULL ){
   (IGNORED) printf("(%s)\n", str);
   return file; }


  str[i] = '\0';
  return  subs?  search_file_ext( name, str, flags):
                FALSE;
}



FILE* search_file_ext
#ifdef ANSI
#define SEP ,
(
    char   *name SEP 
    char   *dir SEP 
    char   *flags

)
#undef SEP
#else
#define SEP ;
( name, dir, flags )
    char   *name SEP 
    char   *dir SEP 
    char   *flags

;
#undef SEP
#endif
{  char   str[256];
    FILE*  file;
    int    n;
  n = (int) strlen(dir);
  (IGNORED) sprintf(str, ( dir[n-1] == 
#ifdef DOS_WIN32
 '\\'
#else
 '/'
#endif

)?
                     "%s%s" : 
#ifdef DOS_WIN32
  "%s\\%s"
#else
  "%s/%s"
#endif

 , dir, name);
  if( (file = fopen(str,flags)) != NULL ){
     (IGNORED) printf("(%s)\n", str);   
{     int found;
      struct cache_font_rec *cur_cache_font;
   found = 0;
   for( cur_cache_font = cache_font;
        cur_cache_font;
        cur_cache_font = cur_cache_font->next )
   {   found = found || eq_str(cur_cache_font->dir, dir ) ; }
   if( !found ){
      cur_cache_font = m_alloc(struct cache_font_rec, 1);
      cur_cache_font->next = cache_font;
      cache_font = cur_cache_font;
      cache_font->dir = m_alloc(char, n+1);
      (IGNORED) strcpy(cache_font->dir, dir);
}  }


     return file;
  }
  if( str[n] == 
#ifdef DOS_WIN32
 '\\'
#else
 '/'
#endif

 ) n++;
  str[n-1] = '\0';
#ifndef NOSUBDIR
#ifdef WIN32
  
{
    WIN32_FIND_DATA find_file_data;
    HANDLE hnd;
    int proceed;
    strcpy(dirname, str);
    strcat(dirname, "/*.*");       
    hnd = FindFirstFile(dirname, &find_file_data);
    if (hnd != INVALID_HANDLE_VALUE) {
      
proceed = 1;
while (proceed) {
  if( !eq_str(find_file_data.cFileName, ".")  &&
      !eq_str(find_file_data.cFileName, "..") )
    {
      (IGNORED) strcpy( str+n, find_file_data.cFileName );
      str[n-1] = '\\';
      if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  if( (file = search_file_ext(name, str, flags)) != NULL ){
    FindClose(hnd);
    return file; }
      }
    }
  proceed = FindNextFile(hnd, &find_file_data);
}
FindClose(hnd);


    }
}


#else
  
{      DIR             *dp;
       struct dirent   *dirp;
       struct STSTAT     buf;
  if( (dp = opendir( str )) != NULL ){
    while( (dirp = readdir(dp)) != NULL ){
      if( !eq_str(dirp->d_name, ".")  &&
          !eq_str(dirp->d_name, "..") )
      { 
(IGNORED) strcpy( str+n, dirp->d_name );
str[n-1] = 
#ifdef DOS_WIN32
 '\\'
#else
 '/'
#endif

;
if( LSTAT(str, &buf) >= 0 )
   if( S_ISDIR( buf.st_mode ) )
      if( (file = search_file_ext(name, str, flags)) != NULL ){
         (void) closedir(dp);
         return file; }


    } }
    (void) closedir(dp);
} }


#endif
#endif
  return NULL;
}



BOOL search_dot_file
#ifdef ANSI
#define SEP ,
(
    int ch
)
#undef SEP
#else
#define SEP ;
( ch )
    int ch
;
#undef SEP
#endif
{  int chr;
  while( TRUE ){
    if( (chr = getc(dot_file)) == ch )  return TRUE;
    do
       if( chr == -1 ) return FALSE;
    while( (chr = getc(dot_file)) != '\n' );
} }



void put_char
#ifdef ANSI
#define SEP ,
(   int ch
)
#undef SEP
#else
#define SEP ;
( ch )   int ch
;
#undef SEP
#endif
{
  if( ch_map_flag ){
     if( special_on || ((ch != '\n') && (ch != ' ')) ){
         
insert_ch_map((char) ch, TRUE);

 }
  }else   (IGNORED) putc( ch, cur_o_file );
}



void print_f
#ifdef ANSI
#define SEP ,
(    char* str
)
#undef SEP
#else
#define SEP ;
(str)    char* str
;
#undef SEP
#endif
{
  if( ch_map_flag ){
     while( *str ){ put_char( *str );  str++; }
  }else  (IGNORED) fprintf(cur_o_file, "%s", str);
}


int get_char(VOID)
{
   return  (int) getc(dvi_file);
}


int get_noop(VOID)
{      int ch;
  while(  (ch = get_char())  ==  
138 
 ){;}
  return ch;
}



long fget_unt
#ifdef ANSI
#define SEP ,
(
    FILE*     file SEP 
    register int  n

)
#undef SEP
#else
#define SEP ;
( file, n )
    FILE*     file SEP 
    register int  n

;
#undef SEP
#endif
{  register long val = 0;
  while( n-- ){ val = (val << 8) + (unsigned INTEGER) getc(file) ;  }
  return val;
}



long fget_int
#ifdef ANSI
#define SEP ,
(
    FILE *file SEP 
    int   n

)
#undef SEP
#else
#define SEP ;
( file, n )
    FILE *file SEP 
    int   n

;
#undef SEP
#endif
{  register long val;
  val = (unsigned INTEGER) getc(file);
  if( val & 0x80 )     val -= 0x100;
  while( --n ){ val = (val << 8) + (unsigned INTEGER) getc(file); }
  return val;
}



long cond_int
#ifdef ANSI
#define SEP ,
(
    register INTEGER  n
)
#undef SEP
#else
#define SEP ;
( n )
    register INTEGER  n
;
#undef SEP
#endif
{  register long val;
    int  ch;
  val = (unsigned int) (ch = get_char());
  cond_idv_char( ch );
  if( val & 0x80 )     val -= 0x100;
  while( --n ){
    val = (val << 8) + (unsigned int) (ch = get_char());
    cond_idv_char( ch );
  }
  return val;
}



void warn_i
#ifdef ANSI
#define SEP ,
(     int  n
)
#undef SEP
#else
#define SEP ;
(n)     int  n
;
#undef SEP
#endif
{  (IGNORED) fprintf(stderr,warning);
   (IGNORED) fprintf(stderr,warn_err_mssg[n]);
}



void warn_i_int
#ifdef ANSI
#define SEP ,
(   int  n SEP  int i

)
#undef SEP
#else
#define SEP ;
(n,i)   int  n SEP  int i

;
#undef SEP
#endif
{  (IGNORED) fprintf(stderr,warning);
   (IGNORED) fprintf(stderr, warn_err_mssg[n], i);
}



void warn_i_int_2
#ifdef ANSI
#define SEP ,
(   int  n SEP  int i SEP  int j

)
#undef SEP
#else
#define SEP ;
(n,i,j)   int  n SEP  int i SEP  int j

;
#undef SEP
#endif
{  (IGNORED) fprintf(stderr,warning);
   (IGNORED) fprintf(stderr, warn_err_mssg[n], i, j);
}



void warn_i_str
#ifdef ANSI
#define SEP ,
(
    int  n SEP 
    char *str

)
#undef SEP
#else
#define SEP ;
(n,str)
    int  n SEP 
    char *str

;
#undef SEP
#endif
{  (IGNORED) fprintf(stderr,warning);
   (IGNORED) fprintf(stderr,warn_err_mssg[n], str);
}



void err_i
#ifdef ANSI
#define SEP ,
(      int  n

)
#undef SEP
#else
#define SEP ;
(n)      int  n

;
#undef SEP
#endif
{  (IGNORED) fprintf(stderr,"--- error --- ");
   (IGNORED) fprintf(stderr, warn_err_mssg[n]);
   exit(EXIT_FAILURE);
}



void err_i_int
#ifdef ANSI
#define SEP ,
(     int  n SEP   int i

)
#undef SEP
#else
#define SEP ;
(n,i)     int  n SEP   int i

;
#undef SEP
#endif
{  (IGNORED) fprintf(stderr,"--- error --- ");
   (IGNORED) fprintf(stderr, warn_err_mssg[n], i);
   exit(EXIT_FAILURE);
}



void err_i_str
#ifdef ANSI
#define SEP ,
(
     int  n SEP 
     char *str

)
#undef SEP
#else
#define SEP ;
(n,str)
     int  n SEP 
     char *str

;
#undef SEP
#endif
{  (IGNORED) fprintf(stderr,"--- error --- ");
   (IGNORED) fprintf(stderr, warn_err_mssg[n], str);
   exit(EXIT_FAILURE);
}



int main
#ifdef ANSI
#define SEP ,
(
       int  argc SEP 
       char **argv
)
#undef SEP
#else
#define SEP ;
(argc, argv)
       int  argc SEP 
       char **argv
;
#undef SEP
#endif
{  
register INTEGER  i;
int  ch;


int unread_pages;


double dx_1_sp, dx_2_sp;


long int eof_op_n, begin_postamble;
int dis_pages;


int stack_id;


char* tex4ht_env_file =
#ifdef DOS_WIN32
  
get_env_dir(argv[0])

;
#endif
#ifndef DOS_WIN32
  (char *) 0;
#endif



char* htf_font_dir = (char *) 0;


   

#ifdef SIGSEGV
  (void) signal(SIGSEGV,sig_err);
#endif
  (void) signal(SIGFPE,sig_err);
#ifdef WIN32
  
SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigint_handler, TRUE);


#else
#ifdef SIGINT
  (void) signal(SIGINT,sig_err);    
#endif
#endif


   (IGNORED) printf("tex4ht.c (v alpha.8)\n");
   
dvi_file = stdin;


img_src = m_alloc(char, (int) 11);
(IGNORED) strcpy(img_src, "<IMG \nSRC=\"" );


img_alt = m_alloc(char, (int) 7);
(IGNORED) strcpy(img_alt, "\"ALT=\"" );


{   int i;  i=256; while( i-- ) {
     span_name[i] = span_open[i] = span_size[i] =
     span_mag[i]  = span_ch[i]   = end_span[i]  =
     span_ord[i]  = NULL;
       if( (i>0) && !(i%2) ) {  store_bit_Z( class_on, i ); }
       else {   store_bit_I( class_on, i ); }
    }
}


pos_text = pos_line = end_pos_body = end_pos_text = pos_body =
                      m_alloc(char, (int) 1);
(IGNORED) strcpy(pos_text, "" );


margin_sp = (double) MARGINSP;     


   
{      long   file_len;
  
{      int i;
       char *p, *q, *in_name = "", *out_name = "";
  
#ifdef KPATHSEA
   kpse_set_program_name (argv[0], NULL);
#endif


  for(i=1; i<argc; i++)
    if( *( p=argv[i] ) == '-' ){ 
if( (int) strlen( argv[i] ) == 2 ){
   if( ++i == argc ) bad_arg;  q = argv[i]; }
else q = p+2;
switch( *(p+1) ){
  case 'd':{ out_dir = q;  break; }
  case 'o':{ out_name = q; break; }
  case 't':{ 
if( com_dir(p) )  fontdir[fontdir_count++] = p+2;

  break; }
  case 'e':{ 
if( !access(p+2,F_OK) ) tex4ht_env_file = p+2;
else warn_i_str(12,p+2);

break; }
  case 'i':{ 
if( com_dir(p) ) htf_font_dir = p+2;

  break; }
  case 's':{ 
font_gif = p+2;

    break; }
  case 'b':{      break; }
  case 'g':{ 
gif = p+2;

      break; }
   default:{ bad_arg; }
}

 }
    else in_name = argv[i];
  
if( *in_name != '\0' ){ 
      BOOL tag;
job_name_n = (int) strlen( in_name );
job_name = m_alloc(char, job_name_n+6);
(IGNORED) strcpy(job_name, in_name);
tag = job_name_n < 5;
if( !tag )  tag = !eq_str( job_name+job_name_n-4,".dvi");
if( tag ){  job_name_n+=4; (IGNORED) strct(job_name, ".dvi");  }
if( (dvi_file = fopen(job_name, READ_BIN_FLAGS)) == NULL )
   { warn_i(9);  bad_in_file(job_name); }

job_name[job_name_n-1] = 'v';
job_name[job_name_n-2] = 'd';
job_name[job_name_n-3] = 'i';
if( (idv_file = fopen(job_name, WRITE_BIN_FLAGS)) == NULL )
   bad_in_file(job_name);




 }


  { 
   char *name;
if( *out_name == '\0' )
  { if( *in_name == '\0' ){ 
bad_arg;

 }
    else                  { 
int n = (int) strlen( in_name );
name = m_alloc(char, 6 + n);
(IGNORED) strcpy(name,in_name);
if( eq_str(name+n-4,".dvi") ){ n -= 4;  *(name + n) = '\0'; }
(IGNORED) strct(name,".html");
#ifdef HTM
name[n+4] ='\0';
#endif

 }
  }
else{ 
   int tag = 1;
   int n = (int) strlen( out_name );
name = m_alloc(char, 6 + n);
(IGNORED) strcpy(name,out_name);
while( n-- )   tag = tag && (*(name+n) != '.') ;
if( tag ) (IGNORED) strct(name,".html");
#ifdef HTM
name[n+4] = '\0';
#endif

 }
cur_o_file = root_file = open_html_file(name);
free((void *)  name);

 }
}


  
  
{         char  str[256];
   dot_file = tex4ht_env_file?
      fopen( tex4ht_env_file, READ_TEXT_FLAGS ) : NULL;
   if( !dot_file )   dot_file = fopen("tex4ht.env", READ_TEXT_FLAGS);
#ifndef DOS_WIN32
   if( !dot_file )   dot_file = fopen(".tex4ht", READ_TEXT_FLAGS);
#endif
   if( !dot_file ){  (IGNORED) sprintf(str,
#ifdef DOS_WIN32
  "%s\\tex4ht.env"
#endif
#ifndef DOS_WIN32
  "%s/tex4ht.env"
#endif


                                          ,
#ifdef DOS_WIN32
"C:"
#endif
#ifndef DOS_WIN32
getenv("HOME")
#endif

);
                     dot_file = fopen(str,READ_TEXT_FLAGS);     }
#ifndef DOS_WIN32
   if( !dot_file ){  (IGNORED) sprintf(str,"%s/.tex4ht", getenv("HOME"));
                     dot_file = fopen(str,READ_TEXT_FLAGS);     }
#endif
#ifdef ENVFILE
   if( !dot_file )  dot_file = fopen( ENVFILE,READ_TEXT_FLAGS);
#endif
   
#ifdef KPATHSEA
  if( !dot_file )
    dot_file = kpse_open_file ("tex4ht.env", kpse_program_text_format);
#endif


   if( !dot_file ) warn_i_str( 1, 
#ifdef  DOS_WIN32
   "tex4ht.env"
#endif
#ifndef  DOS_WIN32
   "tex4ht.env | .tex4ht"
#endif

);
}


  
lg_font_fmt = (char *) get_script(lg_font_fmt,LGFNT,'f');


class_fmt = (char *) get_script(class_fmt,LGCLS,'c');


font_gif = (char *) get_script(font_gif,LGPIC,'s');

{    int n;
  n = (int) strlen(font_gif);
  if( font_gif[n-1] != '%' ){ font_gif[n] = '%'; font_gif[n+1] = '\0'; }
}




begin_char_gif = (char *) get_script(begin_char_gif,LGSEP,'b');


gif = (char *) get_script(gif,LGTYP,'g');
{              int n;
   n = (int) strlen(gif) - 1;
   if( gif[n] == '%' )  gif[n] = '%';
}


  
{      long  curr_pos;
  curr_pos = ftell(dvi_file);
  fseek(dvi_file, 0, SEEK_END);
  file_len = ftell(dvi_file);
  fseek(dvi_file, curr_pos, 
0
);
  if( (file_len % 4) != 0 )  bad_dvi;
}


  
i=0;
do{
  i++; file_len -= 1;
  (IGNORED) fseek(dvi_file, file_len, 
0
);
}   while( (ch=get_char()) == 
223 
 );
eof_op_n = file_len;
if( (i<4) || (ch != 
2 
) )  bad_dvi;


file_len -= 5;
(IGNORED) fseek(dvi_file, file_len, 
0
);
if( get_char() != 
249 
 )  bad_dvi;
eof_op_n -= begin_postamble = get_unt(4);
(IGNORED) fseek(dvi_file, begin_postamble, 
0
);


if( get_char() != 
248 
 )  bad_dvi;
(IGNORED) fseek(dvi_file, 16L, 
1
);

mid_page_y = (INTEGER) get_unt(4) / 2;
mid_page_x = (INTEGER) get_unt(4) / 2;


if( (stack_len = (int) get_unt(2)) < 1)     bad_dvi;

stack = m_alloc(struct stack_entry,
((int) stack_len + 1)

);



unread_pages = (int) get_unt(2);


{      
int fonts_n;
struct html_font_rec *html_font;


       BOOL missing_fonts;
   
fonts_n = 0;


cache_font = (struct cache_font_rec *) 0;
cur_cache_font = (struct cache_font_rec *) 0;


   missing_fonts = FALSE;
   while( (ch =  get_char()) != 
249 
 ){
      
if( (font_tbl_size + 1) < MAXFONTS ){
              INTEGER new_font_checksum;
              int font_name_n;
   font_tbl = font_tbl_size?
              (struct font_entry *) r_alloc((void *) font_tbl,
                 (size_t) ((font_tbl_size+1)*sizeof(struct font_entry)))
            : m_alloc(struct font_entry, 1);
   
switch( ch ){
  case 
243 
:
  case 
244 
:
  case 
245 
: {
     new_font.num = (INTEGER)
                      get_unt(ch - 
243 
 + 1); break; }
  case 
246 
: {
     new_font.num = (INTEGER) get_int(4);  break; }
  default: err_i(8);
}


   new_font_checksum  = (INTEGER) get_int(4);
   new_font.scale     = (INTEGER) get_unt(4);
   new_font.design_sz = (INTEGER) get_unt(4);
   
{    int  n, area_ln;
     char *ch;
  area_ln = (int) get_unt(1);
  n =  area_ln + (font_name_n = (int) get_unt(1)) + 1;
  ch = new_font_name = m_alloc(char, n);
  while( --n ){  *ch = (int) get_unt(1); ch++; }
  *ch = '\0';
}


   

{        int i;
   for( i=font_tbl_size-1; i>0;  i-- )
     if( new_font.num == font_tbl[i].num )  warn_i(10);   }



{       FILE *font_file;
        char  file_name[256];
   
{                           int  i;
   font_file = NULL;
   (IGNORED) sprintf(file_name, "%s.tfm", new_font_name);
   
#ifdef KPATHSEA
   font_file = kpse_open_file (file_name, kpse_tfm_format);
#else


   
for( cur_cache_font = cache_font;
     cur_cache_font;
     cur_cache_font = cur_cache_font->next )
  if( (font_file = search_file(file_name,
                               cur_cache_font->dir,
                               READ_BIN_FLAGS))
      != NULL)  break;


   if( !font_file )
      for( i = fontdir_count; i--; ){
        if( (font_file =  search_file(file_name, fontdir[i],
                                      READ_BIN_FLAGS))
            != NULL )  break;  }
   if( !font_file ) font_file = fopen(file_name, READ_BIN_FLAGS);
   if( !font_file && dot_file )
       font_file = search_in_dot_file( 't', file_name, READ_BIN_FLAGS);
#ifdef TFMDIR
   if( !font_file )
     font_file = search_file(file_name, TFMDIR, READ_BIN_FLAGS);
#endif
   
#endif


}


   if( font_file == NULL ){
      err_i_str(1,file_name);
      missing_fonts = TRUE;
      new_font.char_f = 2;
      new_font.char_l = 1;
   } else {
      
{       
 INTEGER  file_length;     
 int    header_length,
     it_correction_table_length,
     lig_kern_table_length,
     kern_table_length,
     extensible_char_table_length,     
     num_font_parameters;


   
file_length                    = (INTEGER) fget_int(font_file,2);
header_length                  = (int) fget_int(font_file,2);
new_font.char_f = (int) fget_int(font_file,2);
new_font.char_l = (int) fget_int(font_file,2);
new_font.wtbl_n = (int) fget_int(font_file,2);
new_font.htbl_n = (int) fget_int(font_file,2);
new_font.dtbl_n = (int) fget_int(font_file,2);
it_correction_table_length     = (int) fget_int(font_file,2);
lig_kern_table_length          = (int) fget_int(font_file,2);
kern_table_length              = (int) fget_int(font_file,2);
extensible_char_table_length   = (int) fget_int(font_file,2);
num_font_parameters            = (int) fget_int(font_file,2);
if( file_length != ( 6                + header_length
     - new_font.char_f              + new_font.char_l + 1
     + new_font.wtbl_n              + new_font.htbl_n
     + new_font.dtbl_n              + it_correction_table_length
     + lig_kern_table_length        + kern_table_length
     + extensible_char_table_length + num_font_parameters  )
  ) err_i_str(15,file_name);


   

{      INTEGER checksum;
   checksum = ( INTEGER) fget_int(font_file,4);
   if( checksum && new_font_checksum
                && (checksum  != new_font_checksum) )
    {   warn_i(16);
        (IGNORED) fprintf(stderr,"%s: %d\ndvi file: %d\n",file_name,
                     checksum, new_font_checksum);
}   }



new_font.design_pt = ( INTEGER) fget_int(font_file,4); 


(IGNORED) fseek(font_file, (long) ((header_length - 2) * 4), 
1
);


   
{      char *ch, *hidp;
       int i;
   ch = new_font.char_wi = m_alloc(char, new_font.char_l
                                       - new_font.char_f + 1);
   hidp = new_font.char_hidp = m_alloc(char, new_font.char_l
                                       - new_font.char_f + 1);
   for( i = new_font.char_f; i <= new_font.char_l; i++ ){
      *(ch++) = (int) fget_unt(font_file,1);
      *(hidp++) = (int) fget_unt(font_file,1);
      (IGNORED) fseek(font_file, 2L, 
1
);
   }
}


   
{       INTEGER *p;         
            int  i;
   p = new_font.wtbl = m_alloc( INTEGER, new_font.wtbl_n);
   for( i = 0; i < new_font.wtbl_n; i++ ){
      *(p++) = ( INTEGER) fget_int(font_file,4);
}  }


   
{       INTEGER *p;         
            int  i;
   p = new_font.htbl = m_alloc( INTEGER, new_font.htbl_n);
   for( i = 0; i < new_font.htbl_n; i++ ){
      *(p++) = ( INTEGER) fget_int(font_file,4);
}  }


{       INTEGER *p;         
            int  i;
   p = new_font.dtbl = m_alloc( INTEGER, new_font.dtbl_n);
   for( i = 0; i < new_font.dtbl_n; i++ ){
      *(p++) = ( INTEGER) fget_int(font_file,4);
}  }


   
   
                                                   
(IGNORED) fseek(font_file, (long) (it_correction_table_length * 4),
            
1
);


   
(IGNORED) fseek(font_file, (long) (lig_kern_table_length * 4),
             
1
);


   
                          
(IGNORED) fseek(font_file, (long) (kern_table_length * 4),
             
1
);


   
(IGNORED) fseek(font_file, (long) (extensible_char_table_length * 4),
             
1
);


   

new_font.it = ( INTEGER) fget_int(font_file,4);

             

new_font.word_sp = ( INTEGER) fget_int(font_file,4);

if( new_font.word_sp == 0 )  new_font.word_sp = MARGINSP; 





(IGNORED) fseek(font_file, 4L, 
1
);



(IGNORED) fseek(font_file, 4L, 
1
);



new_font.ex = (INTEGER) fget_int(font_file,4);












}


      (IGNORED) fclose(font_file);
}  }


new_font_name[font_name_n] = '\0';
new_font.name = m_alloc(char, font_name_n + 1);
(IGNORED) strcpy( new_font.name, new_font_name );

{    int n, i;
   for( n=0; n<font_name_n; n++ ){
     if(  ( '0' <= new_font_name[n] ) && ( new_font_name[n] <= '9' )){
       break;
     }
   }
   new_font.family_name = m_alloc(char, n + 2);
   new_font.font_size  = m_alloc(char, font_name_n - n + 1 );
   for( i=0; i<n; i++ ){
     new_font.family_name[i] = new_font_name[i];
   }
   new_font.family_name[i] = '\0';   i = 0;
   while(  n<font_name_n ){
     new_font.font_size[i++] = new_font_name[n++];
   }
   new_font.font_size[i] = '\0';
}



new_font.mag = new_font.scale / (new_font.design_sz / 100);




   
{      char str[256];
       int i, j, design_n, n_gif;
   n_gif = new_font.char_l - new_font.char_f + 1;
   
{     int n_gif_bytes;
   n_gif_bytes = (n_gif + 7) / 8;
   new_font.gif_on = m_alloc(char, n_gif_bytes );
   new_font.ch_str = m_alloc(char, n_gif_bytes );
   for( i=n_gif_bytes; i--; )  new_font.ch_str[i] =
                               new_font.gif_on[i] = 0;
   new_font.gif1 = m_alloc(unsigned char, n_gif );
   for( i=n_gif; i--; )        new_font.gif1[i]   = 0;
}


   new_font.ch = m_alloc(unsigned char, n_gif );
   
for( i = new_font.char_f; i <= new_font.char_l ; i++ ){
  new_font.ch[i - new_font.char_f] =
                   ((31<i) && (i<128))? i : ignore_ch;
}


   new_font.str =  m_alloc(unsigned char*, n_gif);  
   new_font.str[0] = &null_str;
   design_n = 0;
      
for( j=0; j<2; j++ ){
   for( ; font_name_n; font_name_n-- ){  FILE* file;
                                         int   char_f, char_l;
     new_font_name[font_name_n] = '\0';
     
{                              char name[256];
   (IGNORED) sprintf(name, "%s.htf", new_font_name);
   file = htf_font_dir?  search_file(name, htf_font_dir, READ_TEXT_FLAGS)
                      : NULL;
   if( !file ){
      if( ((file = fopen(name, READ_TEXT_FLAGS)) == NULL) && dot_file )
         file = search_in_dot_file( 'i', name, READ_TEXT_FLAGS);
#ifdef HTFDIR
      if( !file )  file = search_file(name, HTFDIR, READ_TEXT_FLAGS);
#endif
      
#ifdef KPATHSEA
  if( !file ){ char * htfname;
     htfname= kpse_find_file (name, kpse_program_text_format, 0);
     if ( htfname) file= fopen(htfname,READ_TEXT_FLAGS);
  }
#endif


}  }


     if( file != NULL){
       
{               INTEGER x_char_l;
  x_char_l =
      get_html_file_id(file, new_font.char_f, new_font.char_l, 19);
  char_f = (int) (x_char_l / 1000.0 + 0.5) + new_font.char_f;
  x_char_l -= (char_f-new_font.char_f) * 1000 - new_font.char_l;
  char_l = (int) x_char_l;
}


       
if( char_f <= new_font.char_l ){      char  del;
                                      int  j, n;
   
while( char_f < new_font.char_f ){
  while( get_html_ch(file) != '\n' );
  char_f++;   }


   n =  ((char_l < new_font.char_l)? char_l : new_font.char_l)
        - char_f + 1;
   for( i = char_f - new_font.char_f; i < n; i++ ){
      
{      int indirect_ch, base, value, digit, ch1;
  indirect_ch = 0;
  del = get_html_ch(file);   j=0;
  while( (str[j++] = get_html_ch(file)) != del )
    { 
if( (digit=str[j-1]) == '\\' )
  if( (indirect_ch = !indirect_ch) != 0) {
    switch( value=get_html_ch(file) ){
      case 'x': { base = 16; value = 0;  j--; break; }
      case 'o': { base = 8;  value = 0;  j--; break; }
      default: {
        if( (value < '0') || (value > '9') ) {
          indirect_ch = !indirect_ch;   str[j-1] = value;
        } else { value -= '0';  base = 10; j--; }
  } } }
  else{ if( value>255 )  warn_i_int(28,value);  str[j-1] = value; }
else if ( indirect_ch ){
  j--;   digit -=  (digit>'9')?  'A'-10 : '0';
  if( (digit<0) || (digit>=base) ) warn_i_int(29, str[j]);
  value = value*base + digit;
}

 };
  str[j-1] = '\0';
  while( get_html_ch(file) != del );
  ch1 = 0;
  while( ((ch = (int) get_html_ch(file)) != del) ){
     
     if( (ch < '0') || (ch > '9') ) break;
     ch1 = ch1 * 10 + ch - '0'; }
  new_font.gif1[i] = ch1 % 256;
  while( get_html_ch(file) != '\n' );
}


      
add_bit( new_font.ch_str, i, j!=2 );
switch( j ){
  case 1: { new_font.ch[i] = 0;    break; }
  case 2: { new_font.ch[i] = *str; break; }
  default: {                           unsigned char  *p;
    new_font.str[design_n] = p = m_alloc(unsigned char, j);
    if( design_n==255 ){ design_n--; warn_i(35);}
    new_font.ch[i] = ++design_n;
    while( j-- )  p[j] = str[j];
} }

                     }
   
while( char_l > new_font.char_l ){
  while( get_html_ch(file) != '\n' );
  char_l--;   }


}


       
(void) get_html_file_id(file, new_font.char_f, new_font.char_l, 18);


       (IGNORED) fclose(file);  break;
   } }
   if( (font_name_n==0) && (j==0) ){ 
if( dot_file ){           BOOL  tag;
   (IGNORED) fseek(dot_file, 0L, 
0
);
   tag = TRUE;
   while( tag ){
     switch( getc(dot_file) ){
       case  -1: { j++;  tag = FALSE;  break; } 
       case 'a': { 
   int   chr;
   char *ch;
ch = new_font.name;
while( *ch++ == (chr = getc(dot_file)) );
if( chr==' ' ){
  tag = FALSE;
  while( (new_font_name[0] = getc(dot_file)) == ' ' );
  font_name_n=1;
  while( (chr = getc(dot_file)) != '\n' )
    if( chr != ' ' ) new_font_name[font_name_n++] = chr;
  new_font_name[font_name_n]  = '\0';
  (IGNORED) printf("Loading `%s.htf' for `%s.htf'\n",
                                new_font_name, new_font.name);
}

   }
        default: {                    int ch;
                   do ch = getc(dot_file);
                   while( (ch != '\n') && (ch != -1) );
                   break; }
}  } }

 }
   else j++;
}
if( font_name_n == 0 ){
   warn_i_str(21,new_font.name);
   (IGNORED) fprintf(stderr,
             "%d--%d)\n", new_font.char_f, new_font.char_l);
}


   new_font.str = (unsigned char **) r_alloc((void *)   new_font.str,
                     (size_t) ( (design_n?design_n:1) * sizeof(char *)) );
   
for( i = fonts_n; i--; )
  if( eq_str(html_font[i].name, new_font_name) ){       int k;
     k = html_font[i].i;
     free((void *)  new_font.gif1 ); new_font.gif1= font_tbl[ k ].gif1;
     free((void *)  new_font.ch );   new_font.ch  = font_tbl[ k ].ch;
     free((void *)  new_font.str );  new_font.str = font_tbl[ k ].str;
     free((void *)  new_font.ch_str );
     new_font.ch_str = font_tbl[ k ].ch_str;
     break;     }
if( i < 0 ){ 
html_font = fonts_n? (struct html_font_rec *) r_alloc((void *) html_font,
                 (size_t) ((fonts_n+1) * sizeof(struct html_font_rec) ))
                   :  m_alloc(struct html_font_rec, 1);
html_font[fonts_n].name = m_alloc(char, font_name_n + 1);
(IGNORED) strcpy(html_font[fonts_n].name, new_font_name);
html_font[fonts_n].i    = font_tbl_size;
fonts_n++;

 }


}


   free((void *)  new_font_name);   font_tbl_size++;
} else err_i_int(17, MAXFONTS);

 }
   if( missing_fonts ) err_i(14);
   
while( fonts_n-- )  free((void *)  html_font[fonts_n].name);
free((void *)  html_font );


while( (cur_cache_font = cache_font) != (struct cache_font_rec *)0 ){
   cache_font = cache_font->next;
   free((void *) cur_cache_font->dir );
   free((void *) cur_cache_font );        }


}


  (IGNORED) fclose(dot_file);
}

{      char str[256];
   strcpy(str,job_name);
   str[job_name_n-1] = '\0';
   str[job_name_n-2] = 'g';
   str[job_name_n-3] = 'l';
   if( (log_file = fopen(str, WRITE_TEXT_FLAGS)) == NULL )
                                           bad_in_file(str);
}



(IGNORED) fseek(dvi_file, 0L, 
0
);
ch = get_noop();
if( ch != 
247 
 )   bad_dvi;
if( get_char() != 
2 
 ) bad_dvi;
(void) get_unt(4);     
(void) get_unt(4);     
 (void) get_unt(4);
for( i= get_char(); i>0; i-- ) ch = get_char();



{
  dis_pages = unread_pages;
  while( unread_pages-- ){
    (IGNORED) printf("[%d", dis_pages - unread_pages);
    
x_val = dx_1 = dx_2 = 0;  max_x_val = -10000; 
y_val = max_y_val = prev_y_val = dy_1 = dy_2 = 0;


    if( get_noop() != 
139 
 )  bad_dvi;
    for( i = 1; i<45; i++ )
      if( get_char() == EOF )   bad_dvi;
    while( (ch = get_char()) != 
140 
 ){
      
{       register int ch_1;
   ch_1 = ch;
   
if( (ch > 127) && (ch < 137) && (ch != 
132 
) ){
   ch_1 = (int) get_unt(ch % 4 +1);
}


   
if( trace_dvi && !in_trace_char ){
   if( (ch < 137) && (ch != 
132 
) ){
     in_trace_char = TRUE; block_start = TRUE;
} }
else if ( in_trace_char ){
  if( !trace_dvi || (ch > 136) || (ch == 
132 
) ){
   in_trace_char = FALSE;
} }


   
if( span_on && !in_span_ch
            && (default_font != font_tbl[cur_fnt].num) ){
  if(  (ch < 137) && (ch != 
132 
) ){
    in_span_ch = TRUE; start_span = TRUE;
} }
else if ( in_span_ch ){
  if( !span_on ||
     (ch == 
132 
) ||
     (136 < ch) && (ch < 
143 
) ||
     (ch > 
156 
)
  ){
    in_span_ch = FALSE;
    if( *end_span[0] )
       (IGNORED) fprintf(cur_o_file, end_span[0]);
} }


   if( ch < 132 )  {  x_val += insert_ch(ch_1);       
      if(  max_x_val < x_val ) max_x_val = x_val; }
   else switch( ch ) {
      case 133: case 134: case 135: case 136: {
           INTEGER w;
         w = insert_ch(ch_1);
         max_x_val = ( x_val + w > max_x_val )?  x_val + w : max_x_val; }
     
case 
143 
: {;}
case 
144 
: {;}
case 
145 
: {;}
case 
146 
: {
   try_new_line();
   (void) move_x((INTEGER) get_int(ch - 
143 
 + 1 ));
   break; }


case 
147 
: {                double sv;
   sv = word_sp;          word_sp = dx_1_sp;
   (void) move_x( dx_1 ); word_sp = sv;  break; }
case 
148 
: {;}
case 
149 
: {;}
case 
150 
: {;}
case 
151 
: {
   try_new_line();
   dx_1 = move_x((INTEGER) get_int(ch - 
147 
 ));
   dx_1_sp = word_sp;
   break; }


case 
152 
: {                double sv;
   sv = word_sp;          word_sp = dx_2_sp;
   (void) move_x( dx_2 ); word_sp = sv;  break; }
case 
153  
: {;}
case 
154  
: {;}
case 
155 
: {;}
case 
156 
: {
   try_new_line();
   dx_2 = move_x((INTEGER) get_int(ch - 
152 
 ));
   dx_2_sp = word_sp;
   break; }


case 
157 
: {;}
case 
158 
: {;}
case 
159 
: {;}
case 
160 
: {
  (void) move_y( (INTEGER) get_int(ch - 
157 
 + 1 ));
  break; }


case 
161 
: { (void) move_y( dy_1 );   break; }
case 
162 
: {;}
case 
163  
: {;}
case 
164 
: {;}
case 
165 
: {
  dy_1 = move_y( (INTEGER) get_int(ch - 
161 
 ));
  break; }


case 
166  
: { (void) move_y( dy_2 );   break; }
case 
167 
: {;}
case 
168 
: {;}
case 
169 
: {;}
case 
170 
: {
  dy_2 = move_y( (INTEGER) get_int(ch - 
166  
 ));
  break; }


case 
132 
: {
   (void) rule_x( TRUE );   break;
}
case 
137 
: {
   (void) rule_x( FALSE );  break;
}


case 
246 
:   (void) get_char();
case 
245 
:   (void) get_char();
case 
244 
:   (void) get_char();
case 
243 
: {
  for( i=0; i<14; i++ )  ch = get_char();
  for( i=ch + get_char(); i>0; i--) (void) get_char();
  break;
}


default: {
  if( (ch < 
171  
) || (ch > 
234  
) )  bad_char(ch);
  else { cur_fnt = ch - 
171  
;
         
cur_fnt = search_font_tbl( cur_fnt );
word_sp = (double) font_tbl[cur_fnt].word_sp / (double)(1L<<20)
                   * (double) font_tbl[cur_fnt].scale ;

 }
  break;
}


case 
235  
 :
case 
236  
:
case 
237  
:
case 
238  
    : {
        INTEGER n;
   n = ch - 
235  
 + 1;
   cur_fnt = (int)  ((n==4)? get_int(4) : get_unt((int) n));
   
cur_fnt = search_font_tbl( cur_fnt );
word_sp = (double) font_tbl[cur_fnt].word_sp / (double)(1L<<20)
                   * (double) font_tbl[cur_fnt].scale ;


   break; }


case 
239 
: {;}
case 
240 
: {;}
case 
241 
: {;}
case 
242 
: {  
long int special_n;
  if( tex4ht_special( &ch, &special_n) )  {    int  sv; sv = ch;
     special_on = TRUE;  
try_new_line();
switch( ch ){
  case '@': { 
     int code;
special_n--;
switch ( code = get_char() ){
  case '@': { verb_ch = !verb_ch; break; }
  case '-': { nomargin = TRUE;    break; }
  case '%': { 
if( special_n ) {
   special_n--;
   if (  get_char() == '%' ) {
      if( special_n ) { 
     char  ch, *p;
special_n--;   ch = get_char();
p = trace_dvi_del;
while( special_n-- > 0 ) {
  if ( (*(p++)=get_char() ) == ch ) { p--; break; }
}
*p = '\0';
p = end_trace_dvi_del;
while( special_n-- > 0 ) { *(p++)=get_char(); }    *p='\0';

 }
      else { 
while( special_n-- )  (void) get_char;

 }
   } else { 
while( special_n-- )  (void) get_char;

 }
} else { trace_dvi = ! trace_dvi; }

    break; }
   default: { code -= '0';
     while( special_n-- > 0 )  code = code * 10 + get_char() - '0';
     put_char( code );  }
}

  break; }
  case '+': { 
while( special_n-- > 0 )  (void) get_char();

  break; }
  case '=': { while( special_n-- > 0 )  put_char( get_char() ); break; }
  case '<':
  case '>': { 

   int  i=0;
   char *name;
name =  m_alloc(char, (int) special_n+1);
*(name + (int) special_n) = '\0';
while(  special_n-- > 0 )  *(name + i++) = get_char();



for( p = opened_files; p != (struct files_rec*) 0;  p = p->next )
  { if( eq_str(p->name, name) )  break; }


if( ch == '>' ){ 
if( p !=  (struct files_rec*) 0 ){  out_file = p->file;
free((void *) name );  }
else{
  if( !(*name) ) out_file = (FILE *) 0;
  else { 
p = m_alloc(struct files_rec, 1);
if( opened_files != (struct files_rec*) 0 ) opened_files->prev = p;
p->prev = (struct files_rec *) 0;
p->next = opened_files;     opened_files = p;
p->name = name;
p->file = out_file = open_html_file(name);

 }
}

 }
else           { 
if( p == (struct files_rec *)  0 ) bad_special( name );

if( p->prev != (struct files_rec*) 0 ) (p->prev)->next = p->next;
else                                   opened_files = p->next;
if( p->next != (struct files_rec*) 0 ) (p->next)->prev = p->prev;


if( opened_files !=  (struct files_rec*) 0 )
  { if( out_file == p->file )  out_file = opened_files->file; }
else out_file = (FILE *) 0;
(IGNORED) fclose( p->file );   free((void *)  p->name );
free((void *) p );

 }
cur_o_file = ( out_file == (FILE *) 0 )? root_file
                                       : out_file;

  break; }
  case '!': { 
ch_map_flag = !ch_map_flag;
if( ch_map_flag ){ 
init_ch_map();
xresolution = yresolution = 0;
while( special_n-- > 0 ){
  ch = get_char();
  if( (ch >= '0') && (ch <= '9') )
     { yresolution = yresolution * 10 + ch - '0'; }
  else if( (ch == ',') && !xresolution && yresolution )
     { xresolution = yresolution;  yresolution = 0; }
  else { 
xresolution = yresolution = 0;
warn_i_int( 26, '!');
(IGNORED) putc( ch, stderr);
while( special_n-- > 0 )  (IGNORED) putc( get_char(), stderr);
(IGNORED) putc( '\n', stderr );

 }
}
if( !xresolution )  xresolution = yresolution;
if( !xresolution ){ xresolution = XRESOLUTION;
                    yresolution = YRESOLUTION; }
else { xresolution = xresolution * (INTEGER) (XRESOLUTION / 100);
       yresolution = yresolution * (INTEGER) (YRESOLUTION / 100);  }

 }
else             { 
dump_ch_map();

  }

  break; }
  case '|': { gif_ch = !gif_ch;  break; }
  case ':': { 
if( special_n-- ){
        int code, n;
        char str [255], *p;
        struct count_rec *q;
  code = get_char();
  while( special_n > 254 ){ (void) get_char(); special_n--; }
  p = str;  n = special_n;
  while( special_n-- ) { *(p++) = get_char(); }
  *p = '\0';
  
q = counter;
while( q ){
  if( eq_str(str,q->str) ) break;  q = q->next;
}
if( !q ){
  q = m_alloc(struct count_rec, 1);
  q->i = q->depth = 0;    q->max = 10;
  q->next = counter;  counter = q;
  q->str =  m_alloc(char, (int) n+1);
  (IGNORED) strcpy( q->str, str );
  q->stack =  m_alloc(int, q->max);
}


  
switch ( code ){
  case '+': {  (q->i)++; break; }
  case '-': {  (q->i)--; break; }
  case '>': {  
if( q->depth == q->max ){
   q->max += 10;
   if( (q->stack = (int *) r_alloc( (void *) q->stack,
            (size_t) (q->max * sizeof(int)))) == NULL) bad_mem;
}
q->stack[q->depth++] = q->i;

  break; }
  case '<': {  if( q->depth  ){ 
q->depth--;
if( q->max > q->depth + 20 ){ q->max -= 15;
   if( (q->stack = (int *) r_alloc( (void *) q->stack,
            (size_t) (q->max * sizeof(int)))) == NULL) bad_mem;
}

 }
               break; }
  case '!': {  (IGNORED) fprintf(cur_o_file, "%d", q->i); break; }
  case '|': {  if( q->depth  ){
      (IGNORED) fprintf(cur_o_file, "%d", q->stack[q->depth - 1] );
            }
      break; }
  default: { ; }
}


}

  break; }
  case ';': { 
        int n, code;
        char *p, *q;
code = get_char();
n = 1 + ((--special_n>254)? 254 : special_n);
q = p = m_alloc(char, (int) n);
while( special_n > 254 ){ (void) get_char(); special_n--; }
while( special_n-- ) { *(q++) = get_char(); }
*q = '\0';  q = p;
switch ( code ){
  case '8': {  pause_style--; break; }
  case '9': {  pause_style++;  break; }
  case '-': {  default_font = font_tbl[cur_fnt].num;
               base_font_size = font_tbl[cur_fnt].scale / 100;
               break; }
  case '+': {  default_font = -1;                    break; }
  case '%': { 
   int f;
f = 0; while( *p ){ f = 10*f + *(p++) - '0'; }
(IGNORED) fprintf(cur_o_file, "%d",
  (font_tbl[cur_fnt].scale / base_font_size - 100) * f / 100 +100
   );

  break; }
  case '=': { 
(IGNORED) fprintf(cur_o_file, "%s", font_tbl[cur_fnt].name);
if( font_tbl[cur_fnt].mag != 100 ){
   (IGNORED) fprintf(cur_o_file,"_%d", font_tbl[cur_fnt].mag);
}

  break; }
  case '|': { 
{                 int bad_str, m;
                  char ch, *t[
8
], err_str[256];
bad_str=
7
;   strcpy(err_str,p);
if( n>
10
 ){
   m = 100*( *p-'0' ) + 10*( *(p+1)-'0' )+ *(p+2)-'0';
   if( (m>-1) && (m<256) ){
      ch = *(p + 3);  t[0]=p;
      while( *p = *(p+4) ){
        if( ch == *p ){ *p = '\0';
          if( bad_str-- > 0 ) t[
7
 - bad_str] = p+1;
        }
        p++;
   }  }
   if( !bad_str ){
      if( m==0 ){ span_name_on = n>
11
; }
      q = span_open[m];     span_open[m] = t[0];
      span_name[m] = t[1];  span_size[m] = t[2];
      span_mag[m]  = t[3];  span_ord[m]  = t[4];
      span_ch[m]   = t[5];  end_span[m]  = t[6];
      gif_id[m]   = t[7];
      if( not_notify ) {
        store_bit_I( class_on, m );
        not_notify = FALSE;
      } else   store_bit_Z( class_on, m );
   }
}
if( bad_str ){  warn_i_str(37,err_str); }
}

  break; }
  case ',': { 
not_notify = TRUE;

  break; }
  default: { warn_i_int( 36, code); }
}
span_on = span_name_on && !pause_style;
if( q ) free((void *)  q);

  break; }
  case '"': { 
if( special_n ){
   
{                       char * p, ch, i;
  ch = get_char();
  p = pos_text = pos_line = end_pos_text
    = end_pos_body = pos_body
    = (char *)  r_alloc((void *) pos_body,(size_t) special_n + 1);
  i = 0;  
while(  special_n-- > 0 ){
   if( (*p = get_char()) == ch ){
      *p = '\0'; i++;
           if( i==1 ){ end_pos_body = p + 1; }
      else if( i==2 ){ pos_text     = p + 1; }
      else if( i==3 ){ end_pos_text = p + 1; }
      else if( i==4 ){ pos_line     = p + 1; }
      else           { p++; break; }
   }
   p++;
}


  
{                     long int v;
                      double w[4];
                      int j;
                      char ch, sign;
                      BOOL done;
  for(j=0;j<4;j++){
    
done = FALSE;  sign = 1;
if( --(special_n) > 0 ){
  if( (ch = get_char()) == '-' ){ sign = -1; v=0; }
  else v = ch - '0';
  if( (v<0) || (v>9) ) done = TRUE;
}
if( !done )
   while(  --(special_n) > 0 ){
     ch = get_char();
     if( ('0' <= ch ) && (ch <= '9' ) ){
        v =  v * 10 + ch - '0'; }
     else{  done = TRUE;  break; }
   }


    if( done ){
      i++;
      w[j] = sign * ((double) v + pos_dbl( &special_n ));
    }
  }
  pos_x_A = w[0];  pos_x_B = w[1];
  pos_y_C = w[2];  pos_y_D = w[3];
}


  if( (i != 9) || special_n ){
    warn_i_str(39,pos_text);
    *(pos_text = end_pos_body = pos_line =
      end_pos_text = pos_body) = '\0';
  }
}


} else if( pos_dvi = !pos_dvi ){
   print_f(pos_body);
   min_pos_x = max_pos_x = base_pos_x = x_val;
   min_pos_y = max_pos_y = base_pos_y = y_val ;
} else {
  (IGNORED) fprintf(cur_o_file, end_pos_body,
      pos_x_A * (max_pos_x - base_pos_x) + pos_x_B,
      pos_x_A * (base_pos_x - min_pos_x) + pos_x_B,
      pos_y_C * (base_pos_y - min_pos_y) + pos_y_D,
      pos_y_C * (max_pos_y - base_pos_y) + pos_y_D
  );
}

 break; }
  case '~': { 
if( special_n ){
  
if( get_char() == '>' ) {
            char *q;
  q = stack[ stack_n-1 ].end = m_alloc(char,special_n+1);
  while( --special_n ) *q++ = get_char();
  *q = '\0';
} else {
  (IGNORED) fseek(dvi_file, (long) --special_n,
                             
1
);
  special_n = 0;
}


} else if( group_dvi = !group_dvi ){
               long  curr_pos;
               int   ch, sv_stack_n;
  curr_pos = ftell(dvi_file);  sv_stack_n = stack_n;  stack_id = 0;
  
while( group_dvi ){
  
if( (ch = get_char()) >= 128 )
  switch( ch ){
    
case 128: case 129: case 130: case 131: case 133:
case 134: case 135: case 136: {
  (IGNORED) fseek(dvi_file, (long) ( ch % 4 + 1 ),
                           
1
);
  break;
}


case 
132 
:
case 
137 
:{
  (IGNORED) fseek(dvi_file, 8L, 
1
);
  break;
}


case   
139 
: {
  (IGNORED) fseek(dvi_file, 44L, 
1
);  break; }


case 
143 
: case 
144 
:
case 
145 
: case 
146 
: {
    (IGNORED) (get_int( ch - 
143 
 + 1 ));  break; }
case 
148 
:
case 
149 
:
case 
150 
:
case 
151 
: {
    (IGNORED) (get_int( ch - 
148 
 + 1));
    break;  }
case 
153  
:
case 
154  
:
case 
155 
:
case 
156 
: {
    (IGNORED) (get_int( ch - 
153  
 + 1));
    break;  }
case 
157 
: case 
158 
:
case 
159 
: case 
160 
: {
    (IGNORED) (get_int( ch - 
157 
 + 1));
    break; }
case 
162 
:
case 
163  
:
case 
164 
:
case 
165 
: {
    (IGNORED) (get_int( ch - 
162 
 + 1));
    break; }
case 
167 
:
case 
168 
:
case 
169 
:
case 
170 
: {
    (IGNORED) (get_int( ch - 
167 
 + 1));
    break; }


case 
246 
: (void) get_char();
case 
245 
: (void) get_char();
case 
244 
: (void) get_char();
case 
243 
: {    int i;
  for( i=14; i; i-- ){  ch = get_char(); }
  i = ch +  get_char();
  (IGNORED) fseek(dvi_file, (long) i, 
1
);
  break;  }


case  
235  
:
case 
236  
:
case 
237  
:
case     
238  
: {
  (IGNORED) fseek(dvi_file, (long) (ch - 
235  
 + 1),
                            
1
);
  break; }


case 
239 
:  case 
240 
:
case 
241 
:  case 
242 
: {  long int i;
  if( tex4ht_special( &ch, &i ) ){
     if( ch == '~' ){
        
if( i==0 ){
  group_dvi = FALSE ;
}else{
  switch( get_char() ){
     case '<': { 
          struct group_info *p;
          char *q;
p = m_alloc(struct group_info,1);
p->next = stack[ stack_n - 1].begin; stack[ stack_n - 1].begin = p;
p->stack_id = stack[ stack_n - 1].stack_id;
q = p->info = m_alloc(char,i+1);
while( --i ) *q++ = get_char();
*q = '\0';

  break; }
     default: { (IGNORED) fseek(dvi_file, (long) --i,
                               
1
);  break; }
} }


     } else {
       (IGNORED) fseek(dvi_file, (long) i, 
1
);
     }
  }else{ 
   char *ch;
ch = special_hd + 4;
while( *ch ){   ch++; }
(IGNORED) fseek(dvi_file, (long) i, 
1
);

  }
  break;
}


case 
141 
: {
   stack[stack_n].end = (char *) 0;
   stack[stack_n].stack_id = stack_id++;
   stack_n++;
   if( stack_n > 
((int) stack_len + 1)

 ){ warn_i(40); }
   break;
}
case 
142 
: { stack_n--;  break; }


    default: { break; }
  }


}
group_dvi = TRUE;


  fseek(dvi_file, curr_pos, 
0
);
  stack_n = sv_stack_n;    stack_id = 0;
} else { 
{              int i;
  for( i=stack_n; i>=0; i--){
    if( stack[i].end ){
       print_f( stack[ i ].end );
       free((void *)  stack[ i ].end );       stack[i].end = '\0';
} } }

 }

 break; }
}

  special_on = FALSE;
     
if( special_n > 0 ){
   warn_i_int( 26, sv);
   (IGNORED) fprintf(stderr,"==> ");
   while( special_n-- > 0 )  (IGNORED) putc( get_char(), stderr);
   (IGNORED) putc( '\n', stderr );
}


  } else { while( special_n-- > 0 )  (void) get_char();  }

  break;  }


case     
141 
: { 

if( group_dvi &&  stack[stack_n].begin ){
  if( (stack[stack_n].begin)->stack_id == stack_id ){
                              struct group_info *p;
    p = stack[stack_n].begin;
    print_f(p->info);
    stack[stack_n].begin = p->next;
    free((void *)  p );
} }
stack_id++;


stack[stack_n].text_on = text_on;
push_stack();  
if( push_depth<256 ) { push_st[push_depth] = push_id++; }
if( trace_dvi && !ch_map_flag ){
   (IGNORED) fprintf(cur_o_file, "%sPUSH %d %d%s",
      trace_dvi_del, push_depth,
      push_st[(push_depth<256)? push_depth:256],
      end_trace_dvi_del);
}
push_depth++;



   break; }
case 
142 
: { 

if( group_dvi &&  stack[stack_n-1].end ){
   print_f( stack[ stack_n-1 ].end );
  free((void *)  stack[ stack_n-1 ].end );  stack[ stack_n-1 ].end = '\0';
}



push_depth--;
if( trace_dvi && !ch_map_flag ){
   (IGNORED) fprintf(cur_o_file, "%sPOP %d %d%s",
      trace_dvi_del,  push_depth,
      push_st[(push_depth<256)? push_depth:256],
      end_trace_dvi_del);
}

   pop_stack();
if( ((x_val+0.6*word_sp) <  stack[stack_n].x_val) )  put_char(' ');
text_on = stack[stack_n].text_on;

  break; }


} }

  }
    
if( ch_map_flag ){
   warn_i(27);    init_ch_map(); }


    (IGNORED) printf("]%c",unread_pages % 10 == 0? '\n' : ' ');
} }


put_char('\n');put_char('\n');

if( root_file != (FILE *) 0 )  (IGNORED) fclose(root_file);


while( opened_files != (struct files_rec*) 0 )
{
   (IGNORED) fclose( opened_files->file );
   opened_files = opened_files->next;
}


{ 
INTEGER bop_addr;


int stack_depth;


char cur_font[6];
BOOL visible_cnt;


 
job_name[job_name_n-3] = '\0';

file_n = 14;
(IGNORED) fseek(dvi_file, 0L, 
0
);
do{  ch = get_char();
     idv_char( ch );
     file_n++;
}while( ch == 
138 
 );
for( i=13; i ; i-- )  idv_char( get_char() );
i = get_char();
idv_char( (int) i );  while( i-- ) idv_copy();


page_n = 0;

x_val = 0;   y_val = 0;   stack_n = 0;
idv_char( 
139 
 );
idv_int( page_n + 1 );  for( i=36; i--; ) idv_char( 0);
idv_int( -1 );  bop_addr = file_n;  file_n += 45;
idv_char(
141 
);  file_n++;


while( dis_pages ){ 
if( (ch = get_char()) < 128 ) { visible_cnt = TRUE;  cond_idv_char( ch );}
else switch( ch ){ 
case 128: case 129: case 130: case 131: case 133:
case 134: case 135: case 136: {
  visible_cnt = TRUE;  cond_string( ch, ch % 4 +1 );  break; }


case   
139 
: {
  x_val = 0;   y_val = 0;  stack_n = 0;
  (IGNORED) fseek(dvi_file, 44L, 
1
);  break; }
case     
140 
: { dis_pages--; }
case           
138 
: { break; }


case 
147 
: {
  cond_idv_char( ch );  x_val += dx_1;  break; }
case 
152 
: {
  cond_idv_char( ch );  x_val += dx_2;  break; }
case 
161 
: {
  cond_idv_char( ch );  y_val += dy_1;  break; }
case 
166  
: {
  cond_idv_char( ch );  y_val += dy_2;  break; }


case 
143 
: case 
144 
:
case 
145 
: case 
146 
: {
    cond_idv_char( ch );
    x_val += cond_int( ch - 
143 
 + 1 );  break; }
case 
148 
:
case 
149 
:
case 
150 
:
case 
151 
: {
    cond_idv_char( ch );
    dx_1 = (INTEGER) cond_int( ch - 
148 
 + 1);
    x_val += dx_1;   break;  }
case 
153  
:
case 
154  
:
case 
155 
:
case 
156 
: {
    cond_idv_char( ch );
    dx_2 = (INTEGER) cond_int( ch - 
153  
 + 1);
    x_val += dx_2;   break;  }


case 
157 
: case 
158 
:
case 
159 
: case 
160 
: {
    cond_idv_char( ch );
    y_val += cond_int( ch - 
157 
 + 1);
    break; }
case 
162 
:
case 
163  
:
case 
164 
:
case 
165 
: {
    cond_idv_char( ch );
    dy_1 = (INTEGER) cond_int( ch - 
162 
 + 1);
    y_val += dy_1;   break; }
case 
167 
:
case 
168 
:
case 
169 
:
case 
170 
: {
    cond_idv_char( ch );
    dy_2 = (INTEGER) cond_int( ch - 
167 
 + 1);
    y_val += dy_2;   break; }


case   
132 
:{
  visible_cnt = TRUE; cond_string( ch,4 ); x_val += cond_int(4);
  break;
}
case 
137 
:{
  visible_cnt = TRUE; cond_string( ch, 8 );
  break;
}


case 
239 
:  case 
240 
:
case 
241 
:  case 
242 
: {  long int i;
                                            int special_nr;
  special_nr = ch;
  if( tex4ht_special( &ch, &i ) ){
     if( ch == '+' ){
        
if( i==0 ){ if( dvi_flag ){ dvi_flag = 0;  
if( !visible_cnt ) {                            char  str[256];
   (IGNORED) sprintf(str, "--- empty picture --- %sidv[%d] ---\n",
                          job_name,page_n);
   (IGNORED) printf("%s", str);  (IGNORED) fprintf(log_file, "%s",str); }
while( stack_depth-- > 0 ){
  idv_char(
142 
);  file_n++; }

 } }
else{
  if( dvi_flag ){ 
cond_idv_char( special_nr );
cond_idv_int( i, special_nr - 
239 
 + 1 );
while( i-- )  cond_idv_char( get_char() );
visible_cnt = TRUE;

 }
  else switch( get_char() ){
     case '+': { 
{    char str[256], *ch;
   ch = str;   while( --i )  *(ch++) =  get_char();  *ch = '\0';
   script(font_gif, job_name ,page_n+1, str);
}


                 dvi_flag = 1;  
visible_cnt = FALSE;
bop_addr = advance_idv_page( bop_addr, cur_font );
stack_depth = 0;
set_loc( 
143 
, x_val );
set_loc( 
157 
, y_val );

  break; }
     case '@': { 
while( --i ) (void)  putc( get_char(), log_file );
(IGNORED) putc( '\n', log_file );

 break; }
      default: { while( --i ) (void)  get_char();  break; }
} }

 }
     else   while( i-- ) (void)  get_char();
  }else if( special_on ){ 
   char *ch;
   int j;
ch = special_hd;
(IGNORED) putc( (unsigned) 
242 
, idv_file );  file_n++;
for(j=4; j--; ){  (IGNORED) putc( *ch, idv_file );  file_n++;  ch++; }
while( *ch ){  (IGNORED) putc( *ch, idv_file );  file_n++;  ch++; }
file_n += (int) i;
while( i-- )  (IGNORED) putc( get_char(), idv_file );


  }else { while( i-- )  (IGNORED) get_char(); }
  break;
}


case 
141 
: {
   push_stack();
   stack_depth++;
   cond_idv_char( ch );
   break; }
case 
142 
: {      INTEGER cur_x, cur_y;
   stack_depth--;
   cur_x = (INTEGER) x_val;  cur_y = (INTEGER) y_val;  pop_stack();
   if( dvi_flag ){
      if( stack_depth<0 ){ warn_i_int( 24,  page_n );
                           
cond_idv_char( 
146 
 );
idv_int( x_val - cur_x - dx_1 - dx_2 );
cond_idv_char( 
151 
 );
idv_int( dx_1 );
cond_idv_char( 
156 
 );
idv_int( dx_2 );
cond_idv_char( 
160 
 );
idv_int( y_val - cur_y - dy_1 - dy_2 );
cond_idv_char( 
165 
 );
idv_int( dy_1 );
cond_idv_char( 
170 
 );
idv_int( dy_2 );
cond_idv_char( 
141 
 );  file_n += 24;

     }
      cond_idv_char( ch );
   }
   break; }


case 
246 
:
case 
245 
:
case 
244 
:
case 
243 
: {  idv_char( ch );             file_n++;
  for( i=14; i; i-- ){  ch = get_char(); idv_char( ch ); file_n++; }
  i = ch;  i += ch = get_char();  idv_char( ch );        file_n++;
  while( i-- ){ idv_copy(); }
  break;  }


case  
235  
:
case 
236  
:
case 
237  
:
case     
238  
: {    int i;
   idv_char( ch );  file_n++;
   cur_font[0] = ch - 
235  
 + 2;
   cur_font[1] = ch;
   for( i=2; i <= cur_font[0]; i++ ){
      ch = get_char();    idv_char( ch );
      cur_font[i] = ch;   file_n++;         }
   break;  }


default: {
  if( (ch < 
171  
) || (ch > 
234  
)   )  err_i(23);
  else {  idv_char( ch );  file_n++;
          cur_font[0] = 1;    cur_font[1] = ch;   }
  break;
}

 }

 }

{                                               int   ch, i, mag;
                                                char  str[256];
   (IGNORED) fprintf(log_file, begin_char_gif);
   dvi_flag = TRUE;
   for( cur_fnt = font_tbl_size; cur_fnt--; ){
      
(IGNORED) fprintf(log_file, lg_font_fmt,
  font_tbl[cur_fnt].family_name,
  font_tbl[cur_fnt].font_size,
  font_tbl[cur_fnt].mag);


      for( i = font_tbl[cur_fnt].char_l - font_tbl[cur_fnt].char_f + 1;
           i--; )
         if( get_bit( font_tbl[cur_fnt].gif_on, i) ){
            bop_addr = advance_idv_page( bop_addr, cur_font );
            set_loc( 
143 
, (long int) mid_page_x );
            set_loc( 
157 
, (long int) mid_page_y );
            
{           INTEGER num;
   num = font_tbl[cur_fnt].num;
   if( num <= 
63 
 )
                                cond_idv_char( (int) (num + 
171  
) );
   else if( dvi_flag ){
     if( (num < 0) || (num > 16777215L) ) idv_int(
238  
);
     else if( num < 256 )               idv_char(
235  
);
     else if( num < 65536L ) int_to_dvi((long int) 
236  
,2);
     else                   int_to_dvi((long int) 
237  
,3);
     cond_idv_char( (int) num );
}  }


            
if( (ch = i + font_tbl[cur_fnt].char_f) > 127 )  {
  if( ch < 256 ) cond_idv_char(133);  else  warn_i(23);   }
cond_idv_char( ch );
mag = (int) ((double) font_tbl[cur_fnt].scale /
             font_tbl[cur_fnt].design_sz  * 10 );

#ifndef DOS_GIF_FILE
if( mag == 10 ) (IGNORED) sprintf(str, "%s-%x%s",
                        font_tbl[cur_fnt].name, ch, gif);
else            (IGNORED) sprintf(str, "%s-%x-%x%s",
                        font_tbl[cur_fnt].name, mag, ch, gif);
#endif


#ifdef DOS_GIF_FILE
(IGNORED) strcpy(str, font_tbl[cur_fnt].name);
dos_gif_file(str, mag, ch);
strct(str,gif);
#endif


script(font_gif, job_name ,page_n, str);

        }
   }
   (IGNORED) printf("See file `%slg' for list of required figures\n",
                    job_name);
   (IGNORED) fclose( log_file );
}



idv_char(
142 
);  file_n += 2;
idv_char( 
140 
 );
(IGNORED) fseek(dvi_file, begin_postamble, 
0
);
begin_postamble  = file_n;
idv_char( 
248 
 );   file_n += 5;
idv_int( bop_addr );  (IGNORED) fseek(dvi_file, 5L, 
1
);
for( i = 20; i;  i-- ) idv_copy();


i = (INTEGER) get_int(2) + 1;    idv_char( (int) i >> 8 );  
idv_char( (int) i & 0xFF );  file_n += 2;
if( !page_n ) page_n++;   idv_char( page_n >> 8 );    
idv_char( (int) page_n & 0xFF );  file_n += 2;
(IGNORED) fseek(dvi_file, 2L, 
1
);


eof_op_n -= 32;                                       
while( --eof_op_n ) idv_copy();
idv_int(begin_postamble);                   
(IGNORED) fseek(dvi_file, 4L, 
1
);  file_n += 4;
idv_copy();                                         
for( i = 8 - file_n % 4;  i;  i-- ) idv_char( 
223 
 );



 }


   return 0;
}


