]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/zwgc/X_fonts.c
r4275@bucket (orig r265): kcr | 2008-01-21 02:57:32 -0500
[1ts-debian.git] / zephyr / zwgc / X_fonts.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It is one of the source files comprising zwgc, the Zephyr WindowGram
3  * client.
4  *
5  *      Created by:     Marc Horowitz <marc@athena.mit.edu>
6  *
7  *      $Id$
8  *
9  *      Copyright (c) 1989 by the Massachusetts Institute of Technology.
10  *      For copying and distribution information, see the file
11  *      "mit-copyright.h".
12  */
13
14 #include <sysdep.h>
15
16 #if (!defined(lint) && !defined(SABER))
17 static const char rcsid_X_fonts_c[] = "$Id$";
18 #endif
19
20 #include <zephyr/mit-copyright.h>
21
22 /****************************************************************************/
23 /*                                                                          */
24 /*                          Code dealing with X fonts:                      */
25 /*                                                                          */
26 /****************************************************************************/
27
28 #ifndef X_DISPLAY_MISSING
29
30 #include "X_fonts.h"
31 #include "new_memory.h"
32 #include "new_string.h"
33 #include "error.h"
34 #include "pointer_dictionary.h"
35 #include "zwgc.h"
36
37 /*
38  * font_dict - Lookup cache for fonts (the value pointers are XFontStruct *'s)
39  */
40
41 static pointer_dictionary family_dict = NULL;
42 static pointer_dictionary fontname_dict = NULL;
43 static pointer_dictionary fontst_dict = NULL;
44 static pointer_dictionary fidst_dict = NULL;
45
46 /*
47  * {face,size}_to_string - lookup tables for converting {face,size} int
48  *                         constants to ascii strings:
49  */
50
51 static string face_to_string[] = { "roman", "bold", "italic", "bolditalic" };
52 static string size_to_string[] = { "small", "medium", "large" };
53
54 static char *
55 get_family(char *style,
56            char *substyle)
57 {
58    char *desc;
59    pointer_dictionary_binding *binding;
60    int exists;
61    char *family;
62
63    desc=string_Concat("style.",style);
64    desc=string_Concat2(desc,".substyle.");
65    desc=string_Concat2(desc,substyle);
66    desc=string_Concat2(desc,".fontfamily");
67
68    if (!family_dict)
69       family_dict = pointer_dictionary_Create(37);
70    binding = pointer_dictionary_Define(family_dict,desc,&exists);
71
72    if (exists) {
73       free(desc);
74       return((string) binding->value);
75    } else {
76 #define STYLE_CLASS "StyleKey.Style1.Style2.Style3.SubstyleKey.Substyle.FontfamilyKey"
77       family=get_string_resource(desc,STYLE_CLASS);
78 #undef STYLE_CLASS
79       free(desc);
80       if (family==NULL)
81          pointer_dictionary_Delete(family_dict,binding);
82       else
83          binding->value=(pointer) family;
84       return(family);  /* If resource returns NULL, return NULL also */
85    }
86 }
87
88 static char *
89 get_specific_fontname(char *family,
90                       int size,
91                       int face)
92 {
93    char *desc;
94    pointer_dictionary_binding *binding;
95    int exists;
96    char *fontname;
97
98    desc = string_Concat("fontfamily.",family);
99    desc = string_Concat2(desc, ".");
100    desc = string_Concat2(desc, size_to_string[size]);
101    desc = string_Concat2(desc, ".");
102    desc = string_Concat2(desc, face_to_string[face]);
103
104    if (!fontname_dict)
105       fontname_dict = pointer_dictionary_Create(37);
106    binding = pointer_dictionary_Define(fontname_dict,desc,&exists);
107
108    if (exists) {
109       free(desc);
110       return((string) binding->value);
111    } else {
112 #define FAMILY_CLASS "FontfamilyKey.Fontfamily.Size.Face"
113       fontname=get_string_resource(desc,FAMILY_CLASS);
114       free(desc);
115       if (fontname==NULL)
116          pointer_dictionary_Delete(fontname_dict,binding);
117       else
118          binding->value=(pointer) fontname;
119       return(fontname);  /* If resource returns NULL, return NULL also */
120    }
121 }
122
123 /* fast function to convert Font to hex.  Return value
124  * is on the heap and must be freed.  I'm cheating in
125  * that I know that Font us really an unsigned long. */
126
127 static char hexdigits[] = {"0123456789ABCDEF"};
128 static char *
129 Font_to_hex(Font num)
130 {
131    char *temp;
132    int i;
133
134    temp=(char *) malloc((sizeof(Font)<<1)+2);
135
136    for (i=0;i<((sizeof(Font)<<1)+1);i++)
137       temp[i] = hexdigits[(num>>(i*4))&0x0f];
138    temp[i] = '\0';
139
140    return(temp);
141 }
142
143 void
144 add_fid(XFontStruct *font)
145 {
146    
147    char *fidstr;
148    pointer_dictionary_binding *binding;
149    int exists;
150
151    if (!fidst_dict)
152       fidst_dict = pointer_dictionary_Create(37);
153    fidstr=Font_to_hex(font->fid);
154    binding = pointer_dictionary_Define(fidst_dict,fidstr,&exists);
155    free(fidstr);
156
157    if (!exists)
158       binding->value=(pointer) font;
159 }
160
161 /* requires that the font already be cached. */
162 XFontStruct *
163 get_fontst_from_fid(Font fid)
164 {
165    char *fidstr;
166    pointer_dictionary_binding *binding;
167    int exists;
168
169    fidstr=Font_to_hex(fid);
170
171    binding = pointer_dictionary_Define(fidst_dict,fidstr,&exists);
172    free(fidstr);
173 #ifdef DEBUG
174    if (exists) {
175       return((XFontStruct *) binding->value);
176    } else {
177       printf("Font fid=0x%s not cached.  Oops.\n",fidstr);
178       abort();
179    }
180 #else
181    return((XFontStruct *) binding->value);
182 #endif
183 }
184
185 static XFontStruct *
186 get_fontst(Display *dpy,
187            char *fontname)
188 {
189    pointer_dictionary_binding *binding;
190    int exists;
191    XFontStruct *fontst;
192
193    if (!fontst_dict)
194       fontst_dict = pointer_dictionary_Create(37);
195    binding = pointer_dictionary_Define(fontst_dict,fontname,&exists);
196
197    if (exists) {
198       return((XFontStruct *) binding->value);
199    } else {
200       fontst=XLoadQueryFont(dpy,fontname);
201       if (fontst==NULL) {
202          pointer_dictionary_Delete(fontst_dict,binding);
203       } else {
204          binding->value=(pointer) fontst;
205          add_fid(fontst);
206       } return(fontst);  /* If resource returns NULL, return NULL also */
207    }
208 }
209
210 static char *
211 get_fontname(char *family,
212              int size,
213              int face)
214 {
215    char *fontname;
216
217    if (!(fontname=get_specific_fontname(family,size,face)))
218     if (!(fontname=get_specific_fontname(family,size,ROMAN_FACE)))
219      if (!(fontname=get_specific_fontname(family,MEDIUM_SIZE,face)))
220       fontname=get_specific_fontname(family,MEDIUM_SIZE,ROMAN_FACE);
221    return(fontname);
222 }
223
224 static XFontStruct *
225 complete_get_fontst(Display *dpy,
226                     string style,
227                     string substyle,
228                     int size,
229                     int face)
230 {
231    char *family,*fontname;
232    XFontStruct *fontst;
233
234    if ((family=get_family(style,substyle)))
235      if ((fontname=get_fontname(family,size,face)))
236        if ((fontst=get_fontst(dpy,fontname)))
237          return(fontst);
238    /* If any part fails, */
239    return(NULL);
240 }
241
242 /*
243  *    XFontStruct *get_font(string style, substyle; int size, face)
244  *         Requires: size is one of SMALL_SIZE, MEDIUM_SIZE, LARGE_SIZE and
245  *                   face is one of ROMAN_FACE, BOLD_FACE, ITALIC_FACE,
246  *                   BOLDITALIC_FACE.
247  *          Effects: unknown
248  */
249
250 XFontStruct *
251 get_font(Display *dpy,
252          string style,
253          string substyle,
254          int size,
255          int face)
256 {
257    char *family,*fontname;
258    XFontStruct *fontst;
259
260    if (size == SPECIAL_SIZE) {
261       /* attempt to process @font explicitly */
262       if ((fontst = get_fontst(dpy, substyle)))
263         return(fontst);
264    } else {
265       if ((family = get_family(style, substyle))) {
266          if ((fontname = get_fontname(family, size,face)))
267            if ((fontst = get_fontst(dpy, fontname)))
268              return(fontst);
269       } else {
270          if ((fontname = get_fontname(substyle, size, face)))
271            if ((fontst = get_fontst(dpy, fontname)))
272              return(fontst);
273       }
274
275       /* At this point, the no-failure case didn't happen, and the case
276       of substyle being the fontfamily didn't happen, either. */
277
278       fontst=NULL;
279       if (!(fontst = complete_get_fontst(dpy,style,"text",size,face)))
280         if (!(fontst = complete_get_fontst(dpy,"default",substyle,size,face)))
281           if (!(fontst = complete_get_fontst(dpy,"default","text",size,face)))
282             if ((fontname = get_fontname("default",size,face)))
283               fontst = get_fontst(dpy,fontname);
284       if (fontst) return(fontst);
285    }
286
287    /* If all else fails, try fixed */
288
289    if ((fontst=get_fontst(dpy,"fixed"))) return(fontst);
290
291    /* No fonts available.  Die. */
292
293    ERROR("Unable to open font \"fixed\".  Aborting...");
294 #ifdef DEBUG
295    abort();
296 #else
297    exit(1);
298 #endif
299 }
300
301 #endif /* X_DISPLAY_MISSING */
302