1 //----------------------------------------------------------------------------
2 //  EDGE Data Definition File Code (Fonts)
3 //----------------------------------------------------------------------------
4 //
5 //  Copyright (c) 1999-2008  The EDGE Team.
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; either version 2
10 //  of the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //----------------------------------------------------------------------------
18 //
19 // Font Setup and Parser Code
20 //
21 
22 #include "local.h"
23 
24 #include "font.h"
25 
26 static fontdef_c *dynamic_font;
27 
28 static void DDF_FontGetType( const char *info, void *storage);
29 static void DDF_FontGetPatch(const char *info, void *storage);
30 
31 #define DDF_CMD_BASE  dummy_font
32 static fontdef_c dummy_font;
33 
34 static const commandlist_t font_commands[] =
35 {
36 	DDF_FIELD("TYPE",     type,       DDF_FontGetType),
37 	DDF_FIELD("PATCHES",  patches,    DDF_FontGetPatch),
38 	DDF_FIELD("IMAGE",    image_name, DDF_MainGetString),
39 	DDF_FIELD("MISSING_PATCH", missing_patch, DDF_MainGetString),
40 
41 	DDF_CMD_END
42 };
43 
44 // -ACB- 2004/06/03 Replaced array and size with purpose-built class
45 fontdef_container_c fontdefs;
46 
47 //
48 //  DDF PARSE ROUTINES
49 //
FontStartEntry(const char * name,bool extend)50 static void FontStartEntry(const char *name, bool extend)
51 {
52 	if (!name || !name[0])
53 	{
54 		DDF_WarnError("New font entry is missing a name!");
55 		name = "FONT_WITH_NO_NAME";
56 	}
57 
58 	dynamic_font = fontdefs.Lookup(name);
59 
60 	if (extend)
61 	{
62 		if (! dynamic_font)
63 			DDF_Error("Unknown font to extend: %s\n", name);
64 		return;
65 	}
66 
67 	// replaces the existing entry
68 	if (dynamic_font)
69 	{
70 		dynamic_font->Default();
71 		return;
72 	}
73 
74 	// not found, create a new one
75 	dynamic_font = new fontdef_c;
76 
77 	dynamic_font->name = name;
78 
79 	fontdefs.Insert(dynamic_font);
80 }
81 
82 
FontParseField(const char * field,const char * contents,int index,bool is_last)83 static void FontParseField(const char *field, const char *contents, int index, bool is_last)
84 {
85 #if (DEBUG_DDF)
86 	I_Debugf("FONT_PARSE: %s = %s;\n", field, contents);
87 #endif
88 
89 	if (DDF_MainParseField(font_commands, field, contents, (byte *)dynamic_font))
90 		return;  // OK
91 
92 	DDF_Error("Unknown fonts.ddf command: %s\n", field);
93 }
94 
95 
FontFinishEntry(void)96 static void FontFinishEntry(void)
97 {
98 	if (dynamic_font->type == FNTYP_UNSET)
99 		DDF_Error("No type specified for font.\n");
100 
101 	if (dynamic_font->type == FNTYP_Patch && ! dynamic_font->patches)
102 		DDF_Error("Missing font patch list.\n");
103 
104 	// FIXME: check FNTYP_Image
105 }
106 
107 
FontClearAll(void)108 static void FontClearAll(void)
109 {
110 	I_Warning("Ignoring #CLEARALL in fonts.ddf\n");
111 }
112 
113 
DDF_ReadFonts(void * data,int size)114 bool DDF_ReadFonts(void *data, int size)
115 {
116 	readinfo_t fonts;
117 
118 	fonts.memfile = (char*)data;
119 	fonts.memsize = size;
120 	fonts.tag = "FONTS";
121 	fonts.entries_per_dot = 2;
122 
123 	if (fonts.memfile)
124 	{
125 		fonts.message  = NULL;
126 		fonts.filename = NULL;
127 		fonts.lumpname = "DDFFONT";
128 	}
129 	else
130 	{
131 		fonts.message  = "DDF_InitFonts";
132 		fonts.filename = "fonts.ddf";
133 		fonts.lumpname = NULL;
134 	}
135 
136 	fonts.start_entry  = FontStartEntry;
137 	fonts.parse_field  = FontParseField;
138 	fonts.finish_entry = FontFinishEntry;
139 	fonts.clear_all    = FontClearAll;
140 
141 	return DDF_MainReadFile(&fonts);
142 }
143 
144 //
145 // DDF_FontInit
146 //
DDF_FontInit(void)147 void DDF_FontInit(void)
148 {
149 	fontdefs.Clear();		// <-- Consistent with existing behaviour (-ACB- 2004/05/04)
150 }
151 
152 //
153 // DDF_FontCleanUp
154 //
DDF_FontCleanUp(void)155 void DDF_FontCleanUp(void)
156 {
157 	if (fontdefs.GetSize() == 0)
158 		I_Error("There are no fonts defined in DDF !\n");
159 
160 	fontdefs.Trim();		// <-- Reduce to allocated size
161 }
162 
163 //
164 // DDF_FontGetType
165 //
DDF_FontGetType(const char * info,void * storage)166 static void DDF_FontGetType(const char *info, void *storage)
167 {
168 	SYS_ASSERT(storage);
169 
170 	fonttype_e *type = (fonttype_e *) storage;
171 
172 	if (DDF_CompareName(info, "PATCH") == 0)
173 		(*type) = FNTYP_Patch;
174 	else if (DDF_CompareName(info, "IMAGE") == 0)
175 		(*type) = FNTYP_Image;
176 	else
177 		DDF_Error("Unknown font type: %s\n", info);
178 }
179 
FontParseCharacter(const char * buf)180 static int FontParseCharacter(const char *buf)
181 {
182 #if 0  // the main parser strips out all the " quotes
183 	while (isspace(*buf))
184 		buf++;
185 
186 	if (buf[0] == '"')
187 	{
188 		// check for escaped quote
189 		if (buf[1] == '\\' && buf[2] == '"')
190 			return '"';
191 
192 		return buf[1];
193 	}
194 #endif
195 
196 	if (buf[0]>0 && isdigit(buf[0]) && isdigit(buf[1]))
197 		return atoi(buf);
198 
199 	return buf[0];
200 
201 #if 0
202 	DDF_Error("Malformed character name: %s\n", buf);
203 	return 0;
204 #endif
205 }
206 
207 //
208 // DDF_FontGetPatch
209 //
210 // Formats: PATCH123("x"), PATCH065(65),
211 //          PATCH456("a" : "z"), PATCH033(33:111).
212 //
DDF_FontGetPatch(const char * info,void * storage)213 static void DDF_FontGetPatch(const char *info, void *storage)
214 {
215 	fontpatch_c **patch_list = (fontpatch_c **)storage;
216 
217 	char patch_buf[100];
218 	char range_buf[100];
219 
220 	if (! DDF_MainDecodeBrackets(info, patch_buf, range_buf, 100))
221 		DDF_Error("Malformed font patch: %s\n", info);
222 
223 	// find dividing colon
224 	char *colon = NULL;
225 
226 	if (strlen(range_buf) > 1)
227 		colon = (char *) DDF_MainDecodeList(range_buf, ':', true);
228 
229 	if (colon)
230 		*colon++ = 0;
231 
232 	int char1, char2;
233 
234 	// get the characters
235 
236 	char1 = FontParseCharacter(range_buf);
237 
238 	if (colon)
239 	{
240 		char2 = FontParseCharacter(colon);
241 
242 		if (char1 > char2)
243 			DDF_Error("Bad character range: %s > %s\n", range_buf, colon);
244 	}
245 	else
246 		char2 = char1;
247 
248 	fontpatch_c *pat = new fontpatch_c(char1, char2, patch_buf);
249 
250 	// add to list
251 	pat->next = *patch_list;
252 
253 	*patch_list = pat;
254 }
255 
256 
257 // ---> fontpatch_c class
258 
fontpatch_c(int _ch1,int _ch2,const char * _pat1)259 fontpatch_c::fontpatch_c(int _ch1, int _ch2, const char *_pat1) :
260 	next(NULL), char1(_ch1), char2(_ch2), patch1(_pat1)
261 { }
262 
263 // ---> fontdef_c class
264 
265 //
266 // fontdef_c constructor
267 //
fontdef_c()268 fontdef_c::fontdef_c() : name()
269 {
270 	Default();
271 }
272 
273 //
274 // fontdef_c::CopyDetail()
275 //
276 // Copies all the detail with the exception of ddf info
277 //
CopyDetail(const fontdef_c & src)278 void fontdef_c::CopyDetail(const fontdef_c &src)
279 {
280 	type = src.type;
281 	patches = src.patches;  // FIXME: copy list
282 	image_name = src.image_name;
283 	missing_patch = src.missing_patch;
284 }
285 
286 //
287 // fontdef_c::Default()
288 //
Default()289 void fontdef_c::Default()
290 {
291 	type = FNTYP_Patch;
292 	patches = NULL;
293 	image_name.clear();
294 	missing_patch.clear();
295 }
296 
297 
298 // ---> fontdef_container_c class
299 
300 //
301 // fontdef_container_c::CleanupObject()
302 //
CleanupObject(void * obj)303 void fontdef_container_c::CleanupObject(void *obj)
304 {
305 	fontdef_c *a = *(fontdef_c**)obj;
306 
307 	if (a) delete a;
308 }
309 
310 //
311 // fontdef_container_c::Lookup()
312 //
Lookup(const char * refname)313 fontdef_c* fontdef_container_c::Lookup(const char *refname)
314 {
315 	if (!refname || !refname[0])
316 		return NULL;
317 
318 	for (epi::array_iterator_c it = GetIterator(0); it.IsValid(); it++)
319 	{
320 		fontdef_c *f = ITERATOR_TO_TYPE(it, fontdef_c*);
321 		if (DDF_CompareName(f->name.c_str(), refname) == 0)
322 			return f;
323 	}
324 
325 	return NULL;
326 }
327 
328 //
329 // DDF_MainLookupFont
330 //
DDF_MainLookupFont(const char * info,void * storage)331 void DDF_MainLookupFont(const char *info, void *storage)
332 {
333 	fontdef_c **dest = (fontdef_c **)storage;
334 
335 	*dest = fontdefs.Lookup(info);
336 
337 	if (*dest == NULL)
338 		DDF_Error("Unknown font: %s\n", info);
339 }
340 
341 
342 //--- editor settings ---
343 // vi:ts=4:sw=4:noexpandtab
344