sysutils.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  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 win32
  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. dos,windows;
  20. { Include platform independent interface part }
  21. {$i sysutilh.inc}
  22. type
  23. TSystemTime = Windows.TSystemTime;
  24. EWin32Error = class(Exception)
  25. public
  26. ErrorCode : DWORD;
  27. end;
  28. Var
  29. Win32Platform : Longint;
  30. implementation
  31. { Include platform independent implementation part }
  32. {$i sysutils.inc}
  33. {****************************************************************************
  34. File Functions
  35. ****************************************************************************}
  36. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  37. const
  38. AccessMode: array[0..2] of Cardinal = (
  39. GENERIC_READ,
  40. GENERIC_WRITE,
  41. GENERIC_READ or GENERIC_WRITE);
  42. ShareMode: array[0..4] of Integer = (
  43. 0,
  44. 0,
  45. FILE_SHARE_READ,
  46. FILE_SHARE_WRITE,
  47. FILE_SHARE_READ or FILE_SHARE_WRITE);
  48. Var
  49. FN : string;
  50. begin
  51. FN:=FileName+#0;
  52. result := CreateFile(@FN[1], dword(AccessMode[Mode and 3]),
  53. dword(ShareMode[(Mode and $F0) shr 4]), nil, OPEN_EXISTING,
  54. FILE_ATTRIBUTE_NORMAL, 0);
  55. end;
  56. Function FileCreate (Const FileName : String) : Longint;
  57. Var
  58. FN : string;
  59. begin
  60. FN:=FileName+#0;
  61. Result := CreateFile(@FN[1], GENERIC_READ or GENERIC_WRITE,
  62. 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  63. end;
  64. Function FileCreate (Const FileName : String; Mode:longint) : Longint;
  65. begin
  66. FileCreate:=FileCreate(FileName);
  67. end;
  68. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  69. Var
  70. res : dword;
  71. begin
  72. if ReadFile(Handle, Buffer, Count, res, nil) then
  73. FileRead:=Res
  74. else
  75. FileRead:=-1;
  76. end;
  77. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  78. Var
  79. Res : dword;
  80. begin
  81. if WriteFile(Handle, Buffer, Count, Res, nil) then
  82. FileWrite:=Res
  83. else
  84. FileWrite:=-1;
  85. end;
  86. Function FileSeek (Handle,FOffset,Origin : Longint) : Longint;
  87. begin
  88. Result := longint(SetFilePointer(Handle, FOffset, nil, Origin));
  89. end;
  90. Function FileSeek (Handle : Longint; FOffset,Origin : Int64) : Int64;
  91. begin
  92. {$warning need to add 64bit call }
  93. Result := longint(SetFilePointer(Handle, FOffset, nil, Origin));
  94. end;
  95. Procedure FileClose (Handle : Longint);
  96. begin
  97. if Handle<=4 then
  98. exit;
  99. CloseHandle(Handle);
  100. end;
  101. Function FileTruncate (Handle,Size: Longint) : boolean;
  102. begin
  103. Result:=longint(SetFilePointer(handle,Size,nil,FILE_BEGIN))<>-1;
  104. If Result then
  105. Result:=SetEndOfFile(handle);
  106. end;
  107. Function DosToWinTime (DTime:longint;Var Wtime : TFileTime):longbool;
  108. var
  109. lft : TFileTime;
  110. begin
  111. DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,@lft) and
  112. LocalFileTimeToFileTime(lft,Wtime);
  113. end;
  114. Function WinToDosTime (Var Wtime : TFileTime;var DTime:longint):longbool;
  115. var
  116. lft : FileTime;
  117. begin
  118. WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
  119. FileTimeToDosDateTime(lft,Longrec(Dtime).Hi,LongRec(DTIME).lo);
  120. end;
  121. Function FileAge (Const FileName : String): Longint;
  122. var
  123. Handle: THandle;
  124. FindData: TWin32FindData;
  125. begin
  126. Handle := FindFirstFile(Pchar(FileName), @FindData);
  127. if Handle <> INVALID_HANDLE_VALUE then
  128. begin
  129. Windows.FindClose(Handle);
  130. if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
  131. If WinToDosTime(FindData.ftLastWriteTime,Result) then
  132. exit;
  133. end;
  134. Result := -1;
  135. end;
  136. Function FileExists (Const FileName : String) : Boolean;
  137. var
  138. Handle: THandle;
  139. FindData: TWin32FindData;
  140. begin
  141. Handle := FindFirstFile(Pchar(FileName), @FindData);
  142. Result:=Handle <> INVALID_HANDLE_VALUE;
  143. If Result then
  144. Windows.FindClose(Handle);
  145. end;
  146. Function FindMatch(var f: TSearchRec) : Longint;
  147. begin
  148. { Find file with correct attribute }
  149. While (F.FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
  150. begin
  151. if not FindNextFile (F.FindHandle,@F.FindData) then
  152. begin
  153. Result:=GetLastError;
  154. exit;
  155. end;
  156. end;
  157. { Convert some attributes back }
  158. WinToDosTime(F.FindData.ftLastWriteTime,F.Time);
  159. f.size:=F.FindData.NFileSizeLow;
  160. f.attr:=F.FindData.dwFileAttributes;
  161. f.Name:=StrPas(@F.FindData.cFileName);
  162. Result:=0;
  163. end;
  164. Function FindFirst (Const Path : String; Attr : Longint; Var Rslt : TSearchRec) : Longint;
  165. begin
  166. Rslt.Name:=Path;
  167. Rslt.Attr:=attr;
  168. Rslt.ExcludeAttr:=(not Attr) and ($1e);
  169. { $1e = faHidden or faSysFile or faVolumeID or faDirectory }
  170. { FindFirstFile is a Win32 Call }
  171. Rslt.FindHandle:=FindFirstFile (PChar(Path),@Rslt.FindData);
  172. If Rslt.FindHandle=Invalid_Handle_value then
  173. begin
  174. Result:=GetLastError;
  175. exit;
  176. end;
  177. { Find file with correct attribute }
  178. Result:=FindMatch(Rslt);
  179. end;
  180. Function FindNext (Var Rslt : TSearchRec) : Longint;
  181. begin
  182. if FindNextFile(Rslt.FindHandle, @Rslt.FindData) then
  183. Result := FindMatch(Rslt)
  184. else
  185. Result := GetLastError;
  186. end;
  187. Procedure FindClose (Var F : TSearchrec);
  188. begin
  189. if F.FindHandle <> INVALID_HANDLE_VALUE then
  190. Windows.FindClose(F.FindHandle);
  191. end;
  192. Function FileGetDate (Handle : Longint) : Longint;
  193. Var
  194. FT : TFileTime;
  195. begin
  196. If GetFileTime(Handle,nil,nil,@ft) and
  197. WinToDosTime(FT,Result) then
  198. exit;
  199. Result:=-1;
  200. end;
  201. Function FileSetDate (Handle,Age : Longint) : Longint;
  202. Var
  203. FT: TFileTime;
  204. begin
  205. Result := 0;
  206. if DosToWinTime(Age,FT) and
  207. SetFileTime(Handle, ft, ft, FT) then
  208. Exit;
  209. Result := GetLastError;
  210. end;
  211. Function FileGetAttr (Const FileName : String) : Longint;
  212. begin
  213. Result:=GetFileAttributes(PChar(FileName));
  214. end;
  215. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  216. begin
  217. if not SetFileAttributes(PChar(FileName), Attr) then
  218. Result := GetLastError
  219. else
  220. Result:=0;
  221. end;
  222. Function DeleteFile (Const FileName : String) : Boolean;
  223. begin
  224. DeleteFile:=Windows.DeleteFile(Pchar(FileName));
  225. end;
  226. Function RenameFile (Const OldName, NewName : String) : Boolean;
  227. begin
  228. Result := MoveFile(PChar(OldName), PChar(NewName));
  229. end;
  230. {****************************************************************************
  231. Disk Functions
  232. ****************************************************************************}
  233. function GetDiskFreeSpace(drive:pchar;var sector_cluster,bytes_sector,
  234. freeclusters,totalclusters:longint):longbool;
  235. external 'kernel32' name 'GetDiskFreeSpaceA';
  236. type
  237. TGetDiskFreeSpaceEx = function(drive:pchar;var availableforcaller,total,free):longbool;stdcall;
  238. var
  239. GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
  240. function diskfree(drive : byte) : int64;
  241. var
  242. disk : array[1..4] of char;
  243. secs,bytes,
  244. free,total : longint;
  245. qwtotal,qwfree,qwcaller : int64;
  246. begin
  247. if drive=0 then
  248. begin
  249. disk[1]:='\';
  250. disk[2]:=#0;
  251. end
  252. else
  253. begin
  254. disk[1]:=chr(drive+64);
  255. disk[2]:=':';
  256. disk[3]:='\';
  257. disk[4]:=#0;
  258. end;
  259. if assigned(GetDiskFreeSpaceEx) then
  260. begin
  261. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  262. diskfree:=qwfree
  263. else
  264. diskfree:=-1;
  265. end
  266. else
  267. begin
  268. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  269. diskfree:=int64(free)*secs*bytes
  270. else
  271. diskfree:=-1;
  272. end;
  273. end;
  274. function disksize(drive : byte) : int64;
  275. var
  276. disk : array[1..4] of char;
  277. secs,bytes,
  278. free,total : longint;
  279. qwtotal,qwfree,qwcaller : int64;
  280. begin
  281. if drive=0 then
  282. begin
  283. disk[1]:='\';
  284. disk[2]:=#0;
  285. end
  286. else
  287. begin
  288. disk[1]:=chr(drive+64);
  289. disk[2]:=':';
  290. disk[3]:='\';
  291. disk[4]:=#0;
  292. end;
  293. if assigned(GetDiskFreeSpaceEx) then
  294. begin
  295. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  296. disksize:=qwtotal
  297. else
  298. disksize:=-1;
  299. end
  300. else
  301. begin
  302. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  303. disksize:=int64(total)*secs*bytes
  304. else
  305. disksize:=-1;
  306. end;
  307. end;
  308. Function GetCurrentDir : String;
  309. begin
  310. GetDir(0, result);
  311. end;
  312. Function SetCurrentDir (Const NewDir : String) : Boolean;
  313. begin
  314. {$I-}
  315. ChDir(NewDir);
  316. {$I+}
  317. result := (IOResult = 0);
  318. end;
  319. Function CreateDir (Const NewDir : String) : Boolean;
  320. begin
  321. {$I-}
  322. MkDir(NewDir);
  323. {$I+}
  324. result := (IOResult = 0);
  325. end;
  326. Function RemoveDir (Const Dir : String) : Boolean;
  327. begin
  328. {$I-}
  329. RmDir(Dir);
  330. {$I+}
  331. result := (IOResult = 0);
  332. end;
  333. {****************************************************************************
  334. Time Functions
  335. ****************************************************************************}
  336. Procedure GetLocalTime(var SystemTime: TSystemTime);
  337. Var
  338. Syst : Windows.TSystemtime;
  339. begin
  340. windows.Getlocaltime(@syst);
  341. SystemTime.year:=syst.wYear;
  342. SystemTime.month:=syst.wMonth;
  343. SystemTime.day:=syst.wDay;
  344. SystemTime.hour:=syst.wHour;
  345. SystemTime.minute:=syst.wMinute;
  346. SystemTime.second:=syst.wSecond;
  347. SystemTime.millisecond:=syst.wMilliSeconds;
  348. end;
  349. {****************************************************************************
  350. Misc Functions
  351. ****************************************************************************}
  352. procedure Beep;
  353. begin
  354. MessageBeep(0);
  355. end;
  356. {****************************************************************************
  357. Locale Functions
  358. ****************************************************************************}
  359. Procedure InitAnsi;
  360. Var
  361. i : longint;
  362. begin
  363. { Fill table entries 0 to 127 }
  364. for i := 0 to 96 do
  365. UpperCaseTable[i] := chr(i);
  366. for i := 97 to 122 do
  367. UpperCaseTable[i] := chr(i - 32);
  368. for i := 123 to 191 do
  369. UpperCaseTable[i] := chr(i);
  370. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  371. for i := 0 to 64 do
  372. LowerCaseTable[i] := chr(i);
  373. for i := 65 to 90 do
  374. LowerCaseTable[i] := chr(i + 32);
  375. for i := 91 to 191 do
  376. LowerCaseTable[i] := chr(i);
  377. Move (CPISO88591LCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  378. end;
  379. function GetLocaleStr(LID, LT: Longint; const Def: string): ShortString;
  380. var
  381. L: Integer;
  382. Buf: array[0..255] of Char;
  383. begin
  384. L := GetLocaleInfo(LID, LT, Buf, SizeOf(Buf));
  385. if L > 0 then
  386. SetString(Result, @Buf[0], L - 1)
  387. else
  388. Result := Def;
  389. end;
  390. function GetLocaleChar(LID, LT: Longint; Def: Char): Char;
  391. var
  392. Buf: array[0..1] of Char;
  393. begin
  394. if GetLocaleInfo(LID, LT, Buf, 2) > 0 then
  395. Result := Buf[0]
  396. else
  397. Result := Def;
  398. end;
  399. Function GetLocaleInt(LID,TP,Def: LongInt): LongInt;
  400. Var
  401. S: String;
  402. C: Integer;
  403. Begin
  404. S:=GetLocaleStr(LID,TP,'0');
  405. Val(S,Result,C);
  406. If C<>0 Then
  407. Result:=Def;
  408. End;
  409. procedure GetFormatSettings;
  410. var
  411. HF : Shortstring;
  412. LID : LCID;
  413. I,Day,DateOrder : longint;
  414. begin
  415. LID := GetThreadLocale;
  416. { Date stuff }
  417. for I := 1 to 12 do
  418. begin
  419. ShortMonthNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVMONTHNAME1+I-1,ShortMonthNames[i]);
  420. LongMonthNames[I]:=GetLocaleStr(LID,LOCALE_SMONTHNAME1+I-1,LongMonthNames[i]);
  421. end;
  422. for I := 1 to 7 do
  423. begin
  424. Day := (I + 5) mod 7;
  425. ShortDayNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVDAYNAME1+Day,ShortDayNames[i]);
  426. LongDayNames[I]:=GetLocaleStr(LID,LOCALE_SDAYNAME1+Day,LongDayNames[i]);
  427. end;
  428. DateSeparator := GetLocaleChar(LID, LOCALE_SDATE, '/');
  429. DateOrder := GetLocaleInt(LID, LOCALE_IDate, 0);
  430. Case DateOrder Of
  431. 1: Begin
  432. ShortDateFormat := 'dd/mm/yyyy';
  433. LongDateFormat := 'dddd, d. mmmm yyyy';
  434. End;
  435. 2: Begin
  436. ShortDateFormat := 'yyyy/mm/dd';
  437. LongDateFormat := 'dddd, yyyy mmmm d.';
  438. End;
  439. else
  440. // Default american settings...
  441. ShortDateFormat := 'mm/dd/yyyy';
  442. LongDateFormat := 'dddd, mmmm d. yyyy';
  443. End;
  444. { Time stuff }
  445. TimeSeparator := GetLocaleChar(LID, LOCALE_STIME, ':');
  446. TimeAMString := GetLocaleStr(LID, LOCALE_S1159, 'AM');
  447. TimePMString := GetLocaleStr(LID, LOCALE_S2359, 'PM');
  448. if StrToIntDef(GetLocaleStr(LID, LOCALE_ITLZERO, '0'), 0) = 0 then
  449. HF:='h'
  450. else
  451. HF:='hh';
  452. // No support for 12 hour stuff at the moment...
  453. ShortTimeFormat := HF+':nn';
  454. LongTimeFormat := HF + ':nn:ss';
  455. { Currency stuff }
  456. CurrencyString:=GetLocaleStr(LID, LOCALE_SCURRENCY, '');
  457. CurrencyFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRENCY, '0'), 0);
  458. NegCurrFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_INEGCURR, '0'), 0);
  459. { Number stuff }
  460. ThousandSeparator:=GetLocaleChar(LID, LOCALE_STHOUSAND, ',');
  461. DecimalSeparator:=GetLocaleChar(LID, LOCALE_SDECIMAL, '.');
  462. CurrencyDecimals:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRDIGITS, '0'), 0);
  463. end;
  464. Procedure InitInternational;
  465. begin
  466. InitAnsi;
  467. GetFormatSettings;
  468. end;
  469. {****************************************************************************
  470. Target Dependent
  471. ****************************************************************************}
  472. function FormatMessageA(dwFlags : DWORD;
  473. lpSource : Pointer;
  474. dwMessageId : DWORD;
  475. dwLanguageId: DWORD;
  476. lpBuffer : PCHAR;
  477. nSize : DWORD;
  478. Arguments : Pointer): DWORD; external 'kernel32' name 'FormatMessageA';
  479. function SysErrorMessage(ErrorCode: Integer): String;
  480. const
  481. MaxMsgSize = Format_Message_Max_Width_Mask;
  482. var
  483. MsgBuffer: pChar;
  484. begin
  485. GetMem(MsgBuffer, MaxMsgSize);
  486. FillChar(MsgBuffer^, MaxMsgSize, #0);
  487. FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
  488. nil,
  489. ErrorCode,
  490. MakeLangId(LANG_NEUTRAL, SUBLANG_DEFAULT),
  491. MsgBuffer, { This function allocs the memory }
  492. MaxMsgSize, { Maximum message size }
  493. nil);
  494. SysErrorMessage := StrPas(MsgBuffer);
  495. FreeMem(MsgBuffer, MaxMsgSize);
  496. end;
  497. {****************************************************************************
  498. Initialization code
  499. ****************************************************************************}
  500. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  501. var
  502. s : string;
  503. i : longint;
  504. hp,p : pchar;
  505. begin
  506. Result:='';
  507. p:=GetEnvironmentStrings;
  508. hp:=p;
  509. while hp^<>#0 do
  510. begin
  511. s:=strpas(hp);
  512. i:=pos('=',s);
  513. if upcase(copy(s,1,i-1))=upcase(envvar) then
  514. begin
  515. Result:=copy(s,i+1,length(s)-i);
  516. break;
  517. end;
  518. { next string entry}
  519. hp:=hp+strlen(hp)+1;
  520. end;
  521. FreeEnvironmentStrings(p);
  522. end;
  523. {****************************************************************************
  524. Initialization code
  525. ****************************************************************************}
  526. var
  527. versioninfo : OSVERSIONINFO;
  528. kernel32dll : THandle;
  529. function FreeLibrary(hLibModule : THANDLE) : longbool;
  530. external 'kernel32' name 'FreeLibrary';
  531. function GetVersionEx(var VersionInformation:OSVERSIONINFO) : longbool;
  532. external 'kernel32' name 'GetVersionExA';
  533. function LoadLibrary(lpLibFileName : pchar):THandle;
  534. external 'kernel32' name 'LoadLibraryA';
  535. function GetProcAddress(hModule : THandle;lpProcName : pchar) : pointer;
  536. external 'kernel32' name 'GetProcAddress';
  537. Initialization
  538. InitExceptions; { Initialize exceptions. OS independent }
  539. InitInternational; { Initialize internationalization settings }
  540. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  541. GetVersionEx(versioninfo);
  542. kernel32dll:=0;
  543. GetDiskFreeSpaceEx:=nil;
  544. Win32Platform:=versionInfo.dwPlatformId;
  545. if ((versioninfo.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS) and
  546. (versioninfo.dwBuildNUmber>=1000)) or
  547. (versioninfo.dwPlatformId=VER_PLATFORM_WIN32_NT) then
  548. begin
  549. kernel32dll:=LoadLibrary('kernel32');
  550. if kernel32dll<>0 then
  551. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  552. end;
  553. Finalization
  554. DoneExceptions;
  555. if kernel32dll<>0 then
  556. FreeLibrary(kernel32dll);
  557. end.
  558. {
  559. $Log$
  560. Revision 1.19 2003-01-03 20:41:04 peter
  561. * FileCreate(string,mode) overload added
  562. Revision 1.18 2003/01/01 20:56:57 florian
  563. + added invalid instruction exception
  564. Revision 1.17 2002/12/15 20:24:17 peter
  565. * some more C style functions
  566. Revision 1.16 2002/10/02 21:17:03 florian
  567. * we've to reimport TSystemTime time from the windows unit
  568. Revision 1.15 2002/09/07 16:01:29 peter
  569. * old logs removed and tabs fixed
  570. Revision 1.14 2002/05/09 08:28:23 carl
  571. * Merges from Fixes branch
  572. Revision 1.13 2002/03/24 19:26:49 marco
  573. * Added win32platform
  574. Revision 1.12 2002/01/25 16:23:04 peter
  575. * merged filesearch() fix
  576. }