1 // Font handling
2 // Copyright (C) 2000 Core Technologies.
3
4 // This file is part of e93.
5 //
6 // e93 is free software; you can redistribute it and/or modify
7 // it under the terms of the e93 LICENSE AGREEMENT.
8 //
9 // e93 is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // e93 LICENSE AGREEMENT for more details.
13 //
14 // You should have received a copy of the e93 LICENSE AGREEMENT
15 // along with e93; see the file "LICENSE.TXT".
16
17 #include "includes.h"
18
19 // fallback fonts, (if we dont get the requested font, try these in succession)
20 #define FALLBACK_FONT_0 "-*-lucidatypewriter-medium-r-normal-sans-12-*-*-*-*-*-*-*"
21 #define FALLBACK_FONT_1 "fixed"
22 #define FALLBACK_FONT_2 "-adobe-courier-medium-r-normal--12-120-75-75-*-70-*-*"
23 #define FALLBACK_FONT_3 "7x13"
24
25 static EDITOR_FONT
26 *topFont; // holds top font in linked list of gui fonts
27
LocateLoadedFont(const char * name)28 static EDITOR_FONT *LocateLoadedFont(const char *name)
29 // see if an already loaded font can be located which has name
30 // if so, return a pointer to it, otherwise return NULL
31 // ### this should use a hash table
32 {
33 EDITOR_FONT
34 *testFont;
35
36 testFont=topFont;
37 while(testFont&&(strcasecmp(testFont->name,name)!=0))
38 {
39 testFont=testFont->next;
40 }
41 return(testFont);
42 }
43
GetClosestFont(const char * name)44 static XFontStruct *GetClosestFont(const char *name)
45 // return the X font which is the best we could find
46 {
47 XFontStruct
48 *font;
49
50 if((font=XLoadQueryFont(xDisplay,name)))
51 {
52 return(font);
53 }
54 if((font=XLoadQueryFont(xDisplay,FALLBACK_FONT_0)))
55 {
56 return(font);
57 }
58 if((font=XLoadQueryFont(xDisplay,FALLBACK_FONT_1)))
59 {
60 return(font);
61 }
62 if((font=XLoadQueryFont(xDisplay,FALLBACK_FONT_2)))
63 {
64 return(font);
65 }
66 if((font=XLoadQueryFont(xDisplay,FALLBACK_FONT_3)))
67 {
68 return(font);
69 }
70 SetError("Could not locate font '%s'",name);
71 return(NULL);
72 }
73
GetEditorFontName(EDITOR_FONT * font,char * nameBuffer,UINT32 bufferLength)74 void GetEditorFontName(EDITOR_FONT *font,char *nameBuffer,UINT32 bufferLength)
75 // Copy the name of the passed font into nameBuffer which is
76 // bufferLength bytes long (including the 0 termination)
77 {
78 if(bufferLength)
79 {
80 strncpy(nameBuffer,font->name,bufferLength);
81 nameBuffer[bufferLength-1]='\0';
82 }
83 }
84
FreeEditorFont(EDITOR_FONT * font)85 void FreeEditorFont(EDITOR_FONT *font)
86 // Free a font allocated by LoadEditorFont
87 {
88 if(!(--font->usageCount))
89 {
90 XFreeFont(xDisplay,font->xFont);
91 if(font->previous)
92 {
93 font->previous->next=font->next;
94 }
95 else
96 {
97 topFont=font->next;
98 }
99 if(font->next)
100 {
101 font->next->previous=font->previous;
102 }
103 MDisposePtr(font);
104 }
105 }
106
LoadEditorFont(const char * name)107 EDITOR_FONT *LoadEditorFont(const char *name)
108 // attempt to load the font given by name
109 // if there is a problem, SetError, return NULL
110 {
111 EDITOR_FONT
112 *result;
113 int
114 overhang;
115 int
116 i,j;
117
118 if((result=LocateLoadedFont(name))) // see if we can find this one already loaded
119 {
120 result->usageCount++; // add another user to this font structure
121 return(result);
122 }
123 else
124 {
125 if((result=(EDITOR_FONT *)MNewPtr(sizeof(EDITOR_FONT)))) // allocate one
126 {
127 if((result->xFont=GetClosestFont(name)))
128 {
129 strncpy(result->name,name,sizeof(result->name));
130 result->name[sizeof(result->name)-1]='\0'; // terminate string if copy was too long
131
132 result->usageCount=1;
133
134 result->previous=NULL; // link to font list
135 if((result->next=topFont))
136 {
137 topFont->previous=result;
138 }
139 topFont=result;
140
141 result->ascent=result->xFont->ascent;
142 result->descent=result->xFont->descent;
143
144 result->maxLeftOverhang=0; // initialize the overhang amounts
145 result->maxRightOverhang=0;
146
147 for(i=0;i<256;i++)
148 {
149 result->charWidths[i]=0; // clear widths for non-existent characters
150 }
151 if(result->xFont->per_char) // see if there is information for individual characters
152 {
153 j=0;
154 for(i=result->xFont->min_char_or_byte2;i<=(int)result->xFont->max_char_or_byte2;i++)
155 {
156 // handle left overhang
157 overhang=-result->xFont->per_char[j].lbearing;
158 if(overhang>(INT32)result->maxLeftOverhang)
159 {
160 result->maxLeftOverhang=(UINT32)overhang;
161 }
162
163 // handle right overhang
164 overhang=result->xFont->per_char[j].rbearing-result->xFont->per_char[j].width;
165 if(overhang>(INT32)result->maxRightOverhang)
166 {
167 result->maxRightOverhang=(UINT32)overhang;
168 }
169
170 result->charWidths[i]=result->xFont->per_char[j].width; // set widths for existing characters
171 j++;
172 }
173 }
174 else
175 {
176 for(i=result->xFont->min_char_or_byte2;i<=(int)result->xFont->max_char_or_byte2;i++)
177 {
178 result->charWidths[i]=result->xFont->max_bounds.width; // set widths for existing characters
179 }
180 }
181 return(result);
182 }
183 MDisposePtr(result);
184 }
185 }
186 return(NULL);
187 }
188
UnInitFonts()189 void UnInitFonts()
190 // Undo what InitFonts did
191 {
192 }
193
InitFonts()194 bool InitFonts()
195 // set up font handling stuff
196 {
197 topFont=NULL; // no top font loaded in yet
198 memset(defaultViewFont,0,sizeof(defaultViewFont));
199 memset(defaultMenuFont,0,sizeof(defaultMenuFont));
200 memset(defaultDialogButtonFont,0,sizeof(defaultDialogButtonFont));
201 memset(defaultDialogTextFont,0,sizeof(defaultDialogTextFont));
202 memset(defaultStatusBarFont,0,sizeof(defaultStatusBarFont));
203 return(true);
204 }
205