/* 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 * * $Id$ * * Copyright (c) 1989 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file * "mit-copyright.h". */ #include #if (!defined(lint) && !defined(SABER)) static const char rcsid_X_fonts_c[] = "$Id$"; #endif #include /****************************************************************************/ /* */ /* 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 */