fina.inc 11 KB

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