sysutils.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Sysutils unit for Go32v2
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit sysutils;
  14. interface
  15. {$MODE objfpc}
  16. { force ansistrings }
  17. {$H+}
  18. uses
  19. go32,dos;
  20. { Include platform independent interface part }
  21. {$i sysutilh.inc}
  22. implementation
  23. { Include platform independent implementation part }
  24. {$i sysutils.inc}
  25. {****************************************************************************
  26. File Functions
  27. ****************************************************************************}
  28. { some internal constants }
  29. const
  30. ofRead = $0000; { Open for reading }
  31. ofWrite = $0001; { Open for writing }
  32. ofReadWrite = $0002; { Open for reading/writing }
  33. faFail = $0000; { Fail if file does not exist }
  34. faCreate = $0010; { Create if file does not exist }
  35. faOpen = $0001; { Open if file exists }
  36. faOpenReplace = $0002; { Clear if file exists }
  37. Type
  38. PSearchrec = ^Searchrec;
  39. { converts S to a pchar and copies it to the transfer-buffer. }
  40. procedure StringToTB(const S: string);
  41. var
  42. P: pchar;
  43. Len: integer;
  44. begin
  45. Len := Length(S) + 1;
  46. P := StrPCopy(StrAlloc(Len), S);
  47. SysCopyToDos(longint(P), Len);
  48. StrDispose(P);
  49. end ;
  50. { Native OpenFile function.
  51. if return value <> 0 call failed. }
  52. function OpenFile(const FileName: string; var Handle: longint; Mode, Action: word): longint;
  53. var
  54. Regs: registers;
  55. begin
  56. result := 0;
  57. Handle := 0;
  58. StringToTB(FileName);
  59. if LFNSupport then Regs.Eax:=$716c
  60. else Regs.Eax:=$6c00;
  61. Regs.Edx := Action; { Action if file exists/not exists }
  62. Regs.Ds := tb_segment;
  63. Regs.Esi := tb_offset;
  64. Regs.Ebx := $2000 + (Mode and $ff); { file open mode }
  65. Regs.Ecx := $20; { Attributes }
  66. RealIntr($21, Regs);
  67. if Regs.Flags and CarryFlag <> 0 then result := Regs.Ax
  68. else Handle := Regs.Ax;
  69. end ;
  70. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  71. var
  72. e: integer;
  73. Begin
  74. e := OpenFile(FileName, result, Mode, faOpen);
  75. if e <> 0 then
  76. result := -1;
  77. end;
  78. Function FileCreate (Const FileName : String) : Longint;
  79. var
  80. e: integer;
  81. begin
  82. e := OpenFile(FileName, result, ofReadWrite, faCreate or faOpenReplace);
  83. if e <> 0 then
  84. result := -1;
  85. end;
  86. Function FileCreate (Const FileName : String; Mode:longint) : Longint;
  87. begin
  88. FileCreate:=FileCreate(FileName);
  89. end;
  90. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  91. var
  92. regs : registers;
  93. size,
  94. readsize : longint;
  95. begin
  96. readsize:=0;
  97. while Count > 0 do
  98. begin
  99. if Count>tb_size then
  100. size:=tb_size
  101. else
  102. size:=Count;
  103. regs.realecx:=size;
  104. regs.realedx:=tb_offset;
  105. regs.realds:=tb_segment;
  106. regs.realebx:=Handle;
  107. regs.realeax:=$3f00;
  108. RealIntr($21,regs);
  109. if (regs.realflags and carryflag) <> 0 then
  110. begin
  111. Result:=-1;
  112. exit;
  113. end;
  114. syscopyfromdos(Longint(@Buffer)+readsize,lo(regs.realeax));
  115. inc(readsize,lo(regs.realeax));
  116. dec(Count,lo(regs.realeax));
  117. { stop when not the specified size is read }
  118. if lo(regs.realeax)<size then
  119. break;
  120. end;
  121. Result:=readsize;
  122. end;
  123. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  124. var
  125. regs : registers;
  126. size,
  127. writesize : longint;
  128. begin
  129. writesize:=0;
  130. while Count > 0 do
  131. begin
  132. if Count>tb_size then
  133. size:=tb_size
  134. else
  135. size:=Count;
  136. syscopytodos(Longint(@Buffer)+writesize,size);
  137. regs.realecx:=size;
  138. regs.realedx:=tb_offset;
  139. regs.realds:=tb_segment;
  140. regs.realebx:=Handle;
  141. regs.realeax:=$4000;
  142. RealIntr($21,regs);
  143. if (regs.realflags and carryflag) <> 0 then
  144. begin
  145. Result:=-1;
  146. exit;
  147. end;
  148. inc(writesize,lo(regs.realeax));
  149. dec(Count,lo(regs.realeax));
  150. { stop when not the specified size is written }
  151. if lo(regs.realeax)<size then
  152. break;
  153. end;
  154. Result:=WriteSize;
  155. end;
  156. Function FileSeek (Handle, FOffset, Origin : Longint) : Longint;
  157. var
  158. Regs: registers;
  159. begin
  160. Regs.Eax := $4200;
  161. Regs.Al := Origin;
  162. Regs.Edx := Lo(FOffset);
  163. Regs.Ecx := Hi(FOffset);
  164. Regs.Ebx := Handle;
  165. RealIntr($21, Regs);
  166. if Regs.Flags and CarryFlag <> 0 then
  167. result := -1
  168. else begin
  169. LongRec(result).Lo := Regs.Ax;
  170. LongRec(result).Hi := Regs.Dx;
  171. end ;
  172. end;
  173. Function FileSeek (Handle : Longint; FOffset,Origin : Int64) : Int64;
  174. begin
  175. {$warning need to add 64bit call }
  176. FileSeek:=FileSeek(Handle,Longint(FOffset),Longint(Origin));
  177. end;
  178. Procedure FileClose (Handle : Longint);
  179. var
  180. Regs: registers;
  181. begin
  182. if Handle<=4 then
  183. exit;
  184. Regs.Eax := $3e00;
  185. Regs.Ebx := Handle;
  186. RealIntr($21, Regs);
  187. end;
  188. Function FileTruncate (Handle,Size: Longint) : boolean;
  189. var
  190. regs : trealregs;
  191. begin
  192. FileSeek(Handle,Size,0);
  193. Regs.realecx := 0;
  194. Regs.realedx := tb_offset;
  195. Regs.ds := tb_segment;
  196. Regs.ebx := Handle;
  197. Regs.eax:=$4000;
  198. RealIntr($21, Regs);
  199. FileTruncate:=(regs.realflags and carryflag)=0;
  200. end;
  201. Function FileAge (Const FileName : String): Longint;
  202. var Handle: longint;
  203. begin
  204. Handle := FileOpen(FileName, 0);
  205. if Handle <> -1 then
  206. begin
  207. result := FileGetDate(Handle);
  208. FileClose(Handle);
  209. end
  210. else
  211. result := -1;
  212. end;
  213. Function FileExists (Const FileName : String) : Boolean;
  214. var Handle: longint;
  215. begin
  216. //!! This can be done quicker, need to find out how
  217. Result := (OpenFile(FileName, Handle, ofRead, faOpen) = 0);
  218. if Handle <> 0 then
  219. FileClose(Handle);
  220. end;
  221. Function FindFirst (Const Path : String; Attr : Longint; Var Rslt : TSearchRec) : Longint;
  222. Var Sr : PSearchrec;
  223. begin
  224. //!! Sr := New(PSearchRec);
  225. getmem(sr,sizeof(searchrec));
  226. Rslt.FindHandle := longint(Sr);
  227. DOS.FindFirst(Path, Attr, Sr^);
  228. result := -DosError;
  229. if result = 0 then
  230. begin
  231. Rslt.Time := Sr^.Time;
  232. Rslt.Size := Sr^.Size;
  233. Rslt.Attr := Sr^.Attr;
  234. Rslt.ExcludeAttr := 0;
  235. Rslt.Name := Sr^.Name;
  236. end ;
  237. end;
  238. Function FindNext (Var Rslt : TSearchRec) : Longint;
  239. var
  240. Sr: PSearchRec;
  241. begin
  242. Sr := PSearchRec(Rslt.FindHandle);
  243. if Sr <> nil then
  244. begin
  245. DOS.FindNext(Sr^);
  246. result := -DosError;
  247. if result = 0 then
  248. begin
  249. Rslt.Time := Sr^.Time;
  250. Rslt.Size := Sr^.Size;
  251. Rslt.Attr := Sr^.Attr;
  252. Rslt.ExcludeAttr := 0;
  253. Rslt.Name := Sr^.Name;
  254. end;
  255. end;
  256. end;
  257. Procedure FindClose (Var F : TSearchrec);
  258. var
  259. Sr: PSearchRec;
  260. begin
  261. Sr := PSearchRec(F.FindHandle);
  262. if Sr <> nil then
  263. begin
  264. //!! Dispose(Sr);
  265. // This call is non dummy if LFNSupport is true PM
  266. DOS.FindClose(SR^);
  267. freemem(sr,sizeof(searchrec));
  268. end;
  269. F.FindHandle := 0;
  270. end;
  271. Function FileGetDate (Handle : Longint) : Longint;
  272. var
  273. Regs: registers;
  274. begin
  275. //!! for win95 an alternative function is available.
  276. Regs.Ebx := Handle;
  277. Regs.Eax := $5700;
  278. RealIntr($21, Regs);
  279. if Regs.Flags and CarryFlag <> 0 then
  280. result := -1
  281. else
  282. begin
  283. LongRec(result).Lo := Regs.cx;
  284. LongRec(result).Hi := Regs.dx;
  285. end ;
  286. end;
  287. Function FileSetDate (Handle, Age : Longint) : Longint;
  288. var
  289. Regs: registers;
  290. begin
  291. Regs.Ebx := Handle;
  292. Regs.Eax := $5701;
  293. Regs.Ecx := Lo(Age);
  294. Regs.Edx := Hi(Age);
  295. RealIntr($21, Regs);
  296. if Regs.Flags and CarryFlag <> 0 then
  297. result := -Regs.Ax
  298. else
  299. result := 0;
  300. end;
  301. Function FileGetAttr (Const FileName : String) : Longint;
  302. var
  303. Regs: registers;
  304. begin
  305. StringToTB(FileName);
  306. Regs.Edx := tb_offset;
  307. Regs.Ds := tb_segment;
  308. if LFNSupport then
  309. begin
  310. Regs.Ax := $7143;
  311. Regs.Bx := 0;
  312. end
  313. else
  314. Regs.Ax := $4300;
  315. RealIntr($21, Regs);
  316. if Regs.Flags and CarryFlag <> 0 then
  317. result := -1
  318. else
  319. result := Regs.Cx;
  320. end;
  321. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  322. var
  323. Regs: registers;
  324. begin
  325. StringToTB(FileName);
  326. Regs.Edx := tb_offset;
  327. Regs.Ds := tb_segment;
  328. if LFNSupport then
  329. begin
  330. Regs.Ax := $7143;
  331. Regs.Bx := 1;
  332. end
  333. else
  334. Regs.Ax := $4301;
  335. Regs.Cx := Attr;
  336. RealIntr($21, Regs);
  337. if Regs.Flags and CarryFlag <> 0 then
  338. result := -Regs.Ax
  339. else
  340. result := 0;
  341. end;
  342. Function DeleteFile (Const FileName : String) : Boolean;
  343. var
  344. Regs: registers;
  345. begin
  346. StringToTB(FileName);
  347. Regs.Edx := tb_offset;
  348. Regs.Ds := tb_segment;
  349. if LFNSupport then
  350. Regs.Eax := $7141
  351. else
  352. Regs.Eax := $4100;
  353. Regs.Esi := 0;
  354. Regs.Ecx := 0;
  355. RealIntr($21, Regs);
  356. result := (Regs.Flags and CarryFlag = 0);
  357. end;
  358. Function RenameFile (Const OldName, NewName : String) : Boolean;
  359. var
  360. Regs: registers;
  361. begin
  362. StringToTB(OldName + #0 + NewName);
  363. Regs.Edx := tb_offset;
  364. Regs.Ds := tb_segment;
  365. Regs.Edi := tb_offset + Length(OldName) + 1;
  366. Regs.Es := tb_segment;
  367. if LFNSupport then
  368. Regs.Eax := $7156
  369. else
  370. Regs.Eax := $5600;
  371. Regs.Ecx := $ff;
  372. RealIntr($21, Regs);
  373. result := (Regs.Flags and CarryFlag = 0);
  374. end;
  375. {****************************************************************************
  376. Disk Functions
  377. ****************************************************************************}
  378. TYPE ExtendedFat32FreeSpaceRec=packed Record
  379. RetSize : WORD; { (ret) size of returned structure}
  380. Strucversion : WORD; {(call) structure version (0000h)
  381. (ret) actual structure version (0000h)}
  382. SecPerClus, {number of sectors per cluster}
  383. BytePerSec, {number of bytes per sector}
  384. AvailClusters, {number of available clusters}
  385. TotalClusters, {total number of clusters on the drive}
  386. AvailPhysSect, {physical sectors available on the drive}
  387. TotalPhysSect, {total physical sectors on the drive}
  388. AvailAllocUnits, {Available allocation units}
  389. TotalAllocUnits : DWORD; {Total allocation units}
  390. Dummy,Dummy2 : DWORD; {8 bytes reserved}
  391. END;
  392. function do_diskdata(drive : byte; Free : BOOLEAN) : Int64;
  393. VAR S : String;
  394. Rec : ExtendedFat32FreeSpaceRec;
  395. regs : registers;
  396. BEGIN
  397. if (swap(dosversion)>=$070A) AND LFNSupport then
  398. begin
  399. DosError:=0;
  400. S:='C:\'#0;
  401. if Drive=0 then
  402. begin
  403. GetDir(Drive,S);
  404. Setlength(S,4);
  405. S[4]:=#0;
  406. end
  407. else
  408. S[1]:=chr(Drive+64);
  409. Rec.Strucversion:=0;
  410. dosmemput(tb_segment,tb_offset,Rec,SIZEOF(ExtendedFat32FreeSpaceRec));
  411. dosmemput(tb_segment,tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1,S[1],4);
  412. regs.dx:=tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1;
  413. regs.ds:=tb_segment;
  414. regs.di:=tb_offset;
  415. regs.es:=tb_segment;
  416. regs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);
  417. regs.ax:=$7303;
  418. msdos(regs);
  419. if regs.ax<>$ffff then
  420. begin
  421. copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));
  422. if Free then
  423. Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec
  424. else
  425. Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;
  426. end
  427. else
  428. Do_DiskData:=-1;
  429. end
  430. else
  431. begin
  432. DosError:=0;
  433. regs.dl:=drive;
  434. regs.ah:=$36;
  435. msdos(regs);
  436. if regs.ax<>$FFFF then
  437. begin
  438. if Free then
  439. Do_DiskData:=int64(regs.ax)*regs.bx*regs.cx
  440. else
  441. Do_DiskData:=int64(regs.ax)*regs.cx*regs.dx;
  442. end
  443. else
  444. do_diskdata:=-1;
  445. end;
  446. end;
  447. function diskfree(drive : byte) : int64;
  448. begin
  449. diskfree:=Do_DiskData(drive,TRUE);
  450. end;
  451. function disksize(drive : byte) : int64;
  452. begin
  453. disksize:=Do_DiskData(drive,false);
  454. end;
  455. Function GetCurrentDir : String;
  456. begin
  457. GetDir(0, result);
  458. end;
  459. Function SetCurrentDir (Const NewDir : String) : Boolean;
  460. begin
  461. {$I-}
  462. ChDir(NewDir);
  463. {$I+}
  464. result := (IOResult = 0);
  465. end;
  466. Function CreateDir (Const NewDir : String) : Boolean;
  467. begin
  468. {$I-}
  469. MkDir(NewDir);
  470. {$I+}
  471. result := (IOResult = 0);
  472. end;
  473. Function RemoveDir (Const Dir : String) : Boolean;
  474. begin
  475. {$I-}
  476. RmDir(Dir);
  477. {$I+}
  478. result := (IOResult = 0);
  479. end;
  480. {****************************************************************************
  481. Time Functions
  482. ****************************************************************************}
  483. Procedure GetLocalTime(var SystemTime: TSystemTime);
  484. var
  485. Regs: Registers;
  486. begin
  487. Regs.ah := $2C;
  488. RealIntr($21, Regs);
  489. SystemTime.Hour := Regs.Ch;
  490. SystemTime.Minute := Regs.Cl;
  491. SystemTime.Second := Regs.Dh;
  492. SystemTime.MilliSecond := Regs.Dl;
  493. Regs.ah := $2A;
  494. RealIntr($21, Regs);
  495. SystemTime.Year := Regs.Cx;
  496. SystemTime.Month := Regs.Dh;
  497. SystemTime.Day := Regs.Dl;
  498. end ;
  499. {****************************************************************************
  500. Misc Functions
  501. ****************************************************************************}
  502. procedure Beep;
  503. begin
  504. end;
  505. {****************************************************************************
  506. Locale Functions
  507. ****************************************************************************}
  508. { Codepage constants }
  509. const
  510. CP_US = 437;
  511. CP_MultiLingual = 850;
  512. CP_SlavicLatin2 = 852;
  513. CP_Turkish = 857;
  514. CP_Portugal = 860;
  515. CP_IceLand = 861;
  516. CP_Canada = 863;
  517. CP_NorwayDenmark = 865;
  518. { CountryInfo }
  519. type
  520. TCountryInfo = packed record
  521. InfoId: byte;
  522. case integer of
  523. 1: ( Size: word;
  524. CountryId: word;
  525. CodePage: word;
  526. CountryInfo: array[0..33] of byte );
  527. 2: ( UpperCaseTable: longint );
  528. 4: ( FilenameUpperCaseTable: longint );
  529. 5: ( FilecharacterTable: longint );
  530. 6: ( CollatingTable: longint );
  531. 7: ( DBCSLeadByteTable: longint );
  532. end ;
  533. procedure GetExtendedCountryInfo(InfoId: integer; CodePage, CountryId: word; var CountryInfo: TCountryInfo);
  534. Var Regs: Registers;
  535. begin
  536. Regs.AH := $65;
  537. Regs.AL := InfoId;
  538. Regs.BX := CodePage;
  539. Regs.DX := CountryId;
  540. Regs.ES := transfer_buffer div 16;
  541. Regs.DI := transfer_buffer and 15;
  542. Regs.CX := SizeOf(TCountryInfo);
  543. RealIntr($21, Regs);
  544. DosMemGet(transfer_buffer div 16,
  545. transfer_buffer and 15,
  546. CountryInfo, Regs.CX );
  547. end;
  548. procedure InitAnsi;
  549. var
  550. CountryInfo: TCountryInfo; i: integer;
  551. begin
  552. { Fill table entries 0 to 127 }
  553. for i := 0 to 96 do
  554. UpperCaseTable[i] := chr(i);
  555. for i := 97 to 122 do
  556. UpperCaseTable[i] := chr(i - 32);
  557. for i := 123 to 127 do
  558. UpperCaseTable[i] := chr(i);
  559. for i := 0 to 64 do
  560. LowerCaseTable[i] := chr(i);
  561. for i := 65 to 90 do
  562. LowerCaseTable[i] := chr(i + 32);
  563. for i := 91 to 255 do
  564. LowerCaseTable[i] := chr(i);
  565. { Get country and codepage info }
  566. GetExtendedCountryInfo(1, $FFFF, $FFFF, CountryInfo);
  567. if CountryInfo.CodePage = 850 then
  568. begin
  569. { Special, known case }
  570. Move(CP850UCT, UpperCaseTable[128], 128);
  571. Move(CP850LCT, LowerCaseTable[128], 128);
  572. end
  573. else
  574. begin
  575. { this needs to be checked !!
  576. this is correct only if UpperCaseTable is
  577. and Offset:Segment word record (PM) }
  578. { get the uppercase table from dosmemory }
  579. GetExtendedCountryInfo(2, $FFFF, $FFFF, CountryInfo);
  580. DosMemGet(CountryInfo.UpperCaseTable shr 16, 2 + CountryInfo.UpperCaseTable and 65535, UpperCaseTable[128], 128);
  581. for i := 128 to 255 do
  582. begin
  583. if UpperCaseTable[i] <> chr(i) then
  584. LowerCaseTable[ord(UpperCaseTable[i])] := chr(i);
  585. end;
  586. end;
  587. end;
  588. Procedure InitInternational;
  589. begin
  590. InitAnsi;
  591. end;
  592. function SysErrorMessage(ErrorCode: Integer): String;
  593. begin
  594. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  595. end;
  596. {****************************************************************************
  597. Os utils
  598. ****************************************************************************}
  599. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  600. var
  601. hp : ppchar;
  602. lenvvar,hs : string;
  603. eqpos : longint;
  604. begin
  605. lenvvar:=upcase(envvar);
  606. hp:=envp;
  607. Result:='';
  608. while assigned(hp^) do
  609. begin
  610. hs:=strpas(hp^);
  611. eqpos:=pos('=',hs);
  612. if upcase(copy(hs,1,eqpos-1))=lenvvar then
  613. begin
  614. Result:=copy(hs,eqpos+1,length(hs)-eqpos);
  615. exit;
  616. end;
  617. inc(hp);
  618. end;
  619. end;
  620. {****************************************************************************
  621. Initialization code
  622. ****************************************************************************}
  623. Initialization
  624. InitExceptions; { Initialize exceptions. OS independent }
  625. InitInternational; { Initialize internationalization settings }
  626. Finalization
  627. DoneExceptions;
  628. end.
  629. {
  630. $Log$
  631. Revision 1.11 2003-01-03 20:41:04 peter
  632. * FileCreate(string,mode) overload added
  633. Revision 1.10 2002/09/07 16:01:19 peter
  634. * old logs removed and tabs fixed
  635. Revision 1.9 2002/05/09 08:42:24 carl
  636. * Merges from Fixes branch
  637. Revision 1.8 2002/01/25 16:23:03 peter
  638. * merged filesearch() fix
  639. Revision 1.7 2002/01/19 11:57:55 peter
  640. * merged fixes
  641. }