fina.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  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: string): string;
  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: string): string;
  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 (FileName[i] in 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: string): string;
  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 (FileName[I] in EndSep) do
  47. Dec(I);
  48. if (I > 1) and (FileName[I] in AllowDirectorySeparators) and
  49. not (FileName[I - 1] in EndSep) then
  50. Dec(I);
  51. Result := Copy(FileName, 1, I);
  52. end;
  53. function ExtractFileDrive(const FileName: string): string;
  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 (FileName[2] in AllowDriveSeparators) then
  66. result:=Copy(FileName,1,2)
  67. else if (FileName[1] in AllowDirectorySeparators) and
  68. (FileName[2] in AllowDirectorySeparators) then
  69. begin
  70. i := 2;
  71. { skip share }
  72. While (i<l) and Not (Filename[i+1] in AllowDirectorySeparators) do
  73. inc(i);
  74. inc(i);
  75. While (i<l) and Not (Filename[i+1] in AllowDirectorySeparators) do
  76. inc(i);
  77. Result:=Copy(FileName,1,i);
  78. end;
  79. {$ENDIF}
  80. end;
  81. function ExtractFileName(const FileName: string): string;
  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 (FileName[I] in EndSep) do
  89. Dec(I);
  90. Result := Copy(FileName, I + 1, MaxInt);
  91. end;
  92. function ExtractFileExt(const FileName: string): string;
  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 (FileName[I] in 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 : String) : String;
  107. begin
  108. {$ifdef MSWINDOWS}
  109. SetLength(Result,Max_Path);
  110. SetLength(Result,GetShortPathName(PChar(FileName), Pchar(Result),Length(Result)));
  111. {$else}
  112. Result:=FileName;
  113. {$endif}
  114. end;
  115. type
  116. PathStr=string;
  117. {$DEFINE FPC_FEXPAND_SYSUTILS}
  118. {$I fexpand.inc}
  119. function ExpandFileName (Const FileName : string): String;
  120. Var S : String;
  121. Begin
  122. S:=FileName;
  123. DoDirSeparators(S);
  124. Result:=Fexpand(S);
  125. end;
  126. {$ifndef HASEXPANDUNCFILENAME}
  127. function ExpandUNCFileName (Const FileName : string): String;
  128. begin
  129. Result:=ExpandFileName (FileName);
  130. //!! Here should follow code to replace the drive: part with UNC...
  131. end;
  132. {$endif HASEXPANDUNCFILENAME}
  133. function ExpandFileNameCase (const FileName: string; out MatchFound: TFilenameCaseMatch): string;
  134. var
  135. SR: TSearchRec;
  136. ItemsFound: byte;
  137. FoundPath: string;
  138. RestPos: SizeUInt;
  139. Root: string;
  140. procedure TryCase (const Base, Rest: string);
  141. var
  142. SR: TSearchRec;
  143. RC: longint;
  144. NextDirPos: SizeUInt;
  145. NextPart: string;
  146. NextRest: string;
  147. SearchBase: string;
  148. begin
  149. NextDirPos := 1;
  150. while (NextDirPos <= Length (Rest)) and
  151. not (Rest [NextDirPos] in (AllowDirectorySeparators)) do
  152. Inc (NextDirPos);
  153. NextPart := Copy (Rest, 1, Pred (NextDirPos));
  154. {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
  155. if (Length (Rest) >= NextDirPos) and
  156. (Rest [NextDirPos] in AllowDirectorySeparators) then
  157. {$ELSE FPC_FEXPAND_DIRSEP_IS_UPDIR}
  158. while (Length (Rest) >= NextDirPos) and
  159. (Rest [NextDirPos] in AllowDirectorySeparators) do
  160. {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
  161. Inc (NextDirPos);
  162. NextRest := Copy (Rest, NextDirPos, Length (Rest) - Pred (NextDirPos));
  163. if (Base = '') or (Base [Length (Base)] in AllowDirectorySeparators) then
  164. SearchBase := Base
  165. else
  166. SearchBase := Base + DirectorySeparator;
  167. RC := FindFirst (SearchBase + AllFilesMask, faAnyFile, SR);
  168. while (RC = 0) and (ItemsFound < 2) do
  169. begin
  170. if UpCase (NextPart) = UpCase (SR.Name) then
  171. begin
  172. if Length (NextPart) = Length (Rest) then
  173. begin
  174. Inc (ItemsFound);
  175. if ItemsFound = 1 then
  176. FoundPath := SearchBase + SR.Name;
  177. end
  178. else if SR.Attr and faDirectory = faDirectory then
  179. TryCase (SearchBase + SR.Name + DirectorySeparator, NextRest);
  180. end;
  181. if ItemsFound < 2 then
  182. RC := FindNext (SR);
  183. end;
  184. FindClose (SR);
  185. end;
  186. begin
  187. Result := ExpandFileName (FileName);
  188. if FileName = '' then
  189. MatchFound := mkExactMatch
  190. else
  191. if (FindFirst (FileName, faAnyFile, SR) = 0) or
  192. (* Special check for a root directory or a directory with a trailing slash *)
  193. (* which are not found using FindFirst. *)
  194. DirectoryExists (FileName) then
  195. begin
  196. MatchFound := mkExactMatch;
  197. Result := ExtractFilePath (Result) + SR.Name;
  198. FindClose (SR);
  199. end
  200. else
  201. begin
  202. (* Better close the search handle here before starting the recursive search *)
  203. FindClose (SR);
  204. MatchFound := mkNone;
  205. if FileNameCaseSensitive then
  206. begin
  207. ItemsFound := 0;
  208. FoundPath := '';
  209. RestPos := Length (ExtractFileDrive (FileName)) + 1;
  210. if (Length (FileName) > RestPos) then
  211. begin
  212. {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
  213. if (Length (FileName) >= RestPos) and
  214. (FileName [RestPos] in AllowDirectorySeparators) then
  215. {$ELSE FPC_FEXPAND_DIRSEP_IS_UPDIR}
  216. while (Length (FileName) >= RestPos) and
  217. (FileName [RestPos] in AllowDirectorySeparators) do
  218. {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
  219. Inc (RestPos);
  220. Root := Copy (FileName, 1, Pred (RestPos));
  221. TryCase (Root, Copy (FileName, RestPos, Length (FileName) - Length (Root)));
  222. if ItemsFound > 0 then
  223. begin
  224. Result := ExpandFileName (FoundPath);
  225. if ItemsFound = 1 then
  226. MatchFound := mkSingleMatch
  227. else
  228. MatchFound := mkAmbiguous;
  229. end;
  230. end;
  231. end;
  232. end;
  233. end;
  234. Const
  235. MaxDirs = 129;
  236. function ExtractRelativepath (Const BaseName,DestName : String): String;
  237. Var Source, Dest : String;
  238. Sc,Dc,I,J : Longint;
  239. SD,DD : Array[1..MaxDirs] of PChar;
  240. Const OneLevelBack = '..'+DirectorySeparator;
  241. begin
  242. If Uppercase(ExtractFileDrive(BaseName))<>Uppercase(ExtractFileDrive(DestName)) Then
  243. begin
  244. Result:=DestName;
  245. exit;
  246. end;
  247. Source:=ExcludeTrailingPathDelimiter(ExtractFilePath(BaseName));
  248. Dest:=ExcludeTrailingPathDelimiter(ExtractFilePath(DestName));
  249. SC:=GetDirs (Source,SD);
  250. DC:=GetDirs (Dest,DD);
  251. I:=1;
  252. While (I<=DC) and (I<=SC) do
  253. begin
  254. If StrIcomp(DD[i],SD[i])=0 then
  255. Inc(i)
  256. else
  257. Break;
  258. end;
  259. Result:='';
  260. For J:=I to SC do Result:=Result+OneLevelBack;
  261. For J:=I to DC do Result:=Result+DD[J]+DirectorySeparator;
  262. Result:=Result+ExtractFileName(DestNAme);
  263. end;
  264. Procedure DoDirSeparators (Var FileName : String);
  265. VAr I : longint;
  266. begin
  267. For I:=1 to Length(FileName) do
  268. If FileName[I] in AllowDirectorySeparators then
  269. FileName[i]:=DirectorySeparator;
  270. end;
  271. Function SetDirSeparators (Const FileName : string) : String;
  272. begin
  273. Result:=FileName;
  274. DoDirSeparators (Result);
  275. end;
  276. {
  277. DirName is split in a #0 separated list of directory names,
  278. Dirs is an array of pchars, pointing to these directory names.
  279. The function returns the number of directories found, or -1
  280. if none were found.
  281. }
  282. Function GetDirs (Var DirName : String; Var Dirs : Array of pchar) : Longint;
  283. Var I : Longint;
  284. begin
  285. I:=1;
  286. Result:=-1;
  287. While I<=Length(DirName) do
  288. begin
  289. If (DirName[i] in AllowDirectorySeparators) and
  290. { avoid error in case last char=pathdelim }
  291. (length(dirname)>i) then
  292. begin
  293. DirName[i]:=#0;
  294. Inc(Result);
  295. Dirs[Result]:=@DirName[I+1];
  296. end;
  297. Inc(I);
  298. end;
  299. If Result>-1 then inc(Result);
  300. end;
  301. function IncludeTrailingPathDelimiter(Const Path : String) : String;
  302. Var
  303. l : Integer;
  304. begin
  305. Result:=Path;
  306. l:=Length(Result);
  307. If (L=0) or not(Result[l] in AllowDirectorySeparators) then
  308. Result:=Result+DirectorySeparator;
  309. end;
  310. function IncludeTrailingBackslash(Const Path : String) : String;
  311. begin
  312. Result:=IncludeTrailingPathDelimiter(Path);
  313. end;
  314. function ExcludeTrailingBackslash(Const Path: string): string;
  315. begin
  316. Result:=ExcludeTrailingPathDelimiter(Path);
  317. end;
  318. function ExcludeTrailingPathDelimiter(Const Path: string): string;
  319. Var
  320. L : Integer;
  321. begin
  322. L:=Length(Path);
  323. If (L>0) and (Path[L] in AllowDirectorySeparators) then
  324. Dec(L);
  325. Result:=Copy(Path,1,L);
  326. end;
  327. function IncludeLeadingPathDelimiter(Const Path : String) : String;
  328. Var
  329. l : Integer;
  330. begin
  331. Result:=Path;
  332. l:=Length(Result);
  333. If (L=0) or not(Result[1] in AllowDirectorySeparators) then
  334. Result:=DirectorySeparator+Result;
  335. end;
  336. function ExcludeLeadingPathDelimiter(Const Path: string): string;
  337. Var
  338. L : Integer;
  339. begin
  340. Result:=Path;
  341. L:=Length(Result);
  342. If (L>0) and (Result[1] in AllowDirectorySeparators) then
  343. Delete(Result,1,1);
  344. end;
  345. function IsPathDelimiter(Const Path: string; Index: Integer): Boolean;
  346. begin
  347. Result:=(Index>0) and (Index<=Length(Path)) and (Path[Index] in AllowDirectorySeparators);
  348. end;
  349. function ConcatPaths(const Paths: array of String): String;
  350. var
  351. I: Integer;
  352. begin
  353. if Length(Paths) > 0 then
  354. begin
  355. Result := Paths[0];
  356. for I := 1 to Length(Paths) - 1 do
  357. Result := IncludeTrailingPathDelimiter(Result) + ExcludeLeadingPathDelimiter(Paths[I]);
  358. end else
  359. Result := '';
  360. end;
  361. Function GetFileHandle(var f : File):THandle;
  362. begin
  363. result:=filerec(f).handle;
  364. end;
  365. Function GetFileHandle(var f : Text):THandle;
  366. begin
  367. result:=textrec(f).handle;
  368. end;