/*
 *      FontFamily.c
 *
 *      The AthenaTools Plotter Widget Set - Version 6.0
 *
 *      klin, Tue Jul  7 13:59:47 1992
 *      klin, Sat Aug 15 10:31:50 1992, patchlevel 4
 *                                      Changed <At/..> to <X11/At/..>.
 */
static char SCCSid[] = "@(#) Plotter V6.0  92/08/15  FontFamily.c";

/*

Copyright 1990,1991 by the Massachusetts Institute of Technology

All rights reserved.

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of the firms, institutes
or employers of the authors not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.

THE AUTHORS AND THEIR FIRMS, INSTITUTES OR EMPLOYERS DISCLAIM ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND THEIR FIRMS,
INSTITUTES OR EMPLOYERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

*/

#include <X11/At/FontFamilyP.h>

#define AtFontNUMFACES 4
#define AtFontNUMSIZES 6
static XFontStruct *DefaultFont = NULL;
static AtFontFamily *familycache = NULL;
#define HAS_BOLD 1
#define HAS_ITALIC 2

#define New(type) (type *)malloc(sizeof(type))

AtFontFamilyInfo _AtFontFamilies[] = {
{"courier",
 {"Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique"},
 HAS_BOLD | HAS_ITALIC, 'o', NULL},

{"helvetica",
 {"Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique"},
  HAS_BOLD | HAS_ITALIC, 'o', NULL},

{"times",
 {"Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic"},
 HAS_BOLD | HAS_ITALIC, 'i', NULL},

{"new century schoolbook",
 {"NewCenturySchlbk-Roman", "NewCenturySchlbk-Bold",
      "NewCenturySchlbk-Italic", "NewCenturySchlbk-BoldItalic",},
 HAS_BOLD | HAS_ITALIC, 'i', NULL},

{"symbol",
 {"Symbol", "Symbol", "Symbol", "Symbol"},
     0, '*', NULL},
};


static short pointsize[] = {8,10,12,14,18,24};

int AtFontPointSize(family, size)
AtFontFamily *family;
int size;
/* ARGSUSED */
{
    return pointsize[size];
}

int AtFontPixelSize(family,size)
AtFontFamily *family;
int size;
/* ARGSUSED */
{
    return pointsize[size];   /* this is a hack for now... */
}

char *AtFontFamilyGetName(family)
AtFontFamily *family;
{
    return XNAME(family);
}


AtFontFamily *AtFontFamilyGet(dpy, name)
Display *dpy;
char *name;
{
    AtFontFamily *family;
    char buf[200];
    int num;

    if (DefaultFont==NULL) DefaultFont = XLoadQueryFont(dpy,"fixed");

    if (strcasecmp(name,"new century schoolbook") == 0)
	num = AtFontSCHOOLBOOK;
    else if (strcasecmp(name,"schoolbook") == 0)
	num = AtFontSCHOOLBOOK;
    else if (strcasecmp(name,"times") == 0)
	num = AtFontTIMES;
    else if (strcasecmp(name,"helvetica") == 0)
	num = AtFontHELVETICA;
    else if (strcasecmp(name,"courier") == 0)
	num = AtFontCOURIER;
    else if (strcasecmp(name,"symbol") ==0)
	num = AtFontSYMBOL;
    else
	num = -1;

    /* go look through the family cache to see if its already been created */
    family = familycache;
    while (family != NULL)  {
	if ((family->dpy == dpy) && (family->num == num)) break;
	family = family->next;
    }

    if (family != NULL) {
	family->refcount++;
    }
    else {
	family = New(AtFontFamily);
	family->dpy = dpy;
	family->refcount = 1;
	family->num = num;
	if (num == -1) {
	    family->cache = NULL;
	    sprintf(buf, "Warning: no font family '%s'.\n", name);
	    fprintf(stderr, buf);
	}
	else
	    family->cache = (XFontStruct **)
		calloc(AtFontNUMFACES * AtFontNUMSIZES,sizeof(XFontStruct *));
	family->next = familycache;
	familycache = family;
    }
    return family;
}

void AtFontFamilyRelease(family)
AtFontFamily *family;
{
    AtFontFamily *f,*g;

    family->refcount--;

    /* only really destroy the font family if noone is using it anymore */

    if (family->refcount == 0) {
	/* unlink it from the cache linked list */
	if (family == familycache)
	    familycache = familycache->next;
	else {
	    g = familycache;
	    f = familycache->next;
	    while (f != family) {
		g = f;
		f = f->next;
	    }
	    g->next = f->next;
	}

	/* now free up the internals */
	if (family->cache) {
	    int i;
	    for (i=0; i < AtFontNUMSIZES*AtFontNUMFACES; i++)
		if (family->cache[i]) XFreeFont(family->dpy,family->cache[i]);
	    free(family->cache);
	}
	/* now free the font family struct itself */
	free(family);
    }
}


XFontStruct *AtFontFetch(family, face, size)
AtFontFamily *family;
int face,size;
{
    char namebuf[150];
    char *weight, slant;
    int points;

    if (family->cache == NULL) return DefaultFont;

    if ((face & AtFontBOLD) && !(FLAGS(family) & HAS_BOLD))
	face &= ~AtFontBOLD;
    if ((face & AtFontITALIC) && !(FLAGS(family) & HAS_ITALIC))
	face &= ~AtFontITALIC;
    if (family->cache[face + size * AtFontNUMFACES] == NULL) {
	if (face & AtFontBOLD) weight = "bold";
	else weight = "medium";
	if (face & AtFontITALIC) slant = SLANTCHAR(family);
	else slant = 'r';
	points = AtFontPointSize(family, size);
#ifdef USE_SMALLER_FONTS
	/* For smaller fonts use pixelsize instead of pointsize, klin */
	sprintf(namebuf,"*-%s-%s-%c-*-*-%d-*-*",
		XNAME(family),weight,slant,points);
#else
	sprintf(namebuf,"*-%s-%s-%c-*-*-*-%d-*",
		XNAME(family),weight,slant,points*10);
#endif /* USE_SMALLER_FONTS */

	family->cache[face+size*AtFontNUMFACES] =
	    XLoadQueryFont(family->dpy,namebuf);

	if (family->cache[face+size*AtFontNUMFACES] == NULL)
	    family->cache[face+size*AtFontNUMFACES] = (XFontStruct *)-1;
    }

    if (family->cache[face + size * AtFontNUMFACES] == (XFontStruct *)-1)
	return DefaultFont;
    else
	return family->cache[face + size*AtFontNUMFACES];
}


int AtFontStringToSize (str)
char *str;
{
     int points;

     if (!strcasecmp (str, "smallest"))
	  return AtFontSMALLEST;
     else if (!strcasecmp (str, "small"))
	  return AtFontSMALL;
     else if (!strcasecmp (str, "medium"))
	  return AtFontMEDIUM;
     else if (!strcasecmp (str, "normal"))
	  return AtFontNORMAL;
     else if (!strcasecmp (str, "big"))
	  return AtFontBIG;
     else if (!strcasecmp (str, "biggest"))
	  return AtFontBIGGEST;

     /*
      * else if string is an integer, convert to the font size which
      * is closest to that number of points
      */

     if (((points = atoi(str)) > 0) && (points < 30))
	  switch (points) {
	  case 1: case 2: case 3: case 4:
	  case 5: case 6: case 7: case 8:
	       return AtFontSMALLEST;
	  case 9: case 10:
	       return AtFontSMALL;
	  case 11: case 12:
	       return AtFontMEDIUM;
	  case 13: case 14: case 15:
	       return AtFontNORMAL;
	  case 16: case 17: case 18:
	  case 19: case 20: case 21:
	       return AtFontBIG;
	  case 22: case 23: case 24: case 25:
	  case 26: case 27: case 28: case 29:
	       return AtFontBIGGEST;
	  }
     *SCCSid = *SCCSid;       /* Kepp gcc quiet */
     return -1;
}
