comparison mde/file/paths.d @ 135:bc697a218716

Somewhat unified path lookup between linux and windows and added font paths.
author Diggory Hardy <diggory.hardy@gmail.com>
date Fri, 30 Jan 2009 15:51:42 +0000
parents 7ababdf97748
children 4084f07f2c7a
comparison
equal deleted inserted replaced
134:7ababdf97748 135:bc697a218716
125 Cout ("Data paths found:"); 125 Cout ("Data paths found:");
126 dataDir.coutPaths; 126 dataDir.coutPaths;
127 Cout ("\nConf paths found:"); 127 Cout ("\nConf paths found:");
128 confDir.coutPaths; 128 confDir.coutPaths;
129 Cout ("\nLog file directory:\n\t")(logDir); 129 Cout ("\nLog file directory:\n\t")(logDir);
130 version (Windows) { 130 Cout ("\nFont directories:");
131 Cout ("\nFont directory:\n\t")(fontDir).newline; 131 foreach (path; fontPaths)
132 } else version (linux) { 132 Cout ("\n\t")(path.toString);
133 Cout ("\nFont files found:"); 133 Cout.newline;
134 foreach (f,p; fontFiles)
135 Cout ("\n\t")(f)("\t")(p[0..$-1]);
136 Cout.newline;
137 }
138 } 134 }
139 135
140 private: 136 private:
141 FilePath[] getFiles (char[] filename, PRIORITY readOrder) 137 FilePath[] getFiles (char[] filename, PRIORITY readOrder)
142 { 138 {
200 // Lowest priority paths are first. 196 // Lowest priority paths are first.
201 char[][MAX_PATHS] paths; 197 char[][MAX_PATHS] paths;
202 ubyte pathsLen = 0; 198 ubyte pathsLen = 0;
203 } 199 }
204 200
201 /** Get the actual path of a font file, or throw NoFileException if not found.
202 *
203 * Returns a C string (null terminated). */
204 char[] getFontPath (char[] file) {
205 foreach (path; fontPaths) {
206 FilePath font = path.dup.append (file);
207 if (font.exists && font.isFile)
208 return font.cString;
209 }
210 throw new NoFileException ("Unable to find font file: "~file);
211 }
212
205 /** These are the actual instances, one for each of the data and conf "directories". */ 213 /** These are the actual instances, one for each of the data and conf "directories". */
206 mdeDirectory dataDir, confDir; 214 mdeDirectory dataDir, confDir;
207 char[] logDir; /// Directory for log files 215 char[] logDir; /// Directory for log files
216 FilePath[] fontPaths; /// All directories for fonts
208 217
209 //BEGIN Path resolution 218 //BEGIN Path resolution
219 /// For command line args: these paths are added if non-null, with highest priority.
220 char[] extraDataPath, extraConfPath;
221
222 /** Add an extra font directory. May be called multiple times. */
223 void addFontPath (char[] path) {
224 FilePath fp = FilePath (path);
225 if (fp.exists && fp.isFolder)
226 fontPaths ~= fp;
227 }
228
210 /** Find at least one path for each required directory. */ 229 /** Find at least one path for each required directory. */
211 debug (mdeUnitTest) { 230 debug (mdeUnitTest) {
212 /** In unittest mode, add paths unittest/data and unittest/conf before init runs. */ 231 /** In unittest mode, add paths unittest/data and unittest/conf before init runs. */
213 static this () { 232 static this () {
214 dataDir.tryPath ("unittest/data"); 233 dataDir.tryPath ("unittest/data");
216 if (!(dataDir.pathsLen && confDir.pathsLen)) 235 if (!(dataDir.pathsLen && confDir.pathsLen))
217 throw new mdeException ("Fatal: unittest/data and unittest/conf don't both exist"); 236 throw new mdeException ("Fatal: unittest/data and unittest/conf don't both exist");
218 // Don't bother with real paths or logDir or font dir(s) for unittest. 237 // Don't bother with real paths or logDir or font dir(s) for unittest.
219 } 238 }
220 } 239 }
221 version (linux) { 240 void resolvePaths (char[] base = ".") {
222 SortedMap!(char[],char[]) fontFiles; // key is file name, value is CString path 241 size_t iFP = fontPaths.length;
223 /** Get the actual path of a font file, or throw NoFileException if not found. 242 fontPaths.length = fontPaths.length + 4;
224 * 243
225 * Returns a C string (null terminated). */ 244 version (linux) {
226 char[] getFontPath (char[] file) {
227 char[] ret;
228 if (fontFiles.get (file, ret))
229 return ret;
230 throw new NoFileException ("Unable to find font file: "~file);
231 }
232
233 // base-path not used on posix
234 void resolvePaths (char[] base = "data") {
235 // Home directory: 245 // Home directory:
236 char[] HOME = Environment.get("HOME", "."); 246 char[] HOME = Environment.get("HOME", ".");
237 247
238 // Base paths: 248 // Installation base (should contain "data" and "conf"):
239 // Static data (must exist): 249 FilePath staticPath = findPath (false,
240 FilePath staticPath = 250 "/usr/share/games/mde",
241 findPath (false, "/usr/share/games/mde", "/usr/local/share/games/mde", base); 251 "/usr/local/share/games/mde",
242 // Config (can just use defaults if necessary, so long as we can save afterwards): 252 base~"/data");
253 // Path for user-adjusted files:
243 FilePath userPath = findPath (true, HOME~"/.config/mde", HOME~"/.mde"); 254 FilePath userPath = findPath (true, HOME~"/.config/mde", HOME~"/.mde");
244 255
245 // Static data paths: 256 dataDir.addPath (staticPath.toString);
246 dataDir.addPath (staticPath.toString); // we know this is valid anyway
247 dataDir.tryPath (userPath.toString ~ "/data");
248 if (extraDataPath) dataDir.tryPath (extraDataPath);
249 if (!dataDir.pathsLen) throw new mdeException ("Fatal: no data path found!");
250
251 // Configuration paths:
252 confDir.tryPath (staticPath.toString ~ "/conf"); 257 confDir.tryPath (staticPath.toString ~ "/conf");
253 confDir.tryPath ("/etc/mde"); 258 confDir.tryPath ("/etc/mde");
254 confDir.tryPath (userPath.toString ~ "/conf", true); 259
255 if (extraConfPath) confDir.tryPath (extraConfPath);
256 if (!confDir.pathsLen) throw new mdeException ("Fatal: no conf path found!");
257
258 // Logging path:
259 logDir = userPath.toString;
260
261 // Font paths: 260 // Font paths:
262 auto fs = new FileScan; 261 auto fontP1 = FilePath("/usr/share/fonts").toList;
263 // Scan for directories containing truetype and type1 fonts: 262 foreach (fp1; fontP1)
264 fs.sweep ("/usr/share/fonts", delegate bool(FilePath fp, bool isDir) 263 if (fp1.isFolder)
265 { return isDir || fp.suffix == ".ttf" || fp.suffix == ".pfb"; }, 264 foreach (fp2; fp1.toList)
266 true); 265 if (fp2.isFolder) {
267 fontFiles = new SortedMap!(char[],char[]); 266 if (iFP >= fontPaths.length)
268 foreach (fp; fs.files) 267 fontPaths.length = fontPaths.length * 2;
269 fontFiles.add (fp.file, fp.cString); // both strings should be slices of same memory 268 fontPaths[iFP++] = fp2;
270 } 269 }
271 } else version (Windows) { 270 } else version (Windows) {
272 char[] fontDir;
273 /** Get the actual path of a font file, or throw NoFileException if not found.
274 *
275 * Returns a C string (null terminated). */
276 char[] getFontPath (char[] file) {
277 FilePath path = new FilePath (fontDir~file);
278 if (path.exists && !path.isFolder)
279 return path.cString;
280 throw new NoFileException ("Unable to find font file: "~file);
281 }
282
283 void resolvePaths (char[] base = "./") {
284 //FIXME: Get base path from registry 271 //FIXME: Get base path from registry
285 272
286 // Base paths: 273 FilePath staticPath = findPath (false, base~"/data");
287 FilePath installPath = findPath (false, base);
288 FilePath staticPath = findPath (false, installPath.toString);
289 FilePath userPath = findPath (true, getSpecialPath(CSIDL_LOCAL_APPDATA) ~ "/mde"); 274 FilePath userPath = findPath (true, getSpecialPath(CSIDL_LOCAL_APPDATA) ~ "/mde");
290 275
291 // Static data paths: 276 dataDir.addPath (staticPath.toString);
292 dataDir.addPath (staticPath.toString); // we know this is valid anyway
293 dataDir.tryPath (userPath.toString ~ "/data");
294 if (extraDataPath) dataDir.tryPath (extraDataPath);
295 if (!dataDir.pathsLen) throw new mdeException ("Fatal: no data path found!");
296
297 // Configuration paths:
298 confDir.tryPath (staticPath.toString ~ "/conf"); 277 confDir.tryPath (staticPath.toString ~ "/conf");
299 confDir.tryPath (installPath.append("user").toString);
300 confDir.tryPath (userPath.toString ~ "/conf", true);
301 if (extraConfPath) confDir.tryPath (extraConfPath);
302 if (!confDir.pathsLen) throw new mdeException ("Fatal: no conf path found!");
303
304 // Logging path:
305 logDir = userPath.toString;
306 278
307 // Font path: 279 // Font path:
308 fontDir = getSpecialPath (CSIDL_FONTS) ~ "/"; // append separator 280 fontPaths ~= FilePath(getSpecialPath (CSIDL_FONTS));
309 } 281 } else {
310 } else { 282 static assert (false, "Platform is not linux or Windows: no support for paths on this platform yet!");
311 static assert (false, "Platform is not linux or Windows: no support for paths on this platform yet!"); 283 }
312 } 284
313 285 // Static data paths:
314 /// For command line args: these paths are added if non-null, with highest priority. 286 dataDir.tryPath (userPath.toString ~ "/data");
315 char[] extraDataPath, extraConfPath; 287 if (extraDataPath) dataDir.tryPath (extraDataPath);
288
289 // Configuration paths:
290 confDir.tryPath (userPath.toString ~ "/conf", true);
291 if (extraConfPath) confDir.tryPath (extraConfPath);
292
293 if (!dataDir.pathsLen) throw new mdeException ("Fatal: no data path found!");
294 if (!confDir.pathsLen) throw new mdeException ("Fatal: no conf path found!");
295
296 for (int i = dataDir.pathsLen - 1; i >= 0; --i) {
297 FilePath font = FilePath (dataDir.paths[i] ~ "fonts");
298 Cout ("considering: ")(font.toString).newline;
299 if (font.exists && font.isFolder)
300 fontPaths[iFP++] = font;
301 }
302 fontPaths.length = iFP;
303
304 // Logging path:
305 logDir = userPath.toString;
306 }
316 307
317 private { 308 private {
318 class PathException : mdeException { 309 class PathException : mdeException {
319 this(char[] msg) { 310 this(char[] msg) {
320 super (msg); 311 super (msg);