/* $Id: FontFamily.c,v 1.1 91/05/20 15:12:40 gnb Exp $ */
/* $Source: /export/sources/x/At/Plotter/tmp/RCS/FontFamily.c,v $ */

/*

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 Massachusetts
Institute of Technology (M.I.T.) not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.

M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
M.I.T. 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.

*/

/*
 * $Log:	FontFamily.c,v $
 * Revision 1.1  91/05/20  15:12:40  gnb
 * Initial revision
 * 
 * 
 */

#include <stdio.h>
#ifdef __STDC__
#include <stdlib.h>
#endif

#ifdef _AtDevelopment_
#include "FontFamilyP.h"
#else
#include <At/FontFamilyP.h>
#endif

extern int strcasecmp P((const char *, const char *));

#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))
extern char *strcpy();
#define CopyString(s) strcpy(malloc(strlen(s)+1),s)

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);
	sprintf(namebuf,"*-%s-%s-%c-*-*-*-%d-*",
		XNAME(family),weight,slant,points*10);

	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 */

    else 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;
	}
    else {
	fprintf(stderr,
	      "AtFontStringToSize: cannot convert string '%s' to font size.\n",
		str);
    }
    return AtFontNORMAL;
}
