1 //----------------------------------------------------------------------------
2 //  EDGE Data Definition File Code (Colourmaps)
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 // Colourmap handling.
20 //
21 
22 #include "local.h"
23 
24 #include "colormap.h"
25 
26 static colourmap_c *dynamic_colmap;
27 
28 colourmap_container_c colourmaps;
29 
30 void DDF_ColmapGetSpecial(const char *info, void *storage);
31 
32 #define DDF_CMD_BASE  dummy_colmap
33 static colourmap_c dummy_colmap;
34 
35 static const commandlist_t colmap_commands[] =
36 {
37 	DDF_FIELD("LUMP",    lump_name, DDF_MainGetLumpName),
38 	DDF_FIELD("START",   start,     DDF_MainGetNumeric),
39 	DDF_FIELD("LENGTH",  length,    DDF_MainGetNumeric),
40 	DDF_FIELD("SPECIAL", special,   DDF_ColmapGetSpecial),
41 	DDF_FIELD("GL_COLOUR", gl_colour, DDF_MainGetRGB),
42 
43 	DDF_CMD_END
44 };
45 
46 
47 //
48 //  DDF PARSE ROUTINES
49 //
50 
ColmapStartEntry(const char * name,bool extend)51 static void ColmapStartEntry(const char *name, bool extend)
52 {
53 	if (!name || name[0] == 0)
54 	{
55 		DDF_WarnError("New colormap entry is missing a name!");
56 		name = "COLORMAP_WITH_NO_NAME";
57 	}
58 
59 	dynamic_colmap = colourmaps.Lookup(name);
60 
61 	if (extend)
62 	{
63 		if (! dynamic_colmap)
64 			DDF_Error("Unknown colormap to extend: %s\n", name);
65 		return;
66 	}
67 
68 	// replaces the existing entry
69 	if (dynamic_colmap)
70 	{
71 		dynamic_colmap->Default();
72 
73 		if (strnicmp(name, "TEXT", 4) == 0)
74 			dynamic_colmap->special = COLSP_Whiten;
75 
76 		return;
77 	}
78 
79 	// not found, create a new one
80 	dynamic_colmap = new colourmap_c;
81 
82 	dynamic_colmap->name.Set(name);
83 
84 	// make sure fonts get whitened properly (as the default)
85 	if (strnicmp(name, "TEXT", 4) == 0)
86 		dynamic_colmap->special = COLSP_Whiten;
87 
88 	colourmaps.Insert(dynamic_colmap);
89 }
90 
91 
ColmapParseField(const char * field,const char * contents,int index,bool is_last)92 static void ColmapParseField(const char *field, const char *contents,
93     int index, bool is_last)
94 {
95 #if (DEBUG_DDF)
96 	I_Debugf("COLMAP_PARSE: %s = %s;\n", field, contents);
97 #endif
98 
99 	// -AJA- backwards compatibility cruft...
100 	if (DDF_CompareName(field, "PRIORITY") == 0)
101 		return;
102 
103 	if (DDF_MainParseField(colmap_commands, field, contents, (byte *)dynamic_colmap))
104 		return;  // OK
105 
106 	DDF_WarnError("Unknown colmap.ddf command: %s\n", field);
107 }
108 
109 
ColmapFinishEntry(void)110 static void ColmapFinishEntry(void)
111 {
112 	if (dynamic_colmap->start < 0)
113 	{
114 		DDF_WarnError("Bad START value for colmap: %d\n", dynamic_colmap->start);
115 		dynamic_colmap->start = 0;
116 	}
117 
118 	// don't need a length when using GL_COLOUR
119 	if (! dynamic_colmap->lump_name.empty() && dynamic_colmap->length <= 0)
120 	{
121 		DDF_WarnError("Bad LENGTH value for colmap: %d\n", dynamic_colmap->length);
122 		dynamic_colmap->length = 1;
123 	}
124 
125 	if (dynamic_colmap->lump_name.empty() && dynamic_colmap->gl_colour == RGB_NO_VALUE)
126 		DDF_Error("Colourmap entry missing LUMP or GL_COLOUR.\n");
127 }
128 
129 
ColmapClearAll(void)130 static void ColmapClearAll(void)
131 {
132 	I_Warning("Ignoring #CLEARALL in colormap.ddf\n");
133 }
134 
135 
DDF_ReadColourMaps(void * data,int size)136 bool DDF_ReadColourMaps(void *data, int size)
137 {
138 	readinfo_t colm_r;
139 
140 	colm_r.memfile = (char*)data;
141 	colm_r.memsize = size;
142 	colm_r.tag = "COLOURMAPS";
143 	colm_r.entries_per_dot = 2;
144 
145 	if (colm_r.memfile)
146 	{
147 		colm_r.message = NULL;
148 		colm_r.filename = NULL;
149 		colm_r.lumpname = "DDFCOLM";
150 	}
151 	else
152 	{
153 		colm_r.message = "DDF_InitColourMaps";
154 		colm_r.filename = "colmap.ddf";
155 		colm_r.lumpname = NULL;
156 	}
157 
158 	colm_r.start_entry  = ColmapStartEntry;
159 	colm_r.parse_field  = ColmapParseField;
160 	colm_r.finish_entry = ColmapFinishEntry;
161 	colm_r.clear_all    = ColmapClearAll;
162 
163 	return DDF_MainReadFile(&colm_r);
164 }
165 
166 
DDF_ColmapInit(void)167 void DDF_ColmapInit(void)
168 {
169 	colourmaps.Clear();
170 }
171 
172 
DDF_ColmapCleanUp(void)173 void DDF_ColmapCleanUp(void)
174 {
175 	colourmaps.Trim();
176 }
177 
178 
179 specflags_t colmap_specials[] =
180 {
181 	{"FLASH",  COLSP_NoFlash, true},
182 	{"WHITEN", COLSP_Whiten,  false},
183 
184 	// -AJA- backwards compatibility cruft...
185 	{"SKY", 0, 0},
186 
187 	{NULL, 0, 0}
188 };
189 
190 
191 //
192 // DDF_ColmapGetSpecial
193 //
194 // Gets the colourmap specials.
195 //
DDF_ColmapGetSpecial(const char * info,void * storage)196 void DDF_ColmapGetSpecial(const char *info, void *storage)
197 {
198 	colourspecial_e *spec = (colourspecial_e *)storage;
199 
200 	int flag_value;
201 
202 	switch (DDF_MainCheckSpecialFlag(info, colmap_specials, &flag_value,
203 				true, false))
204 	{
205 		case CHKF_Positive:
206 			*spec = (colourspecial_e)(*spec | flag_value);
207 			break;
208 
209 		case CHKF_Negative:
210 			*spec = (colourspecial_e)(*spec & ~flag_value);
211 			break;
212 
213 		case CHKF_User:
214 		case CHKF_Unknown:
215 			DDF_WarnError("DDF_ColmapGetSpecial: Unknown Special: %s", info);
216 			break;
217 	}
218 }
219 
220 
221 //
222 // This is used to make entries for lumps between C_START and C_END
223 // markers in a (BOOM) WAD file.
224 //
DDF_ColourmapAddRaw(const char * lump_name,int size)225 void DDF_ColourmapAddRaw(const char *lump_name, int size)
226 {
227 	if (size < 256)
228 	{
229 		I_Warning("WAD Colourmap '%s' too small (%d < %d)\n", lump_name, size, 256);
230 		return;
231 	}
232 
233 	colourmap_c *def = colourmaps.Lookup(lump_name);
234 
235 	// not found, create a new one
236 	if (! def)
237 	{
238 		def = new colourmap_c;
239 
240 		colourmaps.Insert(def);
241 	}
242 
243 	def->Default();
244 
245 	def->name = lump_name;
246 
247 	def->lump_name.Set(lump_name);
248 
249 	def->start  = 0;
250 	def->length = MIN(32, size / 256);
251 
252 	I_Debugf("- Added RAW colourmap '%s' start=%d length=%d\n",
253 		lump_name, def->start, def->length);
254 }
255 
256 
257 // --> Colourmap Class
258 
259 //
260 // colourmap_c Constructor
261 //
colourmap_c()262 colourmap_c::colourmap_c() : name()
263 {
264 	Default();
265 }
266 
267 //
268 // colourmap_c Deconstructor
269 //
~colourmap_c()270 colourmap_c::~colourmap_c()
271 {
272 }
273 
274 //
275 // colourmap_c::CopyDetail()
276 //
CopyDetail(colourmap_c & src)277 void colourmap_c::CopyDetail(colourmap_c &src)
278 {
279 	lump_name = src.lump_name;
280 
281 	start   = src.start;
282 	length  = src.length;
283 	special = src.special;
284 
285 	gl_colour   = src.gl_colour;
286 	font_colour = src.font_colour;
287 
288 	// FIXME!!! Cache struct to class
289 	cache.data = src.cache.data;
290 	analysis = NULL;
291 }
292 
293 //
294 // colourmap_c::Default()
295 //
Default()296 void colourmap_c::Default()
297 {
298 	lump_name.clear();
299 
300 	start   = 0;
301 	length  = 0;
302 	special = COLSP_None;
303 
304 	gl_colour   = RGB_NO_VALUE;
305 	font_colour = RGB_NO_VALUE;
306 
307 	// FIXME!!! Cache struct to class
308 	cache.data = NULL;
309 	analysis = NULL;
310 }
311 
312 
313 // --> colourmap_container_c class
314 
315 //
316 // colourmap_container_c::colourmap_container_c()
317 //
colourmap_container_c()318 colourmap_container_c::colourmap_container_c() : epi::array_c(sizeof(atkdef_c*))
319 {
320 }
321 
322 //
323 // ~colourmap_container_c::colourmap_container_c()
324 //
~colourmap_container_c()325 colourmap_container_c::~colourmap_container_c()
326 {
327 	Clear();					// <-- Destroy self before exiting
328 }
329 
330 //
331 // colourmap_container_c::CleanupObject
332 //
CleanupObject(void * obj)333 void colourmap_container_c::CleanupObject(void *obj)
334 {
335 	colourmap_c *c = *(colourmap_c**)obj;
336 
337 	if (c)
338 		delete c;
339 
340 	return;
341 }
342 
343 //
344 // colourmap_c* colourmap_container_c::Lookup()
345 //
Lookup(const char * refname)346 colourmap_c* colourmap_container_c::Lookup(const char *refname)
347 {
348 	epi::array_iterator_c it;
349 	colourmap_c *c;
350 
351 	if (!refname || !refname[0])
352 		return NULL;
353 
354 	for (it = GetIterator(0); it.IsValid(); it++)
355 	{
356 		c = ITERATOR_TO_TYPE(it, colourmap_c*);
357 		if (DDF_CompareName(c->name.c_str(), refname) == 0)
358 			return c;
359 	}
360 
361 	return NULL;
362 }
363 
364 //--- editor settings ---
365 // vi:ts=4:sw=4:noexpandtab
366