#include "xdvi.h"
#include "dvi.h"

#ifndef X_NOT_STDC_ENV
#include <stdlib.h>
#endif

/***
***    VF font reading routines.
***    Public routine is read_index---because virtual characters are presumed
***    to be short, we read the whole virtual font in at once, instead of
***    faulting in characters as needed.
***/

#define LONG_CHAR       242

/*
*      These are parameters which determine whether macros are combined for
*      storage allocation purposes.  Small macros ( <= VF_PARM_1 bytes) are
*      combined into chunks of size VF_PARM_2.
*/

#ifndef VF_PARM_1
#define VF_PARM_1       20
#endif
#ifndef VF_PARM_2
#define VF_PARM_2       256
#endif

/*
*      The main routine
*/

void
read_VF_index(fontp)
       register struct font *fontp;
{
       FILE    *VF_file = fontp->file;
       ubyte   cmnd;
       ubyte   *avail, *availend;      /* available space for macros */

       fontp->read_char = NULL;
       fontp->flags |= FONT_VIRTUAL;
       fontp->set_char_p = set_vf_char;
       if (debug & DBG_PK)
           Printf("Reading VF pixel file %s\n", fontp->filename);
/*
*      Read preamble.
*/
       Fseek(VF_file, (long) one(VF_file), 1); /* skip comment */
       (void) four(VF_file);           /* skip checksum */
       (void) four(VF_file);           /* skip design size */
/*
*      Read the fonts.
*/
       fontp->vf_chain = NULL;
       fontp->first_font = NULL;
       while ((cmnd = one(VF_file)) >= FNTDEF1 && cmnd <= FNTDEF4) {
           define_font(VF_file, cmnd, fontp, &fontp->vf_chain);
           if (fontp->first_font == NULL)
               fontp->first_font = fontp->vf_chain->fontp;
       }
/*
*      Prepare macro array.
*/
       fontp->macro = (struct macro *) xmalloc(256 * sizeof(struct macro),
           "macro array");
       bzero((char *) fontp->macro, 256 * sizeof(struct macro));
/*
*      Read macros.
*/
       avail = availend = NULL;
       for (; cmnd <= LONG_CHAR; cmnd = one(VF_file)) {
           register struct macro *m;
           int len;
           unsigned long cc;
           long width;

           if (cmnd == LONG_CHAR) {    /* long form packet */
               len = four(VF_file);
               cc = four(VF_file);
               width = four(VF_file);
               if (cc >= 256) {
                   Fprintf(stderr,
                       "Virtual character %lu in font %s ignored.\n",
                       cc, fontp->fontname);
                   Fseek(VF_file, (long) len, 1);
                   continue;
               }
           }
           else {      /* short form packet */
               len = cmnd;
               cc = one(VF_file);
               width = num(VF_file, 3);
           }
           m = &fontp->macro[cc];
           m->dvi_adv = width * fontp->dimconv;
           if (len > 0) {
               if (len <= availend - avail) {
                   m->pos = avail;
                   avail += len;
               }
               else {
                   m->free_me = True;
                   if (len <= VF_PARM_1) {
                       m->pos = avail = (ubyte *) xmalloc(VF_PARM_2,
                           "macro array");
                       availend = avail + VF_PARM_2;
                       avail += len;
                   }
                   else m->pos = (ubyte *) xmalloc((unsigned) len,
                       "macro array");
               }
               Fread((char *) m->pos, 1, len, VF_file);
               m->end = m->pos + len;
           }
           if (debug & DBG_PK)
               Printf("Read VF macro for character %lu; dy = %ld, length = %d\n",
                       cc, m->dvi_adv, len);
       }
       if (cmnd != POST)
           oops("Wrong command byte found in VF macro list:  %d", cmnd);
}