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