filutil.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. File utility calls
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {******************************************************************************}
  13. { private functions }
  14. {******************************************************************************}
  15. { some internal constants }
  16. const
  17. ofRead = $0000; { Open for reading }
  18. ofWrite = $0001; { Open for writing }
  19. ofReadWrite = $0002; { Open for reading/writing }
  20. faFail = $0000; { Fail if file does not exist }
  21. faCreate = $0010; { Create if file does not exist }
  22. faOpen = $0001; { Open if file exists }
  23. faOpenReplace = $0002; { Clear if file exists }
  24. { converts S to a pchar and copies it to the transfer-buffer. }
  25. procedure StringToTB(const S: string);
  26. var P: pchar; Len: integer;
  27. begin
  28. Len := Length(S) + 1;
  29. P := StrPCopy(StrAlloc(Len), S);
  30. SysCopyToDos(longint(P), Len);
  31. StrDispose(P);
  32. end ;
  33. { Native OpenFile function.
  34. if return value <> 0 call failed. }
  35. function OpenFile(const FileName: string; var Handle: longint; Mode, Action: word): longint;
  36. var
  37. Regs: registers;
  38. begin
  39. result := 0;
  40. Handle := 0;
  41. StringToTB(FileName);
  42. if LFNSupport then Regs.Eax:=$716c
  43. else Regs.Eax:=$6c00;
  44. Regs.Edx := Action; { Action if file exists/not exists }
  45. Regs.Ds := tb_segment;
  46. Regs.Esi := tb_offset;
  47. Regs.Ebx := $2000 + (Mode and $ff); { file open mode }
  48. Regs.Ecx := $20; { Attributes }
  49. RealIntr($21, Regs);
  50. if Regs.Flags and CarryFlag <> 0 then result := Regs.Ax
  51. else Handle := Regs.Eax;
  52. end ;
  53. {******************************************************************************}
  54. { Public functions }
  55. {******************************************************************************}
  56. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  57. var e: integer;
  58. Begin
  59. e := OpenFile(FileName, result, Mode, faOpen);
  60. if e <> 0 then result := -1;
  61. end ;
  62. Function FileCreate (Const FileName : String) : Longint;
  63. var e: integer;
  64. begin
  65. e := OpenFile(FileName, result, ofReadWrite, faCreate or faOpenReplace);
  66. if e <> 0 then result := -1;
  67. end;
  68. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  69. begin
  70. result := Do_Read(Handle, longint(@Buffer), Count);
  71. end;
  72. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  73. begin
  74. result := Do_Write(Handle, longint(@Buffer), Count);
  75. end;
  76. Function FileSeek (Handle, Offset, Origin : Longint) : Longint;
  77. var Regs: registers;
  78. begin
  79. Regs.Eax := $4200;
  80. Regs.Al := Origin;
  81. Regs.Edx := Lo(Offset);
  82. Regs.Ecx := Hi(Offset);
  83. Regs.Ebx := Handle;
  84. RealIntr($21, Regs);
  85. if Regs.Flags and CarryFlag <> 0 then
  86. result := -1
  87. else begin
  88. LongRec(result).Lo := Regs.Eax;
  89. LongRec(result).Hi := Regs.Edx;
  90. end ;
  91. end;
  92. Procedure FileClose (Handle : Longint);
  93. var Regs: registers;
  94. begin
  95. if Handle<=4 then
  96. exit;
  97. Regs.Eax := $3e00;
  98. Regs.Ebx := Handle;
  99. RealIntr($21, Regs);
  100. end;
  101. Function FileTruncate (Handle,Size: Longint) : boolean;
  102. var
  103. regs : trealregs;
  104. begin
  105. FileSeek(Handle,Size,0);
  106. Regs.realecx := 0;
  107. Regs.realedx := tb_offset;
  108. Regs.ds := tb_segment;
  109. Regs.ebx := Handle;
  110. Regs.eax:=$4000;
  111. RealIntr($21, Regs);
  112. FileTruncate:=(regs.realflags and carryflag)=0;
  113. end;
  114. Function FileAge (Const FileName : String): Longint;
  115. var Handle: longint;
  116. begin
  117. Handle := FileOpen(FileName, 0);
  118. if Handle <> -1 then begin
  119. result := FileGetDate(Handle);
  120. FileClose(Handle);
  121. end
  122. else result := -1;
  123. end;
  124. Function FileExists (Const FileName : String) : Boolean;
  125. var Handle: longint;
  126. begin
  127. //!! This can be done quicker, need to find out how
  128. Result := (OpenFile(FileName, Handle, ofRead, faOpen) = 0);
  129. if Handle <> 0 then
  130. FileClose(Handle);
  131. end;
  132. Type PSearchrec = ^Searchrec;
  133. Function FindFirst (Const Path : String; Attr : Longint; Var Rslt : TSearchRec) : Longint;
  134. Var Sr : PSearchrec;
  135. begin
  136. //!! Sr := New(PSearchRec);
  137. getmem(sr,sizeof(searchrec));
  138. Rslt.FindHandle := longint(Sr);
  139. DOS.FindFirst(Path, Attr, Sr^);
  140. result := -DosError;
  141. if result = 0 then begin
  142. Rslt.Time := Sr^.Time;
  143. Rslt.Size := Sr^.Size;
  144. Rslt.Attr := Sr^.Attr;
  145. Rslt.ExcludeAttr := 0;
  146. Rslt.Name := Sr^.Name;
  147. end ;
  148. end;
  149. Function FindNext (Var Rslt : TSearchRec) : Longint;
  150. var Sr: PSearchRec;
  151. begin
  152. Sr := PSearchRec(Rslt.FindHandle);
  153. if Sr <> nil then begin
  154. DOS.FindNext(Sr^);
  155. result := -DosError;
  156. if result = 0 then begin
  157. Rslt.Time := Sr^.Time;
  158. Rslt.Size := Sr^.Size;
  159. Rslt.Attr := Sr^.Attr;
  160. Rslt.ExcludeAttr := 0;
  161. Rslt.Name := Sr^.Name;
  162. end ;
  163. end ;
  164. end;
  165. Procedure FindClose (Var F : TSearchrec);
  166. var Sr: PSearchRec;
  167. begin
  168. Sr := PSearchRec(F.FindHandle);
  169. if Sr <> nil then
  170. //!! Dispose(Sr);
  171. freemem(sr,sizeof(searchrec));
  172. F.FindHandle := 0;
  173. end;
  174. Function FileGetDate (Handle : Longint) : Longint;
  175. var Regs: registers;
  176. begin
  177. //!! for win95 an alternative function is available.
  178. Regs.Ebx := Handle;
  179. Regs.Eax := $5700;
  180. RealIntr($21, Regs);
  181. if Regs.Flags and CarryFlag <> 0 then result := -Regs.Ax
  182. else begin
  183. LongRec(result).Lo := Regs.cx;
  184. LongRec(result).Hi := Regs.dx;
  185. end ;
  186. end;
  187. Function FileSetDate (Handle, Age : Longint) : Longint;
  188. var Regs: registers;
  189. begin
  190. Regs.Ebx := Handle;
  191. Regs.Eax := $5701;
  192. Regs.Ecx := Lo(Age);
  193. Regs.Edx := Hi(Age);
  194. RealIntr($21, Regs);
  195. if Regs.Flags and CarryFlag <> 0 then result := -Regs.Ax
  196. else result := 0;
  197. end;
  198. Function FileGetAttr (Const FileName : String) : Longint;
  199. var Regs: registers;
  200. begin
  201. StringToTB(FileName);
  202. Regs.Edx := tb_offset;
  203. Regs.Ds := tb_segment;
  204. if LFNSupport then
  205. begin
  206. Regs.Ax := $7143;
  207. Regs.Bx := 0;
  208. end
  209. else
  210. Regs.Ax := $4300;
  211. RealIntr($21, Regs);
  212. if Regs.Flags and CarryFlag <> 0 then
  213. result := -1
  214. else
  215. result := Regs.Cx;
  216. end;
  217. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  218. var Regs: registers;
  219. begin
  220. StringToTB(FileName);
  221. Regs.Edx := tb_offset;
  222. Regs.Ds := tb_segment;
  223. if LFNSupport then
  224. begin
  225. Regs.Ax := $7143;
  226. Regs.Bx := 1;
  227. end
  228. else
  229. Regs.Ax := $4301;
  230. Regs.Cx := Attr;
  231. RealIntr($21, Regs);
  232. if Regs.Flags and CarryFlag <> 0 then result := -Regs.Ax
  233. else result := 0;
  234. end;
  235. Function DeleteFile (Const FileName : String) : Boolean;
  236. var Regs: registers;
  237. begin
  238. StringToTB(FileName);
  239. Regs.Edx := tb_offset;
  240. Regs.Ds := tb_segment;
  241. if LFNSupport then
  242. Regs.Eax := $7141
  243. else
  244. Regs.Eax := $4100;
  245. Regs.Esi := 0;
  246. Regs.Ecx := 0;
  247. RealIntr($21, Regs);
  248. result := (Regs.Flags and CarryFlag = 0);
  249. end;
  250. Function RenameFile (Const OldName, NewName : String) : Boolean;
  251. var Regs: registers;
  252. begin
  253. StringToTB(OldName + #0 + NewName);
  254. Regs.Edx := tb_offset;
  255. Regs.Ds := tb_segment;
  256. Regs.Edi := tb_offset + Length(OldName) + 1;
  257. Regs.Es := tb_segment;
  258. if LFNSupport then
  259. Regs.Eax := $7156
  260. else
  261. Regs.Eax := $5600;
  262. Regs.Ecx := $ff;
  263. RealIntr($21, Regs);
  264. result := (Regs.Flags and CarryFlag = 0);
  265. end;
  266. Function FileSearch (Const Name, DirList : String) : String;
  267. begin
  268. result := DOS.FSearch(Name, DirList);
  269. end;
  270. Procedure GetLocalTime(var SystemTime: TSystemTime);
  271. var Regs: Registers;
  272. begin
  273. Regs.ah := $2C;
  274. RealIntr($21, Regs);
  275. SystemTime.Hour := Regs.Ch;
  276. SystemTime.Minute := Regs.Cl;
  277. SystemTime.Second := Regs.Dh;
  278. SystemTime.MilliSecond := Regs.Dl;
  279. Regs.ah := $2A;
  280. RealIntr($21, Regs);
  281. SystemTime.Year := Regs.Cx;
  282. SystemTime.Month := Regs.Dh;
  283. SystemTime.Day := Regs.Dl;
  284. end ;
  285. { ---------------------------------------------------------------------
  286. Internationalization settings
  287. ---------------------------------------------------------------------}
  288. { Codepage constants }
  289. const
  290. CP_US = 437;
  291. CP_MultiLingual = 850;
  292. CP_SlavicLatin2 = 852;
  293. CP_Turkish = 857;
  294. CP_Portugal = 860;
  295. CP_IceLand = 861;
  296. CP_Canada = 863;
  297. CP_NorwayDenmark = 865;
  298. { CountryInfo }
  299. type
  300. TCountryInfo = packed record
  301. InfoId: byte;
  302. case integer of
  303. 1: ( Size: word;
  304. CountryId: word;
  305. CodePage: word;
  306. CountryInfo: array[0..33] of byte );
  307. 2: ( UpperCaseTable: longint );
  308. 4: ( FilenameUpperCaseTable: longint );
  309. 5: ( FilecharacterTable: longint );
  310. 6: ( CollatingTable: longint );
  311. 7: ( DBCSLeadByteTable: longint );
  312. end ;
  313. procedure GetExtendedCountryInfo(InfoId: integer; CodePage, CountryId: word; var CountryInfo: TCountryInfo);
  314. Var Regs: Registers;
  315. begin
  316. Regs.AH := $65;
  317. Regs.AL := InfoId;
  318. Regs.BX := CodePage;
  319. Regs.DX := CountryId;
  320. Regs.ES := transfer_buffer div 16;
  321. Regs.DI := transfer_buffer and 15;
  322. Regs.CX := SizeOf(TCountryInfo);
  323. RealIntr($21, Regs);
  324. DosMemGet(transfer_buffer div 16,
  325. transfer_buffer and 15,
  326. CountryInfo, Regs.CX );
  327. end;
  328. procedure InitAnsi;
  329. var CountryInfo: TCountryInfo; i: integer;
  330. begin
  331. { Fill table entries 0 to 127 }
  332. for i := 0 to 96 do
  333. UpperCaseTable[i] := chr(i);
  334. for i := 97 to 122 do
  335. UpperCaseTable[i] := chr(i - 32);
  336. for i := 123 to 127 do
  337. UpperCaseTable[i] := chr(i);
  338. for i := 0 to 64 do
  339. LowerCaseTable[i] := chr(i);
  340. for i := 65 to 90 do
  341. LowerCaseTable[i] := chr(i + 32);
  342. for i := 91 to 255 do
  343. LowerCaseTable[i] := chr(i);
  344. { Get country and codepage info }
  345. GetExtendedCountryInfo(1, $FFFF, $FFFF, CountryInfo);
  346. if CountryInfo.CodePage = 850 then
  347. begin
  348. { Special, known case }
  349. Move(CP850UCT, UpperCaseTable[128], 128);
  350. Move(CP850LCT, LowerCaseTable[128], 128);
  351. end
  352. else
  353. begin
  354. { this needs to be checked !!
  355. this is correct only if UpperCaseTable is
  356. and Offset:Segment word record (PM) }
  357. { get the uppercase table from dosmemory }
  358. GetExtendedCountryInfo(2, $FFFF, $FFFF, CountryInfo);
  359. DosMemGet(CountryInfo.UpperCaseTable shr 16, 2 + CountryInfo.UpperCaseTable and 65535, UpperCaseTable[128], 128);
  360. for i := 128 to 255 do
  361. begin
  362. if UpperCaseTable[i] <> chr(i) then
  363. LowerCaseTable[ord(UpperCaseTable[i])] := chr(i);
  364. end;
  365. end;
  366. end;
  367. Procedure InitInternational;
  368. { This routine is called by the unit startup code. }
  369. begin
  370. { Init upper/lowercase tables }
  371. InitAnsi
  372. end;
  373. {
  374. $Log$
  375. Revision 1.13 2000-02-17 22:16:05 sg
  376. * Changed the second argument of FileWrite from "var buffer" to
  377. "const buffer", like in Delphi.
  378. Revision 1.12 2000/02/09 16:59:28 peter
  379. * truncated log
  380. Revision 1.11 2000/01/16 22:25:38 peter
  381. * check handle for file closing
  382. Revision 1.10 2000/01/07 16:41:31 daniel
  383. * copyright 2000
  384. Revision 1.9 1999/11/25 15:55:52 pierre
  385. * web bug 716
  386. Revision 1.8 1999/08/26 11:02:50 peter
  387. * findclose freemem fixed
  388. Revision 1.7 1999/08/24 13:14:28 peter
  389. * fixed DeleteFile()
  390. Revision 1.6 1999/08/19 14:00:08 pierre
  391. * bug in country info code fixed
  392. }