comparison mde/resource/paths.d @ 53:f000d6cd0f74

Changes to paths, command line arguments and font LCD rendering. Use "./" instead of "" as default install dir on windows. Implemented a command-line argument parser. Changes to LCD filter/render-mode option handling after testing what actually happens. Changed some FontTexture messages and internals.
author Diggory Hardy <diggory.hardy@gmail.com>
date Thu, 05 Jun 2008 17:16:52 +0100
parents e0839643ff52
children
comparison
equal deleted inserted replaced
51:387a80724c35 53:f000d6cd0f74
37 import mde.mergetag.DataSet; 37 import mde.mergetag.DataSet;
38 import mde.mergetag.exception; 38 import mde.mergetag.exception;
39 39
40 import tango.io.Console; 40 import tango.io.Console;
41 import tango.io.FilePath; 41 import tango.io.FilePath;
42 import tango.stdc.stdlib; 42 import tango.sys.Environment;
43 import tango.stdc.stringz;
44 //import tango.scrapple.sys.win32.Registry; // Trouble getting this to work 43 //import tango.scrapple.sys.win32.Registry; // Trouble getting this to work
45 44
46 /** Order to read files in. 45 /** Order to read files in.
47 * 46 *
48 * Values: HIGH_LOW, LOW_HIGH, HIGH_ONLY. */ 47 * Values: HIGH_LOW, LOW_HIGH, HIGH_ONLY. */
113 if (FilePath (paths[i]~file~".mtb").exists) return true; 112 if (FilePath (paths[i]~file~".mtb").exists) return true;
114 } 113 }
115 return false; 114 return false;
116 } 115 }
117 116
117 /// Print all paths found.
118 static void printPaths () {
119 Cout ("Data paths found:");
120 dataDir.coutPaths;
121 Cout ("\nConf paths found:");
122 confDir.coutPaths;
123 Cout ("\nLog file directory:\n\t")(logDir).newline;
124 }
125
118 private: 126 private:
119 PathView[] getFiles (char[] filename, PRIORITY readOrder) 127 PathView[] getFiles (char[] filename, PRIORITY readOrder)
120 in { 128 in {
121 assert (readOrder == PRIORITY.LOW_HIGH || 129 assert (readOrder == PRIORITY.LOW_HIGH ||
122 readOrder == PRIORITY.HIGH_LOW || 130 readOrder == PRIORITY.HIGH_LOW ||
163 } 171 }
164 } 172 }
165 return false; 173 return false;
166 } 174 }
167 175
176 void coutPaths () {
177 if (pathsLen) {
178 for (size_t i = 0; i < pathsLen; ++i)
179 Cout ("\n\t" ~ paths[i]);
180 } else
181 Cout ("[none]");
182 }
183
168 // Use a static array to store all possible paths with separate length counters. 184 // Use a static array to store all possible paths with separate length counters.
169 // Lowest priority paths are first. 185 // Lowest priority paths are first.
170 char[][MAX_PATHS] paths; 186 char[][MAX_PATHS] paths;
171 ubyte pathsLen = 0; 187 ubyte pathsLen = 0;
172 } 188 }
183 /** Find at least one path for each required directory. 199 /** Find at least one path for each required directory.
184 * 200 *
185 * Note: the logger cannot be used yet, so only output is exception messages. */ 201 * Note: the logger cannot be used yet, so only output is exception messages. */
186 // FIXME: use tango/sys/Environment.d 202 // FIXME: use tango/sys/Environment.d
187 version (linux) { 203 version (linux) {
188 void resolvePaths () { 204 // base-path not used on posix
205 void resolvePaths (char[] = null) {
189 // Home directory: 206 // Home directory:
190 char[] HOME = fromStringz (getenv (toStringz ("HOME"))); 207 char[] HOME = Environment.get("HOME", ".");
191 208
192 // Base paths: 209 // Base paths:
193 // Static data (must exist): 210 // Static data (must exist):
194 PathView staticPath = findPath (false, "/usr/share/games/mde", "/usr/local/share/games/mde", "data"); 211 PathView staticPath =
212 findPath (false, "/usr/share/games/mde", "/usr/local/share/games/mde", "data");
195 // Config (can just use defaults if necessary, so long as we can save afterwards): 213 // Config (can just use defaults if necessary, so long as we can save afterwards):
196 PathView userPath = findPath (true, HOME~"/.config/mde", HOME~"/.mde"); 214 PathView userPath = findPath (true, HOME~"/.config/mde", HOME~"/.mde");
197 215
198 // Static data paths: 216 // Static data paths:
199 dataDir.addPath (staticPath.toString); // we know this is valid anyway 217 dataDir.addPath (staticPath.toString); // we know this is valid anyway
200 dataDir.tryPath (userPath.toString ~ DATA); 218 dataDir.tryPath (userPath.toString ~ DATA);
219 if (extraDataPath) dataDir.tryPath (extraDataPath);
201 if (!dataDir.pathsLen) throw new mdeException ("Fatal: no data path found!"); 220 if (!dataDir.pathsLen) throw new mdeException ("Fatal: no data path found!");
202 221
203 // Configuration paths: 222 // Configuration paths:
204 confDir.tryPath (staticPath.toString ~ CONF); 223 confDir.tryPath (staticPath.toString ~ CONF);
205 confDir.tryPath ("/etc/mde"); 224 confDir.tryPath ("/etc/mde");
206 confDir.tryPath (userPath.toString ~ CONF, true); 225 confDir.tryPath (userPath.toString ~ CONF, true);
226 if (extraConfPath) confDir.tryPath (extraConfPath);
207 if (!confDir.pathsLen) throw new mdeException ("Fatal: no conf path found!"); 227 if (!confDir.pathsLen) throw new mdeException ("Fatal: no conf path found!");
208 228
209 // Logging path: 229 // Logging path:
210 logDir = userPath.toString; 230 logDir = userPath.toString;
211 } 231 }
212 } else version (Windows) { 232 } else version (Windows) {
213 void resolvePaths () { 233 void resolvePaths (char[] base = "./") {
214 //FIXME: Get path from registry 234 //FIXME: Get path from registry
215 //FIXME: Get user path (Docs&Settings/USER/Local Settings/Application data/mde) 235 //FIXME: Get user path (Docs&Settings/USER/Local Settings/Application data/mde)
236 //http://www.dsource.org/projects/tango/forums/topic/187
216 237
217 // Base paths: 238 // Base paths:
218 PathView installPath = findPath (false, "");; 239 PathView installPath = findPath (false, base);
219 PathView userPath = findPath (true, "user"); // FIXME: see above 240 PathView staticPath = findPath (false, installPath.append("data").toString);
220 PathView staticPath = findPath (false, "data"); 241 PathView userPath = findPath (true, installPath.append("user").toString); // FIXME: see above
221 242
222 // Static data paths: 243 // Static data paths:
223 dataDir.addPath (staticPath.toString); // we know this is valid anyway 244 dataDir.addPath (staticPath.toString); // we know this is valid anyway
224 dataDir.tryPath (userPath.toString ~ DATA); 245 dataDir.tryPath (userPath.toString ~ DATA);
246 if (extraDataPath) dataDir.tryPath (extraDataPath);
225 if (!dataDir.pathsLen) throw new mdeException ("Fatal: no data path found!"); 247 if (!dataDir.pathsLen) throw new mdeException ("Fatal: no data path found!");
226 248
227 // Configuration paths: 249 // Configuration paths:
228 confDir.tryPath (staticPath.toString ~ CONF); 250 confDir.tryPath (staticPath.toString ~ CONF);
229 confDir.tryPath ("conf"); 251 confDir.tryPath (installPath.append("user").toString);
230 confDir.tryPath (userPath.toString ~ CONF, true); 252 confDir.tryPath (userPath.toString ~ CONF, true);
253 if (extraConfPath) confDir.tryPath (extraConfPath);
231 if (!confDir.pathsLen) throw new mdeException ("Fatal: no conf path found!"); 254 if (!confDir.pathsLen) throw new mdeException ("Fatal: no conf path found!");
232 255
233 // Logging path: 256 // Logging path:
234 logDir = userPath.toString; 257 logDir = userPath.toString;
235 } 258 }
236 } else { 259 } else {
237 static assert (false, "Platform is not linux or Windows: no support for paths on this platform yet!"); 260 static assert (false, "Platform is not linux or Windows: no support for paths on this platform yet!");
238 } 261 }
239 262
240 private: 263 /// For command line args: these paths are added if non-null, with highest priority.
264 char[] extraDataPath, extraConfPath;
265
266 private {
267 class PathException : mdeException {
268 this(char[] msg) {
269 super (msg);
270 }
271 }
272
241 // The maximum number of paths for any one "directory". 273 // The maximum number of paths for any one "directory".
242 // There are NO CHECKS that this is not exceeded. 274 // There are NO CHECKS that this is not exceeded.
243 const MAX_PATHS = 3; 275 const MAX_PATHS = 4;
244 276
245 /* Try each path in succession, returning the first to exist and be a folder. 277 /* Try each path in succession, returning the first to exist and be a folder.
246 * If none are valid and create is true, will try creating each in turn. 278 * If none are valid and create is true, will try creating each in turn.
247 * If still none are valid, throws. */ 279 * If still none are valid, throws. */
248 PathView findPath (bool create, char[][] paths ...) { 280 PathView findPath (bool create, char[][] paths ...) {
249 foreach (path; paths) { 281 FilePath[] fps;
250 PathView pv = new FilePath (path); 282 fps.length = paths.length;
251 if (pv.exists && pv.isFolder) return pv; // got a valid path 283 foreach (i,path; paths) {
252 } 284 FilePath pv = new FilePath (path);
253 if (create) { // try to create a folder, using each path in turn until succesful 285 if (pv.exists && pv.isFolder) return pv; // got a valid path
254 foreach (path; paths) { 286 fps[i] = pv;
255 FilePath fp = new FilePath (path); 287 }
256 try { 288 if (create) { // try to create a folder, using each path in turn until succesful
257 return fp.create; 289 foreach (fp; fps) {
258 } 290 try {
259 catch (Exception e) {} 291 return fp.create;
260 } 292 }
261 } 293 catch (Exception e) {}
294 }
295 }
262 // no valid path... 296 // no valid path...
263 char[] msg = "Unable to find"~(create ? " or create" : "")~" a required path! The following were tried:"; 297 char[] msg = "Unable to find"~(create ? " or create" : "")~" a required path! The following were tried:";
264 foreach (path; paths) msg ~= " \"" ~ path ~ '\"'; 298 foreach (path; paths) msg ~= " \"" ~ path ~ '\"';
265 throw new mdeException (msg); 299 throw new PathException (msg);
266 } 300 }
267 //END Path resolution 301 //END Path resolution
268 302
269 /** A special adapter for reading from multiple mergetag files with the same relative path to an 303 /** A special adapter for reading from multiple mergetag files with the same relative path to an
270 * mdeDirectory simultaneously. 304 * mdeDirectory simultaneously.
271 */ 305 */
272 class mdeReader : IReader 306 class mdeReader : IReader
273 { 307 {
274 private this (PathView[] files, DataSet ds, bool rdHeader) 308 private this (PathView[] files, DataSet ds, bool rdHeader)
275 in { 309 in {
276 assert (files !is null, "mdeReader.this: files is null"); 310 assert (files !is null, "mdeReader.this: files is null");
277 } body { 311 } body {
278 if (ds is null) ds = new DataSet; 312 if (ds is null) ds = new DataSet;
279 313
280 foreach (file; files) { 314 foreach (file; files) {
281 IReader r = makeReader (file, ds, rdHeader); 315 IReader r = makeReader (file, ds, rdHeader);
282 316
283 readers[readersLen++] = r; 317 readers[readersLen++] = r;
284 } 318 }
285 } 319 }
286 320
287 DataSet dataset () { /// Get the DataSet 321 DataSet dataset () { /// Get the DataSet
288 return readers[0].dataset; // all readers share the same dataset 322 return readers[0].dataset; // all readers share the same dataset
289 } 323 }
290 void dataset (DataSet ds) { /// Set the DataSet 324 void dataset (DataSet ds) { /// Set the DataSet
291 for (uint i = 0; i < readersLen; ++i) readers[i].dataset (ds); 325 for (uint i = 0; i < readersLen; ++i) readers[i].dataset (ds);
292 } 326 }
293 327
294 void dataSecCreator (IDataSection delegate (ID) dsC) { /// Set the dataSecCreator 328 void dataSecCreator (IDataSection delegate (ID) dsC) { /// Set the dataSecCreator
295 for (uint i = 0; i < readersLen; ++i) readers[i].dataSecCreator = dsC; 329 for (uint i = 0; i < readersLen; ++i) readers[i].dataSecCreator = dsC;
296 } 330 }
297 331
298 /** Get identifiers for all sections. 332 /** Get identifiers for all sections.
299 * 333 *
300 * Note: the identifiers from all sections in all files are just strung together, starting with 334 * Note: the identifiers from all sections in all files are just strung together, starting with
301 * the highest-priority file. */ 335 * the highest-priority file. */
302 ID[] getSectionNames () { 336 ID[] getSectionNames () {
303 ID[] names; 337 ID[] names;
304 for (int i = readersLen-1; i >= 0; --i) names ~= readers[i].getSectionNames; 338 for (int i = readersLen-1; i >= 0; --i) names ~= readers[i].getSectionNames;
305 return names; 339 return names;
306 } 340 }
307 void read () { /// Commence reading 341 void read () { /// Commence reading
308 for (uint i = 0; i < readersLen; ++i) readers[i].read(); 342 for (uint i = 0; i < readersLen; ++i) readers[i].read();
309 } 343 }
310 void read (ID[] secSet) { /// ditto 344 void read (ID[] secSet) { /// ditto
311 for (uint i = 0; i < readersLen; ++i) readers[i].read(secSet); 345 for (uint i = 0; i < readersLen; ++i) readers[i].read(secSet);
312 } 346 }
313 void read (View!(ID) secSet) { /// ditto 347 void read (View!(ID) secSet) { /// ditto
314 for (uint i = 0; i < readersLen; ++i) readers[i].read(secSet); 348 for (uint i = 0; i < readersLen; ++i) readers[i].read(secSet);
315 } 349 }
316 350
317 private: 351 private:
318 IReader[MAX_PATHS] readers; 352 IReader[MAX_PATHS] readers;
319 ubyte readersLen = 0; 353 ubyte readersLen = 0;
320 354
321 PRIORITY rdOrder; 355 PRIORITY rdOrder;
356 }
322 } 357 }