home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / applications / wp / chinesetex.lha / cjk / src / hbf.c next >
Encoding:
C/C++ Source or Header  |  1994-12-19  |  30.0 KB  |  1,457 lines

  1. /*
  2.  * Copyright 1993,1994 by Ross Paterson
  3.  *
  4.  * - You can use this code for any purpose and without fee, except that
  5.  *   you may distribute only verbatim copies of it.  Please send me any
  6.  *   bug fixes, ports or improvements for inclusion in future versions.
  7.  *
  8.  * - The code is supplied with no warranty of any kind.
  9.  *
  10.  * Ross Paterson <rap@doc.ic.ac.uk>
  11.  * 2 September 1994
  12.  *
  13.  * The following people have supplied bug fixes:
  14.  *    Simon Chow    <khsc@synoptics.com>
  15.  *    Fung Fung Lee    <lee@simd.stanford.edu>
  16.  *    Man-Chi Pong    <mcpong@cs.ust.hk>
  17.  *    Steven Simpson    <simpson@math.psu.edu>
  18.  *    Charles Wang    <charles.wang@infores.com>
  19.  *    Werner Lemberg    <a7621gac@awiuni11.bitnet>
  20.  */
  21.  
  22. /*
  23.  * The last two functions of this file were added by Werner Lemberg
  24.  *
  25.  * According to the HBF standard 1.1, CHARS has been made optional
  26.  */
  27.  
  28. /*
  29.  * Two C interfaces to HBF files.
  30.  *
  31.  * The multiple interfaces make this code rather messy; I intend
  32.  * to clean it up as experience is gained on what is really needed.
  33.  *
  34.  * There are also two modes of operation:
  35.  * - the default is to read each bitmap from its file as demanded
  36.  * - if IN_MEMORY is defined, the whole bitmap file is held in memory.
  37.  *   In this case, if running under Unix, the bitmap files may be gzipped
  38.  *   (but the filename used in the HBF file should be the name of the
  39.  *   file before it was gzipped).
  40.  */
  41.  
  42. #include <stddef.h>
  43. #include <ctype.h>
  44.  
  45. #ifdef __MSDOS__
  46. #define msdos
  47. #endif
  48.  
  49.  
  50.  
  51. /*
  52.  * if the linker complains about an unresolved identifier '_strdup',
  53.  * uncomment the following definition.
  54.  */
  55.  
  56. /* #define NO_STRDUP */
  57.  
  58.  
  59.  
  60. #ifdef    __STDC__
  61. #    define    _(x)    x
  62. #else
  63. #    define    _(x)    ()
  64. #endif
  65.  
  66. #define    reg    register
  67.  
  68. typedef    int    bool;
  69. #define    TRUE    1
  70. #define    FALSE    0
  71.  
  72. #define    Bit(n)    (1<<(7 - (n)))
  73.  
  74.  
  75.  
  76. /*
  77.  * Messy file system issues
  78.  */
  79.  
  80. #ifdef unix
  81. #define    PATH_DELIMITER ':'
  82. #define    RelativeFileName(fn)    ((fn)[0] != '/')
  83. #define    LocalFileName(fn)    (strchr(fn, '/') == NULL)
  84. #endif /* unix */
  85. #ifdef msdos
  86. #define    PATH_DELIMITER ';'
  87. #define    HasDrive(fn)    (isalpha((fn)[0]) && (fn)[1] == ':')
  88. #define    RelativeFileName(fn)    (! HasDrive(fn) && (fn)[0] != '\\')
  89. #define    LocalFileName(fn)    (! HasDrive(fn) && strchr(fn, '\\') == NULL)
  90. #define    READ_BINARY    "rb"
  91. #endif /* msdos */
  92. #ifdef vms
  93. #define    PATH_DELIMITER ','
  94. #define    RelativeFileName(fn)    (strchr(fn, ':') == NULL && ((fn)[0] != '[' || (fn)[1] == '.' || (fn)[1] == '-'))
  95. #define    LocalFileName(fn)    (strchr(fn, ':') == NULL && strchr(fn, ']') == NULL)
  96. #endif
  97.  
  98. #ifndef    RelativeFileName
  99. #define    RelativeFileName(fn)    FALSE
  100. #endif
  101.  
  102. #ifndef    LocalFileName
  103. #define    LocalFileName(fn)    FALSE
  104. #endif
  105.  
  106. #ifndef READ_BINARY
  107. #define    READ_BINARY    "r"
  108. #endif
  109.  
  110. #define    MAX_FILENAME    1024
  111.  
  112.  
  113.  
  114. /*
  115.  *    Internal structures
  116.  */
  117.  
  118. typedef    unsigned char    byte;
  119.  
  120. #define PROPERTY    struct _PROPERTY
  121. #define BM_FILE        struct _BM_FILE
  122. #define B2_RANGE    struct _B2_RANGE
  123. #define CODE_RANGE    struct _CODE_RANGE
  124.  
  125. PROPERTY {
  126.     char        *prop_name;
  127.     char        *prop_value;
  128.     PROPERTY    *prop_next;
  129. };
  130.  
  131. BM_FILE {
  132.     char    *bmf_name;
  133. #ifdef IN_MEMORY
  134.     byte    *bmf_contents;
  135.     long    bmf_size;
  136. #else
  137.     FILE    *bmf_file;
  138. #endif
  139.     BM_FILE    *bmf_next;
  140. };
  141.  
  142. B2_RANGE {
  143.     byte        b2r_start;
  144.     byte        b2r_finish;
  145.     B2_RANGE    *b2r_next;
  146. };
  147.  
  148. typedef    unsigned short    CHAR;
  149. typedef    unsigned int    CHAR_INDEX;    /* character index in file */
  150. #define    BAD_CHAR_INDEX    0xffff
  151.  
  152. CODE_RANGE {
  153.     CHAR        code_start;
  154.     CHAR        code_finish;
  155.     BM_FILE        *code_bm_file;
  156.     long        code_offset;
  157.     CHAR_INDEX    code_pos;
  158.     bool        code_transposed;
  159.     CODE_RANGE    *code_next;
  160. };
  161.  
  162.  
  163.  
  164. /*
  165.  *    Extended internal version of HBF
  166.  */
  167.  
  168. typedef struct {
  169.     /* fields corresponding to the definition */
  170.     HBF        public;
  171.     /* plus internal stuff */
  172.     char        *filename;
  173.     byte        *bitmap_buffer;
  174.     unsigned int    b2_size;    /* number of legal byte-2's */
  175.     PROPERTY    *property;
  176.     B2_RANGE    *byte_2_range;
  177.     CODE_RANGE    *code_range;
  178.     BM_FILE        *bm_file;
  179. } HBF_STRUCT;
  180.  
  181.  
  182.  
  183. #define    FirstByte(code)        ((code)>>8)
  184. #define    SecondByte(code)    ((code)&0xff)
  185. #define    MakeCode(byte1,byte2)    (((byte1)<<8)|(byte2))
  186.  
  187. /* size of a bitmap in the file (may be affected by transposition) */
  188. #define    FileBitmapSize(hbfFile,cp) \
  189.         (cp)->code_transposed ? \
  190.             (hbfBitmapBBox(hbfFile)->hbf_height + 7)/8 * \
  191.                 hbfBitmapBBox(hbfFile)->hbf_width : \
  192.             HBF_BitmapSize(hbfFile)
  193.  
  194. #define    NEW(type)    ((type *)malloc((unsigned)(sizeof(type))))
  195.  
  196. #define    QUOTE '"'
  197.  
  198. #define MAXLINE    1024
  199.  
  200.  
  201.  
  202. extern    char    *strdup        _((const char *s));
  203.  
  204. static    void    add_b2r _((B2_RANGE **last_b2r, int start, int finish));
  205. static    bool    add_code_range _((HBF_STRUCT *hbf, const char *line));
  206. static    void    add_property _((HBF_STRUCT *hbf, const char *lp));
  207. static    CHAR_INDEX    b2_pos _((HBF_STRUCT *hbf, HBF_CHAR code));
  208. static    int    b2_size _((B2_RANGE *b2r));
  209. static    void    clear_bbox _((HBF_BBOX *bbox));
  210. static    void    clear_record _((HBF_STRUCT *hbf));
  211. static    char    *concat _((const char *dir, int dirlen, const char *stem));
  212. static    char    *expand_filename _((const char *name, const char *filename));
  213. static    const    byte *get_bitmap
  214.         _((HBF_STRUCT *hbf, HBF_CHAR code, byte *buffer));
  215. static    byte    *local_buffer _((HBF_STRUCT *hbf));
  216. #ifdef IN_MEMORY
  217. static    bool    read_bitmap_file _((BM_FILE *bmf, FILE *f));
  218. static    bool    copy_transposed
  219.         _((HBF *hbf, byte *bitmap, const byte *source));
  220. #else
  221. static    bool    get_transposed _((HBF *hbf, FILE *f, byte *bitmap));
  222. #endif
  223. static    bool    match _((const char *lp, const char *sp));
  224. static    bool    parse_file _((FILE *f, HBF_STRUCT *hbf));
  225. static    FILE    *path_open
  226.         _((const char *path, const char *filename, char **fullp));
  227. static    bool    real_open _((const char *filename, HBF_STRUCT *hbf));
  228.  
  229. /* Error reporting */
  230.  
  231. int    hbfDebug;    /* set this for error reporting */
  232.  
  233.  
  234.  
  235. #ifdef    __STDC__
  236. #include <stdarg.h>
  237.  
  238. static void
  239. eprintf(const char *fmt, ...)
  240. {
  241.     if (hbfDebug) {
  242.         va_list    args;
  243.  
  244.         (void)fprintf(stderr, "HBF: ");
  245.         va_start(args, fmt);
  246.         (void)vfprintf(stderr, fmt, args);
  247.         va_end(args);
  248.         (void)fprintf(stderr, "\n");
  249.     }
  250. }
  251. #else /* ! __STDC__ */
  252. /* poor man's variable-length argument list */
  253. static void
  254. eprintf(fmt, x1, x2, x3, x4, x5, x6, x7, x8, x9)
  255.     const    char    *fmt;
  256.     int    x1, x2, x3, x4, x5, x6, x7, x8, x9;
  257. {
  258.     if (hbfDebug) {
  259.         (void)fprintf(stderr, "HBF: ");
  260.         (void)fprintf(stderr, fmt, x1, x2, x3, x4, x5, x6, x7, x8, x9);
  261.         (void)fprintf(stderr, "\n");
  262.     }
  263. }
  264. #endif /* __STDC__ */
  265.  
  266.  
  267.  
  268. static void
  269. clear_bbox(bbox)
  270.     HBF_BBOX *bbox;
  271. {
  272.     bbox->hbf_width = bbox->hbf_height = 0;
  273.     bbox->hbf_xDisplacement = bbox->hbf_yDisplacement = 0;
  274. }
  275.  
  276. static void
  277. clear_record(hbf)
  278.     HBF_STRUCT *hbf;
  279. {
  280.     clear_bbox(&(hbf->public.hbf_bitmap_bbox));
  281.     clear_bbox(&(hbf->public.hbf_font_bbox));
  282.     hbf->property = NULL;
  283.     hbf->filename = NULL;
  284.     hbf->bitmap_buffer = NULL;
  285.     hbf->byte_2_range = NULL;
  286.     hbf->code_range = NULL;
  287.     hbf->bm_file = NULL;
  288. }
  289.  
  290. /*
  291.  *    Byte-2 ranges
  292.  */
  293.  
  294. static void
  295. add_b2r(last_b2r, start, finish)
  296. reg    B2_RANGE **last_b2r;
  297.     int    start;
  298.     int    finish;
  299. {
  300. reg    B2_RANGE *b2r;
  301.  
  302.     b2r = NEW(B2_RANGE);
  303.     while (*last_b2r != NULL && (*last_b2r)->b2r_start < start)
  304.         last_b2r = &((*last_b2r)->b2r_next);
  305.     b2r->b2r_next = *last_b2r;
  306.     b2r->b2r_start = start;
  307.     b2r->b2r_finish = finish;
  308.     *last_b2r = b2r;
  309. }
  310.  
  311. static CHAR_INDEX
  312. b2_pos(hbf, code)
  313.     HBF_STRUCT    *hbf;
  314.     HBF_CHAR    code;
  315. {
  316. reg    B2_RANGE *b2r;
  317. reg    unsigned c;
  318. reg    CHAR_INDEX    pos;
  319.  
  320.     c = SecondByte(code);
  321.     pos = 0;
  322.     for (b2r = hbf->byte_2_range; b2r != NULL; b2r = b2r->b2r_next)
  323.         if (b2r->b2r_start <= c && c <= b2r->b2r_finish)
  324.             return pos + c - b2r->b2r_start;
  325.         else
  326.             pos += b2r->b2r_finish - b2r->b2r_start + 1;
  327.     return BAD_CHAR_INDEX;
  328. }
  329.  
  330. static int
  331. b2_size(b2r)
  332. reg    B2_RANGE *b2r;
  333. {
  334. reg    int    size;
  335.  
  336.     size = 0;
  337.     for ( ; b2r != NULL; b2r = b2r->b2r_next)
  338.         size += b2r->b2r_finish - b2r->b2r_start + 1;
  339.     return size;
  340. }
  341.  
  342. /*
  343.  *    String stuff
  344.  */
  345.  
  346. static bool
  347. match(lp, sp)
  348. reg    const    char    *lp;
  349. reg    const    char    *sp;
  350. {
  351.     while (*lp == *sp && *sp != '\0') {
  352.         lp++;
  353.         sp++;
  354.     }
  355.     return (*lp == '\0' || isspace(*lp)) && *sp == '\0';
  356. }
  357.  
  358.  
  359.  
  360. #ifdef NO_STRDUP
  361. char *
  362. strdup(s)
  363.     const    char    *s;
  364. {
  365.     char    *new_s;
  366.  
  367.     new_s = malloc((unsigned)strlen(s) + 1);
  368.     strcpy(new_s, s);
  369.     return new_s;
  370. }
  371. #endif
  372.  
  373.  
  374.  
  375. /*
  376.  *    Properties
  377.  */
  378.  
  379. static void
  380. add_property(hbf, lp)
  381. reg    HBF_STRUCT    *hbf;
  382. reg    const char    *lp;
  383. {
  384. reg    PROPERTY    *prop;
  385.     char    tmp[MAXLINE];
  386. reg    char    *tp;
  387.  
  388.     prop = NEW(PROPERTY);
  389.  
  390.     tp = tmp;
  391.     while (*lp != '\0' && ! isspace(*lp))
  392.         *tp++ = *lp++;
  393.     *tp = '\0';
  394.     prop->prop_name = strdup(tmp);
  395.  
  396.     while (*lp != '\0' && isspace(*lp))
  397.         lp++;
  398.  
  399.     tp = tmp;
  400.     if (*lp == QUOTE) {
  401.         lp++;
  402.         while (*lp != '\0' && ! (*lp == QUOTE && *++lp != QUOTE))
  403.             *tp++ = *lp++;
  404.     }
  405.     else
  406.         for (;;) {
  407.             while (*lp != '\0' && ! isspace(*lp))
  408.                 *tp++ = *lp++;
  409.             while (isspace(*lp))
  410.                 lp++;
  411.             if (*lp == '\0')
  412.                 break;
  413.             *tp++ = ' ';
  414.         }
  415.     *tp = '\0';
  416.     prop->prop_value = strdup(tmp);
  417.  
  418.     prop->prop_next = hbf->property;
  419.     hbf->property = prop;
  420. }
  421.  
  422. const char *
  423. hbfProperty(hbfFile, propName)
  424.     HBF        *hbfFile;
  425.     const    char    *propName;
  426. {
  427. reg    HBF_STRUCT    *hbf;
  428. reg    PROPERTY    *prop;
  429.  
  430.     hbf = (HBF_STRUCT *)hbfFile;
  431.     for (prop = hbf->property; prop != NULL; prop = prop->prop_next)
  432.         if (strcmp(prop->prop_name, propName) == 0)
  433.             return prop->prop_value;
  434.     return NULL;
  435. }
  436.  
  437. /*
  438.  *    Compatability routines
  439.  */
  440.  
  441. const char *
  442. HBF_GetProperty(handle, propertyName)
  443.     HBF        *handle;
  444.     const    char    *propertyName;
  445. {
  446.     return hbfProperty(handle, propertyName);
  447. }
  448.  
  449. int
  450. HBF_GetFontBoundingBox(handle, width, height, xDisplacement, yDisplacement)
  451.     HBF_Handle    handle;
  452.     unsigned int    *width;
  453.     unsigned int    *height;
  454.     int        *xDisplacement;
  455.     int        *yDisplacement;
  456. {
  457.     if (width != NULL)
  458.         *width = hbfFontBBox(handle)->hbf_width;
  459.     if (height != NULL)
  460.         *height = hbfFontBBox(handle)->hbf_height;
  461.     if (xDisplacement != NULL)
  462.         *xDisplacement = hbfFontBBox(handle)->hbf_xDisplacement;
  463.     if (yDisplacement != NULL)
  464.         *yDisplacement = hbfFontBBox(handle)->hbf_yDisplacement;
  465.     return 0;
  466. }
  467.  
  468. int
  469. HBF_GetBitmapBoundingBox(handle, width, height, xDisplacement, yDisplacement)
  470.     HBF_Handle    handle;
  471.     unsigned int    *width;
  472.     unsigned int    *height;
  473.     int        *xDisplacement;
  474.     int        *yDisplacement;
  475. {
  476.     if (width != NULL)
  477.         *width = hbfBitmapBBox(handle)->hbf_width;
  478.     if (height != NULL)
  479.         *height = hbfBitmapBBox(handle)->hbf_height;
  480.     if (xDisplacement != NULL)
  481.         *xDisplacement = hbfBitmapBBox(handle)->hbf_xDisplacement;
  482.     if (yDisplacement != NULL)
  483.         *yDisplacement = hbfBitmapBBox(handle)->hbf_yDisplacement;
  484.     return 0;
  485. }
  486.  
  487. /*
  488.  * Prepend a directory to a relative filename.
  489.  */
  490.  
  491. static char *
  492. concat(dir, dirlen, stem)
  493.     const    char    *dir;    /* not necessarily null-terminated */
  494.     int    dirlen;        /* number of significant chars in dir */
  495.     const    char    *stem;    /* relative filename */
  496. {
  497.     char    *fullname;
  498.  
  499.     if (dirlen == 0)    /* null: current directory */
  500.         return strdup(stem);
  501. #ifdef unix
  502.     fullname = malloc(dirlen + strlen(stem) + 2);
  503.     (void)sprintf(fullname, "%.*s/%s", dirlen, dir, stem);
  504. #else
  505. #ifdef msdos
  506.     fullname = malloc(dirlen + strlen(stem) + 2);
  507.     (void)sprintf(fullname, "%.*s\\%s", dirlen, dir, stem);
  508. #else
  509. #ifdef vms
  510.     if (dir[dirlen-1] == ']' && stem[0] == '[' && stem[1] == '-') {
  511.         dirlen--;
  512.         stem++;
  513.         fullname = malloc(dirlen + strlen(stem) + 2);
  514.         (void)sprintf(fullname, "%.*s.%s", dirlen, dir, stem);
  515.     }
  516.     else {
  517.         if (dir[dirlen-1] == ']' && stem[0] == '[' && stem[1] == '.') {
  518.             dirlen--;
  519.             stem++;
  520.         }
  521.         fullname = malloc(dirlen + strlen(stem) + 1);
  522.         (void)sprintf(fullname, "%.*s%s", dirlen, dir, stem);
  523.     }
  524. #else
  525.     fullname = strdup(stem);
  526. #endif /* vms */
  527. #endif /* msdos */
  528. #endif /* unix */
  529.     return fullname;
  530. }
  531.  
  532. /*
  533.  *    Bitmap files
  534.  *
  535.  *    If the host operating system has a heirarchical file system and
  536.  *    the bitmap file name is relative, it is relative to the directory
  537.  *    containing the HBF file.
  538.  */
  539.  
  540. static char *
  541. expand_filename(name, hbf_name)
  542.     const    char    *name;
  543.     const    char    *hbf_name;
  544. {
  545. #ifdef unix
  546. reg    char    *s;
  547. reg    int    size;
  548.  
  549.     size = name[0] != '/' && (s = strrchr(hbf_name, '/')) != NULL ?
  550.         s - hbf_name + 1 : 0;
  551.     s = malloc((unsigned)size + strlen(name) + 1);
  552.     (void)sprintf(s, "%.*s%s", size, hbf_name, name);
  553.     return s;
  554. #else
  555. #ifdef msdos
  556. reg    char    *s;
  557. reg    int    size;
  558.  
  559.     size = HasDrive(name) ? 0 :
  560.         name[0] == '\\' ? (HasDrive(hbf_name) ? 2 : 0) :
  561.         (s = strrchr(hbf_name, '\\')) != NULL ?
  562.             s - hbf_name + 1 : 0;
  563.     s = malloc((unsigned)size + strlen(name) + 1);
  564.     (void)sprintf(s, "%.*s%s", size, hbf_name, name);
  565.     return s;
  566. #else
  567. #ifdef vms
  568. reg    char    *s;
  569. reg    const    char    *copyto;
  570. reg    int    size;
  571.  
  572.     if ((s = strchr(hbf_name, ']')) != NULL && RelativeFileName(name))
  573.         return concat(hbf_name, (s - hbf_name) + 1, name);
  574.  
  575.     copyto = hbf_name;
  576.     if ((s = strstr(copyto, "::")) != NULL && strstr(name, "::") == NULL)
  577.         copyto = s+2;
  578.     if ((s = strchr(copyto, ':')) != NULL && strchr(name, ':') == NULL)
  579.         copyto = s+1;
  580.     size = copyto - hbf_name;
  581.     s = malloc((unsigned)size + strlen(name) + 1);
  582.     (void)sprintf(s, "%.*s%s", size, hbf_name, name);
  583.     return s;
  584. #else
  585.     return strdup(name);
  586. #endif /* vms */
  587. #endif /* msdos */
  588. #endif /* unix */
  589. }
  590.  
  591. static BM_FILE *
  592. find_file(hbf, filename)
  593.     HBF_STRUCT *hbf;
  594.     const char *filename;
  595. {
  596.     BM_FILE    **fp;
  597. reg    BM_FILE    *file;
  598.     FILE    *f;
  599. #ifdef IN_MEMORY
  600. #ifdef unix
  601.     bool    from_pipe;
  602. #endif
  603. #endif
  604.  
  605.     for (fp = &(hbf->bm_file); *fp != NULL; fp = &((*fp)->bmf_next))
  606.         if (strcmp((*fp)->bmf_name, filename) == 0)
  607.             return *fp;
  608.  
  609.     *fp = file = NEW(BM_FILE);
  610.     if (file == NULL) {
  611.         eprintf("out of memory");
  612.         return NULL;
  613.     }
  614.     file->bmf_name = expand_filename(filename, hbf->filename);
  615.     if (file->bmf_name == NULL) {
  616.         free((char *)file);
  617.         return NULL;
  618.     }
  619.     f = fopen(file->bmf_name, READ_BINARY);
  620. #ifdef IN_MEMORY
  621. #ifdef unix
  622.     from_pipe = FALSE;
  623.     if (f == NULL) {
  624.         char    tmp[400];
  625.  
  626.         sprintf(tmp, "%s.gz", file->bmf_name);
  627.         if ((f = fopen(tmp, "r")) != NULL) {
  628.             fclose(f);
  629.             sprintf(tmp, "gzcat %s.gz", file->bmf_name);
  630.             if ((f = popen(tmp, "r")) != NULL)
  631.                 from_pipe = TRUE;
  632.         }
  633.     }
  634. #endif /* unix */
  635. #endif /* IN_MEMORY */
  636.     if (f == NULL) {
  637.         eprintf("can't open bitmap file '%s'", file->bmf_name);
  638.         free(file->bmf_name);
  639.         free((char *)file);
  640.         return NULL;
  641.     }
  642. #ifdef IN_MEMORY
  643.     if (! read_bitmap_file(file, f)) {
  644.         free(file->bmf_name);
  645.         free((char *)file);
  646.         return NULL;
  647.     }
  648. #ifdef unix
  649.     if (from_pipe)
  650.         pclose(f);
  651.     else
  652.         fclose(f);
  653. #else /* ! unix */
  654.     fclose(f);
  655. #endif /* ! unix */
  656. #else /* ! IN_MEMORY */
  657.     file->bmf_file = f;
  658. #endif /* ! IN_MEMORY */
  659.     file->bmf_next = NULL;
  660.     return file;
  661. }
  662.  
  663.  
  664.  
  665. #ifdef IN_MEMORY
  666. #define    GRAIN_SIZE    512
  667.  
  668. static bool
  669. read_bitmap_file(bmf, f)
  670.     BM_FILE    *bmf;
  671.     FILE    *f;
  672. {
  673.     byte    *contents, *cp;
  674.     long    size;
  675.     int    c;
  676.  
  677.     size = 0;
  678.     cp = contents = (byte *)malloc((unsigned)GRAIN_SIZE);
  679.     if (contents == NULL) {
  680.         eprintf("not enough space for bitmap file");
  681.         return NULL;
  682.     }
  683.     while ((c = getc(f)) != EOF) {
  684.         if (size%GRAIN_SIZE == 0) {
  685.             contents = (byte *)realloc((char *)contents,
  686.                     (unsigned)(size + GRAIN_SIZE));
  687.             if (contents == NULL) {
  688.                 eprintf("not enough space for bitmap file");
  689.                 return NULL;
  690.             }
  691.             cp = contents + size;
  692.         }
  693.         *cp++ = c;
  694.         size++;
  695.     }
  696.     bmf->bmf_size = size;
  697.     bmf->bmf_contents = (byte *)realloc((char *)contents, (unsigned)size);
  698.     return TRUE;
  699. }
  700. #endif /* IN_MEMORY */
  701.  
  702.  
  703.  
  704. /*
  705.  *    Code ranges
  706.  */
  707.  
  708. static bool
  709. add_code_range(hbf, line)
  710.     HBF_STRUCT    *hbf;
  711.     const char    *line;
  712. {
  713.     CODE_RANGE *cp;
  714.     CODE_RANGE **cpp;
  715.     long    start, finish;
  716.     long    offset;
  717.     char    filename[MAXLINE];
  718.     char    orientation[MAXLINE];
  719.     int    num_items;
  720.     BM_FILE    *bmf;
  721.     CHAR_INDEX b2pos;
  722.  
  723.     orientation[0] = '\0';
  724.     num_items = sscanf(line, "HBF_CODE_RANGE %li-%li %s %li %s",
  725.                &start, &finish, filename, &offset, orientation);
  726.     if (num_items < 4) {
  727.         eprintf("syntax error in HBF_CODE_RANGE");
  728.         return FALSE;
  729.     }
  730.     /* code ranges are checked in real_open() */
  731.     if ((bmf = find_file(hbf, filename)) == NULL)
  732.         return FALSE;
  733.     if ((cp = NEW(CODE_RANGE)) == NULL) {
  734.         eprintf("out of memory");
  735.         return FALSE;
  736.     }
  737.  
  738.     cp->code_start = (CHAR)start;
  739.     cp->code_finish = (CHAR)finish;
  740.     cp->code_bm_file = bmf;
  741.     cp->code_offset = offset;
  742.     /* allow extra keyword "sideways" or "transposed" */
  743.     cp->code_transposed = num_items == 5 &&
  744.             strchr("sStT", orientation[0]) != NULL;
  745.     /* insert it in order */
  746.     for (cpp = &hbf->code_range;
  747.          *cpp != NULL && (*cpp)->code_finish < start;
  748.          cpp = &((*cpp)->code_next))
  749.         ;
  750.     if (*cpp != NULL && (*cpp)->code_start <= finish) {
  751.         eprintf("code ranges overlap");
  752.         return FALSE;
  753.     }
  754.     cp->code_next = *cpp;
  755.     *cpp = cp;
  756.  
  757.     /* set code_pos, and check range */
  758.     if (start > finish) {
  759.         eprintf("illegal code range 0x%04lx-0x%04lx", start, finish);
  760.         return FALSE;
  761.     }
  762.     if ((b2pos = b2_pos(hbf, start)) == BAD_CHAR_INDEX) {
  763.         eprintf("illegal start code 0x%04lx", start);
  764.         return FALSE;
  765.     }
  766.     cp->code_pos = hbf->b2_size*(long)FirstByte(start) + b2pos;
  767.     if ((b2pos = b2_pos(hbf, finish)) == BAD_CHAR_INDEX) {
  768.         eprintf("illegal finish code 0x%04lx", finish);
  769.         return FALSE;
  770.     }
  771.     /* check that the bitmap file has enough bitmaps */
  772.     offset += (long)(hbf->b2_size*FirstByte(finish) +
  773.                 b2pos - cp->code_pos + 1) *
  774.             FileBitmapSize(&(hbf->public), cp);
  775. #ifdef IN_MEMORY
  776.     if (offset > bmf->bmf_size) {
  777. /*}*/
  778. #else
  779.     if (fseek(bmf->bmf_file, offset, 0) < 0) {
  780. #endif
  781.         eprintf("bitmap file '%s' is too short", bmf->bmf_name);
  782.         return FALSE;
  783.     }
  784.     return TRUE;
  785. }
  786.  
  787. /*
  788.  *    Reading and parsing of an HBF file
  789.  */
  790.  
  791. /* get next non-COMMENT line */
  792. static bool
  793. get_line(buf, len, f)
  794.     char    *buf;
  795.     int    len;
  796.     FILE    *f;
  797. {
  798.     while (fgets(buf, len, f) != NULL)
  799.         if (! match(buf, "COMMENT"))
  800.             return TRUE;
  801.     eprintf("unexpected end of file");
  802.     return FALSE;
  803. }
  804.  
  805. static bool
  806. get_property(line, keyword, hbf)
  807.     const    char    *line;
  808.     const    char    *keyword;
  809.     HBF_STRUCT    *hbf;
  810. {
  811.     if (! match(line, keyword)) {
  812.         eprintf("%s expected", keyword);
  813.         return FALSE;
  814.     }
  815.     add_property(hbf, line);
  816.     return TRUE;
  817. }
  818.  
  819. static bool
  820. get_bbox(line, keyword, bbox)
  821.     const    char    *line;
  822.     const    char    *keyword;
  823.     HBF_BBOX    *bbox;
  824. {
  825.     int    w, h, xd, yd;
  826.  
  827.     if (! match(line, keyword) ||
  828.         sscanf(line + strlen(keyword), "%i %i %i %i",
  829.             &w, &h, &xd, &yd) != 4) {
  830.         eprintf("%s expected", keyword);
  831.         return FALSE;
  832.     }
  833.     if (w <= 0 || h <= 0) {
  834.         eprintf("illegal %s dimensions %dx%d", keyword, w, h);
  835.         return FALSE;
  836.     }
  837.     bbox->hbf_width = w;
  838.     bbox->hbf_height = h;
  839.     bbox->hbf_xDisplacement = xd;
  840.     bbox->hbf_yDisplacement = yd;
  841.     return TRUE;
  842. }
  843.  
  844. /*
  845.  *  HBFHeaderFile ::=
  846.  *     'HBF_START_FONT'        version            EOLN
  847.  *     'HBF_CODE_SCHEME'        word ...        EOLN
  848.  *     'FONT'                fontName        EOLN
  849.  *     'SIZE'                ptsize xres yres    EOLN
  850.  *     'HBF_BITMAP_BOUNDING_BOX'    w h xd yd        EOLN
  851.  *     'FONTBOUNDINGBOX'        w h xd yd        EOLN
  852.  *     X11R5FontPropertySection
  853.  *     'CHARS'                n            EOLN
  854.  *     HBFByte2RangeSection
  855.  *     HBFCodeRangeSection
  856.  *     'HBF_END_FONT'            EOLN .
  857.  *
  858.  * This implementation allows extra lines before HBF_END_FONT.
  859.  * Anything after HBF_END_FONT is ignored.
  860.  */
  861.  
  862. static bool
  863. parse_file(f, hbf)
  864.     FILE    *f;
  865. reg    HBF_STRUCT *hbf;
  866. {
  867.     char    line[MAXLINE];
  868.     int    start, finish;
  869.  
  870.     if (! get_line(line, MAXLINE, f) ||
  871.         ! get_property(line, "HBF_START_FONT", hbf))
  872.         return FALSE;
  873.  
  874.     if (! get_line(line, MAXLINE, f) ||
  875.         ! get_property(line, "HBF_CODE_SCHEME", hbf))
  876.         return FALSE;
  877.  
  878.     if (! get_line(line, MAXLINE, f) ||
  879.         ! get_property(line, "FONT", hbf))
  880.         return FALSE;
  881.  
  882.     if (! get_line(line, MAXLINE, f) ||
  883.         ! get_property(line, "SIZE", hbf))
  884.         return FALSE;
  885.  
  886.     if (! get_line(line, MAXLINE, f) ||
  887.         ! get_bbox(line, "HBF_BITMAP_BOUNDING_BOX",
  888.             &(hbf->public.hbf_bitmap_bbox)))
  889.         return FALSE;
  890.  
  891.     if (! get_line(line, MAXLINE, f) ||
  892.         ! get_bbox(line, "FONTBOUNDINGBOX", &(hbf->public.hbf_font_bbox)))
  893.         return FALSE;
  894.  
  895.     if (! get_line(line, MAXLINE, f))
  896.         return FALSE;
  897.     if (match(line, "STARTPROPERTIES")) {
  898.         for (;;) {
  899.             if (! get_line(line, MAXLINE, f))
  900.                 return FALSE;
  901.             if (match(line, "ENDPROPERTIES"))
  902.                 break;
  903.             add_property(hbf, line);
  904.         }
  905.         if (! get_line(line, MAXLINE, f))
  906.             return FALSE;
  907.     }
  908.  
  909. /*      if (! get_property(line, "CHARS", hbf)) */ /* HBF 1.0 */
  910. /*              return FALSE;                   */
  911. /*      if (! get_line(line, MAXLINE, f))       */
  912. /*              return FALSE;                   */
  913.  
  914.         if (match(line, "CHARS")) {                /* HBF 1.1 */
  915.                 add_property(hbf, line);
  916.                 if (! get_line(line, MAXLINE, f))
  917.                         return FALSE;
  918.                 }
  919.  
  920.     if (match(line, "HBF_START_BYTE_2_RANGES")) {
  921.         for (;;) {
  922.             if (! get_line(line, MAXLINE, f))
  923.                 return FALSE;
  924.             if (match(line, "HBF_END_BYTE_2_RANGES"))
  925.                 break;
  926.             if (sscanf(line, "HBF_BYTE_2_RANGE %i-%i",
  927.                     &start, &finish) != 2) {
  928.                 eprintf("HBF_BYTE_2_RANGE expected");
  929.                 return FALSE;
  930.             }
  931.             add_b2r(&(hbf->byte_2_range), start, finish);
  932.         }
  933.         if (! get_line(line, MAXLINE, f))
  934.             return FALSE;
  935.     }
  936.     else
  937.         add_b2r(&(hbf->byte_2_range), 0, 0xff);
  938.     hbf->b2_size = b2_size(hbf->byte_2_range);
  939.  
  940.     if (! match(line, "HBF_START_CODE_RANGES")) {
  941.         eprintf("HBF_START_CODE_RANGES expected");
  942.         return FALSE;
  943.     }
  944.     for (;;) {
  945.         if (! get_line(line, MAXLINE, f))
  946.             return FALSE;
  947.         if (match(line, "HBF_END_CODE_RANGES"))
  948.             break;
  949.         if (! add_code_range(hbf, line))
  950.             return FALSE;
  951.     }
  952.  
  953.     for (;;) {
  954.         if (! get_line(line, MAXLINE, f))
  955.             return FALSE;
  956.         if (match(line, "HBF_END_FONT"))
  957.             break;
  958.         /* treat extra lines as properties (for private extensions) */
  959.         add_property(hbf, line);
  960.     }
  961.  
  962.     return TRUE;
  963. }
  964.  
  965. static FILE *
  966. path_open(path, filename, fullp)
  967.     const    char    *path;
  968.     const    char    *filename;
  969.     char    **fullp;
  970. {
  971.     if (LocalFileName(filename) && path != NULL) {
  972. #ifdef PATH_DELIMITER
  973.         int    len;
  974.         char    *fullname;
  975.         FILE    *f;
  976.         const    char    *p_next;
  977.  
  978.         len = strlen(filename);
  979.         for (;;) {
  980.             p_next = strchr(path, PATH_DELIMITER);
  981.             if (p_next == NULL)
  982.                 p_next = path + strlen(path);
  983.             fullname = concat(path, p_next - path, filename);
  984.             if ((f = fopen(fullname, "r")) != NULL) {
  985.                 *fullp = fullname;
  986.                 return f;
  987.             }
  988.             free(fullname);
  989.             if (*p_next == '\0')
  990.                 break;
  991.             path = p_next + 1;
  992.         }
  993. #endif
  994.         return NULL;
  995.     }
  996.     else {
  997.         *fullp = strdup(filename);
  998.         return fopen(*fullp, "r");
  999.     }
  1000. }
  1001.  
  1002. static bool
  1003. real_open(filename, hbf)
  1004.     const    char    *filename;
  1005. reg    HBF_STRUCT *hbf;
  1006. {
  1007.     FILE    *f;
  1008.  
  1009.     f = path_open(getenv("HBFPATH"), filename, &(hbf->filename));
  1010.     if (f == NULL) {
  1011.         eprintf("can't read file '%s'", filename);
  1012.         return FALSE;
  1013.     }
  1014.     if (! parse_file(f, hbf)) {
  1015.         fclose(f);
  1016.         return FALSE;
  1017.     }
  1018.     fclose(f);
  1019.     return TRUE;
  1020. }
  1021.  
  1022. HBF *
  1023. hbfOpen(filename)
  1024.     const    char    *filename;
  1025. {
  1026. reg    HBF_STRUCT *hbf;
  1027.  
  1028.     if ((hbf = NEW(HBF_STRUCT)) == NULL) {
  1029.         eprintf("can't allocate HBF structure");
  1030.         return NULL;
  1031.     }
  1032.     clear_record(hbf);
  1033.     if (real_open(filename, hbf))
  1034.         return &(hbf->public);
  1035.     hbfClose(&(hbf->public));
  1036.     return NULL;
  1037. }
  1038.  
  1039. int
  1040. HBF_OpenFont(filename, ptrHandleStorage)
  1041.     const    char    *filename;
  1042.     HBF    **ptrHandleStorage;
  1043. {
  1044.     return (*ptrHandleStorage = hbfOpen(filename)) == NULL ? -1 : 0;
  1045. }
  1046.  
  1047. /*
  1048.  *    Close files, free everything associated with the HBF.
  1049.  */
  1050.  
  1051. int
  1052. HBF_CloseFont(hbfFile)
  1053.     HBF    *hbfFile;
  1054. {
  1055. reg    HBF_STRUCT    *hbf;
  1056.     PROPERTY    *prop_ptr, *prop_next;
  1057.     B2_RANGE    *b2r_ptr, *b2r_next;
  1058.     CODE_RANGE    *code_ptr, *code_next;
  1059.     BM_FILE        *bmf_ptr, *bmf_next;
  1060.     int        status;
  1061.  
  1062.     status = 0;
  1063.     hbf = (HBF_STRUCT *)hbfFile;
  1064.  
  1065.     if (hbf->filename != NULL)
  1066.         free(hbf->filename);
  1067.     if (hbf->bitmap_buffer != NULL)
  1068.         free(hbf->bitmap_buffer);
  1069.  
  1070.     for (prop_ptr = hbf->property;
  1071.          prop_ptr != NULL;
  1072.          prop_ptr = prop_next) {
  1073.         prop_next = prop_ptr->prop_next;
  1074.         free(prop_ptr->prop_name);
  1075.         free(prop_ptr->prop_value);
  1076.         free((char *)prop_ptr);
  1077.     }
  1078.  
  1079.     for (b2r_ptr = hbf->byte_2_range;
  1080.          b2r_ptr != NULL;
  1081.          b2r_ptr = b2r_next) {
  1082.         b2r_next = b2r_ptr->b2r_next;
  1083.         free((char *)b2r_ptr);
  1084.     }
  1085.  
  1086.     for (code_ptr = hbf->code_range;
  1087.          code_ptr != NULL;
  1088.          code_ptr = code_next) {
  1089.         code_next = code_ptr->code_next;
  1090.         free((char *)code_ptr);
  1091.     }
  1092.  
  1093.     for (bmf_ptr = hbf->bm_file;
  1094.          bmf_ptr != NULL;
  1095.          bmf_ptr = bmf_next) {
  1096.         bmf_next = bmf_ptr->bmf_next;
  1097. #ifdef IN_MEMORY
  1098.         free((char *)(bmf_ptr->bmf_contents));
  1099. #else
  1100.         if(bmf_ptr->bmf_file != NULL)
  1101.             if (fclose(bmf_ptr->bmf_file) < 0)
  1102.                 status = -1;
  1103. #endif
  1104.         free(bmf_ptr->bmf_name);
  1105.         free((char *)bmf_ptr);
  1106.     }
  1107.  
  1108.     free((char *)hbf);
  1109.  
  1110.     return status;
  1111. }
  1112.  
  1113. void hbfClose(hbfFile)
  1114.     HBF    *hbfFile;
  1115. {
  1116.     (void)HBF_CloseFont(hbfFile);
  1117. }
  1118.  
  1119. /*
  1120.  *    Fetch a bitmap
  1121.  */
  1122.  
  1123. const char *
  1124. hbfGetBitmap(hbf, code)
  1125.     HBF        *hbf;
  1126.     HBF_CHAR    code;
  1127. {
  1128.     return get_bitmap((HBF_STRUCT *)hbf, code, (byte *)NULL);
  1129. }
  1130.  
  1131. int
  1132. HBF_GetBitmap(hbf, code, buffer)
  1133.     HBF        *hbf;
  1134.     HBF_CHAR    code;
  1135.     byte        *buffer;
  1136. {
  1137.     return get_bitmap((HBF_STRUCT *)hbf, code, buffer) == NULL ? -1 : 0;
  1138. }
  1139.  
  1140. /*
  1141.  * Internal function to fetch a bitmap.
  1142.  * If buffer is non-null, it must be used.
  1143.  */
  1144.  
  1145. static const byte *
  1146. get_bitmap(hbf, code, buffer)
  1147. reg    HBF_STRUCT    *hbf;
  1148.     HBF_CHAR    code;
  1149.     byte        *buffer;
  1150. {
  1151.     CHAR_INDEX    pos, b2pos;
  1152. reg    CODE_RANGE    *cp;
  1153.     BM_FILE        *bmf;
  1154.     int        bm_size;
  1155.     long        offset;
  1156.  
  1157.     if ((b2pos = b2_pos(hbf, code)) == BAD_CHAR_INDEX)
  1158.         return NULL;
  1159.     pos = hbf->b2_size*FirstByte(code) + b2pos;
  1160.     for (cp = hbf->code_range; cp != NULL; cp = cp->code_next)
  1161.         if (cp->code_start <= code && code <= cp->code_finish) {
  1162.             bmf = cp->code_bm_file;
  1163.             bm_size = FileBitmapSize(&(hbf->public), cp);
  1164.             offset = cp->code_offset +
  1165.                    (long)(pos - cp->code_pos) * bm_size;
  1166. #ifdef IN_MEMORY
  1167.             if (cp->code_transposed) {
  1168.                 if (buffer == NULL &&
  1169.                     ((buffer = local_buffer(hbf)) == NULL))
  1170.                     return NULL;
  1171.                 copy_transposed(&(hbf->public),
  1172.                         buffer,
  1173.                         bmf->bmf_contents + offset);
  1174.                 return buffer;
  1175.             }
  1176.             if (buffer == NULL)
  1177.                 return bmf->bmf_contents + offset;
  1178.             memcpy((char *)buffer,
  1179.                    (char *)(bmf->bmf_contents + offset),
  1180.                    bm_size);
  1181.             return buffer;
  1182. #else /* ! IN_MEMORY */
  1183.             if (buffer == NULL &&
  1184.                 ((buffer = local_buffer(hbf)) == NULL))
  1185.                 return NULL;
  1186.             if (fseek(bmf->bmf_file, offset, 0) != 0) {
  1187.                 eprintf("seek error on code 0x%04x", code);
  1188.                 return NULL;
  1189.             }
  1190.             if (cp->code_transposed ?
  1191.                 get_transposed(&(hbf->public), bmf->bmf_file,
  1192.                         buffer) :
  1193.                 fread((char *)buffer,
  1194.                     bm_size, 1, bmf->bmf_file) == 1)
  1195.                 return buffer;
  1196.             eprintf("read error on code 0x%04x", code);
  1197.             return NULL;
  1198. #endif /* IN_MEMORY */
  1199.         }
  1200.     eprintf("code 0x%04x out of range", code);
  1201.     return NULL;
  1202. }
  1203.  
  1204. static byte *
  1205. local_buffer(hbf)
  1206.     HBF_STRUCT    *hbf;
  1207. {
  1208.     if (hbf->bitmap_buffer == NULL &&
  1209.         (hbf->bitmap_buffer = (byte *)malloc(HBF_BitmapSize(&(hbf->public)))) == NULL) {
  1210.         eprintf("out of memory");
  1211.         return NULL;
  1212.     }
  1213.     return hbf->bitmap_buffer;
  1214. }
  1215.  
  1216.  
  1217.  
  1218. #ifdef IN_MEMORY
  1219. static bool
  1220. copy_transposed(hbf, bitmap, source)
  1221.     HBF    *hbf;
  1222. reg    byte    *bitmap;
  1223. reg    const    byte    *source;
  1224. {
  1225. reg    byte    *pos;
  1226. reg    byte    *bm_end;
  1227.     int    x;
  1228.     int    width;
  1229. reg    int    row_size;
  1230. reg    int    c;
  1231. reg    int    imask, omask;
  1232.  
  1233.     width = hbfBitmapBBox(hbf)->hbf_width;
  1234.     row_size = HBF_RowSize(hbf);
  1235.     bm_end = bitmap + HBF_BitmapSize(hbf);
  1236.     (void)memset((char *)bitmap, '\0', HBF_BitmapSize(hbf));
  1237.     for (x = 0; x < width; x++) {
  1238.         pos = bitmap + x/8;
  1239.         omask = Bit(x%8);
  1240.         /* y = 0 */
  1241.         for (;;) {
  1242.             c = *source++;
  1243.             for (imask = Bit(0); imask != 0; imask >>= 1) {
  1244.                 /*
  1245.                  * At this point,
  1246.                  *
  1247.                  *    imask == Bit(y%8)
  1248.                  *    pos == bitmap + y*row_size + x/8
  1249.                  *
  1250.                  * We examine bit y of row x of the input,
  1251.                  * setting bit x of row y of the output if
  1252.                  * required, by applying omask to *pos.
  1253.                  */
  1254.                 if ((c & imask) != 0)
  1255.                     *pos |= omask;
  1256.                 /* if (++y > height) goto end_column */
  1257.                 pos += row_size;
  1258.                 if (pos >= bm_end)
  1259.                     goto end_column;
  1260.             }
  1261.         }
  1262. end_column:
  1263.         ;
  1264.     }
  1265.     return TRUE;
  1266. }
  1267. #else /* ! IN_MEMORY */
  1268. static bool
  1269. get_transposed(hbf, f, bitmap)
  1270.     HBF    *hbf;
  1271.     FILE    *f;
  1272. reg    byte    *bitmap;
  1273. {
  1274. reg    byte    *pos;
  1275. reg    byte    *bm_end;
  1276.     int    x;
  1277.     int    width;
  1278. reg    int    row_size;
  1279. reg    int    c;
  1280. reg    int    imask, omask;
  1281.  
  1282.     width = hbfBitmapBBox(hbf)->hbf_width;
  1283.     row_size = HBF_RowSize(hbf);
  1284.     bm_end = bitmap + HBF_BitmapSize(hbf);
  1285.     (void)memset((char *)bitmap, '\0', HBF_BitmapSize(hbf));
  1286.     for (x = 0; x < width; x++) {
  1287.         pos = bitmap + x/8;
  1288.         omask = Bit(x%8);
  1289.         /* y = 0 */
  1290.         for (;;) {
  1291.             if ((c = getc(f)) == EOF)
  1292.                 return FALSE;
  1293.             for (imask = Bit(0); imask != 0; imask >>= 1) {
  1294.                 /*
  1295.                  * At this point,
  1296.                  *
  1297.                  *    imask == Bit(y%8)
  1298.                  *    pos == bitmap + y*row_size + x/8
  1299.                  *
  1300.                  * We examine bit y of row x of the input,
  1301.                  * setting bit x of row y of the output if
  1302.                  * required, by applying omask to *pos.
  1303.                  */
  1304.                 if ((c & imask) != 0)
  1305.                     *pos |= omask;
  1306.                 /* if (++y > height) goto end_column */
  1307.                 pos += row_size;
  1308.                 if (pos >= bm_end)
  1309.                     goto end_column;
  1310.             }
  1311.         }
  1312. end_column:
  1313.         ;
  1314.     }
  1315.     return TRUE;
  1316. }
  1317. #endif /* ! IN_MEMORY */
  1318.  
  1319.  
  1320.  
  1321. /*
  1322.  * Call function on each valid code in ascending order.
  1323.  */
  1324.  
  1325. void
  1326. hbfForEach(hbfFile, func)
  1327. reg    HBF    *hbfFile;
  1328. reg    void    (*func)_((HBF *sameHbfFile, HBF_CHAR code));
  1329. {
  1330.     HBF_STRUCT    *hbf;
  1331.     CODE_RANGE    *cp;
  1332. reg    B2_RANGE    *b2r;
  1333. reg    unsigned    byte1, byte2;
  1334. reg    unsigned    finish;
  1335.  
  1336.     hbf = (HBF_STRUCT *)hbfFile;
  1337.     for (cp = hbf->code_range; cp != NULL; cp = cp->code_next) {
  1338.         byte1 = FirstByte(cp->code_start);
  1339.         byte2 = SecondByte(cp->code_start);
  1340.         while (MakeCode(byte1, byte2) <= cp->code_finish) {
  1341.             for (b2r = hbf->byte_2_range;
  1342.                  b2r != NULL;
  1343.                  b2r = b2r->b2r_next) {
  1344.                 if (byte2 < b2r->b2r_start)
  1345.                     byte2 = b2r->b2r_start;
  1346.                 finish = b2r->b2r_finish;
  1347.                 if (byte1 == FirstByte(cp->code_finish) &&
  1348.                     finish > SecondByte(cp->code_finish))
  1349.                     finish = SecondByte(cp->code_finish);
  1350.                 while (byte2 <= finish) {
  1351.                     (*func)(hbfFile,
  1352.                         MakeCode(byte1, byte2));
  1353.                     byte2++;
  1354.                 }
  1355.             }
  1356.             byte1++;
  1357.             byte2 = 0;
  1358.         }
  1359.     }
  1360. }
  1361.  
  1362. const char *
  1363. hbfFileName(hbf)
  1364.     HBF    *hbf;
  1365. {
  1366.     return ((HBF_STRUCT *)hbf)->filename;
  1367. }
  1368.  
  1369. long
  1370. hbfChars(hbfFile)
  1371.     HBF    *hbfFile;
  1372. {
  1373.     HBF_STRUCT    *hbf;
  1374.     CODE_RANGE    *cp;
  1375.     long        num_chars;
  1376.  
  1377.     hbf = (HBF_STRUCT *)hbfFile;
  1378.     num_chars = 0;
  1379.     for (cp = hbf->code_range; cp != NULL; cp = cp->code_next)
  1380.         num_chars +=
  1381.             hbf->b2_size*FirstByte(cp->code_finish) +
  1382.             b2_pos(hbf, cp->code_finish) -
  1383.             (hbf->b2_size*FirstByte(cp->code_start) +
  1384.             b2_pos(hbf, cp->code_start));
  1385.     return num_chars;
  1386. }
  1387.  
  1388. /*
  1389.  *    Functions also implemented as macros
  1390.  */
  1391.  
  1392. #ifdef hbfBitmapBBox
  1393. #undef hbfBitmapBBox
  1394. #endif
  1395.  
  1396. HBF_BBOX *
  1397. hbfBitmapBBox(hbf)
  1398.     HBF    *hbf;
  1399. {
  1400.     return &(hbf->hbf_bitmap_bbox);
  1401. }
  1402.  
  1403. #ifdef hbfFontBBox
  1404. #undef hbfFontBBox
  1405. #endif
  1406.  
  1407. HBF_BBOX *
  1408. hbfFontBBox(hbf)
  1409.     HBF    *hbf;
  1410. {
  1411.     return &(hbf->hbf_font_bbox);
  1412. }
  1413.  
  1414. const void *
  1415. hbfGetByte2Range(hbfFile, b2r_pointer, startp, finishp)
  1416.     HBF        *hbfFile;
  1417.     const void    *b2r_pointer;
  1418.     byte        *startp;
  1419.     byte        *finishp;
  1420. {
  1421.     HBF_STRUCT    *hbf;
  1422.     B2_RANGE    *b2r;
  1423.  
  1424.     hbf = (HBF_STRUCT *)hbfFile;
  1425.     if (b2r_pointer == NULL)
  1426.         b2r = hbf->byte_2_range;
  1427.     else
  1428.         b2r = ((B2_RANGE *)b2r_pointer)->b2r_next;
  1429.     if(b2r == NULL)
  1430.         return NULL;
  1431.     *startp = b2r->b2r_start;
  1432.     *finishp = b2r->b2r_finish;
  1433.     return (void *)b2r;
  1434. }
  1435.  
  1436. const void *
  1437. hbfGetCodeRange(hbfFile, code_pointer, startp, finishp)
  1438.     HBF        *hbfFile;
  1439.     const void    *code_pointer;
  1440.     HBF_CHAR    *startp;
  1441.     HBF_CHAR    *finishp;
  1442. {
  1443.     HBF_STRUCT    *hbf;
  1444.     CODE_RANGE    *cp;
  1445.  
  1446.     hbf = (HBF_STRUCT *)hbfFile;
  1447.     if (code_pointer == NULL)
  1448.         cp = hbf->code_range;
  1449.     else
  1450.         cp = ((CODE_RANGE *)code_pointer)->code_next;
  1451.     if(cp == NULL)
  1452.         return NULL;
  1453.     *startp = cp->code_start;
  1454.     *finishp = cp->code_finish;
  1455.     return (void *)cp;
  1456. }
  1457.