source: trunk/NewView/FileUtilsUnit.pas@ 89

Last change on this file since 89 was 89, checked in by RBRi, 18 years ago

small fixes

  • Property svn:eol-style set to native
File size: 13.8 KB
Line 
1Unit FileUtilsUnit;
2
3// NewView - a new OS/2 Help Viewer
4// Copyright 2006/2007 Ronald Brill (rbri at rbri dot de)
5// This software is released under the GNU Public License - see readme.txt
6
7// Helper functions for file handling
8
9Interface
10
11uses
12 Classes,
13 ACLUtility;
14
15
16const
17 DirectorySeparator = '\';
18 PATH_SEPARATOR = ';';
19
20 // TODO
21 HelpPathEnvironmentVar = 'HELP';
22 BookshelfEnvironmentVar = 'BOOKSHELF';
23 LanguageEnvironmentVar = 'LANG';
24 DEFAULT_LANGUAGE = 'EN_US';
25 HELP_FILE_EXTENSION = '.hlp';
26
27
28 // Adds a slash to the end of dir if not present
29 // if aDir is empty this returns '\'
30 Function AddDirectorySeparator(aDirectory : String) : String;
31
32 // Adds a slash to the end of dir if not present
33 // if aDir is empty this returns ''
34 Function AddDirectorySeparatorIfNotEmpty(aDirectory: String) : String;
35
36 // Removes a directory seperator from the end of aDirectory
37 // (if present)
38 Function RemoveRightDirectorySeparator(aDirectory : String) : String;
39
40 // Expands the path given, relative to aBaseDirectory
41 // Handles leading \ for root dir,
42 // .. for parent, . (ignored),
43 // drive spec at start,
44 // ignores repeated \ e.g. \\
45 Function ExpandPath(aBaseDirectory : String; aPath : String): String;
46
47 Function GetLogFilesDir: String;
48
49 Function SearchPath(const aPathEnvVar: String; const aFilename: String; var aResultFilename: String) : boolean;
50
51 Function SearchHelpPaths(const aFilename: String; var aResultFilename: String; const anIncludeAppDir: boolean) : boolean;
52
53 // Find the help file for the current app based on LANG
54 Function FindDefaultLanguageHelpFile(const anApplicationName: String; const aLanguage : String) : String;
55
56 // Breaks up specified Env var path
57 Procedure GetDirsInPath(const aPathEnvVar: String; var aList: TStrings);
58
59 // searches for all files in aDirectory matching aFilter and add
60 // them to aList
61 // it is possible to define different filter if you separate them by semicolon
62 Procedure ListFilesInDirectory(const aDirectory: String; const aFilter: String; var aList: TStrings);
63
64 // searches for all directories in aDirectory and add them to aList
65 Procedure ListSubDirectories(const aDirectory: String; var aList: TStrings);
66
67 Procedure ListFilesInDirectoryRecursiveWithTermination(const aDirectory : String;
68 const aFilter : String;
69 var aList : TStrings;
70 const aTerminateCheck : TTerminateCheck;
71 const aUseTerminateCheck : boolean);
72
73 Function ParentDir(const aDirectory : String) : String;
74
75 Function DirectoryExists(const aDirectory : String) : boolean;
76
77Implementation
78
79uses
80 Dos,
81 BseDos,
82 Os2Def,
83 SysUtils,
84 StringUtilsUnit;
85
86 Function AddDirectorySeparator(aDirectory : String) : String;
87 begin
88 if aDirectory = '' then
89 begin
90 Result:= DirectorySeparator;
91 exit;
92 end;
93
94 if aDirectory[length(aDirectory)] <> DirectorySeparator then
95 begin
96 Result := aDirectory + DirectorySeparator;
97 exit;
98 end;
99
100 Result := aDirectory;
101 end;
102
103
104 Function AddDirectorySeparatorIfNotEmpty(aDirectory: String): String;
105 begin
106 if aDirectory = '' then
107 begin
108 Result := '';
109 exit;
110 end;
111 Result := AddDirectorySeparator(aDirectory);
112 end;
113
114
115 Function RemoveRightDirectorySeparator(aDirectory : String) : String;
116 begin
117 Result := StrTrimRightChars(aDirectory, [DirectorySeparator]);
118 end;
119
120
121 Function ExpandPath(aBaseDirectory : String; aPath : String): String;
122 var
123 tmpDirectory: String;
124 tmpDirectories : TStringList;
125 i : integer;
126 begin
127 Result:= aBaseDirectory;
128
129 if aPath = '' then
130 begin
131 Result := StrTrimRightChars(Result, [DirectorySeparator]);
132 exit;
133 end;
134
135 aPath := trim(aPath);
136 if Length(aPath) > 1 then
137 begin
138 // check for drive spec
139 if aPath[2] = ':' then
140 begin
141 Result := AddDirectorySeparator(aPath);
142 if Length(aPath) > 3 then
143 begin
144 Result := StrTrimRightChars(Result, [DirectorySeparator]);
145 end;
146 exit;
147 end
148 end;
149
150 if Length(aPath) > 0 then
151 begin
152 // check for root dir spec
153 if aPath[1] = DirectorySeparator then
154 begin
155 // take just the drive from the basedir
156 if aBaseDirectory[2] = ':' then
157 begin
158 Result := StrLeft(aBaseDirectory, 2);
159 end
160 else
161 begin
162 Result := DirectorySeparator;
163 end;
164 aPath := StrTrimLeftChars(aPath, [DirectorySeparator]);
165 end;
166 end;
167
168 tmpDirectories := TStringList.Create;
169 StrExtractStringsIgnoreEmpty(tmpDirectories, aPath, [DirectorySeparator], #0);
170 for i := 0 to tmpDirectories.count-1 do
171 begin
172 tmpDirectory := tmpDirectories[i];
173 if tmpDirectory = '..' then
174 begin
175 if NOT ((Length(Result) = 2) AND (Result[2] = ':')) then
176 begin
177 Result := ParentDir(Result);
178 end;
179 end
180 else if tmpDirectory = '.' then
181 begin
182 ; // nothing to do
183 end
184 else
185 begin
186 Result := AddDirectorySeparator(Result) + tmpDirectory;
187 end;
188
189 // strip any extra leading slashes
190 aPath := StrTrimLeftChars(aPath, [DirectorySeparator]);
191 end;
192 tmpDirectories.Destroy;
193
194 if Length(Result) = 2 then
195 begin
196 if Result[2] = ':' then
197 begin
198 // just a drive spec X:, so add a slash
199 Result := Result + DirectorySeparator;
200 end;
201 end;
202 end;
203
204 Function GetLogFilesDir: String;
205 begin
206 // ecomstation 1.1 compat
207 Result := GetEnv('LOGFILES');
208 if Result <> '' then
209 begin
210 Result := AddDirectorySeparator(Result);
211 exit;
212 end;
213 // TODO
214 Result := AddDirectorySeparator(GetApplicationDir);
215 end;
216
217
218 Function SearchPath(const aPathEnvVar: String;
219 const aFilename: String;
220 var aResultFilename: String) : boolean;
221 var
222 tmpSzEnvVar : CString;
223 tmpSzFilename : CString;
224 tmpSzFilenameFound : CString;
225 tmpRC: APIRET;
226 begin
227 Result := false;
228 aResultFilename := '';
229
230 tmpSzEnvVar := aPathEnvVar;
231 tmpSzFilename := aFilename;
232 tmpRC := DosSearchPath( SEARCH_IGNORENETERRS
233 + SEARCH_ENVIRONMENT
234 + SEARCH_CUR_DIRECTORY,
235 tmpSzEnvVar,
236 tmpSzFilename,
237 tmpSzFilenameFound,
238 sizeof(tmpSzFilenameFound));
239 if tmpRC = 0 then
240 begin
241 Result := true;
242 aResultFilename := tmpSzFilenameFound;
243 end;
244 end;
245
246
247 Function SearchHelpPaths(const aFilename: String;
248 var aResultFilename: String;
249 const anIncludeAppDir: boolean) : boolean;
250 begin
251 Result := SearchPath(HelpPathEnvironmentVar, aFileName, aResultFilename);
252 if not Result then
253 begin
254 Result := SearchPath(BookshelfEnvironmentVar, aFileName, aResultFilename);
255 end;
256
257 if (not Result) and anIncludeAppDir then
258 begin
259 aResultFilename := AddDirectorySeparator(GetApplicationDir) + aFilename;
260 Result := FileExists(aResultFilename);
261 if not Result then
262 begin
263 aResultFilename := '';
264 end;
265 end;
266 end;
267
268
269 Function FindDefaultLanguageHelpFile(const anApplicationName: String; const aLanguage : String) : String;
270 var
271 tmpLanguage : String;
272 tmpLanguageParts : TStringList;
273 tmpMajorLanguage : String;
274 tmpMinorLanguage : String;
275 begin
276 Result := '';
277
278 tmpLanguage := aLanguage;
279 if aLanguage = '' then
280 begin
281 tmpLanguage := DEFAULT_LANGUAGE;
282 end;
283
284 tmpLanguageParts := TStringList.Create;
285 StrExtractStrings(tmpLanguageParts, tmpLanguage, ['_'], #0);
286
287 tmpMajorLanguage := '';
288 if tmpLanguageParts.count > 0 then
289 begin
290 tmpMajorLanguage := tmpLanguageParts[0];
291 end;
292
293 tmpMinorLanguage := '';
294 if tmpLanguageParts.count > 1 then
295 begin
296 tmpMinorLanguage := tmpMinorLanguage[1];
297 end;
298
299 tmpLanguageParts.Destroy;
300
301 // note there might be some other stuff on the end of LANG
302 // such as ES_ES_EURO...
303 if tmpMinorLanguage <> '' then
304 begin
305 if SearchHelpPaths( anApplicationName
306 + '_' + tmpMajorLanguage
307 + '_' + tmpMinorLanguage
308 + HELP_FILE_EXTENSION,
309 Result,
310 true ) then
311 begin
312 // found a specifc language
313 exit;
314 end;
315 end;
316
317 // try generic language?
318 if SearchHelpPaths( anApplicationName
319 + '_' + tmpMajorLanguage
320 + HELP_FILE_EXTENSION,
321 Result,
322 true ) then
323 begin
324 exit;
325 end;
326
327 // nothing specific, search for default
328 SearchHelpPaths(anApplicationName + HELP_FILE_EXTENSION, Result, true);
329 end;
330
331
332 Procedure GetDirsInPath(const aPathEnvVar: String; var aList: TStrings);
333 var
334 tmpRC : APIRET;
335 tmpPszPathEnvVar : PChar;
336 tmpSzEnvVar : CString;
337 begin
338 // do this in any case also if there is an error
339 // to garantie a defined behavior
340 aList.Clear;
341
342 tmpSzEnvVar := aPathEnvVar;
343 tmpRC := DosScanEnv(tmpSzEnvVar, tmpPszPathEnvVar);
344
345 if tmpRC <> 0 then
346 begin
347 exit;
348 end;
349
350 StrExtractStringsIgnoreEmpty(aList, StrPas(tmpPszPathEnvVar), [PATH_SEPARATOR], #0);
351 end;
352
353
354 Procedure ListFilesInDirectory(const aDirectory: String; const aFilter: String; var aList: TStrings);
355 var
356 tmpRC : APIRET;
357 tmpSearchResults: TSearchRec;
358 tmpMask: String;
359 tmpFilterParts : TStringList;
360 i : integer;
361 begin
362 tmpFilterParts := TStringList.Create;
363 StrExtractStrings(tmpFilterParts, aFilter, [PATH_SEPARATOR], #0);
364
365 for i:=0 to tmpFilterParts.count-1 do
366 begin
367 tmpMask := tmpFilterParts[i];
368 tmpRC := FindFirst(AddDirectorySeparator(aDirectory) + tmpMask, faAnyFile, tmpSearchResults);
369
370 while tmpRC = 0 do
371 begin
372 if tmpSearchResults.Attr And faDirectory = 0 then
373 begin
374 aList.Add(tmpSearchResults.Name);
375 end;
376
377 tmpRC := FindNext(tmpSearchResults);
378 end;
379
380 FindClose(tmpSearchResults);
381 end;
382 tmpFilterParts.Destroy;
383 end;
384
385
386 Procedure ListSubDirectories(const aDirectory: String; var aList: TStrings);
387 var
388 tmpRC : APIRET;
389 tmpSearchResults: TSearchRec;
390 tmpName : String;
391 begin
392
393 tmpRC := FindFirst(AddDirectorySeparator(aDirectory) + '*', faDirectory or faMustDirectory, tmpSearchResults);
394 if (tmpRC <> 0) then
395 begin
396 exit;
397 end;
398
399 while tmpRC = 0 do
400 begin
401 tmpName := tmpSearchResults.Name;
402 if (tmpName <> '.') AND (tmpName <> '..') then
403 begin
404 aList.Add(AddDirectorySeparatorIfNotEmpty(aDirectory) + tmpSearchResults.Name );
405 end;
406 tmpRC := FindNext(tmpSearchResults);
407 end;
408 FindClose(tmpSearchResults);
409 end;
410
411
412 Procedure ListFilesInDirectoryRecursiveWithTermination(const aDirectory : String;
413 const aFilter : String;
414 var aList : TStrings;
415 const aTerminateCheck : TTerminateCheck;
416 const aUseTerminateCheck : boolean);
417 var
418 i : integer;
419 tmpSubDirectories : TStringList;
420 tmpSubDirectory : String;
421 begin
422 // at first add all files from the directory itself
423 ListFilesInDirectory(aDirectory, aFilter, aList);
424
425 // now determine all subdirectories
426 tmpSubDirectories := TStringList.Create;
427 ListSubDirectories(aDirectory, tmpSubDirectories);
428
429 for i := 0 to tmpSubDirectories.Count - 1 do
430 begin
431 // if Assigned( TerminateCheck ) then - doesn't work in sibyl
432 if aUseTerminateCheck then
433 if aTerminateCheck then
434 break;
435
436 tmpSubDirectory := tmpSubDirectories[i];
437
438 ListFilesInDirectoryRecursiveWithTermination(tmpSubDirectory, aFilter, aList, aTerminateCheck, aUseTerminateCheck);
439 end;
440 tmpSubDirectories.Destroy;
441 end;
442
443
444 Function ParentDir(const aDirectory : String) : String;
445 var
446 tmpPos: integer;
447 begin
448 tmpPos := Length(aDirectory);
449
450 // ends with slash
451 while (aDirectory[tmpPos] = DirectorySeparator) AND (tmpPos > 0) do
452 begin
453 dec(tmpPos);
454 end;
455
456 // find slash
457 while (aDirectory[tmpPos] <> DirectorySeparator) AND (tmpPos > 0) do
458 begin
459 dec(tmpPos);
460 end;
461
462 result:= StrLeft(aDirectory, tmpPos-1);
463 end;
464
465
466 Function DirectoryExists(const aDirectory : String) : boolean;
467 Var
468 tmpRC : APIRET;
469 tmpSearchResults : TSearchRec;
470 tmpDriveMap : ULONG;
471 tmpActualDrive : ULONG;
472 tmpDrive : Char;
473 tmpDriveNum : integer;
474 tmpDriveBit : longword;
475 tmpDirectory : String;
476 Begin
477 Result := false;
478 tmpDirectory := RemoveRightDirectorySeparator(aDirectory);
479 if tmpDirectory = '' then
480 begin
481 Result:= true;
482 exit;
483 end;
484
485 if Length(tmpDirectory) = 2 then
486 begin
487 if tmpDirectory[2] = ':' then
488 begin
489 // a drive only has been specified
490 tmpDrive:= UpCase(tmpDirectory[1] );
491 if (tmpDrive < 'A') or (tmpDrive > 'Z') then
492 begin
493 // invalid drive; return false;
494 exit;
495 end;
496
497 DosQueryCurrentDisk(tmpActualDrive, tmpDriveMap);
498 tmpDriveNum := Ord(tmpDrive) - Ord('A') + 1; // A -> 1, B -> 2...
499 tmpDriveBit := 1 shl (tmpDriveNum-1); // 2^DriveNum
500
501 Result := tmpDriveMap and (tmpDriveBit) > 0;
502 exit;
503 end;
504 end;
505
506 tmpRC := FindFirst(tmpDirectory, faDirectory or faMustDirectory, tmpSearchResults);
507 if tmpRC = 0 then
508 begin
509 Result:= true;
510 FindClose(tmpSearchResults);
511 end;
512 end;
513
514
515Initialization
516End.
Note: See TracBrowser for help on using the repository browser.