T168_111\appl\Text\Agfa:第7~11个文件

bmputl.txt   ///

/* Copyright (C) 2003 Agfa Monotype Corporation. All rights reserved. */

/* $Header:   I:/BULL/URIP/RTS/BMP/BMPUTL.C_V   1.21   Aug 21 2003 16:47:40   Galejs  $ */
/* $Log:   I:/BULL/URIP/RTS/BMP/BMPUTL.C_V  $ 
 * 
 *    Rev 1.21   Aug 21 2003 16:47:40   Galejs
 * update copyright notice
 * 
 *    Rev 1.20   Jul 21 2003 17:11:14   Galejs
 * reentrancy / debug fixes
 * 
 *    Rev 1.19   Jun 23 2003 13:44:56   Galejs
 * ufstport.h
 * 
 *    Rev 1.18   May 03 2001 19:08:10   Galejs
 * data-type cleanup
 * 
 *    Rev 1.17   Aug 10 1999 14:41:20   galejs
 * include-file changes
 * 
 *    Rev 1.16   29 Jul 1999 16:58:02   JOE
 * Changed DEBUG directive to AGFADEBUG (by ks).
 * 
 *    Rev 1.15   12 Jan 1999 18:12:52   GALEJS
 * move EXTERN dcls
 * 
 *    Rev 1.14   22 Jun 1998 18:48:04   GALEJS
 * make Intellifont reentrant too
 * 
 *    Rev 1.13   15 Apr 1998 16:52:34   GALEJS
 * move chr_def_hdr into IF_STATE
 * 
 *    Rev 1.12   24 Mar 1998 14:43:36   GALEJS
 * include-file changes
 * 
 *    Rev 1.11   28 Jan 1998 11:48:04   AL
 * Moved gaso_pn to if_state for re-entrant
 * 
 *    Rev 1.10   15 Apr 1997 15:04:08   MIKE
 * LINT_ARGS replaces LINTARGS
 * 
 *    Rev 1.9   13 Jan 1997 08:36:46   DAVID
 * Removed ELASTIC_X and ELASTIC_Y option as part of project to trim ufst.
 * 
 *    Rev 1.8   06 Apr 1995 15:08:24   LISA
 * Changed copyright from Miles Inc. to Bayer Corp.
 * 
 *    Rev 1.7   03 Jun 1994 08:46:24   JOE
 * In char_left_ref(), when calculating "orig_black_width", check if
 * character is a contourless character. If so, set to 0 rather than
 * using the "bound_box" data in the event that it is invalid.
 * 
 *    Rev 1.6   22 Apr 1994 09:20:48   LISA
 * Modified copyright/disclaimer notice.
 * 
 *    Rev 1.5   18 Apr 1994 08:17:16   JOE
 * Added comment in char_left_ref() describing fix for multi-part
 * characters with nonzero offset in first part.
 * 
 *    Rev 1.4   15 Apr 1994 16:23:14   JOE
 * 
 * Added new function char_left_ref().
 * Added arg to find_part2whole() function.
 * Made changes to fix floating accent problem.
 * 
 *    Rev 1.3   12 Feb 1993 11:04:22   JOE
 * VXWorks support.
 * 
 *    Rev 1.2   05 Jan 1993 15:58:18   JOE
 * ANSI C function declaration changes.
 * 
 *    Rev 1.1   14 Dec 1992 09:28:36   LISA
 * Made change to Log keyword
 * 
 *    Rev 1.0   10 Dec 1992 08:33:04   LISA
 * Initial revision.
*/
/* $Date:   Aug 21 2003 16:47:40  $ */
/* bmputl.c */

/* History                                                           */
/*    03-Oct-91 jfd  Removed #if TILE conditional around print_bm(). */
/*    10-Oct-91 rs   Modify 'translate_coords()' for bezier data &   */
/*                   Type 1 input.                                              */
/*    25-Oct-91 jfd  Instead of conditionally compiling entire file  */
/*                   based on CGBITMAP, conditionally compile based  */
/*                   on (CACHE || CHAR_SIZE || CHAR_HANDLE) to get   */
/*                   rid of link errors that occur if CGBITMAP is not*/
/*                   enabled.                                        */
/*    16-Jan-92 rs   Fix 'translate_coords() for PS type 1.          */
/*    23-Jan-92 awr  Removed translate_coords()                      */
/*    05-Feb-92 jfd  In print_bm(), changed format for x and y origins */
/*                   from "%d" to "%ld".                             */
/*    22-Mar-92 awr  Changed bitmap_dimensions() to take LONGs       */
/*                   Removed unused global tiling variables          */
/*    30-Mar-92 jfd  In bitmap_dimensions(), fixed DBG2 statement      */
/*                   to print "x" and "y" instead of "ur.x" and "ur.y" */
/*    03-Apr-92 rs   Portability cleanup (see port.h).                */
/*    04-Apr-92 awr  Changed calling sequence of find_part2whole()   */
/*    12-Apr-92 awr  Moved translation calcs from manipulate() to    */
/*                   make_gaso()                                     */
/*    18-Apr-92 awr  Removed clip_tile()                             */
/*     2-May-92 awr  Moved if_state.tt initialization from           */
/*                   manipualte() to make_gaso()                     */
/*    14-Jun-92 awr  Changed types of xlate and tbound to INTRs      */
/*    3-Jul-92  awr  Moved structs_are_equal() to comp_pix.c         */
/*                   Fixed test in make_gaso()... was big slow down  */
/*   11-Aug-92  jfd  Trying macro MDES2BM for optimization.          */
/*                   Included imath.h.                                          */
/*   16-Aug-92  rs   Fix nested comment.                                    */
/*   19-Aug-92  awr  In make_gaso(), only return prematurely if      */
/*                   processing a simple character.                  */
/*   15-Sep-92  jfd  Conditionally compile the following routines    */
/*                   based on IF_RDR:                                */
/*                   union_bound_boxes(), find_part2whole(),         */
/*                   make_gaso().                                    */
/*   16-Sep-92  jfd  Removed GLOBAL declarations for "entire_bm" and */
/*                   "entire_tt". They are now being declared GLOBAL */
/*                   in maker.c.                                     */
/*                   Changed declaration for "gaso_pn" from GLOBAL   */
/*                   to EXTERN. It is now declared GLOBAL in         */
/*                   comp_pix.                                       */
/*   15-Nov-92  rs   Port to Macintosh - use ANSI_DEFS on functions  */
/*   05-Jan-93  jfd  ANSI C function declaration changes             */
/*   08-Feb-93  jfd  VXWorks support.                                */
/*   13-Apr-94  awr  Added new function char_left_ref().             */
/*                   Added arg to find_part2whole() function.        */
/*                   Made changes to fixfloating accent problem.     */
/*   15-Apr-94  jfd  Added arg go char_left_ref() - y offset.        */
/*   27-May-94  jfd  In char_left_ref(), when calculating            */
/*                   "orig_black_width", check if character is a     */
/*                   contourless character. If so, set to 0 rather   */
/*                   than using the "bound_box" information in the   */
/*                   event that it is invalid.                       */
/*   13-Jan-97  dlk  Remover ELASTIC_X and ELASTIC_Y as part of pro-
 *                   ject to trim ufst.
 *   14-Apr-97  mby  Replaced "LINTARGS" with "LINT_ARGS".
 *   28-Jan-98  awr  moved gaso_pn to if_state for re-entrant
 *   28-July-99 ks   Changed DEBUG compiler directive to AGFADEBUG. 
 *-------------------------------------------------------------------*/


#ifdef VXWORKS
#include "vxWorks.h"
#endif

#include <stdio.h>

#include "cgconfig.h"
#include "ufstport.h"
#include "dbg_ufst.h"

#include "shareinc.h"

#include "imath.h"


#if IF_RDR
/*----------------------*/
/*      make_gaso       */
/*----------------------*/
/*  Make a Grid aligned, Scaled Outline. Keep track of the current
 *  gaso and don't remake if not necessary.
 */

#if defined (ANSI_DEFS)
GLOBAL UW16  make_gaso(FSP SL32 pn, PCHR_DEF cd)
#else
GLOBAL UW16
make_gaso(pn, cd)
    SL32 pn;
    PCHR_DEF    cd;
#endif
{
    UW16 status;

    DBG("make_gaso()\n");

    if(pn == if_state.gaso_pn && pn == 0)  /* 8-19-92 */
        return SUCCESS;


    if_state.gaso_pn = -1;   /* make invalid in case we fail */

    status = DArd_char(FSA cd);
    if (status)
        return status;

  /*  Set translation for scaling to working fop space. Resulting outline
   *  can end up in any quadrant
   */

    if_state.tt.x = if_state.tt.y = 0;

    status = intel_char(FSA0);
    if (status)
       return status;

  /*  Compute the translation
   *  from working space to working bitmap space for cc base.
   */

#if INTR_SIZE == 16
    DBG4("work buffer bounds:  (%d, %d)   (%d, %d)\n",
                                        if_state.tbound.ll.x,
                                        if_state.tbound.ll.y,
                                        if_state.tbound.ur.x,
                                        if_state.tbound.ur.y);
#else
    DBG4("work buffer bounds:  (%ld, %ld)   (%ld, %ld)\n",
                                        if_state.tbound.ll.x,
                                        if_state.tbound.ll.y,
                                        if_state.tbound.ur.x,
                                        if_state.tbound.ur.y);
#endif

  /*  NOTE: the grid alignment is correct whether x_min and y_min
   *  are positive or negative becase "&" always truncates to the left.
   *  The reason for rounding the two different ways is that after
   *  translating by tt, we want
   *      XFLOOR  (tt.x + tbound.ll.x + x.half_pixel) = 0
   *      YCEILING(tt.y + tbound.ll.y + y.half_pixel) = 1
   *
   *  This requires that:
   *
   *      -x.half_pixel <= tt.x + tbound.ll.x <  x.half_pixel
   *      -y.half_pixel <  tt.y + tbound.ll.y <= y.half_pixel
   */

    if_state.xlate.x =   -((if_state.tbound.ll.x + if_state.x.half_pixel)
                                      & if_state.x.grid_align);
    if_state.xlate.y =   ((-if_state.tbound.ll.y + if_state.y.half_pixel)
                                      & if_state.y.grid_align);

  /*  Compute working bitmap bounding box: assumes we will
   *  translate by if_state.tt
   */

    if_state.tbound.ll.x += if_state.xlate.x;
    if_state.tbound.ll.y += if_state.xlate.y;
    if_state.tbound.ur.x += if_state.xlate.x;
    if_state.tbound.ur.y += if_state.xlate.y;

  /* tt must by SW16 and is used for Intellifont translation before
   * resolution is increased to INTR
   */
    if_state.tt.x = (SW16)if_state.xlate.x;
    if_state.tt.y = (SW16)if_state.xlate.y;
    DBG2("    if_state.tt.x = %d   if_state.tt.y = %d\n",
                    if_state.tt.x, if_state.tt.y);

    if_state.tbound.ll.y += (INTR)if_state.y.half_pixel;
    if_state.tbound.ur.y += (INTR)if_state.y.half_pixel;

#if INTR_SIZE == 16
    DBG4(" bm fops bounding box (%d,%d)   (%d,%d)\n\n",
                                                    if_state.tbound.ll.x,
                                                    if_state.tbound.ll.y,
                                                    if_state.tbound.ur.x,
                                                    if_state.tbound.ur.y);
#else
    DBG4(" bm fops bounding box (%ld,%ld)   (%ld,%ld)\n\n",
                                                    if_state.tbound.ll.x,
                                                    if_state.tbound.ll.y,
                                                    if_state.tbound.ur.x,
                                                    if_state.tbound.ur.y);
#endif

    if_state.gaso_pn = pn;    /* current grid aligned scaled outline */
    return SUCCESS;
}


/*----------------------*/
/*   union_bound_boxes  */
/*----------------------*/
/*  Translate the src bounding box by (dx, dy) and then merge it
 *  with the destination bounding box. Return result in the
 *  destination bounding box.
 */
#if defined (ANSI_DEFS)
GLOBAL VOID union_bound_boxes(PBOX dst, PBOX src, SW16 dx, SW16 dy)
#else
GLOBAL VOID
union_bound_boxes(dst, src, dx, dy)
    PBOX dst, src;
    SW16 dx, dy;
#endif /* ANSI_DEFS */
{
    dst->ll.x = MIN(dst->ll.x, dx + src->ll.x);
    dst->ll.y = MIN(dst->ll.y, dy + src->ll.y);
    dst->ur.x = MAX(dst->ur.x, dx + src->ur.x);
    dst->ur.y = MAX(dst->ur.y, dy + src->ur.y);
}

/*----------------------*/
/* bitmap_dimensions    */
/*----------------------*/
/*
Calculate the width and depth of a bit map in (bytes x pixels)
given the upper right corner in fops. The lower left corner is
assumed to be (1,1) in fops.


    The "final" outline that is rasterized is still in "fops"- fractional
    output pixels. The outline has been translated so as to be close to the
    the axis of the first quadrant. It is then translated 1/2 pixel up
    to make protect againts "widows" and "flats" in curves. The result
    of all of this is that if SW16DVECTOR ll is the lower left corner of
    the resulting fop bounding box, then

            -0.5 pixel <= ll.x <  0.5 pixel
               0       <  ll.y <= 1


    The width calculated is the resulting black width. The charcter
    transition array will be one bit wider to include the rightmost
    off transition.

*/

/*----------------------*/
/*    chr_left_ref      */
/*----------------------*/
/*  This function may only be called for quadrant rotations.
 *  Returned value is not really a box, but two vectors.  The vector ll of
 *  of the box is the new location in design space of the left reference
 *  baseline.  This new location takes into account chages in black width
 *  that cause the left side bearing to change.  It is calculated off the
 *  inverse image of the bitmap so that des2bm() maps it to it's bitmap
 *  location in the bitmap.
 *
 *  The vector ur is the vector from this new origin in design space to the
 *  pre-image in design space of the lower left pixel of the bitmap.
 */
#if defined (ANSI_DEFS)
GLOBAL BOX char_left_ref(FSP SW16VECTOR org, BOX pixBound, SW16 yoff)
#else
GLOBAL BOX char_left_ref(org, pixBound, yoff)
    SW16VECTOR org;
    BOX pixBound;
    SW16 yoff;
#endif
{
    BOX retVal;
    SW16VECTOR prell, preur, dll, dur;
    SW16 orig_lsb, new_lsb;
    SW16VECTOR new_org;    /* character origin (design units)        */

    DBG("char_left_ref()\n");
    DBG2("org %d %d\n", org.x, org.y);
    DBG2("pixBound %d %d\n", pixBound.ll.x, pixBound.ll.y);
    DBG2("          %d %d\n", pixBound.ur.x, pixBound.ur.y);

    pixBound.ur.x <<= log_xpix; 
    pixBound.ur.y <<= log_ypix; 
    /*  assume pixBound.ll is (0,0) */

    prell = inv_des2bm(FSA pixBound.ll);
    preur = inv_des2bm(FSA pixBound.ur);
    DBG2("prell %d %d\n", prell.x, prell.y);
    DBG2("preur %d %d\n", preur.x, preur.y);

    if(prell.x < preur.x)
    {
        dll.x = prell.x;
        dur.x = preur.x;
    }
    else
    {
        dll.x = preur.x;
        dur.x = prell.x;
    }
    if(prell.y < preur.y)
    {
        dll.y = prell.y;
        dur.y = preur.y;
    }
    else
    {
        dll.y = preur.y;
        dur.y = prell.y;
    }

    DBG2("dll = (%d, %d)\n", dll.x, dll.y);
    DBG2("dur = (%d, %d)\n", dur.x, dur.y);

    orig_lsb = if_state.bound_box.ll.x - org.x;

    if(if_state.ConnectingChar)
    {
        pixel_align (FSAvoid org.x, &if_state.x, R_TWO_I);
        new_lsb = dll.x - if_state.value;
        DBG("     ConnectingChar:\n");
        DBG2("    orig_lsb %d    new_lsb %d\n", orig_lsb, new_lsb);
    }
    else
    {
        SW16 orig_black_width, new_black_width;

        if (if_state.num_loops)
           orig_black_width = if_state.bound_box.ur.x
                            - if_state.bound_box.ll.x;
        else
           orig_black_width = 0;

        new_black_width  = dur.x - dll.x;

        new_lsb = orig_lsb + (orig_black_width - new_black_width)/2;
        DBG2("    orig_lsb %d    new_lsb %d\n", orig_lsb, new_lsb);
    }

    new_org.x = dll.x - new_lsb;
    new_org.y = if_state.aBaselnVal;

    /*  Fix for one part compound char with nonzero offset.           */
    /*  There may still be a bug for multiple part chars with nonzero */
    /*  offset in first part.                        -ss,bjg 7/23/91  */
    /*  Using "yoff" to adjust new_org should fix bug for multipart   */
    /*  characters with nonzero offset in first part.   -jfd 4/15/94  */      
/*
    if( if_state.chr_def->offset.y )
       new_org.y -= if_state.chr_def->offset.y;
*/
    new_org.y -= yoff;


    DBG2("new_org = (%d, %d)\n", new_org.x, new_org.y);

    retVal.ll = new_org;

    retVal.ur.x = prell.x - new_org.x;
    retVal.ur.y = prell.y - new_org.y;

    DBG2("retVal %d %d\n", retVal.ll.x, retVal.ll.y);
    DBG2("       %d %d\n", retVal.ur.x, retVal.ur.y);

    return retVal;
}
/*----------------------*/
/*   find_part2whole    */
/*----------------------*/
/* calculate pixel address in destination bitmap of pixel
 * origin (0,0) in compound part bitmap
 */
#if defined (ANSI_DEFS)
GLOBAL SW16VECTOR find_part2whole(FSP SW16VECTOR wholeOrg,
                                          SW16VECTOR tt, PCHR_DEF cd)
#else
GLOBAL SW16VECTOR
find_part2whole(wholeOrg, tt, cd)
    SW16VECTOR wholeOrg;
    SW16VECTOR tt;       /* translation for part  */
    PCHR_DEF   cd;
#endif
{
    SW16VECTOR ctt;       /* translation for part  */
    SW16VECTOR des_tran;
    SW16VECTOR p2w;

    DBG("find_part2whole()\n");
    DBG2("wholeOrg %d %d\n", wholeOrg.x, wholeOrg.y);
    DBG2("pix_bound %d %d\n", cd->pix_bound.ll.x, cd->pix_bound.ll.y);
    DBG2("          %d %d\n", cd->pix_bound.ur.x, cd->pix_bound.ur.y);

  /* des_tran = design unit translation to move compound part so
   * in design space so that it is positioned correctly with respect
   * to the other parts.
   */
    if(!if_state.quadrant)  /* arbitrary rotation */
    {
    des_tran.x = if_state.chr_def_hdr.origin.x-(if_state.escape_box.ll.x - cd->offset.x);
    des_tran.y = if_state.chr_def_hdr.origin.y-(if_state.escape_box.ll.y - cd->offset.y);
        ctt = if_state.tt;       /* save translation of part */
    }
    else
    {
        BOX foo;
        foo = char_left_ref(FSA if_state.escape_box.ll, cd->pix_bound, (SW16)0);
        des_tran.x = wholeOrg.x + cd->offset.x + foo.ur.x;
        des_tran.y = wholeOrg.y + cd->offset.y + foo.ur.y;
        ctt.x = ctt.y = 0;
    }
    DBG2("des_tran = %d %d\n", des_tran.x, des_tran.y);


  /*  Must grid align des_tran. */

    pixel_align (FSAvoid des_tran.x, &if_state.x, R_TWO_I);
    des_tran.x = if_state.value;
    pixel_align (FSAvoid des_tran.y, &if_state.y, R_TWO_I);
    des_tran.y = if_state.value;
    DBG2("grid aligned des_tran = %d %d\n", des_tran.x, des_tran.y);

    if_state.tt = tt;        /* restore translation for whole */
#if defined MDES2BM
    p2w = MDES2BM(des_tran);  /* part to whole translate */
#else
    p2w = des2bm(FSA des_tran);  /* part to whole translate */
#endif /* defined MDES2BM */
    p2w.x -= ctt.x;
    p2w.y -= ctt.y;
    DBG2("p2w in fops = %d %d\n", p2w.x, p2w.y);

    p2w.x = XFLOOR(p2w.x);
    p2w.y = YFLOOR(p2w.y);
    DBG2("p2w in pixels = %d %d\n", p2w.x, p2w.y);

    return p2w;
}
#endif  /* IF_RDR */


#ifdef AGFADEBUG
#if defined (ANSI_DEFS)
GLOBAL VOID  print_bm(FSP PIFBITMAP bm)
#else
GLOBAL VOID
print_bm(bm)
    PIFBITMAP bm;
#endif
{
    DBG3("    width(bytes) x depth:     %d x %d = %ld bytes\n",
                 bm->width, bm->depth, (SL32)bm->width * (SL32)bm->depth);
    DBG2("    left_indent, top_indent   %d %d\n", bm->left_indent,
                                                  bm->top_indent);
    DBG2("    black_width, black_depth  %d %d\n", bm->black_width,
                                                  bm->black_depth);
    DBG2("    xorigin, yorigin          %ld %ld\n", bm->xorigin,
                                                    bm->yorigin);
}
#endif    /* AGFADEBUG */

bold.txt   

/* Copyright (C) 2003 Agfa Monotype Corporation. All rights reserved. */

/* $Header:   I:/BULL/URIP/RTS/COR/BOLD.C_V   1.15   Aug 21 2003 17:03:30   Galejs  $ */
/* $Log:   I:/BULL/URIP/RTS/COR/BOLD.C_V  $ 
 * 
 *    Rev 1.15   Aug 21 2003 17:03:30   Galejs
 * update copyright notice
 * 
 *    Rev 1.14   Jul 21 2003 17:24:42   Galejs
 * reentrancy / debug fixes
 * 
 *    Rev 1.13   Jun 19 2003 18:35:48   Galejs
 * get rid of TEST_INTERSECT option
 * 
 *    Rev 1.12   Aug 13 1999 14:36:58   galejs
 * include-file changes; MSDOS becomes UFST_MSDOS
 * 
 *    Rev 1.11   22 Jun 1998 18:56:28   GALEJS
 * make Intellifont reentrant too
 * 
 *    Rev 1.10   15 Jun 1998 16:04:30   GALEJS
 * include-file changes
 * 
 *    Rev 1.9   15 Apr 1998 18:01:34   GALEJS
 * dup_points[] in IF_STATE now
 * 
 *    Rev 1.8   02 Apr 1998 19:11:16   GALEJS
 * move externs to if_state
 * 
 *    Rev 1.7   24 Mar 1998 15:10:24   GALEJS
 * include-file changes
 * 
 *    Rev 1.6   06 Apr 1995 15:10:50   LISA
 * Changed copyright from Miles Inc. to Bayer Corp.
 * 
 *    Rev 1.5   22 Apr 1994 09:27:54   LISA
 * Modified copyright/disclaimer notice for 1994.
 * 
 *    Rev 1.4   08 Dec 1993 18:59:42   ROB
 * No change.
 * 
 *    Rev 1.3   12 Feb 1993 11:28:10   JOE
 * VXWorks support.
 * 
 *    Rev 1.2   07 Jan 1993 10:47:36   JOE
 * ANSI C function declaration changes.
 * 
 *    Rev 1.1   14 Dec 1992 09:37:06   LISA
 * Made change to Log keyword
 * 
 *    Rev 1.0   10 Dec 1992 08:37:14   LISA
 * Initial revision.
*/
/* $Date:   Aug 21 2003 17:03:30  $ */
/* bold.c */
/*
 *
 *
 * History
 *
 *  28-Jul-90 awr  created
 *  12-Oct-90 tbh  In bold(), computing point of intersection "dp->x",
 *                 "dp->y" differently in the event that both X and Y
 *                 skeletal data do not exist for a duplicate point.
 *  15-Oct-90 awr  In intersect(), check that intersection point does
 *                 not exceed bounding box
 *  30-Jan-91 dET  added function prototyping for MSC.
 *  31-Jan-91 dET  Modify for MSC multi-model compilation.
 *   3-Feb-91 awr  Removed nx(), ny() function declarations,
 *                 updated copyright.
 *                 Changed initialization call from np_init_char() to
 *                 init_xy_tran().
 *   5-Feb-91 awr  Conditionally compiled whole module on BOLD.
 *                 Added #include "cgconfig.h"
 *   8-Feb-91 awr  Removed EXTERN x_skel[] and y_skel[] and made
 *                 parameters of bold().
 *   6-Apr-91 awr  Changed intersect calculations to floating point
 *                 Removed long math code to lmath.c.
 *   8-Apr-91 jfd  In intersect(), call printf() only if MSC.
 *   1-Jun-91 awr  HQ4 changes
 *  17-Jun-91 jfd  Moved "debug.h" after "port.h".
 *                 Moved "profile.h" after "port.h".
 *  24-Aug-91 awr  Moved function decls to include file
 *  19 Sep 91 ss   Added casts for compare to -1 to eliminate warnings on SUN.
 *  03-Apr-92 rs   Portability cleanup (see port.h).
 *  16-Aug-92 rs   Change define from MSC to MSDOS.
 *                       Fix use of '-1' for UB8 & UW16.
 *  15-Sep-92 jfd  Conditionally entire module based on IF_RDR.
 *  14-Nov-92 rs   Port to Mac - ANSI function definitions using ANSI_DEFS,
 *                 rename bold() to cgbold().
 *  07-Jan-93 jfd  ANSI C function declaration changes.
 *  08-Feb-93 jfd  VXWorks support.
 *    15-Apr-98 slg  Move dup_points[] into IF_STATE.
 */
/*-------------------------------------------------------------*/
/*                  b o l d     i n t e r s e c t              */


#include "cgconfig.h"

#if IF_RDR
#if BOLD   /* whole module is conditionally compiled on BOLD */

#ifdef VXWORKS
#include "vxWorks.h"
#endif

#include <stdio.h>

#include "ufstport.h"
#include "dbg_ufst.h"

#include "shareinc.h"

#include "imath.h"
#include "adj_skel.h"


#ifdef LINT_ARGS
MLOCAL BOOLEAN no_intersect(FSP PDUP_POINTS);
MLOCAL BOOLEAN intersect(FSP SW16,SW16,SW16,SW16,SW16,SW16,SW16,SW16,PDUP_POINTS);
MLOCAL VOID set_tran(FSP PTRAN, UW16, UW16);
MLOCAL VOID find_in_scale_seg(FSP UW16, LPUW16, PTRAN, LPUB8, LPUB8);
MLOCAL VOID find_out_scale_seg(FSP UW16,LPUW16, PTRAN, LPUB8, LPUB8);
#endif /* LINT_ARGS */

#if defined (ANSI_DEFS)
MLOCAL BOOLEAN no_intersect(FSP PDUP_POINTS dp)
#else
MLOCAL BOOLEAN
no_intersect(dp)
    PDUP_POINTS  dp;
#endif
{
    DBG("    lines do not intersect\n");

    dp->xsk0 = 255;
    dp->xsk1 = 255;
    dp->ysk0 = 255;
    dp->ysk1 = 255;

    return FALSE;    /* lines don't intersect */
}

#if defined (ANSI_DEFS)
MLOCAL BOOLEAN intersect(FSP SW16 xi0, SW16 yi0, SW16 xi1, SW16 yi1, 
        SW16 xo0, SW16 yo0, SW16 xo1, SW16 yo1, PDUP_POINTS dp)
#else
MLOCAL BOOLEAN
intersect(xi0, yi0, xi1, yi1, xo0, yo0, xo1, yo1, dp)
    SW16 xi0, yi0, xi1, yi1, xo0, yo0, xo1, yo1;
    PDUP_POINTS  dp;
#endif /* ANSI_DEFS */
{
    FPNUM a0, b0, c0, a1, b1, c1;
    FPNUM det;

    FPNUM x_det, y_det;
    SW16  x, y;

    DBG("intersect()\n");
    DBG4("    (%d, %d)  (%d, %d)\n", xi0, yi0, xi1, yi1);
    DBG4("    (%d, %d)  (%d, %d)\n", xo0, yo0, xo1, yo1);

  /*  For the two lines, determine equations of the form:
   *
   *        a0*x + b0*y = c0
   *        a1*x + b1*y = c1
   */
    if_state.fpmath_error = 0;

    a0 = fpint2fp((SL32)(yi1 - yi0));
    b0 = fpint2fp((SL32)(xi0 - xi1));
    c0 = fpint2fp((SL32)xi0*(SL32)yi1 - (SL32)yi0*(SL32)xi1);

    a1 = fpint2fp((SL32)(yo1 - yo0));
    b1 = fpint2fp((SL32)(xo0 - xo1));
    c1 = fpint2fp((SL32)xo0*(SL32)yo1 - (SL32)yo0*(SL32)xo1);

    /*  Solve equations using determinants */

    det = fpsub(fpmul(a0, b1), fpmul(a1, b0));

    if(fpiszero(det))
        return no_intersect(FSA dp);

    x_det = fpsub(fpmul(c0, b1), fpmul(c1, b0));    /* c0*b1 - c1*b0 */
    y_det = fpsub(fpmul(a0, c1), fpmul(a1, c0));    /* a0*c1 - a1*c0 */

    x = fp2word(fpdiv(x_det, det));
    y = fp2word(fpdiv(y_det, det));

    /* Check that we do not exceed bounding box   (10-15-90 awr) */

    if(if_state.fpmath_error || (x < if_state.bound_box.ll.x)
                    || (if_state.bound_box.ur.x < x)
                    || (y < if_state.bound_box.ll.y)
                    || (if_state.bound_box.ur.y < y))
        return no_intersect(FSA dp);

    dp->x = x;
    dp->y = y;

    DBG2("    intersection (%d, %d)\n", dp->x, dp->y);

    return TRUE;
}

#if defined (ANSI_DEFS)
MLOCAL VOID set_tran (FSP PTRAN td, UW16 first_skel_ind, UW16 last_skel_ind)
#else
MLOCAL VOID
set_tran(td, first_skel_ind, last_skel_ind)
    PTRAN td;
    UW16  first_skel_ind, last_skel_ind;
#endif /* ANSI_DEFS */
{
    PADJUSTED_SKEL skel0, skel1;

    skel0 = td->skel + td->sct + first_skel_ind;
    skel1 = td->skel + td->sct + last_skel_ind;

    td->new0 = skel0->adjusted;
    td->new1 = skel1->adjusted;
    td->num  = td->new1 - td->new0;

    td->old0 = skel0->original;
    td->old1 = skel1->original;
    td->den  =  td->old1 - td->old0;
    if(!td->den) td->num = td->den = 1;
    td->half_den = td->den / 2;

    DBG2("new0  %d   new1  %d\n", td->new0, td->new1);
    DBG2("old0  %d   old1  %d\n", td->old0, td->old1);
    DBG2("num %d  den %d\n\n\n",td->num,td->den);
}

/* 10-12-90 tbh  Added argument "pskelMinus1" to find_in_scale_seg() */

#if defined (ANSI_DEFS)
MLOCAL VOID find_in_scale_seg(FSP UW16 coord_index, LPUW16 s2c_base, PTRAN td, 
                   LPUB8 pskel, LPUB8 pskelMinus1)
#else
MLOCAL VOID
find_in_scale_seg(coord_index, s2c_base, td, pskel, pskelMinus1)
    UW16   coord_index;
    LPUW16  s2c_base;
    PTRAN   td;                       /* ptr to x or y transform data  */
    LPUB8  pskel, pskelMinus1;       /* 10-12-90 tbh */
#endif /* ANSI_DEFS */
{
    UW16 i;
    LPUW16 p;
    UW16  first_skel_ind, last_skel_ind;

    DBG1("find_in_scale_seg(%u)\n", coord_index);
    DBG1("    nsk = %u\n", td->nsk);

    for(i=0, p=s2c_base + td->sct; i<td->nsk; i++, p++)
    {
        DBG1("    %u\n", *p);
        if(*p >= coord_index)
        {
            DBG("      found it\n");
            break;
        }
    }
    if(i==0 || i==td->nsk)  /* scale seg = last skel to first skel */
    {
        first_skel_ind = td->nsk - 1;
        last_skel_ind  = 0;
    }
    else
    {
        first_skel_ind = i - 1;
        last_skel_ind = i;
    }
    DBG2("    first_skel_ind %u    last_skel_ind %u\n",
                                 first_skel_ind, last_skel_ind);

    *pskel = 0xff; /* -1 */    /* 255 */
    *pskelMinus1 = (UB8)(td->sct + first_skel_ind);  /* 10-12-90 tbh */
    if(i<td->nsk)
        if(*p == coord_index)
            *pskel = (UB8)(td->sct + last_skel_ind);

    set_tran(FSA td, first_skel_ind, last_skel_ind);
}

/* 10-12-90 tbh  Added argument "pskelPlus1" to find_out_scale_seg() */

#if defined (ANSI_DEFS)
MLOCAL VOID find_out_scale_seg(FSP UW16 coord_index, LPUW16 s2c_base, PTRAN td, 
            LPUB8 pskel, LPUB8 pskelPlus1)
#else
MLOCAL VOID
find_out_scale_seg(coord_index, s2c_base, td, pskel, pskelPlus1)
    UW16   coord_index;
    LPUW16  s2c_base;
    PTRAN   td;                       /* ptr to x or y transform data  */
    LPUB8  pskel, pskelPlus1;        /* 10-12-90 tbh */
#endif /* ANSI_DEFS */
{
    UW16  i;
    LPUW16 p;
    UW16  first_skel_ind, last_skel_ind;

    DBG1("find_out_scale_seg(%u)\n", coord_index);
    DBG1("    nsk = %u\n", td->nsk);

    i=td->nsk-1;
    for(p=s2c_base + td->sct + i; i>0; i--, p--)
    {
        DBG1("    %u\n", *p);
        if(*p <= coord_index)
        {
            DBG("      found it\n");
            break;
        }
    }
    if(i==(UW16)-1 || i==td->nsk-1)  /* scale seg = last skel to first skel */
    {
        first_skel_ind = td->nsk - 1;
        last_skel_ind  = 0;
    }
    else
    {
        first_skel_ind = i;
        last_skel_ind = i + 1;
    }
    DBG2("    first_skel_ind %u    last_skel_ind %u\n",
                                 first_skel_ind, last_skel_ind);

    *pskel = 0xff; /* -1 */   /* 255 */
    *pskelPlus1 = (UB8)(td->sct + last_skel_ind);  /* 10-12-90 tbh */
    if(i != (UW16)(-1)) /* should this be '!= (UW16)(-1)' ?? was '>=0' */
        if(*p == coord_index)
            *pskel = (UB8)(td->sct + first_skel_ind);

    set_tran(FSA td, first_skel_ind, last_skel_ind);
}

#if defined (ANSI_DEFS)
GLOBAL VOID cgbold(FSP PADJUSTED_SKEL x_skel, PADJUSTED_SKEL y_skel)
#else
GLOBAL VOID
cgbold(x_skel, y_skel)
    PADJUSTED_SKEL x_skel, y_skel;
#endif /* ANSI_DEFS */
{
    PDUP_POINTS dp;
    LOOP    loop;         /* current loop */
    UW16   loopct;
    UW16   id;           /* coordinate index of duplicate point in loop */
    UW16   ncoords;
    LPUW16  x_s2c_base;
    LPUW16  y_s2c_base;
    UW16   k;
    UB8   xskPlus1, yskPlus1, xskMinus1, yskMinus1;  /* 10-12-90 tbh */

    SW16VECTOR i0, i1, o0, o1;


    DBG("bold()\n");

  /* Initialize */

    dp = if_state.dup_points;
    init_xy_tran(FSA x_skel, y_skel); /* initialize for skeletal interpolation */
    if_state.x_tran.sct = 0;
    if_state.y_tran.sct = 0;

    x_s2c_base = if_state.xskel.skel_to_contr;
    y_s2c_base = if_state.yskel.skel_to_contr;

    DBG1("    number of loops = %d\n", if_state.num_loops);

    first_loop(FSA0);
    for(loopct = 0; loopct < if_state.num_loops; loopct++)
    {
        if(dp->loop == (UW16)-1) break;

        DBG("\n\n\nN e x t    L o o p\n");

        if_state.x_tran.nsk = *(if_state.x_tran.num_skel_loop++);
        if_state.y_tran.nsk = *(if_state.y_tran.num_skel_loop++);

        next_loop(FSA &loop);
        ncoords = loop.ncoords;

        while(dp->loop == loopct)
        {
          /* set id = index of first duplicate point */

            id = dp->coord_index;      /* index of second duplicate point */
            if(id == 0)
                id =  ncoords - 1;  /* index of point just before */
            else
                id--;

          /* find incoming scaling segment */

            find_in_scale_seg(FSA id, x_s2c_base, &if_state.x_tran, &dp->xsk0, &xskMinus1);  /* 10-12-90 tbh */
            find_in_scale_seg(FSA id, y_s2c_base, &if_state.y_tran, &dp->ysk0, &yskMinus1);  /* 10-12-90 tbh */

          /* compute incoming line segment */

            if(id == 0)
                k = ncoords - 1;
            else
                k = id - 1;

            i0  = *(loop.cv + k);         /* coordinate points */
            i1  = *(loop.cv + id);

            DBG4("    in  old: (%d, %d) (%d, %d)\n", i0.x, i0.y, i1.x, i1.y);

            i0  = nxy(FSA i0);
            i1  = nxy(FSA i1);

            DBG4("    in  new: (%d, %d) (%d, %d)\n", i0.x, i0.y, i1.x, i1.y);

          /* find outgoing scaling segment */

            id = dp->coord_index;     /* index of second duplicate point */

            find_out_scale_seg(FSA id, x_s2c_base, &if_state.x_tran, &dp->xsk1, &xskPlus1); /* 10-12-90 tbh */
            find_out_scale_seg(FSA id, y_s2c_base, &if_state.y_tran, &dp->ysk1, &yskPlus1); /* 10-12-90 tbh */

          /* 10-12-90 tbh  The following code was added */
        
            if ( ( (dp->xsk0 == 255)  /* if no x-skel at this duplicate . .   */
                        && 
                   (dp->xsk1 == 255) 
                 )                    /* and contour is not horizontal . .    */
                 &&                
                 ( ((y_skel+dp->ysk1)->original != (y_skel+yskPlus1)->original) 
                        || 
                   ((y_skel+dp->ysk1)->original != (y_skel+yskMinus1)->original) 
                 )
               )
            {
                if      (dp->ysk0 == 255) dp->y = (y_skel+dp->ysk1)->adjusted;
                else if (dp->ysk1 == 255) dp->y = (y_skel+dp->ysk0)->adjusted;
                else    dp->y = ((y_skel+dp->ysk1)->adjusted + (y_skel+dp->ysk0)->adjusted + 1) >> 1;
            }

            else if
               ( ( (dp->ysk0 == 255)  /* if no y-skel at this duplicate . .   */
                        && 
                   (dp->ysk1 == 255) 
                 )                    /* and contour is not vertical . .      */
                 && 
                 ( ((x_skel+dp->xsk1)->original != (x_skel+xskPlus1)->original) 
                        || 
                   ((x_skel+dp->xsk1)->original != (x_skel+xskMinus1)->original) 
                 )
               )
            {
                if      (dp->xsk0 == 255) dp->x = (x_skel+dp->xsk1)->adjusted;
                else if (dp->xsk1 == 255) dp->x = (x_skel+dp->xsk0)->adjusted;
                else    dp->x = ((x_skel+dp->xsk1)->adjusted + (x_skel+dp->xsk0)->adjusted + 1) >> 1;
            }

            else
            {
                /* compute outgoing line segment */
     
                k = id + 1;
                if(k == ncoords)
                    k = 0;
     
                o0  = *(loop.cv + k);         /* coordinate points */
                o1  = *(loop.cv + id);
     
                 DBG4("    out old: (%d, %d) (%d, %d)\n",
                                                o0.x, o0.y, o1.x, o1.y);
     
                o0  = nxy(FSA o0);
                o1  = nxy(FSA o1);
     
                DBG4("    out new: (%d, %d) (%d, %d)\n",
                                                o0.x, o0.y, o1.x, o1.y);
      
                /* compute intersection of incomming and outgoing line segments */
     
                intersect(FSA i0.x, i0.y, i1.x, i1.y, o0.x, o0.y, o1.x, o1.y, dp);
            }
     
          /* move to next duplicate point */

            dp++;

        } /*  while(dp->loop == loopct) */

        if_state.x_tran.sct += if_state.x_tran.nsk;
        if_state.y_tran.sct += if_state.y_tran.nsk;

    } /* end of character */

  /*  Change skeletal points  */

    for(dp = if_state.dup_points; dp->loop != (UW16)-1; dp++)
    {
        if(dp->xsk0 != 255) (x_skel+dp->xsk0)->adjusted = dp->x;
        if(dp->xsk1 != 255) (x_skel+dp->xsk1)->adjusted = dp->x;
        if(dp->ysk0 != 255) (y_skel+dp->ysk0)->adjusted = dp->y;
        if(dp->ysk1 != 255) (y_skel+dp->ysk1)->adjusted = dp->y;
    }
}
#endif  /* BOLD */
#endif  /* IF_RDR */

 

bucket.c    //

/* 
 * Copyright (C) 2005 Monotype Imaging Inc. All rights reserved.
 */

/* $Header:   I:/BULL/URIP/RTS/DA/BUCKET.C_V   1.141   Dec 14 2004 14:17:46   galejss  $ */
/* $Log:   I:/BULL/URIP/RTS/DA/BUCKET.C_V  $ 
 * 
 *    Rev 1.141   Dec 14 2004 14:17:46   galejss
 * make all DBG calls 16-bit-compatible
 * 
 *    Rev 1.140   Nov 29 2004 17:36:56   jardima
 * added code for the memory fund check
 * 
 *    Rev 1.139   Nov 08 2004 14:37:38   DugganJ
 * Corrected printf() call in print_bucket_status().
 * 
 * 
 *    Rev 1.138   Oct 26 2004 11:23:10   dugganj
 * Multithread changes.
 * 
 *    Rev 1.137   Sep 27 2004 16:27:44   dugganj
 * Added multithread support.
 * 
 *    Rev 1.136   Aug 10 2004 16:48:40   galejss
 * changes for runtime no-symset-mapping option
 * 
 *    Rev 1.135   Jul 16 2004 17:42:58   galejss
 * changes for IF disk/rom support; copy ttc_index field only if current font is TT
 * 
 *    Rev 1.134   Jun 04 2004 16:18:56   GalejsS
 * change type of "pathname" to FILECHAR (fix compiler warnings)
 * 
 *    Rev 1.133   Nov 10 2003 13:41:16   Joe
 * In BUCKfree(), calling MEMSET to reset "if_state.cur_loc_fc" whenever a
 * bucket is freed.
 * 
 *    Rev 1.132   Oct 17 2003 16:53:40   Galejs
 * remove obsolete MEM_DUMP_INT code; compile fixes for PRINT_BUCKETS option
 * 
 *    Rev 1.131   Aug 26 2003 10:28:34   Joe
 * In BUCKfind(), added fix for unbound pcleos.
 * 
 *    Rev 1.130   Aug 22 2003 08:52:46   LynchR
 * Updated coppyright notice.
 * 
 *    Rev 1.129   Aug 21 2003 13:58:18   IndrelR
 * Added feature for processing XL bitmaps.
 * 
 *    Rev 1.128   Aug 20 2003 11:25:40   IndrelR
 *    Rev 1.127   Aug 08 2003 17:14:26   Galejs
 * fix link error for FIpath with DISKROM utility
 * 
 *    Rev 1.126   Jul 28 2003 17:22:12   Galejs
 * add new all-FSTs no-plugins option; extend IXopen_file to PST1 as well
 * 
 *    Rev 1.125   Jul 07 2003 11:47:02   Galejs
 * DYNAMIC_FONTS option is only relevant if IF_RDR
 * 
 *    Rev 1.124   Jun 19 2003 18:37:56   Galejs
 * clean up debugging options
 * 
 *    Rev 1.123   Dec 02 2002 11:14:58   Galejs
 * BUCKfree() needs to be global now, not static
 * 
 *    Rev 1.122   Nov 26 2002 17:59:04   Galejs
 * fix uninit-vbl compiler warning; conditional include of unistd.h
 * 
 *    Rev 1.121   Oct 03 2002 09:51:44   Joe
 * In BUCKfind(), fixed bug which was resulting in wrong bucket being
 * chosen when switching from RAW_GLYPH mode to a non-Asian
 * encoded symbolset.
 * 
 *    Rev 1.120   Sep 30 2002 14:12:34   WuQ
 * Changes for CCC font
 * 
 *    Rev 1.119   Sep 24 2002 11:44:02   Doolittl
 * Correction for CGIFfont_purge(); In BUCKfind(), == goes back to !=.
 * 
 *    Rev 1.118   Sep 23 2002 20:48:04   Galejs
 * add DIMM_DISK option (bug # 92) (for awr)
 * 
 *    Rev 1.117   Sep 23 2002 15:18:20   Galejs
 * fix possibly-uninitialized-vbl warnings (part of bug # 76)
 * 
 *    Rev 1.116   Sep 06 2002 17:22:48   Galejs
 * centralize #if-TT includes
 * 
 *    Rev 1.115   Aug 19 2002 16:15:42   Joe
 * Added disable-plugins support for stroke fonts
 * in BUCKfind().
 * 
 *    Rev 1.114   24 Aug 2001 14:02:52   JOE
 * DISK / ROM changes (by jwd).
 * 
 *    Rev 1.113   Jun 28 2001 18:52:08   Galejs
 * fix DYNAMIC_FONTS  conditional compile
 * 
 *    Rev 1.112   Jun 15 2001 18:15:54   Galejs
 * add #if-PLUGINS conditional compile
 * 
 *    Rev 1.111   04 Jun 2001 10:05:56   JOE
 * OpenType changes.
 * 
 *    Rev 1.110   01 Jun 2001 07:21:50   AOF
 * Doc's fixes! 
 * 
 *    Rev 1.0   01 Jun 2001 07:21:32   AOF
 * Initial revision.
 * 
 *    Rev 1.109   May 21 2001 18:51:22   Galejs
 * get rid of "rom_length" for CFF_ROM
 * 
 *    Rev 1.108   May 03 2001 20:02:08   Galejs
 * data-type cleanup (+ remove AGFATOOLS)
 * 
 *    Rev 1.107   Jan 12 2001 20:59:30   Galejs
 * get rid of control-z yet again
 * 
 *    Rev 1.106   12 Jan 2001 16:02:00   JOE
 * In BUCKfind(), made some bucket recognition changes.
 * 
 *    Rev 1.105   Jan 10 2001 14:17:12   Song
 * Remove ctrl-z
 * 
 *    Rev 1.104   18 Dec 2000 13:32:24   JOE
 * In BUCKfind(), changed the bucket search test to accomodate TrueType
 * collection fonts.
 * 
 *    Rev 1.103   Dec 14 2000 19:00:50   Galejs
 * integrate fix for TTC files (for ks)
 * 
 *    Rev 1.102   Dec 04 2000 15:54:44   Galejs
 * use new is_it_Asian() macro rather than explicit Asian-symbolset tests
 * 
 *    Rev 1.101   Nov 28 2000 18:47:52   Galejs
 * get_tt_ids() doesn't need reentancy parameter
 * 
 *    Rev 1.100   Nov 21 2000 09:34:46   Joe
 * In BUCKfind(), moved closing brace
 * inside ASIAN_ENCODING block to resolve
 * compiler error.
 * 
 *    Rev 1.99   Nov 20 2000 16:10:42   Joe
 * Added support for 'set cmap tables' functionality.
 * 
 *    Rev 1.98   Feb 02 2000 13:17:58   galejs
 * bugfixes in IXopen_file (for jd), & BUCKfind (for ks)
 * 
 *    Rev 1.97   Jan 28 2000 15:32:10   galejs
 * use PATHNAMELEN (from port.h) rather than MAXNAME for buffersize
 * 
 *    Rev 1.96   Jan 24 2000 13:02:18   galejs
 * get rid of "entityACT" field
 * 
 *    Rev 1.95   Dec 10 1999 16:04:54   galejs
 * get rid of TT_ROM1 code
 * 
 *    Rev 1.94   Nov 15 1999 12:27:58   galejs
 * set "ttc_index" field in TT_BUCK from FC
 * 
 *    Rev 1.93   Aug 16 1999 12:14:04   galejs
 * include-file changes; BUCKfree() becomes MLOCAL
 * 
 *    Rev 1.92   24 Jun 1999 13:32:52   JOE
 * In BUCKfind(), made changes to bucket searching due to moving the
 * get_tt_ids() call from CGIFfont() to ttload...().
 * 
 *    Rev 1.91   26 Jan 1999 11:32:42   JOE
 * Revised handling of extern_font variable to allow FORMAT16
 * and ASIAN_ENCODING independence (by jwd).
 * 
 *    Rev 1.90   21 Jan 1999 13:48:08   GALEJS
 * standardize #include tests
 * 
 *    Rev 1.89   12 Jan 1999 18:22:40   GALEJS
 * move EXTERN dcls
 * 
 *    Rev 1.88   06 Aug 1998 15:47:58   AL
 * CFF Rom support
 * 
 *    Rev 1.87   28 Jul 1998 10:28:42   DAVID
 * Added EXTERN BOOLEAN declaration for 'ps_is_same()' to eliminate
 * compiler warning and return of wrong type.
 * 
 *    Rev 1.86   22 Jul 1998 16:36:34   AL
 * Removed extra settings of platformID, specificID and languageID from
 * BUCKfind
 * 
 *    Rev 1.85   20 Jul 1998 15:17:24   AL
 * Multiple master and CFF support
 * 
 *    Rev 1.84   22 Jun 1998 17:56:22   GALEJS
 * pcleo.h in shareinc.h now
 * 
 *    Rev 1.83   17 Jun 1998 16:35:28   GALEJS
 * add arg to load/unload_font() calls (for reentrancy)
 * 
 *    Rev 1.82   15 Jun 1998 15:59:08   GALEJS
 * reentrancy parm-passing changes
 * 
 *    Rev 1.81   11 May 1998 13:57:30   JOE
 * Removed condition which included 'ttroment.h' based on TT_ROM_ACT
 * being enabled (by keb).
 * 
 *    Rev 1.80   15 Apr 1998 17:45:32   GALEJS
 * symbolset in IF_STATE
 * 
 *    Rev 1.79   14 Apr 1998 18:35:08   GALEJS
 * move fontindex into IF_STATE
 * 
 *    Rev 1.78   02 Apr 1998 18:29:06   GALEJS
 * max_open_files now in if_state
 * 
 *    Rev 1.77   30 Mar 1998 12:06:00   GALEJS
 * move all MLOCALs into if_state
 * 
 *    Rev 1.76   04 Mar 1998 16:48:14   JOE
 * Removed CTRL-Z at end of file.
 * 
 *    Rev 1.75   03 Mar 1998 16:09:14   JOE
 * Added AGFATOOLS (by dah).
 * 
 *    Rev 1.74   10 Feb 1998 17:13:22   GALEJS
 * only use pathname for Disk modes
 * 
 *    Rev 1.73   04 Feb 1998 01:13:32   DAVID
 * In BUCKfind() added code to copy fcCur.ExtndFlags word to
 * b->fc_ExtndFlags in two places - for support of HP4000 emulation.
 * 
 *    Rev 1.72   30 Jan 1998 16:32:42   GALEJS
 * delete unused TT plugin options; #-files vbls only needed if DISK
 * 
 *    Rev 1.71   04 Sep 1997 17:03:42   MARTIN
 * Modified references to AGFA Compressed TrueType (ACT).
 *  
 *    Rev 1.70   04 Jun 1997 17:19:38   DAVID
 * In BUCKfind(), added WANSUNG and JOHAB encoding support to ASIAN_
 * ENCODINGs.
 * 
 *    Rev 1.69   30 May 1997 09:50:16   MARTIN 
 * Added TrueType ROM ACT (compressed random access).
 * 
 *    Rev 1.68   28 Apr 1997 20:11:58   MIKE
 * Conditionally compiled if_state.if_init_face
 * 
 *    Rev 1.67   11 Mar 1997 14:04:06   MIKE
 * Changed TT plugin augmentation logic to disregard state of FC_PCL6_EMU
 * 
 *    Rev 1.66   14 Jan 1997 17:14:18   DAVID
 * Removed MULTIFORMAT option as part of project to trim ufst.
 * 
 *    Rev 1.65   13 Jan 1997 15:49:02   DAVID
 * Removed CONVERGENT_FONTS option as part of project to trim ufst.
 * 
 *    Rev 1.64   02 Jan 1997 17:51:46   DAVID
 * Added languageID, and langId fields to help distinguish betweeen
 * GB and BIG5 encoded Asian fonts.
 * 
 *    Rev 1.63   14 Nov 1996 20:36:14   MIKE
 * In BUCKfind(), don't set cur_ssnum=0 if search_lvl > 0
 * 
 *    Rev 1.62   04 Oct 1996 09:16:40   JOE
 * Removed CTRL-Z at end of file.
 * 
 *    Rev 1.61   01 Oct 1996 16:46:00   JOE
 * Included CACHE.H (needed for PFONT typedef in DLL.H).
 * 
 *    Rev 1.60   25 Sep 1996 11:49:40   MIKE
 * For DYNAMIC_FONTS/ROM fixed bug in BUCKfind() - bucket search loop
 * 
 *    Rev 1.59   16 Sep 1996 17:22:10   MIKE
 * Assign (bucket)->fc_format before calling load_font()
 * 
 *    Rev 1.57   30 Aug 1996 17:47:02   MIKE
 * Changed test for fco_pluginSearchPath(). Added b->fc_format.
 * 
 *    Rev 1.56   27 Jun 1996 09:59:44   DBK
 * Made ifdef changes based on NO_SYMSET_MAPPING
 * 
 *    Rev 1.54   14 Jun 1996 16:59:44   JOE
 * Changed "//" comment delimiter to "slash-asterisk ... asterisk-slash".
 * 
 *    Rev 1.53   13 Jun 1996 17:00:26   JWD
 * Revised handling of extern_font flag, to implement format16 support
 * 
 *    Rev 1.52   16 May 1996 14:41:54   MIKE
 * Made 2/27/96 change conditional on TT_RDR = 1
 * 
 *    Rev 1.50   22 Apr 1996 17:55:36   MIKE
 * OS9 support.
 * 
 *    Rev 1.49   29 Feb 1996 10:05:06   MIKE
 * Repeat call to ttload_font if insufficient memory. Add BUFpurgeBUCK().
 * 
 *    Rev 1.48   06 Dec 1995 13:48:14   MIKE
 * Fix bug in while loop in BUFalloc()
 * 
 *    Rev 1.47   05 Dec 1995 15:05:28   MERRILL
 * quiet BC4 warnings
 * 
 *    Rev 1.46   19 Jun 1995 15:33:52   MIKE
 * BUCKfind() should call SYMnoMap() for PCLEO with !b->usePlugins
 * 
 *    Rev 1.45   06 Apr 1995 15:14:14   LISA
 * Changed copyright from Miles Inc. to Bayer Corp.
 * 
 *    Rev 1.44   17 Dec 1994 17:56:24   JOE
 * In BUCKfind(), if TFS was a pcleo, need to load symbolset first
 * and last character in order to locate the character in the
 * FCO plugins.
 * 
 *    Rev 1.43   15 Dec 1994 16:53:46   MIKE
 * Return error if "buck_search_lvl" too large (BUCKfind)
 * 
 *    Rev 1.42   02 Dec 1994 21:26:02   YAN
 * KSC.
 * 
 *    Rev 1.41   30 Nov 1994 11:02:52   JOE
 * In BUCKfind(), if FCO_RDR is enabled, always set up FCO plugins
 * regardless of fst type.
 * 
 *    Rev 1.40   09 Nov 1994 16:21:22   BJG/DBK
 * In BUCKfind(), added braces following "if" statement to correct
 * improper bucket searching algorithm.
 * 
 *    Rev 1.39   15 Sep 1994 20:44:24   MIKE
 * In BUCKfind() for FCO plugins, set font_type.
 * 
 *    Rev 1.37   02 Sep 1994 12:58:34   MIKE
 * In BUCKfind() set up plugin faces for FCO_RDR.
 * 
 *    Rev 1.36   05 Aug 1994 13:39:32   MIKE
 * Added FCO changes from 1.25.1.2
 * 
 *    Rev 1.35   29 Apr 1994 16:10:36   JOE
 * In BUCKfind(), only call IXopen_file() for TT data for which we
 * have a path.
 * 
 *    Rev 1.34   22 Apr 1994 15:39:02   JOE
 * Changed conditional compile statement prior to including <hif.h>
 * to #if (_AM29K && !UNIX) to resolve UNIX Metaware compiler error.
 * 
 *    Rev 1.33   22 Apr 1994 15:12:00   JOE
 * In BUCKfind(), when calling xxload_font(), cast first arg as LPSB8.
 * 
 *    Rev 1.32   22 Apr 1994 13:54:40   LISA
 * Made modifications to copyright/disclaimer notice.
 * 
 *    Rev 1.31   30 Mar 1994 11:45:54   JOE
 * In BUCKfind(), if processing TT, after finding bucket, call IXopen_file()
 * in the event that the TT file was closed due to num_open_files exceeding
 * max_open_files.
 * 
 *    Rev 1.30   29 Mar 1994 10:08:02   JOE
 * Changed conditional compile for IXopen_file() and IXclose_file()
 * to include TT_RDR too. 
 * Modified IXopen_file() for TT support.
 * 
 *    Rev 1.29   09 Feb 1994 12:07:14   JOE
 * More _AM29K changes.
 * 
 *    Rev 1.28   03 Feb 1994 15:30:20   MIKE
 * Change fontindex.awtsub_on to if_state.awtsub_on.
 * 
 *    Rev 1.27   02 Feb 1994 09:05:18   JOE
 * AM29K changes.
 * 
 *    Rev 1.26   19 Jan 1994 08:57:48   JOE
 * In BUCKfind(), conditionally compiled code which stores platform and
 * specific IDs based on TT_RDR to resolve compiler error.
 * 
 *    Rev 1.25   05 Jan 1994 18:12:18   ROB
 * Add support for "GB" encoding.
 * 
 *    Rev 1.24   08 Dec 1993 19:00:00   ROB
 * General cleanup for MSDOS, FLAT, OS2.
 * 
 *    Rev 1.23   07 Dec 1993 15:20:08   JOE
 * 
 * In BUCKfind(), for KANJI TT fonts, set platform ID and specific ID
 * from "symbolset" data (loaded by cgif_Font() ).
 * Changed conditional compile statement for OS2 support.
 * 
 *    Rev 1.22   01 Dec 1993 08:52:38   JOE
 * 
 * Changed KANJI_ENCODING to ASIAN_ENCODING.
 * 
 *    Rev 1.21   30 Nov 1993 14:48:56   ROB
 * Add BIG5 support and TCA hooks.
 * 
 *    Rev 1.20   18 Nov 1993 13:34:34   MIKE
 * In BUCKfind() set platId & specId to 0 in the TT bucket, if plugins disable
 * 
 *    Rev 1.19   11 Nov 1993 16:32:16   JOE
 * In BUCKfind(), added UNICODE changes for KANJI support (platformID
 * set to 3 instead of 1).
 * 
 *    Rev 1.18   23 Sep 1993 20:26:28   MIKE
 * Before setting up plugin search path, test pbucket->usePlugins
 * 
 *    Rev 1.17   23 Sep 1993 19:29:32   MIKE
 * BUCKfind() changes.
 * 
 *    Rev 1.16   12 Aug 1993 11:08:18   MIKE
 * For CONVERGENT_FONTS: change IF plugin search path setup in BUCKfind().
 * 
 *    Rev 1.15   10 Aug 1993 15:33:54   JOE
 * In BUCKfind(), conditionally compiled call to ifload_font() based on IF_RDR.
 * In BUCKfree(), conditionally compiled call to ifunload_font() bsd on IF_RDR.
 * In BUCKfree(), changed statement "return (fst_type)" to "return"
 * because BUCKfree() returns VOID.
 * 
 *    Rev 1.14   15 Jul 1993 11:55:46   MIKE
 * Convergent font changes -- see comments.
 * 
 *    Rev 1.13   01 Jul 1993 15:21:40   JOE
 * 
 * EUC KANJI support.
 * 
 *    Rev 1.12   30 Jun 1993 08:54:56   JOE
 * In BUCKfind(), conditionally compiling test for JIS or SJIS encoding
 * based on KANJI_ENCODING.
 * 
 *    Rev 1.11   29 Jun 1993 14:49:52   JOE
 * In BUCKfind(), storing 1 for platformID and specificID if using JIS or
 * SJIS encoding.
 * 
 *    Rev 1.10   28 Jun 1993 14:08:32   JOE
 * 
 * In BUCKfind(), when searching for bucket, generalized code which
 * determines whether TFS font has changed.
 * 
 *    Rev 1.9   24 Jun 1993 14:21:00   JOE
 * 
 * In BUCKfind(), if processing KANJI fonts, check encoding value in
 * addition to pathname before determining that TFS font has not changed.
 * This fixes a bug when switching from JIS to SJIS encoding and vice versa.
 * 
 *    Rev 1.8   03 May 1993 17:07:16   MIKE
 * Fix ROM problem in bucket search algorithm in BUCKfind().
 * 
 *    Rev 1.7   22 Apr 1993 11:18:04   MIKE
 * BUCKfind - support IF dynamic fonts (has_path, etc.).
 * IXopen_file() - dynamic font support (don't call buildpath()).
 * 
 *    Rev 1.6   13 Apr 1993 13:26:14   JOE
 * In BUCKfree(), conditionally compiled calls to psunload_font() and
 * ttunload_font() if !USE_JUMP_TABLES. In BUCKfind(), conditionally compiled
 * calls to psload_font() and ttload_font() if !USE_JUMP_TABLES.
 * 
 *    Rev 1.5   29 Mar 1993 10:50:00   ROB
 * Kanji cleanup.
 * 
 *    Rev 1.4   11 Mar 1993 15:06:08   MAIB
 * Initial changes to support Asian character encoding (TrueType 1st pass)
 * 
 *    Rev 1.3   12 Feb 1993 13:36:58   JOE
 * VXWorks support.
 * 
 *    Rev 1.2   06 Jan 1993 16:05:36   JOE
 * ANSI C function declaration changes.
 * 
 *    Rev 1.1   14 Dec 1992 15:47:30   LISA
 * Made change to Log keyword
 * 
 *    Rev 1.0   09 Dec 1992 15:38:52   LISA
 * Initial revision.
*/
/* $Date:   Dec 14 2004 14:17:46  $ */
/* bucket.c */
/*
 *
 *
 * History
 *
 *    24-Aug-90  awr   Initialize BUCKET's "my_handle" field in BUCKnew()
 *    03-Dec-90  awr   In BUCKfree(), reset if_init_face (last face processed
 *                     by if_init())
 *     7 Jan 91  ss    Added PCLEO_RDR support
 *    24-Jan-91  jfd   As a result of removing the "name_off" field from
 *                     the INDEX_ENTRY structure (#if ROM), conditionally
 *                     compile the DBG5 statement in IXfind_bucket().
 *    28-Jan-91  tnc   Window-ized file "close" and "read".
 *    28-Jan-91  jfd   Made size arg of MEMalloc() LONG
 *    30-Jan-91  dET   Added function prototyping for MSC
 *    31-Jan-91  dET   Modify for MSC multi-model compilation.
 *     4-Feb-91  awr   Split off from ix.c
 *     8-Feb-91  awr   Added dll.h to declare functions.
 *    15-Feb-91  awr   changed IXfind_bucket() name to BUCKfind()
 *    23-Feb-91  awr   removed reference to hfi by adding calls to
 *                     FIpath() and FIentry().
 *    23-Feb-91  awr   Moved BUCKET defund logic from mem.c
 *    04-Mar-91  jfd   Conditionally declared FIpath (#if !ROM).
 *    06-Mar-91  jfd   Removed BUCKdefund().
 *    09-Apr-91  dET   Added BUFdump routines for aid in debugging. 
 *    17-Jun-91  jfd   Moved "debug.h" after "port.h".
 *                     Moved "cgconfig.h" before "port.h".
 *    24 Jun 91  ss    Conditionally compile io.h based on system type.
 *                     Added prototypes for BUCK,BUF...() when not LINT_ARGS.
 *     3-Jan-92  awr   Removed font_open field from BUCKET
 *                     Removed BUCKnew(); coded inline.
 *    15-Jan-92  jfd   Added functofin prototype for IXset_search_path().
 *    17 Jan 92  ss    In BUCKfind() made test for matching to an existing
 *                     bucket more strict.
 *    29-Jan-92  rs    Move IF_FUNC_TBL from cgif.c for URIP ptrs.
 *    07-Mar-92  rs    Remove duplicate global 'pras' (in cgif.c).
 *     8-Mar-92  awr   Added core font substitution for PS and TT
 *    03-Apr-92  rs    Portability cleanup (see port.h).
 *    23 Apr 92  ss    In BUCKfind(), reordered initial setup code based
 *                     on buck_search_lvl which wraps in the PS,TT specific
 *                     code instead of duplicating it.
 *                     - Improved test for matching typeface in bucket search
 *                     to the one requested in fontindex.
 *                     - Changed test for buck_search_lvl==MAX_UWORD to ==0.
 *                     No longer using MAX_UWORD to determine a non-IF type.
 *                     Added items set when have a TFS round (buck_search_lvl
 *                     == 0).
 *                     - Changed name fontindex.num_levels to .num_searches.
 *     6-Jul-92  jfd   Added "ifget_width" to iffunc_tbl structure.
 *                     Added "psget_width" to psfunc_tbl structure.
 *                     Added "ttget_width" to ttfunc_tbl structure.
 *     9-Jul-92  jfd   Conditionally compiled "ifget_width", "psget_width"
 *                     and "ttget_width" based on WIDTHS.
 *    21-Jul-92  awr   Conditional compile changes.
 *    28-Jul-92  ss    In BUCKfind(), initialize tfnum to 0; if not IF font
 *                     and ROM is true, has_path = FALSE.
 *    05-Aug-92  jfd   Replaced calls to "clear_mem()" with MEMSET for
 *                     optimization.
 *                     Included "mixmodel.h" and "string.h".
 *    16-Aug-92  rs    #defined 'MEM_DUMP' = 0 if not already defined.
 *    14-Sep-92  jfd   Conditionally compiled table iffunc_tbl{} based on
 *                     IF_RDR.
 *                     In BUCKfind(), conditionally compiled case clause
 *                     which stores pointer to IF function table based on
 *                     IF_RDR.
 *    16-Sep-92  jfd   Conditionally compile routines IXopen_file() and
 *                     IXclose_file() based on IF_RDR.
 *    28-Sep-92  awr   Changed BUCKfind() parameters.
 *                     Changed FIentry() parameter.
 *    10-Oct-92  rs    Implement USE_JUMP_TABLES feature for overlays.
 *    13-Oct-92  mby   Changed BUCKfind() for TT: platformID & specificID.
 *                     Set has_path = TRUE, if TT_TTPLUGIN && not ROM font
 *    26-Oct-92  jfd   In BUCKfind(), before storing "platId" and "specId"
 *                     into TT bucket, check if bucket is a TT bucket.
 *                     In same routine, storing "cur_ssnum" into bucket
 *                     structure at same time that other fields are loaded.
 *    06-Nov-92  jfd   In BUCKfind(), moved closing brace to line following
 *                     #endif for (IF_RDR || PS_IFPLUG || TT_IFPLUG). This
 *                     fixes a compiler error if compiling for TT only.\
 *    15-Nov-92  rs    Port to Macintosh - #include <unix.h>, casting in call
 *                     to load_font().
 *    22-Nov-92  rs    Port to Macintosh - prototype for set_tt_universal().
 *    06-Jan-93  jfd   ANSI C function declaration changes.
 *    08-Feb-93  jfd   VXWorks support.
 *    11-Mar-93  maib  began support for jis and shift jis character encoding.
 *    27-Mar-93  rs    Add defines for KANJI_ENCODING, JIS_ENCODING &
 *                     SJIS_ENCODING per cgconfig.h.
 *    13-Apr-93  jfd   In BUCKfree(), conditionally compiled calls to
 *                     psunload_font() and ttunload_font() if !USE_JUMP_TABLES.
 *                     in BUCKfind(), conditionally compiled calls to
 *                     psload_font() and ttload_font() if !USE_JUMP_TABLES.
 *    10-Apr-93  mby   DYNAMIC_FONTS: IXopen_file() builds pathname differently.
 *                     In BUCKfind(), has_path can be true for IF; BUCKET->dynIFActive.
 *    30-Apr-93  mby   Fix ROM problem in BUCKfind() bucket search algorithm.
 *    24-Jun-93  jfd   In BUCKfind(), if processing KANJI fonts, check 
 *                     encoding value in addition to pathname before
 *                     determining that TFS font has not changed. This
 *                     fixes a bug when switching from JIS to SJIS encoding
 *                     and vice versa.
 *    28-Jun-93  jfd   In BUCKfind(), when searching for bucket, generalize
 *                     the code. For PS, TT, KANJI, or IF using dynamic
 *                     fonts, the symbolset is checked in addition to the
 *                     pathname before determining that TFS font has not 
 *                     changed.
 *    29-Jun-93  jfd   In BUCKfind(), storing 1 for platformID and specificID
 *                     if using JIS or SJIS encoding.
 *    30-Jun-93  jfd   In BUCKfind(), conditionally compiling test for
 *                     JIS or SJIS encoding based on KANJI_ENCODING.
 *    30-Jun93 jfd/gy  EUC KANJI support.
 *    13-Jul-93  mby   Conditionally compiled set_tt_universal() based on
 *                     TT_TTPLUG and TT_TTPLUG_IF.
 *                     Modified TT plugin font selection for TT_TTPLUG_IF.
 *                     Added debug routine print_buckets().
 *    10-Aug-93  jfd   In BUCKfind(), conditionally compile call to
 *                     ifload_font() based on IF_RDR. 
 *                     In BUCKfree(), conditionally compile call to 
 *                     ifunload_font() based on IF_RDR.
 *                     In BUCKfree(), changed "return (ERR_fst_type);"
 *                     to "return" because BUCKfree() returns VOID.
 *    12-Aug-93  mby   For CONVERGENT_FONTS: change plugin search path setup
 *                     in BUCKfind().
 *    22-Sep-93  mby   Add default case to switch(fontindex.plug_type)
 *                     Set usePlugins boolean in bucket. ROM1 support.
 *    11-Nov-93  gy    In BUCKfind(), added UNICODE changes for KANJI
 *                     support (platformID set to 3 instead of 1).
 *    18-Nov-93  mby   In BUCKfind() set platId and specId to 0 in the TrueType
 *                     bucket if if_state.usePlugins is 0.
 *    23-Nov-93  rs    Add BIG5 & TCA to KANJI_ENCODING support.
 *    01-Dec-93  jfd   Changed KANJI_ENCODING to ASIAN_ENCODING.
 *    03-Dec-93  jfd   In BUCKfind(), for KANJI fonts, set platform ID and
 *                     and specificID from "symbolset" data (loaded by
 *                     cgif_Font() ).
 *    07-Dec-93  rs    Changed conditional compile statement for OS2.
 *    08-Dec-93  rs    General cleanup - MSDOS & OS2.
 *    05-Jan-94  rs    Add support for "GB" encoding.
 *    19-Jan-94  jfd   In BUCKfind(), conditionally compiled block of code
 *                     which stores platform ID and specific ID based on
 *                     TT_RDR.
 *    27-Jan-94  jfd   Conditionally compiled #include for fcntl.h
 *                     (if !(_AM29K && UNIX) ).
 *    02-Feb-94  mby   Change fontindex.awtsub_on to if_state.awtsub_on.
 *    09-Feb-94  jfd   Including "hif.h" if _AM29K.
 *    28-Mar-94  jfd   Change conditional compile for IXopen_file() and
 *                     IXclose_file() to include TT_RDR too.
 *                     Modified  IXopen_file() for TT support.
 *    30-Mar-94  jfd   In BUCKfind(), if processing TT, after finding 
 *                     bucket, call IXopen_file() in the event that
 *                     the TT file was closed due to num_open_files
 *                     exceeding max_open_files.
 *    22-Apr-94  dbk   In BUCKfind(), when calling xxload_font(), cast
 *                     first arg as LPSB8.
 *               jfd   Changed conditional compile statement prior to
 *                     including <hif.h> to #if (_AM29K && !UNIX) to
 *                     resolve UNIX Metaware compiler error.
 *    29-Apr-94  jfd   In BUCKfind(), only call IXopen_file() for TT data
 *                     for which we have a path .
 *    09-Nov-94  bg/dbk In BUCKfind(), added braces following "if" statement
 *                     to correct improper bucket searching algorithm.
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 *  FCO Changes from 1.25.1.2:
 *    15-Mar-94  mby   Added fco_func_tbl structure for FCO function calls.
 *                     In BUCKfind(), cur_font_hdr = fontindex.FCObject for
 *                     FCO font type.
 *    26-May-94  mby   Change fontindex.FCObject to if_state.FCObject.
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 *    02-Sep-94  mby   In BUCKfind() set up plugin faces for FCO_RDR.
 *    08-Sep-94  mby   Add missing break statement.
 *    15-Sep-94  mby   In BUCKfind() for FCO plugins, set font_type.
 *    28-Nov-94  jfd   In BUCKfind(), if FCO_RDR is enabled, always set
 *                     up FCO plugins regardless of fst type.
 *    15-Dec-94  mby   In BUCKfind() for FCO_RDR, if "buck_search_lvl"
 *                     argument too large, return ERR_no_cgnum.
 *    17-Dec-94  jfd   In BUCKfind(), if TFS was a pcleo, need to load 
 *                     symbolset first and last character in order to 
 *                     locate the character in the FCO plugins.
 *    06-Jun-95  mby   In BUCKfind() for plugin search path, if TFS is PCLEO
 *                     or PCLETTO and !(b->usePlugins), call SYMnoMap(),
 *                     not SYMnew().
 *    06-Dec-95  mby   Fix bug in BUFalloc() - restore v46 code.
 *  27-Feb-96  mby  In BUCKfind() repeat call to load_font (TT only) to fix
 *                  memory fragmentation in BUFFER pool.
 *                  Add BUFpurgeBUCK() function to remove all font buckets.
 *  22-Apr-96  mby  Conditionalize <fcntl.h> for OS9 port.
 *  16-May-96  mby  Made 2/27/96 change conditional on TT_RDR.
 *  13-Jun-96  jwd  Revised handling of extern_font flag, to implement
 *                  format16 support.
 *  17-Jun-96  dbk  Made ifdef changes based on NO_SYMSET_MAPPING.
 *  26-Aug-96  mby  In BUCKfind(), removed "b->rom_font"; added "b->fc_format".
 *                  b->fc_format has to be set every time we call BUCKfind()
 *                  to keep it uptodate.
 *                  Changed test for calling fco_pluginSearchPath().
 *  16-Sep-96  mby  Assignment of (bucket)->fc_format must be made in 2 places
 *                  -- before load_font() & before fco_pluginSearchPath().
 *                  Code cleanup: added calls to BUFfree().
 *  25-Sep-96  mby  Fixed bug in bucket search loop in BUCKfind() - for
 *                  DYNAMIC_FONTS && ROM make sure fst_type is FC_IF_TYPE.
 *  01-Oct-96  jfd  Included CACHE.H (needed for PFONT typedef in DLL.H).
 *  14-Nov-96  mby  In BUCKfind(), buck_search_lvl > 0 (plugins), set
 *                  cur_ssnum = fontindex.cur_ssnum INSTEAD OF 0.
 *  01-Jan-97  dlk  Added tt_langId field and languageID to help distinguish
 *                  between GB and BIG5 encoded Asian fonts.
 *  13-Jan-97  dlk  Removed CONVERGENT_FONTS option as part of project to
 *                  trim ufst.
 *  14-Jan-97  dlk  Removed MULTIFORMAT option as part of project to trim ufst.
 *  11-Mar-97  mby  In BUCKfind() modified test for calling fco_pluginSearchPath()
 *                  to ignore state of FC_PCL6_EMU in fontcontext.format
 *  28-Apr-97  mby  In BUCKinit(), conditionally compiled if_state.if_init_face.
 *  29-May-97  sbm  Add TT_ROM_ACT functionality.
 *  04-Jun-97  dlk  In BUCKfind() added WANSUNG and JOHAB Korean encoding sup-
 *                  port to lists of ASIAN_ENCODINGs.
 *    30-Jan-98  slg    Delete code for unused TT plugin options; number-of-files
 *                    vbls are only needed for DISK cases. 
 *  04-Feb-98  dlk  In BUCKfind() added code to copy fcCur.ExtndFlags word to
 *                  b->fc_ExtndFlags -n two places - for support of HP4000
 *                  emulation.
 *    10-Feb-98  slg    can't use pathname if ROM mode
 *  02-Mar-98  dah  Added AGFATOOLS to allow ROM simulation
 *  30-Mar-98  slg    Move all MLOCALs into IF_STATE, use "shareinc.h".
 *    02-Apr-98  slg  Move max_open_files into IF_STATE.
 *  11-may-98 keb  removed condition which included 'ttroment.h' based on 
 *                 TT_ROM_ACT being enabled
 *  28-Jul-98  dlk  Added EXTERN BOOLEAN declaration for 'ps_is_same()' to
 *                  eliminate compiler warning and return BOOLEAN instead of
 *                  int.
 * 25-Jan-99  jwd  Revised handling of extern_font variable to allow FORMAT16 
 *                 and ASIAN_ENCODING independence
 * 24-Jun-99  jfd  In BUCKfind(), made changes to bucket searching
 *                 due to moving the get_tt_ids() call from CGIFFont()
 *                 to ttload...().
 * 28-Jan-00 slg  Use PATHNAMELEN (from port.h) rather than locally-defined (and
 *                  incorrect) MAXNAME; replace !ROM tests by DISK_FONTS.
 * 02-Feb-00 slg  Integrate bugfix for ks ("extern_font" setting in BUCKfind);
 *                  change conditional compile in IXopen_file for jd (disk/ROM). 
 * 13-Nov-00 jfd  In BUCKfind(), before searching for bucket, call get_tt_ids()
 *                to derive platform ID and specific ID.
 *                In same function, when checking for a matching bucket, check for
 *                a match on platform ID and specific ID.
 * 21-Nov-00 jfd  In BUCKfind(), moved closing brace inside ASIAN_ENCODING
 *                block to resolve compiler error.
 * 14-Dec-00 slg  Sign in Kimberley's TTC bugfix (previously, we were not
 *                  distinguishing between different TTC indices when looking    up
 *                  TT chars, so chars from one index were returned for others).                
 * 18-Dec-00 jfd  In BUCKfind(), changed the bucket search testing to
 *                accomodate TrueType collection fonts.
 * 12-Jan-01 jfd  In BUCKfind(), added bucket recognition changes.
 * 23-May-01 jfd  OpenType changes:
 *                In BUCKfree(), free OTCFF bucket if applicable.
 *                In BUCKfind(), initialize new BUCKET fields.
 *                In same function, create new BUCKET if processing an OpenType CFF font
 *                and call psload_font() to load.
 * 31-May-01 jwd  In BUCKfind(), corrected purge bucket code (used by CGIFfont_purge()).
 * 24-Aug-01 jwd  DISK / ROM changes.
 * 19-Aug-02 jfd   Added disable-plugins support for stroke fonts in BUCKfind().
 * 15-Aug-02 awr  Added DIMM_DISK
 * 03-Oct-02 jfd  In BUCKfind(), fixed bug which was resulting in wrong bucket being
 *                chosen when switching from RAW_GLYPH mode to a non-Asian encoded symbolset.
 * 10-Nov-03 jfd  In BUCKfree(), calling MEMSET to reset "if_state.cur_loc_fc" whenever a
 *                bucket is freed.
 *
 */

#include <string.h>
#ifdef VXWORKS
#include "vxWorks.h"
#endif

#include <stdio.h>

#include "cgconfig.h"
#include "ufstport.h"

#if MAYBE_FCNTL_H
#include <fcntl.h>
#endif

#if MAYBE_FCNTL_HIF_H
#include <fcntl.h>
#include <hif.h>  /* 2-7-94 jfd */
#endif

#if MAYBE_IO_H
#include <io.h>
#endif

#if MAYBE_UNISTD_H
#include <unistd.h>
#endif

#include "dbg_ufst.h"

#include "shareinc.h"

#include "mixmodel.h"
#include "segments.h"
#include "dll.h"

#ifdef LINT_ARGS
VOID        BUCKfree(FSP HBUCKET);

#else    /*  NOT LINT_ARGS  */
VOID        BUCKfree();

#endif


#if (USE_JUMP_TABLES)
/*
URIP function interface tables - 1 for each font type
*/
#if IF_RDR
MLOCAL IF_FUNC_TBL iffunc_tbl = {
    ifload_font,
    ifunload_font,
    ifset_trans,
    ifset_char,
    ifmake_gaso_and_stats,
    ifrender
#if WIDTHS
   ,ifget_width
#endif /* WIDTHS */
};
#endif /* IF_RDR */

#if PST1_RDR
MLOCAL IF_FUNC_TBL psfunc_tbl = {
    psload_font,
    psunload_font,
    psset_trans,
    psset_char,
    psmake_gaso_and_stats,
    psrender
#if WIDTHS
   ,psget_width
#endif /* WIDTHS */
};
#endif /* PST1_RDR */

#if TT_RDR
MLOCAL IF_FUNC_TBL ttfunc_tbl = {
    ttload_font,
    ttunload_font,
    ttset_trans,
    ttset_char,
    ttmake_gaso_and_stats,
    ttrender
#if WIDTHS
   ,ttget_width
#endif /* WIDTHS */
};
#endif /* TT_RDR */

#if FCO_RDR
MLOCAL IF_FUNC_TBL fco_func_tbl = {
    fco_load_font,
    fco_unload_font,
    fco_set_trans,
    fco_set_char,
    fco_make_gaso_and_stats,
    fco_render
#if WIDTHS
   ,fco_get_width
#endif /* WIDTHS */
};
#endif /* FCO_RDR */

#endif /* USE_JUMP_TABLES */

/*-------------------------------------------------------------*/

#if DISK_FONTS && (IF_RDR || TT_RDR || PST1_RDR)

/*-------------------*/
/*   IXclose_file    */
/*-------------------*/
/*  Close buckets file if it's open and decrement
 *  global count of open files.
 */
#if defined (ANSI_DEFS)
GLOBAL VOID  IXclose_file(FSP PBUCKET b)
#else
GLOBAL VOID
IXclose_file(b)
    PBUCKET   b;
#endif
{
    if(b->fh != -1)
    {
#if DIMM_DISK
        if(b->fc_ExtndFlags & EF_DIMM_DISK_TYPE)
            dd_close(b);
        else
#endif
            CLOSE(b->fh);

        b->fh = -1;
        if_state.num_open_files--;
    }
}


/*-------------------*/
/*   IXopen_file     */
/*-------------------*/
#if defined (ANSI_DEFS)
GLOBAL UW16  IXopen_file(FSP PINDEX_ENTRY ix, PBUCKET bucket)
#else
GLOBAL UW16
IXopen_file(ix, bucket)
    PINDEX_ENTRY ix;
    PBUCKET      bucket;
#endif
{
    HBUCKET      hb;
    PBUCKET      b;
    FILECHAR pathname[PATHNAMELEN];

    if(bucket->fh != -1) 
        return SUCCESS;   /* file is already open */

  /*  Make sure too many files aren't open  */

    while(if_state.num_open_files >= if_state.max_open_files)
    {
        hb = ((PDLL)MEMptr(if_state.pserver->hBUCKlru))->b;       /* lru BUCKET in lru list */
        while(hb != if_state.pserver->hBUCKlru)
        {
            b  = (PBUCKET)MEMptr(hb);
            if(b->fh != -1)
            {
                IXclose_file(FSA b);
                break;
            }
            hb = b->link.b;                /* previous BUCKET in the list */
        }
        if(hb == if_state.pserver->hBUCKlru)
        {
            DBG("    couldn't close file\n");
            return ERR_IXopen_file;
        }
    }

  /*  Open the file  */

#if IF_DISK        /* changed from IF_RDR to resolve FIpath DISKROM link error - sandra, 8 Aug 03 */
    if (bucket->fst_type == FC_IF_TYPE)
    {
#if DYNAMIC_FONTS
    if (bucket->dynIFActive)
      STRCPY(pathname, bucket->pathname);
    else
#endif
      buildpath (pathname, if_state.typePath, FIpath(FSA ix));
    }
#endif    /* IF_DISK */

#if TT_RDR
    if (bucket->fst_type == FC_TT_TYPE)
       STRCPY(pathname, bucket->pathname);
#endif

#if PST1_RDR
    if (bucket->fst_type == FC_PST1_TYPE)
       STRCPY(pathname, bucket->pathname);
#endif

#if DIMM_DISK
    if(bucket->fc_ExtndFlags & EF_DIMM_DISK_TYPE)
        dd_open(bucket);
    else
#endif
    {
        if((bucket->fh = OPEN(pathname, O_READFLAGS)) == -1)
        {
            DBG1("        Open lib file failed. pathname = %s\n", pathname);
            return ERR_open_lib;
        }
    }
    if_state.num_open_files++;
    return SUCCESS;
}

#endif    /* DISK_FONTS && (IF_RDR || TT_RDR || PST1_RDR) */

/*-------------------*/
/*     BUCKinit      */
/*-------------------*/
#if defined (ANSI_DEFS)
GLOBAL UW16  BUCKinit(FSP0)
#else
GLOBAL UW16
BUCKinit()
#endif
{
#if DISK_FONTS
    if_state.num_open_files = 0;               /* number of open library files     */
#endif
#if IF_RDR
    if_state.if_init_face   = 0;      /* Last face processed by if_init() */
#endif
    /* 06-28-04 jfd   Only initialize the BUCKET lru once */
    if (if_state.pserver->MTinitstate & not_BUCKlru)
    {
        if_state.pserver->hBUCKlru = MEMalloc(FSA BUFFER_POOL, (SL32)sizeof(DLL));
        if(!(if_state.pserver->hBUCKlru))
            return ERRmem;

        dll_null(FSA if_state.pserver->hBUCKlru);               /*  Set BUCKET lru to empty.        */

        if_state.pserver->MTinitstate &= ~not_BUCKlru;
    }

    return SUCCESS;
}


/*-------------------*/
/*     BUCKexit      */
/*-------------------*/
#if defined (ANSI_DEFS)
GLOBAL VOID  BUCKexit(FSP0)
#else
GLOBAL VOID
BUCKexit()
#endif
{
#if UFST_MULTITHREAD
    PBUCKET b;
    HBUCKET hb;
    HBUCKET next_hb;
    UL32 thread_id;
#endif

    if(if_state.pserver->MTinitstate & not_BUCKlru) return;   /* bucket LRU list not initialized */

#if UFST_MULTITHREAD
    thread_id = get_thread_id(FSA0);

    hb = ((PDLL)MEMptr(if_state.pserver->hBUCKlru))->f;   /* first BUCKET in lru list */
    while(hb != if_state.pserver->hBUCKlru)
    {
        b = (PBUCKET)MEMptr(hb);
        next_hb = b->link.f;
        BUCKfree(FSA hb);
        hb = next_hb;            /* next BUCKET in the list */
    }

    if (!if_state.pserver->client_count)
    {
        if (dll_empty(FSA if_state.pserver->hBUCKlru))
        {
            MEMfree(FSA BUFFER_POOL, if_state.pserver->hBUCKlru);
            if_state.pserver->MTinitstate |= not_BUCKlru;          /* set not initialized bit */
        }
    }
#else
    while(!dll_empty(FSA if_state.pserver->hBUCKlru))
        BUCKfree(FSA ((PDLL)MEMptr(if_state.pserver->hBUCKlru))->b);

    MEMfree(FSA BUFFER_POOL, if_state.pserver->hBUCKlru);

    if_state.pserver->MTinitstate |= not_BUCKlru;          /* set not initialized bit */
#endif
}


#if FCO_RDR
/*-------------------*/ /* This function is almost the same as      */
/*    BUFpurgeBUCK   */ /* BUCKexit but does not remove 'hBUCKlru'. */
/*-------------------*/
/*  Arguments: none
 *  Called by: CGIFfco_Open
 *  Notes: CGIFfco_Open allocates permanent memory in the BUFFER pool for the
 *         FCO. To avoid fragmentation, use BUFpurgeBUCK to remove all buckets.
 */

#if defined (ANSI_DEFS)
GLOBAL VOID  BUFpurgeBUCK(FSP0)
#else
GLOBAL VOID BUFpurgeBUCK()
#endif
{
#if UFST_MULTITHREAD
    PBUCKET b;
    HBUCKET hb;
    HBUCKET next_hb;

    hb = ((PDLL)MEMptr(if_state.pserver->hBUCKlru))->f;   /* first BUCKET in lru list */
    while(hb != if_state.pserver->hBUCKlru)
    {
        b = (PBUCKET)MEMptr(hb);
        next_hb = b->link.f;
        BUCKfree(FSA hb);
        hb = next_hb;            /* next BUCKET in the list */
    }
#else 

    while(!dll_empty(FSA if_state.pserver->hBUCKlru))
        BUCKfree(FSA ((PDLL)MEMptr(if_state.pserver->hBUCKlru))->b);
#endif
}
#endif  /* FCO_RDR */


/*-------------------*/
/*    BUCKfree       */
/*-------------------*/
#if defined (ANSI_DEFS)
VOID  BUCKfree(FSP HBUCKET hb)
#else
VOID
BUCKfree(hb)
    HBUCKET hb;
#endif
{
    PBUCKET      b;
#if UFST_MULTITHREAD
    UW16 status;
#endif

    b = ((PBUCKET)MEMptr(hb));

#if UFST_MULTITHREAD
    status = remove_thread_id_from_list(FSA b->thread_ids);
    if (!thread_list_is_empty(FSA b->thread_ids))
        return;
    b->locked = FALSE;
#endif

#if USE_JUMP_TABLES
    (*((PIF_FUNC_TBL)b->pft)->unload_font) (FSA b);
#else

   switch (b->fst_type)
   {
#if IF_RDR
      case FC_IF_TYPE:
         ifunload_font (FSA b);
         break;
#endif
#if PST1_RDR
      case FC_PST1_TYPE:
         psunload_font (FSA b);
         break;
#endif
#if TT_RDR
      case FC_TT_TYPE:
         ttunload_font (FSA b);
         break;
#endif
#if FCO_RDR
      case FC_FCO_TYPE:
         fco_unload_font (FSA b);
         break;
#endif
      default:
/*         return (ERR_fst_type); */
         return;
     }
#endif /* USE_JUMP_TABLES */

    MEMSET (&if_state.cur_loc_fc, '\0', sizeof (FONTCONTEXT));

    /* Reset system copy of fontcontext too. */
    MEMSET (&if_state.pserver->cur_loc_fc, '\0', sizeof (FONTCONTEXT));

    dll_remove(FSA hb);                        /* remove from active lru list */
#if TT_RDR && CFF_RDR    /* 05-23-01 jfd */
    if ( B_ISOTCFF(b) )
        BUFfree(FSA ((PBUCKET)(b->potcff))->my_handle);
#endif    /* TT_RDR && CFF_RDR */

    BUFfree(FSA hb);

}


#if TT_TTPLUG
/* TT Plugins are in TrueType format. */

/*-------------------*/
/*  CGIFtt_universal */
/*-------------------*/
/*  This function defines the current font as set by the last call
 *  to CGIFfont() as a plugin font.
 */
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFtt_universal (FSP LPUB8 ptr, SL32 rom_font)
#else
UW16 CGENTRY CGIFtt_universal (ptr, rom_font)
    LPUB8 ptr;
    SL32   rom_font;
#endif /* ANSI_DEFS */
{
    if_state.ttplug_font_type = FC_TT_TYPE;
    if(rom_font)
    {
        if_state.ttplug_font_type |= FC_ROM_TYPE;
        if_state.tt_fnt_hdr = ptr;
    }
    else
    {
#if DISK_FONTS
        if(STRLEN((FILECHAR *)ptr) >= PATHNAMELEN)
            return ERRlong_font_name;
        STRCPY(if_state.tt_universal, (FILECHAR *)ptr);
        if_state.tt_fnt_hdr = (LPUB8)if_state.tt_universal;
#endif
    }

    return SUCCESS;
}
#endif  /*  TT_TTPLUG  */

#if UFST_MULTITHREAD
#if defined (ANSI_DEFS)
GLOBAL UW16  add_thread_id_to_list(FSP LPUL32 ids)
#else
GLOBAL UW16  add_thread_id_to_list(ids)
LPUL32 ids;
#endif
{
    UW16 ctr = 0;
    UW16 status = SUCCESS;
    UL32 thread_id = get_thread_id(FSA0);

    /* Add id of current thread to list */
    while (ctr < MAX_THREADS && ids[ctr] != -1L)
    {
        if (ids[ctr] == thread_id)
            return status;
        ctr++;
    }

    if (ctr < MAX_THREADS)
        ids[ctr] = thread_id;
    else
        status = ERR_max_threads_exceeded;

    return status;
}

#if defined (ANSI_DEFS)
GLOBAL UW16  remove_thread_id_from_list(FSP LPUL32 ids)
#else
GLOBAL UW16  remove_thread_id_from_list(ids)
LPUL32 ids;
#endif
{
    UW16 ctr = 0;
    UW16 status = SUCCESS;
    UL32 thread_id = get_thread_id(FSA0);

    while (ctr < MAX_THREADS && ids[ctr] != thread_id)
        ctr++;

    /* Remove id of current thread from thread list */
    if (ctr < MAX_THREADS)
        MEMCPY((LPSB8)&ids[ctr], (LPSB8)&ids[ctr+1], (MAX_THREADS - ctr - 1) * sizeof(UL32));
    else
        status = ERR_thread_not_found_in_list;

    return status;
}

#if defined (ANSI_DEFS)
GLOBAL BOOLEAN  thread_list_is_empty(FSP LPUL32 ids)
#else
GLOBAL BOOLEAN  thread_list_is_empty(ids)
LPUL32 ids;
#endif
{
    UW16 ctr = 0;

    while (ctr < MAX_THREADS && ids[ctr] == -1L)
        ctr++;

    /* Return TRUE if bucket "pb"'s thread list is empty */
    return (ctr < MAX_THREADS) ? FALSE : TRUE;
}

#if defined (ANSI_DEFS)
GLOBAL BOOLEAN  only_thread_in_list(FSP LPUL32 ids, UL32 thread_id)
#else
GLOBAL BOOLEAN  only_thread_in_list(ids, thread_id)
LPUL32 ids;
UL32 thread_id;
#endif
{
    UW16 ctr = 0;

    while (ctr < MAX_THREADS && ids[ctr] != -1L)
        ctr++;

    /* Return TRUE is thread_id is the only thread in list */
    return (ctr == 1 && ids[0] == thread_id) ? TRUE : FALSE;
}

#if defined (ANSI_DEFS)
GLOBAL VOID  print_bucket_status(FSP0)
#else
GLOBAL VOID  print_bucket_status()
#endif
{
    PBUCKET b;
    HBUCKET hb;
    UW16 ctr;

    printf("\n print_bucket_status()");
    hb = ((PDLL)MEMptr(if_state.pserver->hBUCKlru))->f;   /* first BUCKET in lru list */
    while(hb != if_state.pserver->hBUCKlru)
    {
        b = (PBUCKET)MEMptr(hb);
        printf("\n bucket %lx:", b);
        if (b->locked)
        {
            printf(" locked by: ");
            ctr = 0;
            while (ctr < MAX_THREADS)
            {
                if (b->thread_ids[ctr] != -1L)
                    printf(" [%d]=%8x", ctr, b->thread_ids[ctr]);
                ctr++;
            }
        }
        else
            printf(" unlocked!!!");
        hb = b->link.f;            /* next BUCKET in the list */
    }
    printf("\n");
}
#endif

/*-------------------*/
/*     BUCKfind      */
/*-------------------*/
/* Inputs: buck_search_level == 0       buck_search_level > 0
 *    fontindex.cur_tf_num
 *              cur_ssnum
 *              font_type
 *              has_path
 *              cur_pix
 *              cur_font_hdr
 *              pathname
 *              symbolset.tt_platID
 *              symbolset.tt_specID
 *              symbolset.tt_langID
 */
#if defined (ANSI_DEFS)
GLOBAL UW16  BUCKfind(FSP SL32 buck_search_lvl, SL32 purge_bucket, PPBUCKET p_bucket)
#else
GLOBAL UW16
BUCKfind(buck_search_lvl, purge_bucket, p_bucket)
    SL32 buck_search_lvl;
    SL32 purge_bucket;
    PPBUCKET p_bucket;
#endif
{
    SL32         tfnum=0;
    UW16         cur_ssnum=0;
    HBUCKET      hb, hb0;
    PBUCKET      b = NULL;
    UW16         status;
    BOOLEAN      has_path=FALSE;

    LPUB8        cur_font_hdr=0;

    SL32          font_type=0;
#if (DYNAMIC_FONTS && IF_ROM)
    SL32          rom_font;
#endif
    SL32          extern_font=0;   /* Changed from BOOLEAN 6/13/96 jwd, FMT 16. */
    UW16         fst_type=0;
#if UFST_MULTITHREAD
    int thread_id = get_thread_id(FSA0);
#endif

    DBG1("BUCKfind(%ld)\n", buck_search_lvl);

    if( buck_search_lvl == 0 )      /* Typeface Sensitive level */
    {
        tfnum        = if_state.fontindex.cur_tf_num;
        cur_ssnum    = if_state.fontindex.cur_ssnum;
        font_type    = if_state.fontindex.font_type;
        has_path     = if_state.fontindex.has_path;

#if (DYNAMIC_FONTS && IF_ROM)
        rom_font     = (SL32)(font_type & FC_ROM_TYPE);
#endif
/*        extern_font  = ((font_type & FC_EXTERN_TYPE)   == FC_EXTERN_TYPE) + 
                       ((font_type & EF_FORMAT16_TYPE) == EF_FORMAT16_TYPE);

*/
        /* ks - Fixed reported error - Jan 26, 2000 */

        /* Need to setup extern_font based on bitmap/scalable check as well. */
        /* Revisit to optimize/make constants. jwd, 07/21/03.                */


        if ( FC_ISXLFONT(&if_state.fcCur))
         {
#if PCLEO_RDR
            if (if_state.DLBmpInProcess)
               extern_font = PCL_BITMAP_FONT;
            else
#endif
               extern_font  = (((font_type & FC_EXTERN_TYPE) == FC_EXTERN_TYPE) +  /* keb 8/99 */
                  ((EF_FONTTYPE_MASK & EF_XLFONT_TYPE) == EF_XLFONT_TYPE) + 1);
        }
        else      
        {
#if PCLEO_RDR
            if (if_state.DLBmpInProcess)
               extern_font = PCL_BITMAP_FONT;
            else
#endif
               extern_font  = ((font_type & FC_EXTERN_TYPE) == FC_EXTERN_TYPE) + 
                  ((font_type & EF_FORMAT16_TYPE) == EF_FORMAT16_TYPE);
        }
        
        fst_type     = font_type & FC_FONTTYPE_MASK;

        switch (fst_type)
        {
#if IF_RDR
            case FC_IF_TYPE:
                if_state.fontindex.pix = if_state.fontindex.cur_pix;   /* IF disk or ROM */
#if DYNAMIC_FONTS
                if (if_state.fontindex.cur_pix)  /* If cur_pix is valid, then the TFS */
                    has_path = FALSE;   /* is in if.fnt. Even if there if a */
#endif                                  /* pathname, ignore it. */
                break;
#endif  /* IF_RDR */

            default:  break;
        } /* switch (fst_type) */
#if DISK_FONTS
        if (has_path)
            cur_font_hdr = (LPUB8)if_state.fontindex.pathname;
        else
#endif
            cur_font_hdr = if_state.fontindex.cur_font_hdr;
#if FCO_RDR
        if (fst_type == FC_FCO_TYPE)
            cur_font_hdr = (LPUB8)MEMptr(if_state.pserver->FCObject);
#endif
    } /* if( buck_search_lvl == 0 ) */


#if PLUGINS
    else  /* loading a plugin, buck_search_level > 0 */
    {
        has_path = FALSE;
        switch( if_state.fontindex.plug_type )
        {
#if (IF_RDR || PS_IFPLUG)
            case FC_IF_TYPE:   /*  Intellifont plugins  */
            {
                if_state.fontindex.pix = FIentry( FSA buck_search_lvl - 1 );
                tfnum         = if_state.fontindex.pix->tfnum;
                font_type     = FC_IF_TYPE;   /* disk based */
                cur_font_hdr  = (LPUB8)NULL;

/* I don't think this test needs to be #if IF_ROM, but... (sandra, 17 Jun 04) */
#if ROM    
                /* if ROM is enabled, we assume ROM plugins for IF */
                font_type    |= FC_ROM_TYPE;
#endif
                break;
            }
#endif  /* (IF_RDR || PS_IFPLUG) */

#if (TT_RDR && TT_TTPLUG)
            case FC_TT_TYPE:  /* TrueType plugins */
            {
                font_type = if_state.ttplug_font_type;

                tfnum = 0;
                cur_font_hdr = if_state.tt_fnt_hdr;

                if ( !(font_type & FC_ROM_TYPE) )
                    has_path = TRUE;
                break;
            }
#endif  /* TT_RDR && TT_TTPLUG */

#if FCO_RDR  /* If FCO_RDR is enabled, plug_type will ALWAYS be set to FCO_TYPE */
            case FC_FCO_TYPE:  /* MicroType plugins */
            {
                font_type = FC_FCO_TYPE;
                cur_font_hdr = (LPUB8)MEMptr(if_state.pserver->FCO_PluginH);
                tfnum = if_state.fontindex.fcoSearchPath[buck_search_lvl-1];
                break;
               /* NOTE [ mby 09-25-96 ]: tfnum is not strictly correct;
                *   it should have the index number in the lower word AND
                *   the FCO handle in upper word. But this is a benign bug
                *   for now.  */
            }
#endif  /* FCO_RDR */

            default:
                return ERR_no_cgnum;
        }  /* switch if_state.fontindex.plug_type  */

      /*  For any type of plugins, break out details of plugin font.
       */
        cur_ssnum = if_state.fontindex.cur_ssnum;  /* code in tt_if.c fc_if.c */
                    /* checks b->cur_ssnum == UNICODE - mby 11-14-96 */
        extern_font   = ((font_type & FC_EXTERN_TYPE) == FC_EXTERN_TYPE);
        fst_type      = font_type & FC_FONTTYPE_MASK;
#if (DYNAMIC_FONTS && IF_ROM)
        rom_font      = (SL32)(font_type & FC_ROM_TYPE);
#endif
    }
#endif  /*  PLUGINS  */

  /* Search for BUCKET  */

    hb0 = hb = ((PDLL)MEMptr(if_state.pserver->hBUCKlru))->f;   /* first BUCKET in lru list */
    while(hb != if_state.pserver->hBUCKlru)
    {
        b = (PBUCKET)MEMptr(hb);

        /* Search algorithm:
         *  - For TrueType, compare platform ID, spec ID
         *    (if using an ASIAN encoding scheme, compare ssnum)
         *  - For TT, PS, IF (dynamic): if there's a pathname, compare to
         *      b->pathname
         *  - For DYNAMIC/ROM, compare cur_font_hdr
         *  - Else compare tfnum, symbol set, font_hdr, and font_type.
         */
#if TT_RDR
        if (fst_type == FC_TT_TYPE)
        {
            /* TFS search and no plugins */
            if (buck_search_lvl == 0 && !if_state.usePlugins)
            {
               if (b->p.tt.platId != 0  ||  b->p.tt.specId != 0)
                  goto Bf1;  /* match failed */
            }

#if PLUGINS
            /* !TFS search and TT plugins */
            else if (buck_search_lvl > 0 && if_state.fontindex.plug_type == FC_TT_TYPE)
            {
               if (b->p.tt.platId != TT_PLUGPLID  ||  b->p.tt.specId != TT_PLUGSPID)
                  goto Bf1;  /* match failed */
            }
#endif    /* PLUGINS */

#if ASIAN_ENCODING
            /* TFS search and no ASIAN encoding */
            else if (buck_search_lvl == 0 && (is_it_Asian(cur_ssnum) || is_it_Asian(b->cur_ssnum)) )
            {
               if (b->cur_ssnum != cur_ssnum)
                  goto Bf1;  /* match failed */
                if ( FC_ISUSERCMAPTBL(&if_state.fcCur) )
                {
                    /* If user has specified a platform ID and specific ID,
                     * test for a match with the current bucket
                     */
                    if (b->p.tt.platId != if_state.fcCur.user_platID ||
                        b->p.tt.specId != if_state.fcCur.user_specID)
                        goto Bf1;    /* match failed */
                }
            }    /* 11-21-00 jfd */
#endif    /* ASIAN_ENCODING */

            /* All other cases */
            else
            {
               if (b->p.tt.platId != if_state.symbolset.tt_platID  ||
                   b->p.tt.specId != if_state.symbolset.tt_specID)
                  goto Bf1;  /* match failed */
            }
        }
#endif    /* TT_RDR */

#if PST1_RDR
        if ((fst_type == FC_PST1_TYPE) && (b->fst_type == FC_PST1_TYPE))
        {
            BOOLEAN filesmatch = FALSE;
#if DISK_FONTS
            if(has_path && b->has_path)
                filesmatch = (STRNCMP((FILECHAR *)cur_font_hdr,
                                      b->pathname, PATHNAMELEN) == 0);
            else if(!has_path && !b->has_path)
#endif
                filesmatch = (b->cur_font_hdr == cur_font_hdr);
            if(!filesmatch)
                goto Bf1;

            if(!ps_is_same(FSA b))
                goto Bf1;
        }
#endif    /* PST1_RDR */

#if DISK_FONTS
        if (has_path)
        {
            if(b->has_path)
            {
                if( STRNCMP((FILECHAR *)cur_font_hdr, b->pathname, PATHNAMELEN) == 0
#if TT_RDR
                    /*
                     * For TT collections, match on index number too.
                     */

                    && ( (fst_type == FC_TT_TYPE && (b->p.tt.ttc_index == if_state.fcCur.ttc_index))
                    ||   (fst_type != FC_TT_TYPE))
#endif    /* TT_RDR */
                )
                {
                       b->cur_ssnum = cur_ssnum;
                       break;  /* We have a match! (pathname + symset) */
                }
            }
        }
        else
#endif  /* DISK_FONTS */

#if (DYNAMIC_FONTS && IF_ROM)
        if ( (fst_type == FC_IF_TYPE) && (tfnum == 0) && rom_font )
        {
            if (b->cur_font_hdr == cur_font_hdr)
                break;   /* We have a match! (DYNAMIC/ROM, IF format) */
        }
        else
#endif  /* DYNAMIC_FONTS && IF_ROM */

        /*** Test if this is our bucket ***/

        if( (b->tfnum        == tfnum       )   && 
              (b->cur_ssnum    == cur_ssnum   )   &&
                (b->cur_font_hdr == cur_font_hdr)   &&
#if TT_RDR    /* 12-18-00 jfd */
                /*
                 * For TT collections, match on index number too.
                 */
                (  (b->fst_type == FC_TT_TYPE && (b->p.tt.ttc_index == if_state.fcCur.ttc_index))
                || (b->fst_type != FC_TT_TYPE) )
                &&
#endif    /* TT_RDR */
                  (b->font_type    == font_type))
            break;

#if (TT_RDR || PST1_RDR)
Bf1:
#endif
        if(hb == hb0)              /*  if first bucket in lru list, */
        {
#if UFST_MULTITHREAD
            status = remove_thread_id_from_list(FSA b->thread_ids);
            if (thread_list_is_empty(FSA b->thread_ids))
                b->locked = FALSE;     /*  unlock                       */
#else
            b->locked = FALSE;     /*  unlock                       */
#endif
        }

        hb = b->link.f;            /* next BUCKET in the list */
    } /* bucket search loop */

    if(purge_bucket)
    {
        if(hb != if_state.pserver->hBUCKlru)   /* found it; changed != to == */
        {
#if UFST_MULTITHREAD
            status = remove_thread_id_from_list(FSA b->thread_ids);
            if (thread_list_is_empty(FSA b->thread_ids))
#endif
            BUCKfree(FSA hb);         /* jwd, 5/31/01.              */
                                      /* Back to !=. jwd, 09/23/02. */
        }
        return SUCCESS;
    }

    if(hb != if_state.pserver->hBUCKlru)
    {                         /* found it */
      /*  Make BUCKET most recently used */
        DBG("    search succeeded\n");
#if TT_DISK
        if (fst_type == FC_TT_TYPE)
        {
           if(b->has_path)    /* 4-29-94 jfd */
           {
              status = IXopen_file(FSA (PINDEX_ENTRY)NULL, b);
              if (status)
                 return status;
           }
        }
#endif
        if(hb != hb0)              /* if not already first in list... */
        {
            b->locked =TRUE;
#if UFST_MULTITHREAD
            status = add_thread_id_to_list(FSA b->thread_ids);
#endif
            dll_remove(FSA hb);
            dll_after(FSA if_state.pserver->hBUCKlru, hb);
        }
#if UFST_MULTITHREAD
        else
            status = add_thread_id_to_list(FSA b->thread_ids);
#endif
    }
    else  /* not found */
    {
        SL32 againFlag = 1;  /* to fix fragmentation in BUFpool memory */
        DBG("    search failed- making new BUCKET\n");
#if TT_RDR
TryAgain:
#endif
        hb = (HBUCKET)BUFalloc(FSA (SL32)sizeof(BUCKET));
        if(!(hb))
            return ERR_no_buck_mem;
        b = (PBUCKET)MEMptr(hb);
        MEMSET((LPUB8)b, (SL32)0, (SL32)sizeof(BUCKET) );

        b->my_handle   = hb;            /* remember who I am for freeing */
        b->fh          = -1;            /* no open file */
        b->tfnum       = tfnum;
        b->bucket_num  = 0;             /* set to default  */
        b->font_type   = font_type;
        b->fc_format   = if_state.fcCur.format;  /* copy of fontcontext.format word */
        b->fc_ExtndFlags = if_state.fcCur.ExtndFlags;
                                        /* copy of fontcontext.ExtndFlags word */
        b->fst_type    = fst_type;
        b->extern_font = extern_font;
        b->cur_font_hdr = cur_font_hdr;
        b->cur_ssnum   = cur_ssnum;
        b->usePlugins  = if_state.usePlugins;
#if TT_RDR
        /* only copy ttc_index if CURRENT font is a TT font */
        if (FC_ISTT(&if_state.fcCur))
            b->p.tt.ttc_index = if_state.fcCur.ttc_index;
#endif  /* TT_RDR */

#if DISK_FONTS
#if DYNAMIC_FONTS && IF_RDR
/* test was #if ROM - I believe this is correct, but... (sandra, 17 Jun 04) */
#if IF_ROM    
        b->dynIFActive = (fst_type == FC_IF_TYPE) && !extern_font && cur_font_hdr;
        /* If dynamic, cur_font_hdr points to a font in ROM. */
#else
        b->dynIFActive = (fst_type == FC_IF_TYPE) && has_path;
#endif
#endif  /* DYNAMIC_FONTS && IF_RDR */
        b->has_path = has_path;
        if(has_path)
            STRCPY(b->pathname, (FILECHAR *)cur_font_hdr);
#if CFF_RDR && TT_RDR    /* 05-23-01 jfd */
        b->potcff = (PBUCKET)0;
        b->otcff_font = FALSE;
#endif    /* CFF_RDR && TT_RDR */
#endif  /* DISK_FONTS */

#if UFST_MULTITHREAD
        MEMSET(b->thread_ids, (UL32)-1L, MAX_THREADS * sizeof(UL32));
#endif

#if USE_JUMP_TABLES
        switch (b->fst_type)
        {
        case FC_IF_TYPE:
#if IF_RDR    /* should this be one line up? (sandra, 28 Jun 04) */
         DBG("    fst_type = Intellifont\n");
         b->pft = &iffunc_tbl;
         break;
#endif
#if PST1_RDR
        case FC_PST1_TYPE:
         DBG("    fst_type = PostScript\n");
         b->pft = &psfunc_tbl;
         break;
#endif
#if TT_RDR
        case FC_TT_TYPE:
         DBG("    fst_type = TrueType\n");
         b->pft = &ttfunc_tbl;
         break;
#endif /* TT_RDR */
#if FCO_RDR
        case FC_FCO_TYPE:
         DBG("    fst_type = Font Collection Object\n");
         b->pft = &fco_func_tbl;
         break;
#endif /* FCO_RDR */
        default:
         BUFfree(FSA hb);
         return ERR_fst_type;
        }

        status =
          ((*((PIF_FUNC_TBL)b->pft)->load_font)(FSA (PFONT_DES)cur_font_hdr, b));

#else    /* !USE_JUMP_TABLES */

         switch (b->fst_type)
         {
#if IF_RDR
            case FC_IF_TYPE:
               status = ifload_font (FSA (LPSB8)cur_font_hdr, b);
               break;
#endif
#if PST1_RDR
            case FC_PST1_TYPE:
               status = psload_font (FSA (LPSB8)cur_font_hdr, b);
               break;
#endif
#if TT_RDR
            case FC_TT_TYPE:
               status = ttload_font (FSA (LPSB8)cur_font_hdr, b);
               break;
#endif
#if FCO_RDR
            case FC_FCO_TYPE:
               status = fco_load_font (FSA (LPSB8)cur_font_hdr, b);
               break;
#endif
            default:
               BUFfree(FSA hb);  /* added 09-16-96 */
               return (ERR_fst_type);
         }
#endif /* USE_JUMP_TABLES */

        if (status)
        {
            DBG("    load_font() failed in BUCKfind()\n");
            BUFfree(FSA hb);
#if TT_RDR
            if (status == ERR_TT_MEMFAIL && againFlag) {   /* Low Memory */
                /* Check for TrueType BUFalloc failure. Then try again.
                 * The 1st call to load_font should free all the other
                 * buckets; hence the 2nd time around might work.     */
                againFlag = 0;
                goto TryAgain;
            }
#endif
            return status;
        }
        else
            dll_after(FSA if_state.pserver->hBUCKlru, hb);      /* link at start of BUCKET lru list */

#if TT_RDR && CFF_RDR    /* 05-23-01 jfd */
        /* If processing an OpenType CFF font, create the CFF bucket. */
        if (B_ISOTCFF(b))
        {
           PBUCKET otcff_b = NULL;
           HBUCKET otcff_hb;

           otcff_hb = (HBUCKET)BUFalloc(FSA (SL32)sizeof(BUCKET));
           if(!(otcff_hb))
              return ERR_no_buck_mem;

           otcff_b = (PBUCKET)MEMptr(otcff_hb);
           MEMSET((LPUB8)otcff_b, (int)0, (int)sizeof(BUCKET) );

           otcff_b->my_handle   = otcff_hb;      /* remember who I am for freeing */
           otcff_b->bucket_num  = 0;              /* set to default  */
           otcff_b->fst_type    = FC_PST1_TYPE;
           otcff_b->extern_font = extern_font;
           otcff_b->cur_ssnum   = cur_ssnum;
           otcff_b->cur_font_hdr = cur_font_hdr;
           otcff_b->p.ps.cft.CFFTableOffset = b->p.tt.CFFTableOffset;
           otcff_b->p.ps.cft.CFFTableSize = b->p.tt.CFFTableSize;
           otcff_b->otcff_font = TRUE;

           otcff_b->fh            = b->fh;
           otcff_b->tfnum         = b->tfnum;
           otcff_b->font_type     = b->font_type;
           otcff_b->fc_format     = b->fc_format;
           otcff_b->fc_ExtndFlags = b->fc_ExtndFlags;
           otcff_b->usePlugins    = b->usePlugins;

#if USE_JUMP_TABLES
           DBG("    fst_type = PostScript\n");
           otcff_b->pft = &psfunc_tbl;

           status =
              ((*((PIF_FUNC_TBL)otcff_b->pft)->load_font)(FSA (PFONT_DES)cur_font_hdr, otcff_b));

#else    /* !USE_JUMP_TABLES */
           status = psload_font (FSA (LPSB8)cur_font_hdr, otcff_b);
#endif /* USE_JUMP_TABLES */
           if (status)
           {
              DBG("    load_font() failed in BUCKfind()\n");
              BUFfree(FSA otcff_hb);
              b->potcff = (PBUCKET)0;
              return status;
           }
           b->potcff = otcff_b;
        }
#endif    /* TT_RDR && CFF_RDR */
    }  /* bucket not found; made a new bucket. */

    /* Copy of fontcontext.format word. MUST do this here
     * in case we skipped the bucket-not-found code block.
     */
    b->fc_format = if_state.fcCur.format;

    /* Copy of fontcontext.ExtndFlags word. MUST do this here
     * in case we skipped the bucket-not-found code block.
     */
    b->fc_ExtndFlags = if_state.fcCur.ExtndFlags;


#if PLUGINS
    /*  If have only determined up to TFS level, now determine plugins.  */

#if FCO_RDR
    /* If FCO_RDR is enabled, always use FCO plugins regardless of fst type.
     */
    if (if_state.fontindex.fcoMakeNewSrchPath)
    {
        if_state.fontindex.plug_type = FC_FCO_TYPE;
        fco_pluginSearchPath(FSA b, if_state.fontindex.fcoSearchPath,
                             &if_state.fontindex.num_searches);
        if_state.fontindex.fcoMakeNewSrchPath = 0;

#if PCLEO_RDR

        /* If TFS was a pcleo, need to load symbolset first and last
         * character in order to locate the character in the FCO plugins */

        if (if_state.fcCur.format & FC_EXTERN_TYPE && (b->cur_ssnum != DL_SYMSET))
        {
           if (!b->usePlugins)  /* mby, 6-06-95 */
           {
              if (!SYMnoMap(FSA if_state.fcCur.font_hdr, if_state.fcCur.format)) {
                 BUFfree(FSA hb);    /* added 09-16-96 */
                 return ERR_IXnew_ss;
              }
           }
           else if (FC_SSMAP(&if_state.fcCur))
           {
              if (!SYMnew(FSA if_state.fcCur.ssnum, if_state.fcCur.format)) {
                 BUFfree(FSA hb);    /* added 09-16-96 */
                 return ERR_IXnew_ss;
              }
           }
        }
#endif /* PCLEO_RDR */

    }  /* endif (if_state.fontindex.fcoMakeNewSrchPath)  */
#else  /* ~FCO_RDR */

    if(if_state.fontindex.num_searches <= 1  &&  b->usePlugins) /* setup plugin search path */
    {
        if_state.fontindex.plug_type = 0xFFFF;   /* Invalid type */

#if TT_TTPLUG
        /* also make sure global disable-all-plugins bit is OFF (i.e. plugins are enabled) */
        if(fst_type == FC_TT_TYPE && !FC_NOPLUGINS(&if_state.fcCur))
        {
#if STIK
            fs_GlyphInfoType *fsg = (fs_GlyphInfoType *)MEMptr(b->p.tt.buffInfo);

            /* Do not augment stik fonts with plugins */
            /* for CCC font */
            if (!(IS_STIK_FONT(fsg) && FC_STIKNOPLUGINS(&if_state.fcCur)))
#endif    /* STIK */
            {
            if_state.fontindex.plug_type = FC_TT_TYPE;
            if_state.fontindex.num_searches++;    /* added another search level */
            }
        }
#endif    /* TT_TTPLUG */

#if (IF_RDR || PS_IFPLUG)   /* Intellifont plugins  */
        /* also make sure global disable-all-plugins bit is OFF (i.e. plugins are enabled) */
        if( !FC_NOPLUGINS(&if_state.fcCur) && 
                ((fst_type == FC_IF_TYPE) ||
                 ((fst_type == FC_PST1_TYPE) && PS_IFPLUG) ))
        {
/* A quick rundown:
    if AWT font substitution is on, then pass bits in awt header to
        IXset_search_path().
    else pass bits in b->bucket_num to IXset_search_path().
        if B_PLUGIN_TYPE_TT is set, then use the TT plugin
*/
            {
                {
                    if_state.fontindex.plug_type = FC_IF_TYPE;
                    status = IXset_search_path(FSA b->bucket_num);
                    if (status)
                       return status;
                }
            }
        }
#endif  /* (IF_RDR || PS_IFPLUG)   Intellifont plugins  */
    }  /* if (if_state.fontindex.num_searches <= 1) */

#endif  /*  FCO_RDR  */
#endif  /*  PLUGINS  */

    b->locked = TRUE;
    {
#if UFST_MULTITHREAD
        status = add_thread_id_to_list(FSA b->thread_ids);
#endif
    }
    if_state.pbucket = b;
    *p_bucket = b;
    return SUCCESS;

}  /* BUCKfind */


/*------------------------------------------------------------------*/
/*         B u f f e r    M e m o r y    M a n a g e m e n t        */

/*------------------*/
/*     BUFalloc    */
/*------------------*/
/* Acquire size SB8s. Free lru BUCKETs if need be   */
#if defined (ANSI_DEFS)
GLOBAL MEM_HANDLE BUFalloc(FSP SL32 size)
#else
GLOBAL MEM_HANDLE
BUFalloc(size)
    SL32 size;
#endif
{
    MEM_HANDLE hbuf;
    HBUCKET hb;
#if UFST_MULTITHREAD
    PBUCKET b;
    HBUCKET next_hb;
#endif

    /* AJ - added for memory fund check*/
    if (size > if_state.pserver->mem_fund[BUFFER_POOL])
        return NIL_MH;

    hb = ((PDLL)MEMptr(if_state.pserver->hBUCKlru))->b;
    while ( (hbuf=MEMalloc(FSA BUFFER_POOL, size)) == NIL_MH
#if UFST_MULTITHREAD
                && hb != if_state.pserver->hBUCKlru
#endif
        )
    {
       if(dll_empty(FSA if_state.pserver->hBUCKlru)) return NIL_MH;
#if UFST_MULTITHREAD
        b = (PBUCKET)MEMptr(hb);
        next_hb = b->link.b;
        if (thread_list_is_empty(FSA b->thread_ids))
            BUCKfree(FSA hb);
        hb = next_hb;            /* next BUCKET in the list */
#else
       hb = ((PDLL)MEMptr(if_state.pserver->hBUCKlru))->b;
       if(((PBUCKET)MEMptr(hb))->locked) return NIL_MH;
              /* Only the most recently used BUCKET can be locked. */
       BUCKfree(FSA hb);     /* free lru BUCKET */
#endif
    }
    return hbuf;
}


/*------------------*/
/*     BUFfree      */
/*------------------*/
#if defined (ANSI_DEFS)
GLOBAL VOID  BUFfree(FSP MEM_HANDLE h)
#else
GLOBAL VOID
BUFfree(h)
    MEM_HANDLE h;
#endif
{
    MEMfree(FSA BUFFER_POOL, h);
}


#if PRINT_BUCKETS
print_buckets(FSP0)
{
    HBUCKET      hb;
    PBUCKET      b;
    hb = ((PDLL)MEMptr(if_state.pserver->hBUCKlru))->f;   /* first BUCKET in lru list */
    while(hb != if_state.pserver->hBUCKlru)
    {
        b = (PBUCKET)MEMptr(hb);
        hb = b->link.f;            /* next BUCKET in the list */
        printf("bucket %lx:  tfnum = %ld  bucket_num = %04X\n", b, b->tfnum, b->bucket_num);
        printf("  font_type = %04X, extern_font = %d, cur_ssnum = %04X\n", b->font_type, b->extern_font, b->cur_ssnum);
        printf("  has_path = %d", b->has_path);
#if DISK_FONTS
        if (b->has_path)
           printf("  pathname = %s", b->pathname);
#endif
        printf("\n");
    }
}
#endif

 

cache.c   

/* 
 * Copyright (C) 2005 Monotype Imaging Inc. All rights reserved.
 */

/* $Header:   I:/BULL/URIP/RTS/DEP/CACHE.C_V   1.54   Dec 14 2004 15:47:36   galejss  $ */
/* $Log:   I:/BULL/URIP/RTS/DEP/CACHE.C_V  $ 
 * 
 *    Rev 1.54   Dec 14 2004 15:47:36   galejss
 * make all DBG calls 16-bit-compatible
 * 
 *    Rev 1.53   Nov 30 2004 11:34:20   jardima
 * Memory fund check added to TEMPCHARalloc
 * 
 *    Rev 1.52   Nov 29 2004 17:36:38   jardima
 * added code for memory fund check
 * 
 *    Rev 1.51   Oct 26 2004 11:32:44   dugganj
 * Multithreading changes.
 * 
 *    Rev 1.50   Oct 14 2004 11:46:56   galejss
 * NEW_POOL becomes CHARGEN_POOL
 * 
 *    Rev 1.49   Oct 13 2004 08:08:40   dugganj
 * Corrected !ANSI_DEFS function declaration for
 * CACfont_free().
 * 
 *    Rev 1.48   Oct 01 2004 14:41:52   azimaf
 * added new function CACfont_free to handle
 * freeing the CASHE pool
 * 
 *    Rev 1.47   Sep 27 2004 16:14:30   dugganj
 * Added multithread support.
 * 
 *    Rev 1.46   Sep 23 2004 09:17:18   dugganj
 * Fixed incorrect SUN declarations for functions
 * TEMPCHARalloc() and TEMPCHARfree().
 * 
 *    Rev 1.45   Sep 09 2004 16:56:12   galejss
 * add TEMPCHARalloc / free functions (which use new 3rd memory pool NEW_POOL)
 * 
 *    Rev 1.44   Aug 10 2004 14:08:28   galejss
 * new USE_ASIAN_CACHE test
 * 
 *    Rev 1.43   Jul 16 2004 13:31:58   galejss
 * changes for extended disk/rom support; BOOLEAN type cleanup
 * 
 *    Rev 1.42   Apr 26 2004 17:28:56   GalejsS
 * support for below-the-line IFBITSPLIT option; fix incorrect scope of conditional compile for char-by-ref
 * 
 *    Rev 1.41   Oct 17 2003 16:35:58   Galejs
 * compile fixes for MEM_TRACE, ASIAN_HASH_TRACE options
 * 
 *    Rev 1.40   Aug 22 2003 08:57:08   LynchR
 * Updated copyright notice.
 * 
 *    Rev 1.39   Jul 11 2003 12:12:18   Galejs
 * replace cache_by_ref_mode tests with CACHE_BY_REF tests
 * 
 *    Rev 1.38   Jun 19 2003 18:56:14   Galejs
 * move debug flags into header files; get rid of NON_IF_FONT
 * 
 *    Rev 1.37   Jun 12 2003 16:12:08   Joe
 * Added "cache-by-reference" support.
 * 
 *    Rev 1.36   Oct 01 2002 12:25:32   Galejs
 * add cast for chId
 * 
 *    Rev 1.35   Sep 30 2002 13:13:58   Galejs
 * 32-bit charcode support (for rjl)
 * 
 *    Rev 1.34   Sep 23 2002 15:24:54   Galejs
 * fix possibly-uninitialized-vbl warnings (part of bug # 76)
 * 
 *    Rev 1.33   May 03 2001 20:13:12   Galejs
 * data-type cleanup
 * 
 *    Rev 1.32   Mar 29 2000 13:48:50   galejs
 * fix massively messed-up indents
 * 
 *    Rev 1.31   27 Mar 2000 14:55:36   JOE
 * CACHE with NO_SYMSET_MAPPING fix (by jwd).
 * 
 *    Rev 1.30   Aug 18 1999 17:25:40   galejs
 * FONT becomes cacheFONT (to resolve conflict with customer's typedef)
 * 
 *    Rev 1.29   Aug 17 1999 11:40:10   galejs
 * include-file changes
 * 
 *    Rev 1.28   12 Jan 1999 18:31:48   GALEJS
 * move EXTERN dcls
 * 
 *    Rev 1.27   22 Jun 1998 18:21:10   GALEJS
 * more reentrancy parm changes (compressed-cache)
 * 
 *    Rev 1.26   15 Jun 1998 14:32:30   GALEJS
 * reentrancy changes (parm-passing, CHARalloc(), CHARfree())
 * 
 *    Rev 1.25   01 Apr 1998 19:11:34   GALEJS
 * move all GLOBALs to IF_STATE; CAChdr_font() interface change
 * 
 *    Rev 1.24   30 Mar 1998 12:11:20   GALEJS
 * move 2 MLOCALs into if_state, delete 1 unused MLOCAL
 * 
 *    Rev 1.23   24 Mar 1997 11:44:16   MIKE
 * Fixed CACinsert() for grayscale
 * 
 *    Rev 1.22   16 Oct 1996 16:38:24   JOE
 * In CACinsert(), before calculating size of character, test whether
 * processing bitmap or outline.
 * 
 *    Rev 1.21   04 Oct 1996 09:10:10   JOE
 * Removed CTRL-Z at end of file.
 * 
 *    Rev 1.20   01 Oct 1996 16:40:44   JOE
 * Implemented new ASIAN cache architecture.
 * 
 *    Rev 1.19   24 Jan 1996 17:24:54   AL
 * Compressed cache
 * 
 *    Rev 1.18   05 Dec 1995 13:27:16   MERRILL
 * cleaned up warnings for borland4.0
 * 
 *    Rev 1.17   07 Apr 1995 08:36:32   LISA
 * Changed copyright from Miles Inc. to Bayer Corp.
 * 
 *    Rev 1.16   13 Feb 1995 15:10:08   JOE
 * In FNTfree(), when freeing the hash table, removed call to dll_remove()
 * because it is unnecessary and was causing an infinite loop.
 * 
 *    Rev 1.15   26 Jan 1995 16:22:44   JOE
 * ASIAN cache manager changes:
 * In CACinsert(), check if MEMalloc() call failed before inserting character in hash list.
 * In CACfont() and CAChdr_font(), return error if not enough cache memory for hash list.
 * In FNTfree(), free hash table.
 * 
 *    Rev 1.14   26 Sep 1994 09:37:44   JOE
 * In CAChdr_purge(), reset similar_fonts_purged flag before
 * looping thru every font.
 * 
 *    Rev 1.13   20 Sep 1994 11:50:06   JOE
 * In CAChdr_font(), conditionally compiled statements which reference
 * "font_hdr" field of fontcontext to resolve compiler error.
 * In same function, returning ERRfont_hdr_purge error if this function
 * iis not supported.
 * 
 *    Rev 1.12   11 Sep 1994 09:02:48   JOE
 * Added new functions CAChdr_purge() and CAChdr_font().
 * 
 *    Rev 1.11   05 Aug 1994 20:17:52   MIKE
 * Added FCO changes from 1.8.1.1
 * 
 *    Rev 1.10   21 Apr 1994 15:43:10   LISA
 * Made modifications to copyright/disclaimer notice.
 * 
 *    Rev 1.9   25 Jan 1994 10:45:08   MAIB
 * Created a two-byte character code caching scheme, conditionally compiled
 * on ASIAN_ENCODING
 * 
 *    Rev 1.8   01 Nov 1993 13:09:56   MAIB
 * Additional check for current font added
 * 
 *    Rev 1.7   29 Oct 1993 17:27:58   MAIB
 * Fixed condition missed in CACfont() optimization
 * 
 *    Rev 1.6   25 Oct 1993 10:58:52   MAIB
 * Optimizations for cache access and font access in place
 * 
 *    Rev 1.5   06 May 1993 16:09:36   MIKE
 * In CACfont() change "has_path" condition from NON_IF_FONT to
 *   PST1_DISK || TT_DISK || (DYNAMIC_FONTS && IF_DISK).
 *   has_path is true for IF disk + dynamic font.
 * 
 *    Rev 1.4   12 Feb 1993 19:38:28   MIKE
 * Application Generated Bitmap support: in BMfree() call
 * app_free_character() to clear char from cache.
 * 
 *    Rev 1.3   12 Feb 1993 13:55:46   JOE
 * VXWorks support.
 * 
 *    Rev 1.2   14 Jan 1993 13:55:32   LISA
 * Removeed CtrlZ character from end of file
 * 
 *    Rev 1.1   11 Dec 1992 15:31:42   LISA
 * Made change to Log keyword
 * 
 *    Rev 1.0   09 Dec 1992 15:25:46   LISA
 * Initial revision.
*/
/* cache.c */
/*
 *
 * History
 *
 *    29-Jul-90  awr   changed conditional compile on MEMstat() from DEBUG
 *                     to MEM_TRACE
 *    05-Aug-90  awr   added bitMapCount in FONTCONTEXT to improve cache
 *                     performance. If last bitmap is freed from a font
 *                     and it's not the current font, then the font is freed.
 *    20-Nov-90  jfd   Compiling all routines conditionally based on CACHE;
 *                     Added  #include "cgconfig.h".
 *    04-Dec-90  jfd   Moved "include" statement for  "cgconfig.h" to line
 *                     following "port.h"
 *    28-Jan-91  jfd   Made size arg of BMnew() LONG
 *                     Made size arg of MEMalloc() LONG
 *    30-Jan-91  dET   Added function prototyping for MSC.
 *    31-Jan-91  dET   Modify for MSC multi-model compilation.
 *     3-Feb-90  awr   Split BMnew() into CACalloc() and CACinsert()
 *                     changed make_char() for memory callbacks
 *                     changed mem_avail[] to a LONG.
 *     8-Feb-91  awr   Added dll.h to declare functions.
 *                     Moved FNTfree() call in CGIFfont() to start of
 *                     FNTfind().
 *                     Renamed FNTfind() to CACfont().
 *                     Removed BMnew()- no longer used.
 *    05-Mar-91  jfd   Added new routine CACpurge().
 *    06-Mar-91  jfd   In CACexit(), free list headers.
 *                     Changed CACdefund() to BOOLEAN and am calling
 *                     CACExit() if necessary.
 *    09-Apr-91  dET   Added print_fnt_lru() and cac_dump routines for aid
 *                     in debugging. 
 *    17-Jun-91  jfd   Moved "debug.h" after "port.h".
 *                     Moved "cgconfig.h" before "port.h".
 *    26 Jun 91  ss    Added not LINT_ARGS prototype for FNTfree().
 *    18-Aug-91  awr   Added htileBM to keep track of tile bm memory
 *    28-Aug-91  jfd   Added function prototype for purge_page() and
 *                     (*free)() to resolve compiler warnings.
 *    29-Aug-91  jfd   In CACfont(), replaced call to structs_are_equal()
 *                     with call to FCis_equal().
 *    25-Sep-91  jfd   In CACpurge(), changed type of argument from
 *                     "FONTCONTEXT *" to "PFONTCONTEXT" to get rid of
 *                     compiler warning.
 *    28-Seo-91  awr   Use CGIFinitstate to signal whether cache is
 *                     initialized and protect against out of sequence
 *                     calls to CACinit() or CACexit()
 *    14-Feb-92  jfd   Included "mixmodel.h".
 *    26-Feb-92  jfd   In CACfont(), conditionally compiled all references
 *                     to "fc->font_hdr" based on EXTERN_FONT.
 *                     Included <string.h> dur to STRNCMP call.
 *    03-Apr-92  rs    Portability cleanup (see port.h).
 *    05-Apr-92  rs    Fix CACfont - always said font was found after call
 *                     to 'FCis_equal()'.
 *    12 May 92  ss    Changed conditional compiles based on EXTERN_FONT
 *                     to (PST1I || TT_RDR) since EXTERN_FONT is used
 *                     elsewhere to mean PCLEO.
 *    08-Jul-92  rs    Code cleanup.
 *   21-Jul-92   awr   Conditional compile changes.
 *   05-Aug-92   jfd   Replaced calls to FCis_equal() with MEMCMP for
 *                     optimization.
 *   04-Sep-92   jfd   In CACfont(), moved setting of "has_path" outside
 *                     of "for" loop to ensure thatit is set properly.
 *   17-Nov-92   rs    Add ANSI function definitions base on ANSI_DEFS.
 *   08-Feb-93   jfd   VXWorks support.
 *   09-Feb-93   mby   Application Generated Bitmap support: in BMfree() call
 *                     app_free_character() to clear character from cache.
 *   05-May-93   mby   In CACfont() change has_path condition from NON_IF_FONT
 *                     to PST1_DISK || TT_DISK || (DYNAMIC_FONTS && IF_DISK)
 *                     Set has_path if dynamic font and IF disk.
 *   25-Oct-93   maib  Conditionally left out CACaccess, now inline in CGIFchar.
 *                     Optimized CACfont for multi-threading
 *   29-Oct-93   maib  Fixed optimization when same fontcontext passed
 *   01-Nov-93   maib  Made sure to check for valid pfontCur before comparing
 *                     fontcontexts
 *   25-Jan-94   maib  Included new cache accessing scheme for ASIAN_ENCODING
 *   30-Aug-94   jfd   Added new functions CAChdr_purge() and
 *                     CAChdr_font().
 *   20-Sep-94   jfd   In CAChdr_font(), conditionally compiled statement
 *                     which references "font_hdr" field of fontcontext
 *                     to resolve compiler error.
 *                     In same function, returning ERRhdr_font_purge error
 *                     if this function is not supported.
 *   23-Sep-94   jfd   In CAChdr_purge(), reset similar_fonts_purged
 *                     before looping thru every font.
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * FCO Changes from 1.8.1.1:
 *   15-Jun-94   mby   In CACfont() has_path = 0 if fst type is FCO.
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 *   26-Jan-95   jfd   Made the following changes to ASIAN_ENCODING
 *                     version of cache manager:
 *                     In CACinsert(), check if MEMalloc() call failed
 *                     before inserting character in hash list.
 *                     In CACfont() and CAChdr_font(), return error if
 *                     there is not enough cache memory for hash list.
 *                     In FNTfree(), free hash table.
 *   13-Feb-95   jfd   In FNTtree(), when freeing the hash table, removed
 *                     call to dll_remove() because it is unnecessary.
 *   01-Oct-96   jfd   Implemented new Asian cache architecture.
 *                     Added option for Asian hash trace.
 *                     Deleted obsolete function CACaccess().
 *                     Replaced function CAChashLookup() with CACbmLookup().
 *   16-Oct-96   jfd   In CACinsert(), before calculating size of character,
 *                     test whether processing bitmap or outline.
 *   24-Mar-97   mby   In CACinsert() correctly calculate size of grayscale
 *                     char, which was not happening.
 *                     Fixed a few warnings; removed BorlandC #pragma.
 *    20-Mar-98  slg    "MLOCAL fcCur" set but never used - delete
 *    24-Mar-98  slg    Move MLOCALs hFNTlru, hBigBM into if_state
 *    01-Apr-98  slg  Move all GLOBALs into IF_STATE.    Also - add 2nd parm to
 *                    CAChdr_font() = ptr to "similar_fonts_purged" flag.
 *    15-Jun-98  slg    Same version of CHARfree() for CACHE and non-CACHE;
 *                    Add non-CACHE version of CHARalloc();
 *                    parameter-passing changes for reentrancy
 *  24-Mar-00  jwd  Cache w/ NO_SYMSET_MAPPING fix.
 *  12-Jun-03  jfd  Added "cache-by-reference" support.
 *
 */

#ifdef VXWORKS
#include "vxWorks.h"
#endif

#include <stdio.h>
#include <string.h>

#include "cgconfig.h"

#include "ufstport.h"
#include "dbg_ufst.h"

#include "shareinc.h"

#include "mixmodel.h"
#include "dll.h"

#if CACHE

#ifdef LINT_ARGS
MLOCAL VOID        BMfree(FSP HIFBITMAP);
MLOCAL VOID        FNTfree(FSP HIFFONT);
#if DEFUND
MLOCAL VOID        purge_page(FSP UW16, MEM_HANDLE, VOID (*)(FSP MEM_HANDLE));
#endif /* DEFUND */
GLOBAL UW16        CAChdr_purge(FSP PFONTCONTEXT);
MLOCAL UW16        CAChdr_font (FSP PFONTCONTEXT, UW16*);
#if ASIAN_ENCODING && ASIAN_HASH_TRACE
GLOBAL VOID        hash_trace(FSP PFONT);
#endif
#else /* not LINT_ARGS */
MLOCAL VOID        FNTfree();           /*  added -ss 6/26/91  */
#if DEFUND
MLOCAL VOID        purge_page();
#endif /* DEFUND */
GLOBAL UW16        CAChdr_purge();
MLOCAL UW16        CAChdr_font ();
#if ASIAN_ENCODING && ASIAN_HASH_TRACE
GLOBAL VOID        hash_trace();
#endif
#endif /* LINT_ARGS */


/*
 * 9/24/96 jfd
 * return a MEM_HANDLE to the IFBITMAP for a particular
 * character ID, look in the font passed
 */
#if USE_ASIAN_CACHE
#if defined (ANSI_DEFS)
GLOBAL MEM_HANDLE CACbmLookup(FSP PFONT pf, UL32 chId)
#else
GLOBAL MEM_HANDLE 
CACbmLookup(pf, chId)
  PFONT pf;
  UL32 chId;
#endif
{
#if USE_LOW_BYTE
  UB8 row = (chId & 0x00ff);
#else
  UB8 row = ((chId & 0xff00) >> 8);
#endif
  MEM_HANDLE hItem = pf->hash_table[row];
  PIFBITMAP pifb;

  /*
   * hrowDLL is a handle to the first IFBITMAP of a list of IFBITMAPS
   * for the particular row. traverse each IFBITMAP item to determine
   * if the character has been previously cached. if found, return the
   * handle to the IFBITMAP item. if not found, return null...
   */
  while (hItem != NIL_MH)
  {
    pifb = (PIFBITMAP)MEMptr(hItem);
    if ((UL32)(pifb->index) == chId)
      return hItem;
    hItem = pifb->f;
  }

  return (MEM_HANDLE)0L;
}
#endif  /* USE_ASIAN_CACHE */


/*
 * 1/25/94 maib
 * return a MEM_HANDLE to the hash list item for a particular
 * character ID, look in the font passed
 */


/*----------------------*/
/*       BMfree         */
/*----------------------*/
/*  Free an IFBITMAP. Remove all references to this bitmap. References can
 *  be from FONTs or from hBigBM.
 */
#if defined (ANSI_DEFS)
MLOCAL VOID BMfree(FSP HIFBITMAP hbm)
#else
MLOCAL VOID
BMfree(hbm)
    HIFBITMAP hbm;              /* handle of IFBITMAP that is to be freed */
#endif
{
    PIFBITMAP bm;
    HIFFONT   hf;
    PFONT     f;
#if IFBITSPLIT
    BOOLEAN in_two_parts = TRUE;
#endif

    if(hbm == if_state.hBigBM)
        if_state.hBigBM = (HIFBITMAP)0L;

    bm = (PIFBITMAP)MEMptr(hbm);       /* Recover pointer to the IFBITMAP */

  /*  Remove the reference to the IFBITMAP from the font. If there are
   *  no more bitmaps in the font and the font is not the current font
   *  then free up the font also.
   */

    hf = bm->hiffont;                          /* handle to my FONT owner */
    f = (PFONT)MEMptr(hf);
#if IFBITSPLIT && OUTLINE
    /* outline memory is NOT declared in two parts (unlike bitmap & graymap memory) */
    if (FC_ISOUTLINE(&f->fc))
        in_two_parts = FALSE; 
#endif
/*
 * 1/25/94 maib
 * new caching scheme for asian encoding
 */
#if USE_ASIAN_CACHE
    remove_from_list(FSA hbm, f);  /* moved here from after "dll_remove(hbm)" */
#else
    *(f->hbuf+bm->index) = (HIFBITMAP)0L;      /* forget about me         */
#endif /* USE_ASIAN_CACHE */
    if(!(--f->bitmapCount) && (hf != if_state.hfontCur))
        FNTfree(FSA hf);

    dll_remove(FSA hbm);                    /*  Remove IFBITMAP from lru list */

#if ALIEN_BITS
    if (FC_ISAPPGEN( &(f->fc) ))
    {
        app_free_character(hbm);
        return;
    }
#endif  /* ALIEN_BITS */

#if IFBITSPLIT
    if (in_two_parts)
    {                
    IFBITMAP *pbm;

        pbm = (IFBITMAP *)MEMptr(hbm);
        MEMfree(FSA CACHE_POOL, pbm->datahandle);           /*  Free the IFBITMAP memory      */
    }
#endif

    MEMfree(FSA CACHE_POOL, hbm);           /*  Free the IFBITMAP memory      */
}

/*----------------------*/
/*     CACinsert        */
/*----------------------*/
/*  Insert the character whose handle is hbm into the current font
 *  at index chId.
 *  ASSUMES that hfontCur and pfontCur are valid.
 *  Returns a handle to the cached bitmap which may be different than
 *  the input handle if cache compression is used.  In that case, the
 *  caller should not rely on the input handle to be valid.
 */
#if defined (ANSI_DEFS)
GLOBAL HIFBITMAP CACinsert(FSP HIFBITMAP hbm, UL32 chId)
#else
GLOBAL HIFBITMAP
CACinsert(hbm, chId)
    HIFBITMAP hbm;
    UL32     chId;
#endif
{
    PIFBITMAP bm;
#if OUTLINE
    PIFOUTLINE out;
#endif
    HIFBITMAP retval;
    SL32 size=0;    /* size of bitmap/outline/graymap */

    retval = hbm;
    bm = (PIFBITMAP)MEMptr(hbm);

    if (FC_ISBITMAP(&(if_state.pfontCur->fc)))
    {
        size = (SL32)bm->width * (SL32)bm->depth;
    }
#if GRAYSCALING
    else if (FC_ISGRAY(&(if_state.pfontCur->fc)))
    {
        size = bm->size;
    }
#endif
#if OUTLINE
    else
    {
        out = (PIFOUTLINE)MEMptr(hbm);
        size = (SL32)out->size * (SL32)out->depth;
    }
#endif

#if COMPRESSED_CACHE
  {
    HIFBITMAP hcmp;
    PIFBITMAP pbuf;
    UW16 status;


    if(!FC_ISBITMAP(&if_state.pfontCur->fc))    /* only compress bitmaps */
        goto cache_it;


    /* Make sure current fonts decompression IFBITMAP is at least
     * as big as the one we are inserting.  If not, reallocate a
     * bigger one.
     */
    if(if_state.pfontCur->hifbm == NIL_MH)
    {
        if_state.pfontCur->hifbm = (HIFBITMAP)CHARalloc(FSA (SL32)BMHEADERSIZE+size);
        if(if_state.pfontCur->hifbm == NIL_MH)
            goto cache_it;    /* cache the incomming character as is */
        pbuf = if_state.pfontCur->pifbm = (PIFBITMAP)MEMptr(if_state.pfontCur->hifbm);
        if_state.pfontCur->size = size;
    }
    else
        pbuf = if_state.pfontCur->pifbm;

    if(if_state.pfontCur->size < size)
    {
        MEMfree(FSA CACHE_POOL,if_state.pfontCur->hifbm);    /* free the one we've outgrown */
        if_state.pfontCur->hifbm = (HIFBITMAP)CHARalloc(FSA (SL32)BMHEADERSIZE+size);
        if(if_state.pfontCur->hifbm == NIL_MH)
            goto cache_it;    /* cache the incomming character as is */
        pbuf = if_state.pfontCur->pifbm = (PIFBITMAP)MEMptr(if_state.pfontCur->hifbm);
        if_state.pfontCur->size = size;
    }

    status = compress_ifbitmap(FSA bm, pbuf, &hcmp);

    if(status==SUCCESS)
    {
#define TEST_COMPRESSED_CACHE 0  /* set to 1 to test */

#if TEST_COMPRESSED_CACHE
        {
            UW16 status;
            UB8 *p, *q;
            SL32 size;
            PIFBITMAP pcmp;

            pcmp = (PIFBITMAP)MEMptr(hcmp);
            status = decompress_ifbitmap(FSA pcmp, if_state.pfontCur->pifbm);
            if(status && status != ERRcmpr_notcompressed)   /* error */
                goto test_bad;

            size = (SL32)BMHEADERSIZE + (SL32)bm->width * (SL32)bm->depth;


            p = (UB8*)bm;
            q = (UB8*)if_state.pfontCur->pifbm;
            while(size--)
                if(*p++ != *q++)

            goto test_good;
test_bad:
            printf("Decompressed bitmap differs from compressed bitmap\n");
            exit(9);
        }
test_good:
#endif

    /* Copy the full bitmap into the buffer ifbitmap */
        {
            UB8 *p, *q;
            SL32 size;
            size = (SL32)bm->width * (SL32)bm->depth;

            *if_state.pfontCur->pifbm = *bm;   /* header */
            p = (UB8*)&bm->bm[0];
            q = (UB8*)&if_state.pfontCur->pifbm->bm[0];
            while(size--)
                *q++ = *p++;
        }

        MEMfree(FSA CACHE_POOL, hbm);
        hbm = hcmp;
        bm = (PIFBITMAP)MEMptr(hbm);   /* Recover pointer */
        retval = if_state.pfontCur->hifbm;
        size = bm->size;   /* size of compressed data */
    }
    /* else  we just leave the old memory handle */

  }
cache_it:
#endif /* COMPRESSED_CACHE */


  /*  If memory block is too big to cache, remember it in hBigBM.
   *  It will be freed on the next call to CHARalloc().
   *  (If using "cache-by-reference" method, don't treat large bitmaps any differently.)
   */

#if !CACHE_BY_REF
    if(size > (SL32)if_state.max_char_size)
        if_state.hBigBM = hbm;
#endif    /* !CACHE_BY_REF */

  /*  make least recently used */

    bm->notmru = 0;             /* Keep CACaccess() from calling me again */
    dll_after(FSA if_state.pserver->hBMlru, hbm);     /* link at start of IFBITMAP lru list     */

  /*  Remember my new owner so that I can remove all references to
   *  myself if I have to be reclaimed. Tell new owner there's one more
   *  of us bitmaps.
   */

    bm->index = chId;
    bm->hiffont = if_state.hfontCur;
    if_state.pfontCur->bitmapCount++;

  /* Insert bitmap handle in current FONT table */

/*
 * 1/25/94 maib
 * new caching scheme for asian encoding
 */
#if USE_ASIAN_CACHE
    insert_at_head_of_list(FSA hbm, if_state.pfontCur);
#else
    *(if_state.pfontCur->hbuf + chId) = hbm;
#endif /* USE_ASIAN_CACHE */
    return retval;
}

/*                              I F B I T M A P                           */
/*========================================================================*/
/*                                 F O N T                                */


/*----------------------*/
/*    FNTfree           */
/*----------------------*/
/*  Free a currently active FONT and associated IFBITMAPs */

#if defined (ANSI_DEFS)
MLOCAL VOID FNTfree(FSP HIFFONT hf)
#else
MLOCAL VOID
FNTfree(hf)
    HIFFONT hf;                             /* Handle of FONT to be freed */
#endif
{
    PFONT      f;                           /* Pointer to FONT to be freed */
#if !USE_ASIAN_CACHE
    PHIFBITMAP phbm;
#endif
    SW16       i;

  /*  Clear cache state pointers if this is the current font. Leave
   *  the current FONTCONTEXT
   */

    if(hf == if_state.hfontCur)
    {
        if_state.hfontCur = (HIFFONT)0;
        if_state.pfontCur = (PFONT)0;
    }

    f = (PFONT)MEMptr(hf);                             /* Recover pointer */

#if ASIAN_ENCODING && ASIAN_HASH_TRACE  /* added 8/20/96 dlk */
        hash_trace(FSA f);
#endif /* ASIAN_ENCODING && ASIAN_HASH_TRACE */


#if COMPRESSED_CACHE
    if(f->hifbm != NIL_MH)
        MEMfree(FSA CACHE_POOL, f->hifbm);
#endif

  /*  Free each IFBITMAP in the font. Bump the font's bitmapCount by 1 so
   *  that it won't go to 0 when the last bitmap is freed. Otherwise,
   *  BMfree() will try to free me.
   */

    f->bitmapCount++;                 /* One more than I really have      */
/*
 * 1/25/94 maib
 * new caching scheme for asian encoding
 */
#if USE_ASIAN_CACHE
    /*
     * just make sure all cached bitmaps are accessed here, the
     * actual cleanup, for both the bitmap and hash list item,
     * is done within BMfree...
     * traverse each row, and each column w/in each row...
     */
    {
      MEM_HANDLE hItem, cur_hItem;
      IFBITMAP *pifb;

      for (i = 0; i < HASHMAX; i++)
      {
        hItem = f->hash_table[i]; /* handle to an IFBITMAP */
        while (hItem)             /* free bitmaps until NULL handle is reached */
        {
          /* get the next item in the list before it is freed */
          pifb = (PIFBITMAP)MEMptr(hItem);
          cur_hItem = hItem;
          hItem = pifb->f;
          BMfree(FSA cur_hItem);
        }
      }
    }
#else
    phbm = f->hbuf;                   /* start of array of bitmap handles */
    for(i = 0; i<SSMAX; i++)
    {
        if (*phbm) BMfree(FSA *phbm);
        phbm++;
    }
#endif /* USE_ASIAN_CACHE */

    dll_remove(FSA hf);                         /*  Remove FONT from lru list */
    MEMfree(FSA CACHE_POOL, hf);                /*  Free the FONT memory      */
}


/*-------------------*/
/*    CACfont        */
/*-------------------*/
/*  Find the active FONT that matches the given FONTCONTEXT. If no
 *  match, then create a new FONT.
 */
#if defined (ANSI_DEFS)
GLOBAL UW16 CACfont(FSP PFONTCONTEXT fc)
#else
GLOBAL UW16
CACfont(fc)
    PFONTCONTEXT fc;
#endif
{
    HIFFONT   hf;
    PFONT     f;
    HIFBITMAP hbm;
    PIFBITMAP bm;

#if UFST_MULTITHREAD
    UW16 status;
#endif
#if DISK_FONTS
    BOOLEAN       has_path;

#if ROM
    has_path = FALSE;
#else
    has_path = (!FC_ISEXTERN(fc) && !fc->font_id); /* PS, TT disk, IF dynamic */
    if (FC_ISFCO(fc))
        has_path = FALSE;
#endif /* ROM */
#endif    /* DISK_FONTS */

    /*
     * 10/25/93 maib
     * in an attempt to optimize CACfont, do not perform any changes if
     * the fontcontext passed is identical to what the cache believes is
     * the current font's fontcontext. ie. there is no need to make the
     * font the most current if this already is true...
     */
    if (if_state.pfontCur &&
        !MEMCMP((LPSB8)fc, (LPSB8)&if_state.pfontCur->fc, sizeof(FONTCONTEXT)))
    {
#if DISK_FONTS
       if (has_path)
       {
         if (STRNCMP((FILECHAR *)fc->font_hdr, if_state.pfontCur->pathname, PATHNAMELEN) == 0)
#if UFST_MULTITHREAD
         {
             /* Add this thread to FNT's list of referenced threads */
             status = add_thread_id_to_list(FSA if_state.pfontCur->thread_ids);
             if (status)
                 return ERR_max_threads_exceeded;

             return SUCCESS;
         }
#else
           return SUCCESS;
#endif
       }
       else
#endif    /* DISK_FONTS */
#if UFST_MULTITHREAD
    {
        /* Add this thread to FNT's list of referenced threads */
        status = add_thread_id_to_list(FSA if_state.pfontCur->thread_ids);
        if (status)
            return ERR_max_threads_exceeded;

        return SUCCESS;
    }
#else
       return SUCCESS;
#endif
    }

  /*  Free old FONT if it has no bitmaps */
    if(if_state.pfontCur)
        if(!if_state.pfontCur->bitmapCount) FNTfree(FSA if_state.hfontCur);

  /* Set cache state to no valid FONT in case we fail */
    if_state.pfontCur = (PFONT)0;
    if_state.hfontCur = (HIFFONT)0;

  /*  Search active fonts for a match with
   *  the user's device font context
   */

    for(hf = ((PDLL)MEMptr(if_state.pserver->hFNTlru))->f; hf != if_state.pserver->hFNTlru; hf = f->link.f)
    {
        f = (PFONT)MEMptr(hf);
        if (!MEMCMP((LPSB8)fc, (LPSB8)&f->fc, sizeof(FONTCONTEXT)))
        {
#if DISK_FONTS
            if (has_path)
            {
                if(STRNCMP((FILECHAR *)fc->font_hdr, f->pathname, PATHNAMELEN) == 0)
                    break;
            }
            else
#endif
            break;
        }
    }

    if(hf != if_state.pserver->hFNTlru)
    {
      /*  Make FONT most recently used */
        dll_remove(FSA hf);
        dll_after(FSA if_state.pserver->hFNTlru, hf);
    }
    else
    {
      /*  No active FONT matches the app's FONTCONTEXT. Make a new FONT */

        SW16       i;
#if !USE_ASIAN_CACHE
        PHIFBITMAP phbm;
#endif

      /*  Allocate a new FONT */
        hf = (HIFFONT)CHARalloc(FSA (SL32)sizeof(cacheFONT));
        if(!(hf))
            return ERR_no_font;

        /*  Make new FONT most recently used */

        dll_after(FSA if_state.pserver->hFNTlru, hf);

      /* Initialize font data. */

        f = (PFONT)MEMptr(hf);                       /* Recover pointer */
        f->fc = *fc;                          /* Copy FONTCONTEXT to new FONT */    
#if DISK_FONTS
        if(has_path)
            STRCPY(f->pathname, (FILECHAR *)fc->font_hdr);
#endif

        f->bitmapCount = 0;          /* No character IFBITMAPs are cached yet */

#if UFST_MULTITHREAD
        /* Initialize thread list and add this thread to it. */
        MEMSET(f->thread_ids, (UL32)-1L, MAX_THREADS * sizeof(UL32));
#endif
#if COMPRESSED_CACHE
        f->hifbm = NIL_MH; 
#endif

/*
 * 1/25/94 maib
 * new caching scheme for asian encoding
 */
#if USE_ASIAN_CACHE
        for (i = 0; i < HASHMAX; i++)
        {
          /*
           * each row of array is initially empty
           */
          f->hash_table[i] = (MEM_HANDLE)NIL_MH;
        }
#else
        phbm = f->hbuf;                  /* point to list of IFBITMAP handles */
        for(i=0; i < SSMAX; i++)
            *phbm++ = (HIFBITMAP)0L;
#endif /* USE_ASIAN_CACHE */
    }  /* end make a new FONT */
#if UFST_MULTITHREAD
    /* Add this thread to FNT's list of referenced threads */
    status = add_thread_id_to_list(FSA f->thread_ids);
#endif

  /*  Set all IFBITMAPs' notmru flags to 1 indicating that they have not
   *  been moved to the front of the lru list during calls to CGIFchar() for
   *  the current FONT. CGIFchar() checks the notmru flag for the IFBITMAP
   *  it is about to return. If it is 1, then a call is made to BMmru()
   *  above to move the IFBITMAP to the head of the lru list making it
   *  "most recently used". At that time the notmru flag is cleared so that
   *  it will be moved to the head of the list only once during a sequence
   *  of calls to CGIFchar() for a given FONT. This is to keep CGIFchar()'s
   *  performance up. All IFBITMAPs that need to have their
   *  notmru flags set are at the beginning of the lru list.
   */
    hbm = ((PDLL)MEMptr(if_state.pserver->hBMlru))->f;        /* first IFBITMAP in lru list */
    while(hbm != if_state.pserver->hBMlru)
    {
        bm = (PIFBITMAP)MEMptr(hbm);
        if(bm->notmru) break;
        bm->notmru = 1;
        hbm = bm->link.f;                    /* next IFBITMAP in the list */
    }

  /* Set cache state for current font */

    if_state.pfontCur = f;
    if_state.hfontCur = hf;

    return SUCCESS;
}

/*--------------------*/
/*    CAChdr_font     */
/*--------------------*/
/*  Find the active FONT that matches the given FONTCONTEXT. If no
 *  match, then create a new FONT.
 */
#if defined (ANSI_DEFS)
MLOCAL UW16 CAChdr_font(FSP PFONTCONTEXT fc, UW16 *fonts_purged) 
#else
MLOCAL UW16
CAChdr_font(fc, fonts_purged)
    UW16 *fonts_purged;
    PFONTCONTEXT fc;
#endif
{
    HIFFONT   hf;
    PFONT     f;
    HIFBITMAP hbm;
    PIFBITMAP bm;
#if UFST_MULTITHREAD
    UW16 status;
#endif
#if DISK_FONTS
    BOOLEAN       has_path;

#if ROM
    has_path = FALSE;
#else
    has_path = (!FC_ISEXTERN(fc) && !fc->font_id); /* PS, TT disk, IF dynamic */
#endif /* ROM */
#endif

    /*
     * 10/25/93 maib
     * in an attempt to optimize CACfont, do not perform any changes if
     * the fontcontext's font_hdr passed is identical to what the cache believes is
     * the current font's fontcontext's font_hdr. ie. there is no need to make the
     * font the most current if this already is true...
     */
    if (if_state.pfontCur &&
        ((LPSB8)fc->font_hdr == (LPSB8)if_state.pfontCur->fc.font_hdr))
    {
#if DISK_FONTS
       if (has_path)
       {
         if (STRNCMP((FILECHAR *)fc->font_hdr, if_state.pfontCur->pathname, PATHNAMELEN) == 0)
         {
#if UFST_MULTITHREAD
            /* Add this thread to FNT's list of referenced threads */
            status = add_thread_id_to_list(FSA if_state.pfontCur->thread_ids);
#endif
           *fonts_purged = FALSE;
           return SUCCESS;
         }
       }
       else
#endif /* DISK_FONTS */
       {
#if UFST_MULTITHREAD
        /* Add this thread to FNT's list of referenced threads */
        status = add_thread_id_to_list(FSA if_state.pfontCur->thread_ids);
#endif
       *fonts_purged = FALSE;
       return SUCCESS;
       }
    }

  /*  Free old FONT if it has no bitmaps */
    if(if_state.pfontCur)
        if(!if_state.pfontCur->bitmapCount) FNTfree(FSA if_state.hfontCur);

  /* Set cache state to no valid FONT in case we fail */
    if_state.pfontCur = (PFONT)0;
    if_state.hfontCur = (HIFFONT)0;

  /*  Search active fonts for a match with
   *  the user's device font context's font_hdr
   */

    for(hf = ((PDLL)MEMptr(if_state.pserver->hFNTlru))->f; hf != if_state.pserver->hFNTlru; hf = f->link.f)
    {
        f = (PFONT)MEMptr(hf);
        if ((LPSB8)fc->font_hdr == (LPSB8)f->fc.font_hdr)
        {
#if DISK_FONTS
            if (has_path)
            {
                if(STRNCMP((FILECHAR *)fc->font_hdr, f->pathname, PATHNAMELEN) == 0)
                    break;
            }
            else
#endif
            break;
        }
    }

    if(hf != if_state.pserver->hFNTlru)
    {
      /*  Make FONT most recently used */
        dll_remove(FSA hf);
        dll_after(FSA if_state.pserver->hFNTlru, hf);
        *fonts_purged = FALSE;
    }
    else
    {
      /*  No active FONT matches the app's FONTCONTEXT's font_hdr. Make a new FONT */

        SW16       i;
#if !USE_ASIAN_CACHE
        PHIFBITMAP phbm;
#endif
        *fonts_purged = TRUE;

      /*  Allocate a new FONT */
        hf = (HIFFONT)CHARalloc(FSA (SL32)sizeof(cacheFONT));
        if(!(hf))
            return ERR_no_font;

        /*  Make new FONT most recently used */

        dll_after(FSA if_state.pserver->hFNTlru, hf);

      /* Initialize font data. */

        f = (PFONT)MEMptr(hf);                       /* Recover pointer */
        f->fc = *fc;                          /* Copy FONTCONTEXT to new FONT */    
#if DISK_FONTS
        if(has_path)
            STRCPY(f->pathname, (FILECHAR *)fc->font_hdr);
#endif

        f->bitmapCount = 0;          /* No character IFBITMAPs are cached yet */
#if UFST_MULTITHREAD
        /* Initialize thread list and add this thread to it. */
        MEMSET(f->thread_ids, (UL32)-1L, MAX_THREADS * sizeof(UL32));
#endif
/*
 * 1/25/94 maib
 * new caching scheme for asian encoding
 */
#if USE_ASIAN_CACHE
        for (i = 0; i < HASHMAX; i++)
        {
          /*
           * each row of array is initially empty
           */
          f->hash_table[i] = (MEM_HANDLE)NIL_MH;
        }
#else
        phbm = f->hbuf;                  /* point to list of IFBITMAP handles */
        for(i=0; i < SSMAX; i++)
            *phbm++ = (HIFBITMAP)0L;
#endif /* USE_ASIAN_CACHE */
    }  /* end make a new FONT */
#if UFST_MULTITHREAD
    /* Add this thread to FNT's list of referenced threads */
    status = add_thread_id_to_list(FSA f->thread_ids);
#endif

  /*  Set all IFBITMAPs' notmru flags to 1 indicating that they have not
   *  been moved to the front of the lru list during calls to CGIFchar() for
   *  the current FONT. CGIFchar() checks the notmru flag for the IFBITMAP
   *  it is about to return. If it is 1, then a call is made to BMmru()
   *  above to move the IFBITMAP to the head of the lru list making it
   *  "most recently used". At that time the notmru flag is cleared so that
   *  it will be moved to the head of the list only once during a sequence
   *  of calls to CGIFchar() for a given FONT. This is to keep CGIFchar()'s
   *  performance up. All IFBITMAPs that need to have their
   *  notmru flags set are at the beginning of the lru list.
   */
    hbm = ((PDLL)MEMptr(if_state.pserver->hBMlru))->f;        /* first IFBITMAP in lru list */
    while(hbm != if_state.pserver->hBMlru)
    {
        bm = (PIFBITMAP)MEMptr(hbm);
        if(bm->notmru) break;
        bm->notmru = 1;
        hbm = bm->link.f;                    /* next IFBITMAP in the list */
    }

  /* Set cache state for current font */

    if_state.pfontCur = f;
    if_state.hfontCur = hf;

    return SUCCESS;
}


#if MEM_TRACE
#if defined (ANSI_DEFS)
MLOCAL VOID print_fnt_lru(FSP0)
#else
MLOCAL VOID
print_fnt_lru()
#endif
{
    HIFFONT   hf;
    PFONT     f;

  /*  Search active fonts and print
   */

    for(hf = ((PDLL)MEMptr(if_state.pserver->hFNTlru))->f; hf != if_state.pserver->hFNTlru; hf = f->link.f)
    {
        f = (PFONT)MEMptr(hf);
    
        DBG3("%ld: %d %d\n", f->fc.font_id,f->fc.point_size, f->bitmapCount);
        DBG3("%ld: %d %d\n", f->fc.font_id,f->fc.s.m1.em_depth, f->bitmapCount);
    }                
}
#endif


/*----------------------*/
/*       CACinit        */
/*----------------------*/
#if defined (ANSI_DEFS)
GLOBAL UW16 CACinit(FSP0)
#else
GLOBAL UW16
CACinit()
#endif
{
    if(!(if_state.CGIFinitstate & not_cac))
        return ERR_CACinit; /* already initialized */

  /* Set cache state to no valid FONT */

    if_state.pfontCur = (PFONT)0;
    if_state.hfontCur = (HIFFONT)0;

#if TILE
    if_state.htileBM = NIL_MH;     /* Handle of last made tile part   */
#endif

  /* Get doubly linked list headers. These must be handles */
    /* 06-28-04 jfd   Only have to initialize the IFBITMAP lru once */
    if (if_state.pserver->MTinitstate & not_BMlru)
    {
        if_state.pserver->hBMlru = MEMalloc(FSA CACHE_POOL, (SL32)sizeof(DLL));
        if(!(if_state.pserver->hBMlru))
            return ERR_CACinit;
        dll_null(FSA if_state.pserver->hBMlru);                     /*  Set IFBITMAP lru to empty.  */

        if_state.pserver->MTinitstate &= ~not_BMlru;

    }

    /* 06-28-04 jfd   Only have to initialize the FONT lru once */
    if (if_state.pserver->MTinitstate & not_FNTlru)
    {
        if_state.pserver->hFNTlru = MEMalloc(FSA CACHE_POOL, (SL32)sizeof(DLL));
        if(!(if_state.pserver->hFNTlru))
        {
            MEMfree(FSA CACHE_POOL, if_state.pserver->hBMlru);
            return ERR_CACinit;
        }
        dll_null(FSA if_state.pserver->hFNTlru);                    /*  Set FONT lru list to empty. */

        if_state.pserver->MTinitstate &= ~not_FNTlru;
    }
    if_state.hBigBM = (HIFBITMAP)0L;               /*  No big character yet        */
    if_state.CGIFinitstate &= ~not_cac;            /* turn off not initialized bit */
    return SUCCESS;
}


/*----------------------*/
/*       CACexit        */
/*----------------------*/
#if defined (ANSI_DEFS)
GLOBAL VOID CACexit(FSP0)
#else
GLOBAL VOID
CACexit()
#endif
{
    DBG("\n\nCACexit()\n");

    if(if_state.CGIFinitstate & not_cac) return;   /* cache not initialized */
    if (if_state.pserver->MTinitstate & not_FNTlru) return;    /* FNT lru list not initialized */
    if (if_state.pserver->MTinitstate & not_BMlru) return;    /* BM lru list not initialized */
    {
#if UFST_MULTITHREAD
        PFONT f;
        HIFFONT hf;
        HIFFONT next_hf;
        UL32 thread_id;

        thread_id = get_thread_id(FSA0);

        hf = ((PDLL)MEMptr(if_state.pserver->hFNTlru))->b;
        while(hf != if_state.pserver->hFNTlru)
        {
            f = (PFONT)MEMptr(hf);
            next_hf = f->link.b;
            if (only_thread_in_list(FSA f->thread_ids, thread_id))
                FNTfree(FSA hf);
            hf = next_hf;
        }
#else
      /* Free all FONTs */
        while(!dll_empty(FSA if_state.pserver->hFNTlru))
            FNTfree(FSA ((PDLL)MEMptr(if_state.pserver->hFNTlru))->b);
#endif


#if UFST_MULTITHREAD
        if (!if_state.pserver->client_count)
        {
#endif
      /* free list headers */
        MEMfree(FSA CACHE_POOL, if_state.pserver->hFNTlru);
        MEMfree(FSA CACHE_POOL, if_state.pserver->hBMlru);

        if_state.pserver->MTinitstate |= not_FNTlru;          /* set not initialized bit */
        if_state.pserver->MTinitstate |= not_BMlru;           /* set not initialized bit */
#if UFST_MULTITHREAD
        }
#endif
    }

#if TILE
    if(if_state.htileBM)
    {
#if IFBITSPLIT
    IFBITMAP *pbm;

        pbm = (IFBITMAP *)MEMptr(if_state.htileBM);
        MEMfree(FSA CACHE_POOL, pbm->datahandle);           /*  Free the IFBITMAP memory      */
#endif
        MEMfree(FSA CACHE_POOL, if_state.htileBM);
        if_state.htileBM = NIL_MH;
    }
#endif

    if_state.CGIFinitstate |= not_cac;           /* set not initialized bit */

#if MEM_TRACE
    MEMstat(FSA CACHE_POOL);
#endif
}


/*------------------*/
/*   CACpurge       */
/*------------------*/
#if defined (ANSI_DEFS)
GLOBAL UW16 CACpurge(FSP PFONTCONTEXT fc)
#else
GLOBAL UW16
CACpurge(fc)
    PFONTCONTEXT fc;
#endif
{
#if UFST_MULTITHREAD
    PFONT f;
#endif
    UW16 status;
    status = CACfont(FSA fc);
    if (status)
        return status;
#if UFST_MULTITHREAD
    f = (PFONT)MEMptr(if_state.hfontCur);
    status = remove_thread_id_from_list(FSA f->thread_ids);
    if (thread_list_is_empty(FSA f->thread_ids))
#endif
    FNTfree(FSA if_state.hfontCur);
    return SUCCESS;
}
/*-----------------------*/
/*   CACfont_free        */
/*-----------------------*/
#if defined (ANSI_DEFS)
GLOBAL UW16 CACfont_free(FSP HIFFONT hf)
#else
GLOBAL UW16
CACfont_free(hf)
    HIFFONT hf;
#endif
{
#if UFST_MULTITHREAD
    PFONT f;
    UW16 status;

    f = (PFONT)MEMptr(hf);
    status = remove_thread_id_from_list(FSA f->thread_ids);
    if (thread_list_is_empty(FSA f->thread_ids))
#endif
    FNTfree(FSA hf);
    return SUCCESS;
}
/*-----------------------*/
/*   CAChdr_purge        */
/*-----------------------*/
#if defined (ANSI_DEFS)
GLOBAL UW16 CAChdr_purge(FSP PFONTCONTEXT fc)
#else
GLOBAL UW16
CAChdr_purge(fc)
    PFONTCONTEXT fc;
#endif
{
    UW16 status;
    UW16 similar_fonts_purged;
#if UFST_MULTITHREAD
    PFONT f;
#endif

    similar_fonts_purged = FALSE;
    while (!similar_fonts_purged)
    {
       status = CAChdr_font(FSA fc, &similar_fonts_purged);
       if (status)
           return status;
#if UFST_MULTITHREAD
        f = (PFONT)MEMptr(if_state.hfontCur);
        status = remove_thread_id_from_list(FSA f->thread_ids);
        if (thread_list_is_empty(FSA f->thread_ids))
#endif
       FNTfree(FSA if_state.hfontCur);
    }
    return SUCCESS;
}

/*------------------------------------------------------------------*/
/*         C a c h e    M e m o r y    M a n a g e m e n t          */


#if DEFUND
/*  If DEFUND is enabled, we may get called via the CGIFdefund()
 *  function to relinquish all use of a particlular ufst memory
 *  page. CACdefund() is called in this case. If the linked list
 *  headers need to be freed, we just call CACexit() to clear out the
 *  whole cache and return TRUE so that CGIFdefund() will call CACinit()
 *  once it has disposed of the page.
 */


/*----------------*/
/*  purge_page    */
/*----------------*/
/*  Search all entries in the least recently used list whose handle is
 *  "lru". If any entry has been allocated from the memory block "page",
 *  then free it using the function "free".
 */
#if defined (ANSI_DEFS)
MLOCAL VOID purge_page (FSP UW16 page, MEM_HANDLE lru, VOID (*free)(FSP MEM_HANDLE))
#else
MLOCAL VOID
purge_page(page, lru, free)
    UW16      page;
    MEM_HANDLE lru;            /* handle of lru list */
#ifdef LINT_ARGS
    VOID       (*free)(MEM_HANDLE);
#else
    VOID       (*free)();      /* function that frees members of lru list */
#endif
#endif /* (ANSI_DEFS) */
{
    MEM_HANDLE    hp, hnext;

    hp = ((PDLL)MEMptr(lru))->f;
    while(hp != lru)
    {
        hnext = ((PDLL)MEMptr(hp))->f;
        if(PAGE(hp) == page)
            (*free)(FSA hp);
        hp = hnext;
    }
}


/*----------------------*/
/*       CACdefund      */
/*----------------------*/
/*  Free all BITMAPs and FONTs that are part of memory page "page". */
#if defined (ANSI_DEFS)
GLOBAL BOOLEAN CACdefund (FSP UW16 page)
#else
GLOBAL BOOLEAN
CACdefund(page)
    UW16 page;
#endif
{
#if UFST_MULTITHREAD
    if (if_state.pserver->client_count > 1)    /* 10-25-04 jfd - was 0 */
        return FALSE;
#endif
    purge_page(FSA page, if_state.pserver->hFNTlru, FNTfree);  /* Free FONTs using this page */
    purge_page(FSA page, if_state.pserver->hBMlru,  BMfree);   /* Free BITMAPs using this page */
    if((PAGE(if_state.pserver->hFNTlru) == page) || (PAGE(if_state.pserver->hBMlru) == page))
    {
        CACexit(FSA0);
        return TRUE;
    }
    else
        return FALSE;
}
#endif  /*  DEFUND  */


/*----------------------*/
/*       CHARalloc      */
/*----------------------*/
/*  Acquire cache memory, freeing character bitmaps if need be.
 *  Return a handle to the memory.
 */
#if defined (ANSI_DEFS)
GLOBAL MEM_HANDLE CHARalloc (FSP SL32 size)
#else
GLOBAL MEM_HANDLE
CHARalloc(size)
    SL32 size;
#endif
{
    MEM_HANDLE h;

    /* AJ - memory fund check*/
    if (size > if_state.pserver->mem_fund[CACHE_POOL])
        return NIL_MH;

  /*  Free up big character IFBITMAP if any */

    if (if_state.hBigBM)
        BMfree(FSA if_state.hBigBM);


#if TILE
    if(if_state.htileBM)
    {
#if IFBITSPLIT
    IFBITMAP *pbm;

        pbm = (IFBITMAP *)MEMptr(if_state.htileBM);
        MEMfree(FSA CACHE_POOL, pbm->datahandle);           /*  Free the IFBITMAP memory      */
#endif
        MEMfree(FSA CACHE_POOL, if_state.htileBM);
        if_state.htileBM = NIL_MH;
    }
#endif

    while( (h = MEMalloc(FSA CACHE_POOL, (SL32)size)) == NIL_MH )
    {
#if MEM_TRACE
        MEMstat(FSA CACHE_POOL);
#endif
        if(dll_empty(FSA if_state.pserver->hBMlru))

        {
#if MEM_TRACE
            print_fnt_lru(FSA0);
#endif
            return (MEM_HANDLE)0;
        }
        else
        {
#if CACHE_BY_REF
           /* If using "cache-by-reference" method, loop through unreferenced characters
            * to reacquire cache memory and try again.
            */
               HIFBITMAP hbm;
               PIFBITMAP bm;

               /* Loop thru the LRU list (starting at the end with the LRU
                * character) and free unreferenced characters.
                */
               hbm = ((PDLL)MEMptr(if_state.pserver->hBMlru))->b;
               while(hbm != if_state.pserver->hBMlru)
               {
                  bm = (PIFBITMAP)MEMptr(hbm);
                  if (bm->ref_counter == 0)
                  {
                     BMfree(FSA hbm);
                     break;
                  }
                  hbm = bm->link.b;
               }
               if (hbm == if_state.pserver->hBMlru)
                  break;
#else
               BMfree(FSA ((PDLL)MEMptr(if_state.pserver->hBMlru))->b );     /* free lru IFBITMAP */
#endif    /* CACHE_BY_REF */
         }
    }
    return h;
}


#if MEM_TRACE
#if defined (ANSI_DEFS)
GLOBAL SL32 CACdump (FSP UW16 print)
#else
GLOBAL SL32
CACdump(print)
    UW16 print;
#endif
{

    HIFFONT   hf;
    PFONT     f;
    HIFBITMAP hbm;
    PIFBITMAP bm;

    SL32 size;
    SL32 total = 0L;
    SL32 bmTotal = 0L;
    SL32 ftTotal = 0L;

    if(print) DBG("FONTS\n");

    for(hf = ((PDLL)MEMptr(if_state.pserver->hFNTlru))->f; hf != if_state.pserver->hFNTlru; hf = f->link.f)
    {
        f = (PFONT)MEMptr(hf);
        size = *((LPSL32)((LPSB8)f - 4));
        total += size;
        ftTotal += size;

        if(print) DBG4("Handle %6lx  Pointer %Fp  Bitmapcount %3d Size %5ld\n",
                        hf, f, f->bitmapCount, size);
    }
    if(print)// DBG1("FONT totals = %ld\n", ftTotal);
    {
        sprintf(cTempBuffer,"FONT totals = %ld\n", ftTotal);
        Send_String(cTempBuffer);
    }
        

    if(print)DBG("BITMAPS\n");
    
    hbm = ((PDLL)MEMptr(if_state.pserver->hBMlru))->f;        /* first IFBITMAP in lru list */
    while(hbm != if_state.pserver->hBMlru)
    {
        bm = (PIFBITMAP)MEMptr(hbm);

        size = *((LPSL32)((LPSB8)bm - 4));
        total += size;
        bmTotal += size;
        
        if(print) DBG4("Handle %6lx  Pointer %Fp size %5ld charcode %ld\n",
        hbm, bm, size, bm->index);
        
        hbm = bm->link.f;                    /* next IFBITMAP in the list */
    }
    if(print) DBG1("BITMAP totals %ld\n", bmTotal);

    return total;

}
#endif  /* MEM_TRACE */

#if ASIAN_ENCODING && ASIAN_HASH_TRACE  /* added 8/20/96 dlk */
/******************************/
/*     HASH_TRACE             */
/******************************/
#if defined (ANSI_DEFS)
GLOBAL VOID hash_trace(FSP PFONT pf)
#else
GLOBAL VOID
hash_trace(pf)
  PFONT pf;
#endif /* ANSI_DEFS */
{
  SL32 i;  /* loop index to rows */
  SL32 j;  /* loop counter */
  SL32 atemp;
  SL32 xCount;  /* scaled down count of '*' to print */
  SL32 totalItemCount;
  SL32 r;  /* rows per output page */
  SL32 pageNumber;  /* printed page number counter */
  SL32 hItemCount[HASHMAX];  /* holds number of cached bitmaps per row */

  SL32 row;
  MEM_HANDLE hItem;
  PIFBITMAP pifb;

  totalItemCount = 0;
  r = 86;  /* set this to the number of rows to print on each page */

  for(row = 0; row < HASHMAX; row++)
  {
    hItemCount[row] = 0;
    hItem = pf->hash_table[row];
    while(hItem != NIL_MH)
    {

#if CACHE_BY_REF
         pifb = (PIFBITMAP)MEMptr(hItem);
         hItemCount[row] += pifb->ref_counter;
#else
         hItemCount[row]++;
         pifb = (PIFBITMAP)MEMptr(hItem);
#endif    /* CACHE_BY_REF */

      hItem = pifb->f;
    }  /* end of while to count hash items in this row */
    totalItemCount = totalItemCount + hItemCount[row];
  }  /* end of checking all rows */

  pageNumber = 0;
  for(i = 0; i < HASHMAX; i++)
  {
    if((i == 0)|(i == r)|(i == 2*r)|(i == 3*r)|(i == 4*r)|(i == 5*r)|(i == 6*r))
    {
      pageNumber++;
      printf("\f");  /* start a new page of output */
      printf("\n ASIAN_ENCODING: HASH TABLE  --  Utilization / Distribution Chart    (PAGE: %d)", pageNumber);
#if DISK_FONTS
  printf(" font %s", pf->pathname);
#endif
      printf("\n     | Item  |        100       200       300       400       500       600       700       800       900      1000|");
      printf("\n Row | Count |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    | |");
      printf("\n=====|=======|=========|=========|=========|=========|=========|=========|=========|=========|=========|=========|=|");
    } /* end of new page header */

    xCount = hItemCount[i];
    atemp = xCount % 10;
    xCount = xCount / 10;

    if(atemp) xCount++;
    if((hItemCount[i] / 10) > 100) xCount = 101;

    printf("\n %4d|%7d|", i, hItemCount[i]);
    for(j = 1; j <= xCount; j++) printf("X");
    for(j = 1; j <= (101 - xCount); j++) printf(".");
    printf("|");

    if((i == (r-1))|(i == ((2*r)-1))|(i == ((3*r)-1))|(i == ((4*r)-1))|(i == ((5*r)-1))|(i == ((6*r)-1)))
    {
      printf("\n=====|=======|=========|=========|=========|=========|=========|=========|=========|=========|=========|=========|=|");
    }  /* end of page footer */
  }  /* end of rows to print */

      printf("\n=====|=======|=========|=========|=========|=========|=========|=========|=========|=========|=========|=========|=|");
 

  printf("\n");
  printf("\n*** END OF CHART ***       Total Count Of Cached Items = %d", totalItemCount);

}  /* end of hash_trace() */
#endif /* ASIAN_ENCODING && ASIAN_HASH_TRACE */  /* added 8/20/96 dlk */

#if CACHE_BY_REF
/* New "cache-by-reference" freeing method */
/*-----------------------*/
/*    CGIFFfree_by_ref   */
/*-----------------------*/
#if defined (ANSI_DEFS)
UW16 CGENTRY CGIFFfree_by_ref (FSP PIFBITMAP pifb)
#else
UW16 CGENTRY
CGIFFfree_by_ref(pifb)
    PIFBITMAP pifb;
#endif
{
    HIFFONT hf;
    PFONT f;
    MEM_HANDLE hItem;
    UL32 chId;
    HIFFONT uhf;

    uhf = pifb->hiffont;
    chId = pifb->index;

    /* Search every cached font for font containing character to free */
    for (hf = ((PDLL)MEMptr(if_state.pserver->hFNTlru))->f, f = (PFONT)MEMptr(hf);
            hf != if_state.pserver->hFNTlru && hf != uhf;
            hf = f->link.f)
        {
            f = (PFONT)MEMptr(hf);
        }

    if (hf == if_state.pserver->hFNTlru)
        return ERR_char_not_cached;    /* font containing character to free is not cached */

    /* Found font. Search font for character to free */
    f = (PFONT)MEMptr(hf);
#if USE_ASIAN_CACHE
    hItem = CACbmLookup(FSA f, chId);
#else
    hItem = *(f->hbuf + chId);
#endif
    /* If character exists in cache, decrement reference count. */
    if (hItem)
    {
        PIFBITMAP pb;

        pb = (PIFBITMAP)MEMptr(hItem);
        if (pb->ref_counter)
            pb->ref_counter--;
        else
            return ERR_char_not_cached;

        /* If no more references exist for character ... */
        if (!pb->ref_counter)
        {
            SL32 size = 0;

            /* If character should not have been cached due to its large size, free it */
            if (FC_ISBITMAP(&f->fc))
                size = (SL32)pb->width * (SL32)pb->depth;
#if GRAYSCALING
            else if (FC_ISGRAY(&f->fc))
                size = pb->size;
#endif
#if OUTLINE
            else
            {
                PIFOUTLINE pout;

                pout = (PIFOUTLINE)pifb;
                size = (SL32)pout->size * (SL32)pout->depth;
            }
#endif
            if (size > (SL32)if_state.max_char_size)
                BMfree(FSA hItem);
        }
    }
    return SUCCESS;
}
#endif /* CACHE_BY_REF */

#else  /*  not CACHE */

#if defined (ANSI_DEFS)
GLOBAL MEM_HANDLE CHARalloc (FSP SL32 size)
#else
GLOBAL MEM_HANDLE
CHARalloc(size)
    SL32 size;
#endif
{
    return ( MEMalloc(FSA CACHE_POOL, (size)) );
}

#endif  /* CACHE  */

/* (used by both CACHE and non-CACHE cases) */
/*----------------------*/
/*       CHARfree       */
/*----------------------*/
#if defined (ANSI_DEFS)
GLOBAL VOID CHARfree (FSP MEM_HANDLE h)
#else
GLOBAL VOID
CHARfree(h)
    MEM_HANDLE h;
#endif
{
    MEMfree(FSA CACHE_POOL, h);
}

/* allocate / free from new memory pool (for per-char temporary data) */
#if defined (ANSI_DEFS)
GLOBAL MEM_HANDLE TEMPCHARalloc (FSP SL32 size)
#else
GLOBAL MEM_HANDLE
TEMPCHARalloc(size)
    SL32 size;
#endif
{
    /* AJ memory fund check */
    if (size <= if_state.pserver->mem_fund[CHARGEN_POOL])
        return ( MEMalloc(FSA CHARGEN_POOL, (size)) );
    else
        return NIL_MH;
}

#if defined (ANSI_DEFS)
GLOBAL VOID TEMPCHARfree (FSP MEM_HANDLE h)
#else
GLOBAL VOID
TEMPCHARfree(h)
    MEM_HANDLE h;
#endif
{
    MEMfree(FSA CHARGEN_POOL, h);
}

 

canon.txt    ///

/* 
 * Copyright (C) 2005 Monotype Imaging Inc. All rights reserved.
 */
/* $Header:   I:/BULL/URIP/RTS/RAC/CANON.C_V   1.11   Dec 13 2004 15:53:42   galejss  $ */
/* $Log:   I:/BULL/URIP/RTS/RAC/CANON.C_V  $ 
 * 
 *    Rev 1.11   Dec 13 2004 15:53:42   galejss
 * make all DBG calls 16-bit-compatible
 * 
 *    Rev 1.10   Jun 04 2004 17:22:48   GalejsS
 * fix 3 compile warnings (signed-unsigned assignment mismatches)
 * 
 *    Rev 1.9   Aug 22 2003 09:22:06   LynchR
 * Updated copyright notice.
 * 
 *    Rev 1.8   Aug 13 2003 15:46:02   LynchR
 * Added error checking for memory allocations.
 * 
 *    Rev 1.7   Jul 21 2003 17:40:50   Galejs
 * reentrancy / debug fixes
 * 
 *    Rev 1.6   Jun 20 2003 15:02:58   Galejs
 * get rid of asserts; debug cleanup; VOID
 * 
 *    Rev 1.5   Jan 03 2003 13:58:10   Galejs
 * fixes for tiny ACT-compressed files (for awr)
 * 
 *    Rev 1.4   Jun 12 2001 16:39:10   Galejs
 * use UFST types rather than SHORT, CHAR, etc
 * 
 *    Rev 1.3   May 03 2001 20:47:12   Galejs
 * data-type cleanup
 * 
 *    Rev 1.2   Jan 15 2001 09:41:34   Song
 * changed DEBUG to AGFADEBUG, uppercae to lowercase for #include files
 * 
 *    Rev 1.1   Oct 20 2000 10:56:44   Galejs
 * return ERR_bad_ACT_version if old ACT format opened
 * 
 *    Rev 1.0   Oct 20 2000 08:35:40   Pvcsadmn
 * Original (by awr)
 *
 */


#include "cgconfig.h"
#if TT_ROM_ACT    /* conditional compile entire module */ 


#include "ufstport.h"
#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>        /* memcpy */

#include "shareinc.h"

#include "dbg_ufst.h"
#include "ra_mem.h"
#include "bitio.h"
#include "radecomp.h"    /* BYTE_CACHE_INTERVAL */


static SL32 get_next_token(FSP ACT_RA_DECOMP *r);

#ifdef AGFADEBUG

/****************************************************************/
/* print a number in binary ... a printf("%b") ... */
#if defined (ANSI_DEFS)
VOID print_code(UL32 code, SL32 len)
#else
VOID print_code(code, len)
UL32 code;
SL32 len;
#endif
{
    UL32 m;

    if (len)
        {
        m = 1 << (len-1);
        while (m)
            {
            putchar( (code & m) ? '1' : '0');
            m >>= 1;
            }
        putchar(' ');
        }
}
#endif
/****************************************************************/
/****************************************************************/
/* given a RAC3 file in memory, readin all the necessary glop 
* to facilitate decoding a file 
*
* code assumes that a UB8 pointer can be any address
* if NOT, you will need to allocate and readin the BYTES
* Also you'll need to free them in MTX_RA_DECOMP_Destroy
*
* NB: this handles BOTH inferred and explicit offsets
* even though <write_canonical_header> can only do inferred
* offsets at this time. 
*/
#if defined (ANSI_DEFS)
ACT_RA_DECOMP *ACT_RA_DECOMP_Create(FSP ACT_MemHandler *mem, UB8 *data )
#else
ACT_RA_DECOMP *ACT_RA_DECOMP_Create(mem, data )
ACT_MemHandler *mem;
UB8 *data;
#endif
    {
    BITIO *bio;
    ACT_RA_DECOMP *r;
    SL32 offset_length;    /* length in bytes of each offset entry. 0 => inferred offsets */

    SL32 *p,i,n,offset,crumbs;
    SL32 fsize = 0;        /*** bytes in the compressed file ... ***/

    DBG("***** reading *****\n");

    /* verify 'RAC3' signature */
    if (data[0] != 'R' || data[1] != 'A' || data[2] != 'C' || data[3] != 3)
        {
        DBG("*** not a RAC3 data image ***\n");
        mem->err = ERR_bad_ACT_version;
        return 0;
        }

    /* get compressed file size */
    fsize = data[4];
    fsize = (fsize << 8) | data[5];
    fsize = (fsize << 8) | data[6];
    fsize = (fsize << 8) | data[7];

    r = (ACT_RA_DECOMP*) ACT_mem_malloc(FSA mem, sizeof(ACT_RA_DECOMP));

    if( !r )    /* Added error handler */ /* rjl 8/4/2003 - */
        return 0;

    r->mem = mem;

    /* create BITIO and skip signature and compressed file size */
    bio = MTX_BITIO_Create(FSA mem, data, fsize);
    
    if( !bio )    /* Added error handler */ /* rjl 8/4/2003 - */
        goto error;
        
    
    MTX_BITIO_fseek(bio,8<<3);

    
    r->bio = bio;

    /* Initialize the Huffman code lookup table */
    for (i=0; i<TABLE_SIZE; i++)
        r->token_bits_table[i] = 0;  /* means no entry for code i */
    r->token_num_table[0] = -1;      /* means table not built     */

    /* read uncompressed file size */
    r->unCompressedByteCount = MTX_BITIO_Read32(bio);

    /* read number of tokens */
    r->num_tokens = MTX_BITIO_Read32(bio);

    /* establish pointer to lengths[] -- and skip the data */
    offset = MTX_BITIO_ftell(bio);
    r->lengths = data + (offset >> 3);
    offset += (r->num_tokens << 3);
    MTX_BITIO_fseek(bio,offset);

    /* read in the offset_length */
    offset_length = MTX_BITIO_Read8(bio);
    
    /* allocate and calculate or read the offsets */
    n = r->num_tokens;
    p = r->offsets = (SL32 *)ACT_mem_malloc(FSA mem, n * 4);

    if( !p )    /* Added error handler */ /* rjl 8/4/2003 - */
        goto error;
    

    if (offset_length == 0)
        {
        /* infer the offsets of the non_overlapping token strings from their lengths */
        p[0] = 0;
        for (i=1; i<r->num_tokens; i++)
            p[i] = p[i-1] + r->lengths[i-1];
        }
    else
        {
        /* read in the offsets of the overlapping token strings */
        offset_length <<= 3;
        for (i=0; i<r->num_tokens; i++)
            p[i] = MTX_BITIO_ReadValue(r->bio,offset_length);
        }

#ifdef AGFADEBUG
    if (UFST_get_debug(FSA0))
        {
        DBG("offsets\n");
        for (i=0; i<r->num_tokens; i++)
            DBG2("%ld: %ld\n",i,r->offsets[i]);
        }
#endif /* AGFADEBUG */

    /* read total string data length */
    n = r->string_len = MTX_BITIO_Read32(bio);
    DBG1("r->string_len=%ld\n",r->string_len);


    /* establish pointer to string[] -- and skip the data */
    offset = MTX_BITIO_ftell(bio);
    r->string = data + (offset >> 3);
    offset += (r->string_len<<3);
    MTX_BITIO_fseek(bio,offset);

    /* read number of canonical huffman code groups */
    r->num_groups = MTX_BITIO_Read8(bio);
    DBG1("r->num_groups=%ld\n",r->num_groups);
    
    /* establish pointer to bits[] -- and skip the data */
    offset = MTX_BITIO_ftell(bio);
    r->bits = data + (offset>>3);
    offset += (r->num_groups<<3);
    MTX_BITIO_fseek(bio,offset);

    /* allocate and read in firsts[]  */
    n = r->num_groups;
    r->firsts = (UL32 *)ACT_mem_malloc(FSA mem, n * 4);
    p = (SL32 *)r->firsts;

    if( !p )    /* Added error handler */ /* rjl 8/4/2003 - */
        goto error;
    

    while (n--)
        *p++ = MTX_BITIO_Read32(bio);


#ifdef AGFADEBUG
    if (UFST_get_debug(FSA0))
        {
        SL32 i;
        DBG("firsts[] = ");
        for (i=0; i<r->num_groups; i++)
            print_code(r->firsts[i], r->bits[i]);
        DBG("\n");
        }
#endif /* AGFADEBUG */

    /* allocate and read in lasts[]  */
    n = r->num_groups;
    r->lasts = (UL32 *)ACT_mem_malloc(FSA mem, n * 4);
    p = (SL32 *)r->lasts;

    if( !p )    /* Added error handler */ /* rjl 8/4/2003 - */
        goto error;
    

    while (n--)
        *p++ = MTX_BITIO_Read32(bio);

#ifdef AGFADEBUG
    if (UFST_get_debug(FSA0))
        {
        SL32 i;
        DBG("lasts[]  = ");
        for (i=0; i<r->num_groups; i++)
            print_code(r->lasts[i], r->bits[i]);
        DBG("\n");
        }
#endif /* AGFADEBUG */

    /* calculate next_mask to keep rightmost MAX bits */
    if(r->bits[r->num_groups-1] == 32)
        r->next_mask = 0xFFFFFFFF;
    else
        r->next_mask = (1 << r->bits[r->num_groups-1]) - 1;

    /* allocate and calculate tokens[]  */
    n = r->num_groups;
    p = r->tokens = (SL32 *)ACT_mem_malloc(FSA mem, n * 4);

    if( !p )    /* Added error handler */ /* rjl 8/4/2003 - */
        goto error;

    p[0] = 0;
    for (i=1; i<n; i++)
        p[i] = p[i-1] + 1 + (r->lasts[i-1] - r->firsts[i-1]);

#ifdef AGFADEBUG
    if (UFST_get_debug(FSA0))
        {
        SL32 i;
        DBG("tokens[] = ");
        for (i=0; i<r->num_groups; i++)
            DBG1("%ld ",r->tokens[i]);
        DBG("\n");
        }
#endif /* AGFADEBUG */

    /* read crumbs (size of bitMarks and deltaBytes arrays) */
    crumbs = MTX_BITIO_Read32(bio);

    /* bitMarks[]  */
    r->bitMarks = &bio->array[bio->index>>3]; /* point at the ROM, we'll decode the LONGs on the fly */
    bio->index += 32*crumbs;

#ifdef AGFADEBUG
    if (UFST_get_debug(FSA0))
        {
        SL32 i;
        DBG("bitMarks[] =");
        for (i=0; i<crumbs; i++)
        {
        UL32  bitMark;
        UB8 *p = &r->bitMarks[4*i];
        bitMark = *p++;
        bitMark = (bitMark<<8) | *p++;
        bitMark = (bitMark<<8) | *p++;
        bitMark = (bitMark<<8) | *p++;
        DBG1("%ld ",bitMark);
        }

        DBG("\n");
        }
#endif /* AGFADEBUG */

    /* establish pointer to deltaBytes[] */
    n = crumbs;
    offset = MTX_BITIO_ftell(bio);
    r->deltaBytes = data + (offset>>3);
    offset += n<<3;
    MTX_BITIO_fseek(bio,offset);

#ifdef AGFADEBUG
    if (UFST_get_debug(FSA0))
        {
        SL32 i;
        DBG("deltaBytes[] =");
        for (i=0; i<crumbs; i++)
            DBG1("%d ",r->deltaBytes[i]);
        DBG("\n");
        }
#endif /* AGFADEBUG */

    /* read token_offset */
    r->token_offset = MTX_BITIO_Read32(bio);
#ifdef AGFADEBUG
    if (UFST_get_debug(FSA0))
        {
        DBG1("token_offset = %ld\n",r->token_offset);
        fflush(stdout);
        }
#endif /* AGFADEBUG */
    MTX_TTC_InitCoordEncoding();
    return r;

error:
    ACT_RA_DECOMP_Destroy(FSA r );
    return 0;

    }
/****************************************************************/
#if defined (ANSI_DEFS)
VOID ACT_RA_DECOMP_Destroy(FSP ACT_RA_DECOMP *t)
#else
VOID ACT_RA_DECOMP_Destroy(t)
ACT_RA_DECOMP *t;
#endif
    {
    ACT_mem_free(FSA t->mem,t->firsts);
    ACT_mem_free(FSA t->mem,t->lasts);
    ACT_mem_free(FSA t->mem,t->tokens);
    ACT_mem_free(FSA t->mem,t->offsets);
    MTX_BITIO_Destroy(FSA t->bio );
    ACT_mem_free(FSA t->mem, t );
    }
/****************************************************************/
/* from current position (assuming someone else has done the
* MTX_BITIO_fseek() and read in <next>) get the next token
* number and refresh <next>.
*/

/****************************************************************/
#ifdef AGFADEBUG
/* build the table by decoding codes  */
#if defined (ANSI_DEFS)
static old_build_token_table(FSP ACT_RA_DECOMP *r)
#else
static old_build_token_table(r)
ACT_RA_DECOMP *r;
#endif
    {
    SL32 lo,hi,mid;
    UL32 first;
    UL32 last;
    UL32 next;
    SL32 drop;
    SL32 i,token_num;
    UB8 n;
    UB8 max = TABLE_BITS;


    for (i=0; i<TABLE_SIZE; i++)
        {
        /* binary search for <i> in first/last */
        lo = 0;
        hi = r->num_groups-1;
        while (lo <= hi)
            {
            mid = (lo + hi)/2;
            n = r->bits[mid];
            drop = max - n;    
            next = i >> drop;
            first = r->firsts[mid];
            last = r->lasts[mid];

            if (next < first)
                hi = mid-1;
            else if (next > last)
                lo = mid+1;
            else
                {
                token_num = r->tokens[mid] + (next - first);
                r->token_num_table[i] = token_num;
                r->token_bits_table[i] = n;
                break;
                }
            }
        }

#ifdef AGFADEBUG
    if (UFST_get_debug(FSA0))
        {
        DBG("code         bits token_num\n");
        for (i=0; i<TABLE_SIZE; i++)
            {
            print_code(i,TABLE_BITS);
            DBG2("%4d %9ld\n",r->token_bits_table[i],r->token_num_table[i]);
            }
        fflush(stdout);
        }
#endif
    }
#endif /* AGFADEBUG */
/****************************************************************/
/* here is the faster one ... always the same (I think) */
#if defined (ANSI_DEFS)
static build_token_table(FSP ACT_RA_DECOMP *r)
#else
static build_token_table(r)
        ACT_RA_DECOMP *r;
#endif
{
    SL32 i,j,k,bits,count,num,token,index;
#ifdef AGFADEBUG
    /* do it the old fashioned way */
    old_build_token_table(FSA r);
    DBG("*** checking for errors in (fast) build_token_table()\n");
#endif /* AGFADEBUG */
    
    for (i=0,index=0;  (index < TABLE_SIZE) &&  (i < r->num_groups) && (r->bits[i] <= TABLE_BITS); i++)
    {
        bits = r->bits[i];
        count = 1 << (TABLE_BITS - bits);
        num = 1 + r->lasts[i] - r->firsts[i];
        token = r->tokens[i];
        for (j=0,token=r->tokens[i]; (index < TABLE_SIZE) &&  (j<num); j++,token++)
        {
            for (k=0; (index < TABLE_SIZE) &&  (k < count); k++)
            {
#ifdef AGFADEBUG
                /* and compare with the fast way */
                if (r->token_num_table[index] != token)
                    DBG2("*** token_num_table[%ld] != %ld\n",index,token);
                if (r->token_bits_table[index] != bits)
                    DBG2("*** token_bits_table[%ld] != %ld\n",index,bits);
#endif /* AGFADEBUG */
                
                r->token_num_table[index] = token;
                r->token_bits_table[index] = (UB8)bits;
                index++;
            }
        }
    }
    r->slowGroup = i;   /* first group not completely contained in the table */
    
    
#ifdef AGFADEBUG
    if (UFST_get_debug(FSA0))
    {
        DBG("code         bits token_num\n");
        for (i=0; i<TABLE_SIZE; i++)
        {
            print_code(i,TABLE_BITS);
            DBG2("%4d %9ld\n",r->token_bits_table[i],r->token_num_table[i]);
        }
        fflush(stdout);
    }
#endif /* AGFADEBUG */
    
}

/****************************************************************/
#define NEXT_MASK   (1<<TABLE_BITS)-1
#if defined (ANSI_DEFS)
static SL32 get_next_token(FSP ACT_RA_DECOMP *r)
#else
static SL32 get_next_token(r)
ACT_RA_DECOMP *r;
#endif
    {
    SL32 lo,hi,mid;
    UL32 first;
    UL32 last;
    UL32 next;
    UL32 rest;
    SL32 bitsNeeded;
    SL32 drop;
    SL32 token_num;
    UB8 n;
    UB8 max;

    /* do we need to build the token table ? */
    if (r->token_num_table[0] < 0)
        build_token_table(FSA r);

    next = r->next;

    /* ? possible && legitimate entry in the table */
    if (r->token_bits_table[next])
        {
        n = r->token_bits_table[next];
        token_num = r->token_num_table[next];
        next <<= n;
        next |= MTX_BITIO_ReadValue(r->bio,n);
        next &= NEXT_MASK;
        r->next = next;
        return token_num;
        }
    else
        {
        /* not in table ... binary search the longer length groups */
        max = r->bits[r->num_groups-1];
        bitsNeeded = max - TABLE_BITS;
        if (bitsNeeded > 0)
            r->next = (next << bitsNeeded) | MTX_BITIO_ReadValue(r->bio, bitsNeeded);
        else if (bitsNeeded < 0)
        {
            r->next >>= -bitsNeeded;
            r->bio->index += bitsNeeded;
        }
        lo = r->slowGroup;
        hi = r->num_groups-1;
        while (lo <= hi)
            {
            mid = (lo + hi)/2;
            n = r->bits[mid];
            drop = max - n;    
            next = r->next >> drop;
            first = r->firsts[mid];
            last = r->lasts[mid];

            if (next < first)
                hi = mid-1;
            else if (next > last)
                lo = mid+1;
            else
                {
                token_num = r->tokens[mid] + (next - first);
                bitsNeeded = TABLE_BITS - max + n;  /* to get TABLE_BITS bits into next */
                if(bitsNeeded > 0)
                    {
                    r->next <<= bitsNeeded;
                    rest = MTX_BITIO_ReadValue(r->bio,bitsNeeded);
                    r->next |= rest;
                    }
                else if(bitsNeeded<0)
                    {
                    r->next >>= -bitsNeeded;
                    r->bio->index += bitsNeeded ;
                    }
                r->next &= NEXT_MASK;
                
                return token_num;
                }
            }
        /* This can't happen, we got a bad token number */
        return 0;  /* to keep the compiler happy */
        }
    }


/****************************************************************/
/* return the next token's string pointer and set its length */
#if defined (ANSI_DEFS)
SB8 *ReadSymbol(FSP ACT_RA_DECOMP *t, SL32 *len )
#else
SB8 *ReadSymbol(t, len )
ACT_RA_DECOMP *t;
SL32 *len;
#endif
    {
    SL32 n;
    SB8 *r;
    
    n = get_next_token(FSA t);
#ifdef AGFADEBUG
    if (UFST_get_debug(FSA0))
        DBG1("index=%ld ",n);
#endif /* AGFADEBUG */
    *len = t->lengths[n];
    r = (SB8*)(t->string + t->offsets[n]);
    return r;
    }
/****************************************************************/

#endif   /* TT_ROM_ACT  */
 

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值