1 //----------------------------------------------------------------------------
2 // EDGE Data Definition File Code (Styles)
3 //----------------------------------------------------------------------------
4 //
5 // Copyright (c) 2004-2005 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 // Style Setup and Parser Code
20 //
21
22 #include "local.h"
23
24 #include "epi/utility.h"
25
26 #include "font.h"
27 #include "style.h"
28
29 #undef DF
30 #define DF DDF_FIELD
31
32 styledef_c *default_style;
33
34 static void DDF_StyleGetSpecials(const char *info, void *storage);
35
36 styledef_container_c styledefs;
37
38 #undef DDF_CMD_BASE
39 #define DDF_CMD_BASE dummy_bgstyle
40 static backgroundstyle_c dummy_bgstyle;
41
42 static const commandlist_t background_commands[] =
43 {
44 DF("COLOUR", colour, DDF_MainGetRGB),
45 DF("TRANSLUCENCY", translucency, DDF_MainGetPercent),
46 DF("IMAGE", image_name, DDF_MainGetString),
47 DF("SCALE", scale, DDF_MainGetFloat),
48 DF("ASPECT", aspect, DDF_MainGetFloat),
49
50 DDF_CMD_END
51 };
52
53
54 #undef DDF_CMD_BASE
55 #define DDF_CMD_BASE dummy_textstyle
56 static textstyle_c dummy_textstyle;
57
58 static const commandlist_t text_commands[] =
59 {
60 DF("COLOURMAP", colmap, DDF_MainGetColourmap),
61 DF("TRANSLUCENCY", translucency, DDF_MainGetPercent),
62 DF("FONT", font, DDF_MainLookupFont),
63 DF("SCALE", scale, DDF_MainGetFloat),
64 DF("ASPECT", aspect, DDF_MainGetFloat),
65
66 DDF_CMD_END
67 };
68
69
70 #undef DDF_CMD_BASE
71 #define DDF_CMD_BASE dummy_soundstyle
72 static soundstyle_c dummy_soundstyle;
73
74 static const commandlist_t sound_commands[] =
75 {
76 DF("BEGIN", begin, DDF_MainLookupSound),
77 DF("END", end, DDF_MainLookupSound),
78 DF("SELECT", select, DDF_MainLookupSound),
79 DF("BACK", back, DDF_MainLookupSound),
80 DF("ERROR", error, DDF_MainLookupSound),
81 DF("MOVE", move, DDF_MainLookupSound),
82 DF("SLIDER", slider, DDF_MainLookupSound),
83
84 DDF_CMD_END
85 };
86
87
88 static styledef_c* dynamic_style;
89
90 #undef DDF_CMD_BASE
91 #define DDF_CMD_BASE dummy_style
92 static styledef_c dummy_style;
93
94 static const commandlist_t style_commands[] =
95 {
96 // sub-commands
97 DDF_SUB_LIST("BACKGROUND", bg, background_commands),
98 DDF_SUB_LIST("TEXT", text[0], text_commands),
99 DDF_SUB_LIST("ALT", text[1], text_commands),
100 DDF_SUB_LIST("TITLE", text[2], text_commands),
101 DDF_SUB_LIST("HELP", text[3], text_commands),
102 DDF_SUB_LIST("SOUND", sounds, sound_commands),
103
104 DF("SPECIAL", special, DDF_StyleGetSpecials),
105
106 DDF_CMD_END
107 };
108
109
110 //
111 // DDF PARSE ROUTINES
112 //
113
StyleStartEntry(const char * name,bool extend)114 static void StyleStartEntry(const char *name, bool extend)
115 {
116 if (!name || !name[0])
117 {
118 DDF_WarnError("New style entry is missing a name!");
119 name = "STYLE_WITH_NO_NAME";
120 }
121
122 // replaces an existing entry?
123 dynamic_style = styledefs.Lookup(name);
124
125 if (extend)
126 {
127 if (! dynamic_style)
128 DDF_Error("Unknown style to extend: %s\n", name);
129 return;
130 }
131
132 if (dynamic_style)
133 {
134 dynamic_style->Default();
135 return;
136 }
137
138 // not found, create a new one
139 dynamic_style = new styledef_c;
140 dynamic_style->name = name;
141
142 styledefs.Insert(dynamic_style);
143 }
144
145
StyleParseField(const char * field,const char * contents,int index,bool is_last)146 static void StyleParseField(const char *field, const char *contents,
147 int index, bool is_last)
148 {
149 #if (DEBUG_DDF)
150 I_Debugf("STYLE_PARSE: %s = %s;\n", field, contents);
151 #endif
152
153 if (DDF_MainParseField(style_commands, field, contents, (byte *)dynamic_style))
154 return; // OK
155
156 DDF_WarnError("Unknown styles.ddf command: %s\n", field);
157 }
158
159
StyleFinishEntry(void)160 static void StyleFinishEntry(void)
161 {
162 // TODO: check stuff
163 }
164
165
StyleClearAll(void)166 static void StyleClearAll(void)
167 {
168 I_Warning("Ignoring #CLEARALL in styles.ddf\n");
169 }
170
171
DDF_ReadStyles(void * data,int size)172 bool DDF_ReadStyles(void *data, int size)
173 {
174 readinfo_t styles;
175
176 styles.memfile = (char*)data;
177 styles.memsize = size;
178 styles.tag = "STYLES";
179 styles.entries_per_dot = 2;
180
181 if (styles.memfile)
182 {
183 styles.message = NULL;
184 styles.filename = NULL;
185 styles.lumpname = "DDFSTYLE";
186 }
187 else
188 {
189 styles.message = "DDF_InitStyles";
190 styles.filename = "styles.ddf";
191 styles.lumpname = NULL;
192 }
193
194 styles.start_entry = StyleStartEntry;
195 styles.parse_field = StyleParseField;
196 styles.finish_entry = StyleFinishEntry;
197 styles.clear_all = StyleClearAll;
198
199 return DDF_MainReadFile(&styles);
200 }
201
202
DDF_StyleInit(void)203 void DDF_StyleInit(void)
204 {
205 styledefs.Clear();
206 }
207
208
DDF_StyleCleanUp(void)209 void DDF_StyleCleanUp(void)
210 {
211 if (styledefs.GetSize() == 0)
212 I_Error("There are no styles defined in DDF !\n");
213
214 default_style = styledefs.Lookup("DEFAULT");
215
216 if (! default_style)
217 I_Error("Styles.ddf is missing the [DEFAULT] style.\n");
218 else if (! default_style->text[0].font)
219 I_Warning("The [DEFAULT] style is missing TEXT.FONT\n");
220
221 styledefs.Trim();
222 }
223
224
225 static specflags_t style_specials[] =
226 {
227 {"TILED", SYLSP_Tiled, 0},
228 {"TILED_NOSCALE", SYLSP_TiledNoScale, 0},
229 {NULL, 0, 0}
230 };
231
DDF_StyleGetSpecials(const char * info,void * storage)232 void DDF_StyleGetSpecials(const char *info, void *storage)
233 {
234 style_special_e *dest = (style_special_e *)storage;
235
236 int flag_value;
237
238 switch (DDF_MainCheckSpecialFlag(info, style_specials,
239 &flag_value, true, false))
240 {
241 case CHKF_Positive:
242 *dest = (style_special_e)(*dest | flag_value);
243 break;
244
245 case CHKF_Negative:
246 *dest = (style_special_e)(*dest & ~flag_value);
247 break;
248
249 case CHKF_User:
250 case CHKF_Unknown:
251 DDF_WarnError("Unknown style special: %s", info);
252 break;
253 }
254 }
255
256 // --> backgroundstyle_c definition class
257
258 //
259 // backgroundstyle_c Constructor
260 //
backgroundstyle_c()261 backgroundstyle_c::backgroundstyle_c()
262 {
263 Default();
264 }
265
266 //
267 // backgroundstyle_c Copy constructor
268 //
backgroundstyle_c(const backgroundstyle_c & rhs)269 backgroundstyle_c::backgroundstyle_c(const backgroundstyle_c &rhs)
270 {
271 *this = rhs;
272 }
273
274 //
275 // backgroundstyle_c Destructor
276 //
~backgroundstyle_c()277 backgroundstyle_c::~backgroundstyle_c()
278 {
279 }
280
281 //
282 // backgroundstyle_c::Default()
283 //
Default()284 void backgroundstyle_c::Default()
285 {
286 colour = RGB_NO_VALUE;
287 translucency = PERCENT_MAKE(100);
288
289 image_name.clear();
290
291 scale = 1.0f;
292 aspect = 1.0f;
293 }
294
295 //
296 // backgroundstyle_c assignment operator
297 //
operator =(const backgroundstyle_c & rhs)298 backgroundstyle_c& backgroundstyle_c::operator= (const backgroundstyle_c &rhs)
299 {
300 if (&rhs != this)
301 {
302 colour = rhs.colour;
303 translucency = rhs.translucency;
304
305 image_name = rhs.image_name;
306
307 scale = rhs.scale;
308 aspect = rhs.aspect;
309 }
310
311 return *this;
312 }
313
314 // --> textstyle_c definition class
315
316 //
317 // textstyle_c Constructor
318 //
textstyle_c()319 textstyle_c::textstyle_c()
320 {
321 Default();
322 }
323
324 //
325 // textstyle_c Copy constructor
326 //
textstyle_c(const textstyle_c & rhs)327 textstyle_c::textstyle_c(const textstyle_c &rhs)
328 {
329 *this = rhs;
330 }
331
332 //
333 // textstyle_c Destructor
334 //
~textstyle_c()335 textstyle_c::~textstyle_c()
336 {
337 }
338
339 //
340 // textstyle_c::Default()
341 //
Default()342 void textstyle_c::Default()
343 {
344 colmap = NULL;
345 translucency = PERCENT_MAKE(100);
346
347 font = NULL;
348 scale = 1.0f;
349 aspect = 1.0f;
350 }
351
352 //
353 // textstyle_c assignment operator
354 //
operator =(const textstyle_c & rhs)355 textstyle_c& textstyle_c::operator= (const textstyle_c &rhs)
356 {
357 if (&rhs != this)
358 {
359 colmap = rhs.colmap;
360 translucency = rhs.translucency;
361
362 font = rhs.font;
363 scale = rhs.scale;
364 aspect = rhs.aspect;
365 }
366
367 return *this;
368 }
369
370 // --> soundstyle_c definition class
371
372 //
373 // soundstyle_c Constructor
374 //
soundstyle_c()375 soundstyle_c::soundstyle_c()
376 {
377 Default();
378 }
379
380 //
381 // soundstyle_c Copy constructor
382 //
soundstyle_c(const soundstyle_c & rhs)383 soundstyle_c::soundstyle_c(const soundstyle_c &rhs)
384 {
385 *this = rhs;
386 }
387
388 //
389 // soundstyle_c Destructor
390 //
~soundstyle_c()391 soundstyle_c::~soundstyle_c()
392 {
393 }
394
395 //
396 // soundstyle_c::Default()
397 //
Default()398 void soundstyle_c::Default()
399 {
400 begin = NULL;
401 end = NULL;
402 select = NULL;
403 back = NULL;
404 error = NULL;
405 move = NULL;
406 slider = NULL;
407 }
408
409 //
410 // soundstyle_c assignment operator
411 //
operator =(const soundstyle_c & rhs)412 soundstyle_c& soundstyle_c::operator= (const soundstyle_c &rhs)
413 {
414 if (&rhs != this)
415 {
416 begin = rhs.begin;
417 end = rhs.end;
418 select = rhs.select;
419 back = rhs.back;
420 error = rhs.error;
421 move = rhs.move;
422 slider = rhs.slider;
423 }
424
425 return *this;
426 }
427
428 // --> style definition class
429
430 //
431 // styledef_c Constructor
432 //
styledef_c()433 styledef_c::styledef_c() : name()
434 {
435 Default();
436 }
437
438 //
439 // styledef_c Destructor
440 //
~styledef_c()441 styledef_c::~styledef_c()
442 {
443 }
444
445
446 //
447 // styledef_c::CopyDetail()
448 //
CopyDetail(const styledef_c & src)449 void styledef_c::CopyDetail(const styledef_c &src)
450 {
451 bg = src.bg;
452
453 for (int T = 0; T < NUM_TXST; T++)
454 text[T] = src.text[T];
455
456 sounds = src.sounds;
457
458 special = src.special;
459 }
460
461 //
462 // styledef_c::Default()
463 //
Default()464 void styledef_c::Default()
465 {
466 bg.Default();
467
468 for (int T = 0; T < NUM_TXST; T++)
469 text[T].Default();
470
471 sounds.Default();
472
473 special = (style_special_e) 0;
474 }
475
476
477 // --> map definition container class
478
479 //
480 // styledef_container_c::CleanupObject()
481 //
CleanupObject(void * obj)482 void styledef_container_c::CleanupObject(void *obj)
483 {
484 styledef_c *m = *(styledef_c**)obj;
485
486 if (m) delete m;
487 }
488
489 //
490 // styledef_container_c::Lookup()
491 //
492 // Finds a styledef by name, returns NULL if it doesn't exist.
493 //
Lookup(const char * refname)494 styledef_c* styledef_container_c::Lookup(const char *refname)
495 {
496 epi::array_iterator_c it;
497 styledef_c *m;
498
499 if (!refname || !refname[0])
500 return NULL;
501
502 for (it = GetTailIterator(); it.IsValid(); it--)
503 {
504 m = ITERATOR_TO_TYPE(it, styledef_c*);
505 if (DDF_CompareName(m->name.c_str(), refname) == 0)
506 return m;
507 }
508
509 return NULL;
510 }
511
512 //--- editor settings ---
513 // vi:ts=4:sw=4:noexpandtab
514