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