/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:ffont.c 12.0$ */
/* $ACIS:ffont.c 12.0$ */
/* $Source: /ibm/acis/usr/src/ibm/ditroff/dit3812/RCS/ffont.c,v $ */

#ifndef lint
static char *rcsid = "$Header:ffont.c 12.0$";
#endif

#include <stdio.h>
#include <utils.h>
#include <hash.h>
#include <pmp/pmp.h>
#include "ffont.h"

#define WHERE_AM_I "ffont.c"

/***===================================================================***/


int ff_debug=0;

/***===================================================================***/

static ffsize     *fs_lfree= NULL;
static f_font     *ff_lfree= NULL;

#define FF_TBLSIZE 251
#define fs_new(f)  (fs_lfree==NULL?(f=(ffsize *)u_malloc(sizeof(ffsize)),f):(f=fs_lfree,fs_lfree=fs_lfree->ffs_next,f))
#define fs_free(f) (f?(f->fs_next=fs_lfree,fs_lfree=f,f=NULL):NULL)
#define ff_new(f)  (ff_lfree==NULL?(f=(f_font *)u_malloc(sizeof(f_font))):(f=ff_lfree,ff_lfree=ff_lfree->ff_next,f))
#define ff_free(f) (f?(f->ff_next=ff_lfree,ff_lfree=f,f=NULL):NULL)

static hashtable  *ff_fonts= NULL;

/***====================================================================***/

_ff_Debug(fil)
register1 FILE  *fil;
{
   fprintf(fil,"ff_fonts= %x\n",ff_fonts);
}

  /*\
  |* Creates an initialized entry for a font named 'name', and returns
  |* a pointer to it.
  \*/

static f_font *
_ff_New(name)
register2 char   *name;
{
register1 f_font *ftmp;

   D_ENTRY1(ff_debug,"_ff_New(%s)\n",name);
   ff_new(ftmp);
   ftmp->ff_name=  (char *)u_malloc(strlen(name)+1);
   strcpy(ftmp->ff_name,name);
   ftmp->ff_cpage= NULL;
   ftmp->ff_sizes= NULL;
   ht_put(ff_fonts,name,ftmp);
   RETURN(ftmp);
}

/***=====================================================================***/

static ffsize *
_ff_SzNew(ffont,size,a_font)
register2 f_font	*ffont;
register3 int		 size;
register4 pmp_font	*a_font;
{
register1 ffsize   *stmp;

   D_ENTRY3(ff_debug,"_ff_SzNew(%x,%d,0x%x)\n",ffont,size,a_font);
   fs_new(stmp);
   stmp->ffs_size= size;
   stmp->ffs_font= a_font;
   stmp->ffs_next= ffont->ff_sizes;
   ffont->ff_sizes= stmp;
   RETURN(stmp);
}

/***=====================================================================***/

static ffsize *
_ff_SzInfo(ffont,size)
register3 f_font    *ffont;
register2 int        size;
{
register1 ffsize    *stmp= ffont->ff_sizes;

   D_ENTRY2(ff_debug,"_ff_SzInfo(%x,%d)\n",ffont,size);
   if (stmp==NULL)
      RETURN(NULL);
   while (stmp->ffs_size!=size) {
     stmp= stmp->ffs_next;
     if (stmp==NULL)
        RETURN(NULL);
   }
   RETURN(stmp);
}

/***=====================================================================***/

pmp_font *
ff_Add(name,size,a_font)
register2 char		*name;
register3 int     	 size;
register5 pmp_font	*a_font;
{
register4 f_font	*ftmp;
register1 ffsize	*stmp= NULL;
register6 pmp_font	*old;

  D_ENTRY3(ff_debug,"ff_Add(%s,%d,0x%x)\n",name,size,a_font);
  if (ff_fonts==NULL) {
     ff_fonts= ht_new(FF_TBLSIZE);
     ftmp= _ff_New(name);
  }
  else {
     ftmp= (f_font *)ht_get(ff_fonts,name);
     if (ftmp==NULL)
        ftmp= _ff_New(name);
  }
  stmp= _ff_SzInfo(ftmp,size);
  if (!stmp) {
     stmp= _ff_SzNew(ftmp,size,a_font);
     old= NULL;
  }
  else {
     old= stmp->ffs_font;
     stmp->ffs_font= a_font;
  }
  RETURN(old);
}

/***===================================================================***/

pmp_font *
ff_FAdd(font,size,a_font)
register2 f_font	*font;
register3 int		 size;
register4 pmp_font	*a_font;
{
register1 ffsize	*stmp;
register5 pmp_font	*old;

    D_ENTRY3(ff_debug,"ff_FAdd(0x%x,%d,0x%x)\n",font,size,a_font);
    stmp= _ff_SzInfo(font,size);
    if (!stmp) {
	stmp= _ff_SzNew(font,size,a_font);
	old= NULL;
    }
    else {
	old= stmp->ffs_font;
	stmp->ffs_font= a_font;
    }
    RETURN(old);
}

/***=====================================================================***/

f_font *
ff_Info(name)
register1 char   *name;
{
   D_ENTRY1(ff_debug,"ff_Info(%s)\n",name);
   if (ff_fonts==NULL)
        RETURN(NULL);
   else RETURN((f_font *)ht_get(ff_fonts,name));
}

/***=====================================================================***/

pmp_font *
ff_PFont(ffont,size)
register3 f_font *ffont;
register2 int     size;
{
register1 ffsize *stmp;

   D_ENTRY2(ff_debug,"ff_PFont(%x,%d)\n",ffont,size);
   if (ffont==NULL)
      RETURN(NULL);
   stmp= ffont->ff_sizes;
   while (stmp!=NULL) {
     if (stmp->ffs_size==size) RETURN(stmp->ffs_font);
     stmp= stmp->ffs_next;
   }
   RETURN(NULL);
}

/***=====================================================================***/

pmp_font *
ff_Squeeze(ffont,size,newsize)
f_font *ffont;
int     size;
int    *newsize;
{
register1 ffsize *stmp;
register5 ffsize *lower=NULL;
register6 ffsize *upper=NULL;
register2 int     tmpsize;
register3 int     lowsize=0;
register4 int     highsize=MAXINT;

   D_ENTRY3(ff_debug,"ff_Squeeze(%x,%d,%x)\n",ffont,size,newsize);
   if (ffont==NULL)
      RETURN(NULL);
   stmp= ffont->ff_sizes;
   while (stmp!=NULL) {
     tmpsize= stmp->ffs_size;
     if ((tmpsize<=size)&&(tmpsize>lowsize)) {
        lowsize= tmpsize;
        lower= stmp;
        if (tmpsize==size)
	   break;
     }
     else if (tmpsize<highsize) {
        highsize= tmpsize;
        upper= stmp;
     }
     stmp= stmp->ffs_next;
   }
   if      (lower) {*newsize=lowsize;  RETURN(lower->ffs_font);}
   else if (upper) {*newsize=highsize; RETURN(upper->ffs_font);}
   else            {*newsize=0;        RETURN(NULL);}
}

/***=====================================================================***/

int
ff_Print(fil,font)
register2 FILE   *fil;
register3 f_font *font;
{
register1 ffsize	*ffs= (font?font->ff_sizes:NULL);

   if (!font) return(TRUE);
   fprintf(fil,"%s: ",ff_Name(font));
   while (ffs!=NULL) {
      fprintf(fil,"(%d,0x%x) ",ffs->ffs_size,ffs->ffs_font);
      ffs= ffs->ffs_next;
   }
   fprintf(stderr,"\n");
   return(TRUE);
}

/***=====================================================================***/
