fina.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. {
  2. *********************************************************************
  3. Copyright (C) 1997, 1998 Gertjan Schouten
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************
  10. System Utilities For Free Pascal
  11. }
  12. function ChangeFileExt(const FileName, Extension: PathStr): PathStr;
  13. var
  14. i : longint;
  15. EndSep : Set of Char;
  16. begin
  17. i := Length(FileName);
  18. EndSep:=AllowDirectorySeparators+AllowDriveSeparators+[ExtensionSeparator];
  19. while (I > 0) and not(FileName[I] in EndSep) do
  20. Dec(I);
  21. if (I = 0) or (FileName[I] <> ExtensionSeparator) then
  22. I := Length(FileName)+1;
  23. Result := Copy(FileName, 1, I - 1) + Extension;
  24. end;
  25. function ExtractFilePath(const FileName: PathStr): PathStr;
  26. var
  27. i : longint;
  28. EndSep : Set of Char;
  29. begin
  30. i := Length(FileName);
  31. EndSep:=AllowDirectorySeparators+AllowDriveSeparators;
  32. while (i > 0) and not CharInSet(FileName[i],EndSep) do
  33. Dec(i);
  34. If I>0 then
  35. Result := Copy(FileName, 1, i)
  36. else
  37. Result:='';
  38. end;
  39. function ExtractFileDir(const FileName: PathStr): PathStr;
  40. var
  41. i : longint;
  42. EndSep : Set of Char;
  43. begin
  44. I := Length(FileName);
  45. EndSep:=AllowDirectorySeparators+AllowDriveSeparators;
  46. while (I > 0) and not CharInSet(FileName[I],EndSep) do
  47. Dec(I);
  48. if (I > 1) and CharInSet(FileName[I],AllowDirectorySeparators) and
  49. not CharInSet(FileName[I - 1],EndSep) then
  50. Dec(I);
  51. Result := Copy(FileName, 1, I);
  52. end;
  53. function ExtractFileDrive(const FileName: PathStr): PathStr;
  54. var
  55. i,l: longint;
  56. begin
  57. Result := '';
  58. l:=Length(FileName);
  59. if (l<2) then
  60. exit;
  61. {$IF DEFINED(AMIGA) OR DEFINED(MORPHOS)}
  62. i:=Pos(DriveSeparator,FileName);
  63. if (i > 0) then Result:=Copy(FileName,1,i);
  64. {$ELSE}
  65. If CharInSet(FileName[2],AllowDriveSeparators) then
  66. result:=Copy(FileName,1,2)
  67. else if CharInSet(FileName[1],AllowDirectorySeparators) and
  68. CharInSet(FileName[2],AllowDirectorySeparators) then
  69. begin
  70. i := 2;
  71. { skip share }
  72. While (i<l) and Not CharInSet(Filename[i+1],AllowDirectorySeparators) do
  73. inc(i);
  74. inc(i);
  75. While (i<l) and Not CharInSet(Filename[i+1],AllowDirectorySeparators) do
  76. inc(i);
  77. Result:=Copy(FileName,1,i);
  78. end;
  79. {$ENDIF}
  80. end;
  81. function ExtractFileName(const FileName: PathStr): PathStr;
  82. var
  83. i : longint;
  84. EndSep : Set of Char;
  85. begin
  86. I := Length(FileName);
  87. EndSep:=AllowDirectorySeparators+AllowDriveSeparators;
  88. while (I > 0) and not CharInSet(FileName[I],EndSep) do
  89. Dec(I);
  90. Result := Copy(FileName, I + 1, MaxInt);
  91. end;
  92. function ExtractFileExt(const FileName: PathStr): PathStr;
  93. var
  94. i : longint;
  95. EndSep : Set of Char;
  96. begin
  97. I := Length(FileName);
  98. EndSep:=AllowDirectorySeparators+AllowDriveSeparators+[ExtensionSeparator];
  99. while (I > 0) and not CharInSet(FileName[I],EndSep) do
  100. Dec(I);
  101. if (I > 0) and (FileName[I] = ExtensionSeparator) then
  102. Result := Copy(FileName, I, MaxInt)
  103. else
  104. Result := '';
  105. end;
  106. function ExtractShortPathName(Const FileName : PathStr) : PathStr;
  107. begin
  108. {$ifdef MSWINDOWS}
  109. SetLength(Result,Max_Path);
  110. if sizeof(FileName[1])=1 then
  111. SetLength(Result,GetShortPathNameA(PChar(FileName), PChar(Result),Length(Result)))
  112. else
  113. SetLength(Result,GetShortPathNameW(PWideChar(FileName), PWideChar(Result),Length(Result)));
  114. {$else}
  115. Result:=FileName;
  116. {$endif}
  117. end;
  118. {$DEFINE FPC_FEXPAND_SYSUTILS}
  119. {$I fexpand.inc}
  120. function ExpandFileName (Const FileName : PathStr): PathStr;
  121. Var S : PathStr;
  122. Begin
  123. S:=FileName;
  124. DoDirSeparators(S);
  125. Result:=Fexpand(S);
  126. end;
  127. {$ifndef HASEXPANDUNCFILENAME}
  128. function ExpandUNCFileName (Const FileName : PathStr): PathStr;
  129. begin
  130. Result:=ExpandFileName (FileName);
  131. //!! Here should follow code to replace the drive: part with UNC...
  132. end;
  133. {$endif HASEXPANDUNCFILENAME}
  134. function ExpandFileNameCase (const FileName: PathStr; out MatchFound: TFilenameCaseMatch): PathStr;
  135. var
  136. SR: TSearchRec;
  137. ItemsFound: byte;
  138. FoundPath: PathStr;
  139. RestPos: SizeUInt;
  140. Root: PathStr;
  141. procedure TryCase (const Base, Rest: PathStr);
  142. var
  143. SR: TSearchRec;
  144. RC: longint;
  145. NextDirPos: SizeUInt;
  146. NextPart: PathStr;
  147. NextRest: PathStr;
  148. SearchBase: PathStr;
  149. begin
  150. NextDirPos := 1;
  151. while (NextDirPos <= Length (Rest)) and
  152. not CharInSet(Rest[NextDirPos],(AllowDirectorySeparators)) do
  153. Inc (NextDirPos);
  154. NextPart := Copy (Rest, 1, Pred (NextDirPos));
  155. {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
  156. if (Length (Rest) >= NextDirPos) and
  157. CharInSet(Rest[NextDirPos],AllowDirectorySeparators) then
  158. {$ELSE FPC_FEXPAND_DIRSEP_IS_UPDIR}
  159. while (Length (Rest) >= NextDirPos) and
  160. CharInSet(Rest[NextDirPos],AllowDirectorySeparators) do
  161. {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
  162. Inc (NextDirPos);
  163. NextRest := Copy (Rest, NextDirPos, Length (Rest) - Pred (NextDirPos));
  164. if (Base = '') or CharInSet(Base[Length (Base)],AllowDirectorySeparators) then
  165. SearchBase := Base
  166. else
  167. SearchBase := Base + DirectorySeparator;
  168. RC := FindFirst (SearchBase + AllFilesMask, faAnyFile, SR);
  169. while (RC = 0) and (ItemsFound < 2) do
  170. begin
  171. if UpCase (NextPart) = UpCase (SR.Name) then
  172. begin
  173. if Length (NextPart) = Length (Rest) then
  174. begin
  175. Inc (ItemsFound);
  176. if ItemsFound = 1 then
  177. FoundPath := SearchBase + SR.Name;
  178. end
  179. else if SR.Attr and faDirectory = faDirectory then
  180. TryCase (SearchBase + SR.Name + DirectorySeparator, NextRest);
  181. end;
  182. if ItemsFound < 2 then
  183. RC := FindNext (SR);
  184. end;
  185. FindClose (SR);
  186. end;
  187. begin
  188. Result := ExpandFileName (FileName);
  189. if FileName = '' then
  190. MatchFound := mkExactMatch
  191. else
  192. if (FindFirst (FileName, faAnyFile, SR) = 0) or
  193. (* Special check for a root directory or a directory with a trailing slash *)
  194. (* which are not found using FindFirst. *)
  195. DirectoryExists (FileName) then
  196. begin
  197. MatchFound := mkExactMatch;
  198. Result := ExtractFilePath (Result) + SR.Name;
  199. FindClose (SR);
  200. end
  201. else
  202. begin
  203. (* Better close the search handle here before starting the recursive search *)
  204. FindClose (SR);
  205. MatchFound := mkNone;
  206. if FileNameCaseSensitive then
  207. begin
  208. ItemsFound := 0;
  209. FoundPath := '';
  210. RestPos := Length (ExtractFileDrive (FileName)) + 1;
  211. if (Length (FileName) > RestPos) then
  212. begin
  213. {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
  214. if (Length (FileName) >= RestPos) and
  215. CharInSet(FileName[RestPos],AllowDirectorySeparators) then
  216. {$ELSE FPC_FEXPAND_DIRSEP_IS_UPDIR}
  217. while (Length (FileName) >= RestPos) and
  218. CharInSet(FileName[RestPos],AllowDirectorySeparators) do
  219. {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
  220. Inc (RestPos);
  221. Root := Copy (FileName, 1, Pred (RestPos));
  222. TryCase (Root, Copy (FileName, RestPos, Length (FileName) - Length (Root)));
  223. if ItemsFound > 0 then
  224. begin
  225. Result := ExpandFileName (FoundPath);
  226. if ItemsFound = 1 then
  227. MatchFound := mkSingleMatch
  228. else
  229. MatchFound := mkAmbiguous;
  230. end;
  231. end;
  232. end;
  233. end;
  234. end;
  235. {$if not declared(MaxDirs)}
  236. Const
  237. MaxDirs = 129;
  238. {$endif}
  239. function ExtractRelativepath (Const BaseName,DestName : PathStr): PathStr;
  240. Var Source, Dest : PathStr;
  241. Sc,Dc,I,J : Longint;
  242. SD,DD : Array[1..MaxDirs] of PathPChar;
  243. Const OneLevelBack = '..'+DirectorySeparator;
  244. begin
  245. If Uppercase(ExtractFileDrive(BaseName))<>Uppercase(ExtractFileDrive(DestName)) Then
  246. begin
  247. Result:=DestName;
  248. exit;
  249. end;
  250. Source:=ExcludeTrailingPathDelimiter(ExtractFilePath(BaseName));
  251. Dest:=ExcludeTrailingPathDelimiter(ExtractFilePath(DestName));
  252. SC:=GetDirs (Source,SD);
  253. DC:=GetDirs (Dest,DD);
  254. I:=1;
  255. While (I<=DC) and (I<=SC) do
  256. begin
  257. If StrIcomp(DD[i],SD[i])=0 then
  258. Inc(i)
  259. else
  260. Break;
  261. end;
  262. Result:='';
  263. For J:=I to SC do Result:=Result+OneLevelBack;
  264. For J:=I to DC do Result:=Result+DD[J]+DirectorySeparator;
  265. Result:=Result+ExtractFileName(DestNAme);
  266. end;
  267. Procedure DoDirSeparators (Var FileName : PathStr);
  268. VAr I : longint;
  269. begin
  270. For I:=1 to Length(FileName) do
  271. If CharInSet(FileName[I],AllowDirectorySeparators) then
  272. FileName[i]:=DirectorySeparator;
  273. end;
  274. Function SetDirSeparators (Const FileName : PathStr) : PathStr;
  275. begin
  276. Result:=FileName;
  277. DoDirSeparators (Result);
  278. end;
  279. {
  280. DirName is split in a #0 separated list of directory names,
  281. Dirs is an array of pchars, pointing to these directory names.
  282. The function returns the number of directories found, or -1
  283. if none were found.
  284. }
  285. Function GetDirs (Var DirName : PathStr; Var Dirs : Array of PathPChar) : Longint;
  286. Var I : Longint;
  287. begin
  288. I:=1;
  289. Result:=-1;
  290. While I<=Length(DirName) do
  291. begin
  292. If CharInSet(DirName[i],AllowDirectorySeparators) and
  293. { avoid error in case last char=pathdelim }
  294. (length(dirname)>i) then
  295. begin
  296. DirName[i]:=#0;
  297. Inc(Result);
  298. Dirs[Result]:=@DirName[I+1];
  299. end;
  300. Inc(I);
  301. end;
  302. If Result>-1 then inc(Result);
  303. end;
  304. function IncludeTrailingPathDelimiter(Const Path : PathStr) : PathStr;
  305. Var
  306. l : Integer;
  307. begin
  308. Result:=Path;
  309. l:=Length(Result);
  310. If (L=0) or not CharInSet(Result[l],AllowDirectorySeparators) then
  311. Result:=Result+DirectorySeparator;
  312. end;
  313. function IncludeTrailingBackslash(Const Path : PathStr) : PathStr;
  314. begin
  315. Result:=IncludeTrailingPathDelimiter(Path);
  316. end;
  317. function ExcludeTrailingBackslash(Const Path: PathStr): PathStr;
  318. begin
  319. Result:=ExcludeTrailingPathDelimiter(Path);
  320. end;
  321. function ExcludeTrailingPathDelimiter(Const Path: PathStr): PathStr;
  322. Var
  323. L : Integer;
  324. begin
  325. L:=Length(Path);
  326. If (L>0) and CharInSet(Path[L],AllowDirectorySeparators) then
  327. Dec(L);
  328. Result:=Copy(Path,1,L);
  329. end;
  330. function IncludeLeadingPathDelimiter(Const Path : PathStr) : PathStr;
  331. Var
  332. l : Integer;
  333. begin
  334. Result:=Path;
  335. l:=Length(Result);
  336. If (L=0) or not CharInSet(Result[1],AllowDirectorySeparators) then
  337. Result:=DirectorySeparator+Result;
  338. end;
  339. function ExcludeLeadingPathDelimiter(Const Path: PathStr): PathStr;
  340. Var
  341. L : Integer;
  342. begin
  343. Result:=Path;
  344. L:=Length(Result);
  345. If (L>0) and CharInSet(Result[1],AllowDirectorySeparators) then
  346. Delete(Result,1,1);
  347. end;
  348. function IsPathDelimiter(Const Path: PathStr; Index: Integer): Boolean;
  349. begin
  350. Result:=(Index>0) and (Index<=Length(Path)) and CharInSet(Path[Index],AllowDirectorySeparators);
  351. end;
  352. function ConcatPaths(const Paths: array of PathStr): PathStr;
  353. var
  354. I: Integer;
  355. begin
  356. if Length(Paths) > 0 then
  357. begin
  358. Result := Paths[0];
  359. for I := 1 to Length(Paths) - 1 do
  360. Result := IncludeTrailingPathDelimiter(Result) + ExcludeLeadingPathDelimiter(Paths[I]);
  361. end else
  362. Result := '';
  363. end;