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