256 lines
6.8 KiB
C

/* This file is part of the Project Athena Zephyr Notification System.
* It is one of the source files comprising zwgc, the Zephyr WindowGram
* client.
*
* Created by: Marc Horowitz <marc@athena.mit.edu>
*
* $Id$
*
* Copyright (c) 1989 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <sysdep.h>
#if (!defined(lint) && !defined(SABER))
static const char rcsid_X_fonts_c[] = "$Id$";
#endif
#include <zephyr/mit-copyright.h>
/****************************************************************************/
/* */
/* Code dealing with X fonts: */
/* */
/****************************************************************************/
#ifndef X_DISPLAY_MISSING
#include "X_fonts.h"
#include "new_memory.h"
#include "new_string.h"
#include "error.h"
#include "pointer_dictionary.h"
#include "zwgc.h"
/*
* font_dict - Lookup cache for fonts (the value pointers are XFontSet's)
*/
static pointer_dictionary family_dict = NULL;
static pointer_dictionary fontname_dict = NULL;
static pointer_dictionary fontst_dict = NULL;
/*
* {face,size}_to_string - lookup tables for converting {face,size} int
* constants to ascii strings:
*/
static string face_to_string[] = { "roman", "bold", "italic", "bolditalic" };
static string size_to_string[] = { "small", "medium", "large" };
static char *
get_family(char *style, char *substyle)
{
char *desc;
pointer_dictionary_binding *binding;
int exists;
char *family;
desc=string_Concat("style.", style);
desc=string_Concat2(desc, ".substyle.");
desc=string_Concat2(desc, substyle);
desc=string_Concat2(desc, ".fontfamily");
if (!family_dict)
family_dict = pointer_dictionary_Create(37);
binding = pointer_dictionary_Define(family_dict, desc, &exists);
if (exists) {
free(desc);
return((string) binding->value);
} else {
family = get_string_resource(desc,
"StyleKey.Style1.Style2.Style3.SubstyleKey.Substyle.FontfamilyKey");
free(desc);
if (family == NULL)
pointer_dictionary_Delete(family_dict, binding);
else
binding->value = (pointer)family;
return(family); /* If resource returns NULL, return NULL also */
}
}
static char *
get_specific_fontname(char *family,
int size,
int face)
{
char *desc;
pointer_dictionary_binding *binding;
int exists;
char *fontname;
desc = string_Concat("fontfamily.", family);
desc = string_Concat2(desc, ".");
desc = string_Concat2(desc, size_to_string[size]);
desc = string_Concat2(desc, ".");
desc = string_Concat2(desc, face_to_string[face]);
if (!fontname_dict)
fontname_dict = pointer_dictionary_Create(37);
binding = pointer_dictionary_Define(fontname_dict, desc, &exists);
if (exists) {
free(desc);
return (string)binding->value;
} else {
fontname = get_string_resource(desc, "FontfamilyKey.Fontfamily.Size.Face");
free(desc);
if (fontname == NULL)
pointer_dictionary_Delete(fontname_dict, binding);
else
binding->value = (pointer)fontname;
return fontname; /* If resource returns NULL, return NULL also */
}
}
static XFontSet
get_fontst(Display *dpy, char *fontname)
{
pointer_dictionary_binding *binding;
int exists;
XFontSet fontst;
char **missing_list;
int missing_count;
char *def_string;
if (!fontst_dict)
fontst_dict = pointer_dictionary_Create(37);
binding = pointer_dictionary_Define(fontst_dict, fontname, &exists);
if (exists)
return((XFontSet)binding->value);
fontst = XCreateFontSet(dpy, fontname, &missing_list, &missing_count,
&def_string);
XFreeStringList(missing_list);
if (fontst == NULL)
pointer_dictionary_Delete(fontst_dict,binding);
else
binding->value = (pointer)fontst;
return(fontst); /* If resource returns NULL, return NULL also */
}
static char *
get_fontname(char *family, int size, int face)
{
char *fontname;
fontname = get_specific_fontname(family, size, face);
if (!fontname)
fontname = get_specific_fontname(family, size, ROMAN_FACE);
if (!fontname)
fontname = get_specific_fontname(family, MEDIUM_SIZE, face);
if (!fontname)
fontname = get_specific_fontname(family, MEDIUM_SIZE, ROMAN_FACE);
return(fontname);
}
static XFontSet
complete_get_fontst(Display *dpy,
string style,
string substyle,
int size,
int face)
{
char *family, *fontname;
XFontSet fontst;
family = get_family(style, substyle);
if (!family)
return NULL;
fontname = get_fontname(family, size, face);
if (!fontname)
return NULL;
fontst = get_fontst(dpy, fontname);
if (!fontst)
return NULL;
return fontst;
}
/*
* XFontSet get_font(string style, substyle; int size, face)
* Requires: size is one of SMALL_SIZE, MEDIUM_SIZE, LARGE_SIZE and
* face is one of ROMAN_FACE, BOLD_FACE, ITALIC_FACE,
* BOLDITALIC_FACE.
* Effects: unknown
*/
XFontSet
get_font(Display *dpy,
string style,
string substyle,
int size,
int face)
{
char *family,*fontname;
XFontSet fontst = NULL;
if (size == SPECIAL_SIZE) {
/* attempt to process @font explicitly */
fontst = get_fontst(dpy, substyle);
} else {
family = get_family(style, substyle);
if (family)
fontname = get_fontname(family, size, face);
else
fontname = get_fontname(substyle, size, face);
if (fontname) {
fontst = get_fontst(dpy, fontname);
if (fontst)
return fontst;
}
/* At this point, the no-failure case didn't happen, and the case
of substyle being the fontfamily didn't happen, either. */
fontst = complete_get_fontst(dpy, style, "text", size, face);
if (!fontst)
fontst = complete_get_fontst(dpy, "default", substyle, size, face);
if (!fontst)
fontst = complete_get_fontst(dpy, "default", "text", size, face);
if (!fontst) {
fontname = get_fontname("default", size, face);
if (fontname)
fontst = get_fontst(dpy, fontname);
}
}
if (fontst)
return fontst;
/* If all else fails, try fixed */
fontst = get_fontst(dpy, "fixed");
if (fontst)
return fontst;
/* No fonts available. Die. */
ERROR("Unable to open font \"fixed\". Aborting...");
#ifdef DEBUG
abort();
#else
exit(1);
#endif
}
#endif /* X_DISPLAY_MISSING */