fina.inc 11 KB

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