home *** CD-ROM | disk | FTP | other *** search
/ Chip 1999 March / Chip_1999-03_cd.bin / zkuste / delphi / D234C13 / RALIB.ZIP / RALib / Lib / RAUtilsW.pas < prev    next >
Pascal/Delphi Source File  |  1998-12-25  |  40KB  |  1,388 lines

  1. {***********************************************************
  2.                 R&A Library
  3.        Copyright (C) 1996-98 R&A
  4.  
  5.        component   : none
  6.        description : Small routines
  7.  
  8.        programer   : black, white
  9.        e-mail      : blacknbs@chat.ru
  10.        www         : www.chat.ru\~blacknbs\ralib
  11. ************************************************************}
  12.  
  13. { You don't need include this unit into uses list in
  14.   normal delphi application. Use unit RAUtils, that are
  15.   automatically includes this unit. }
  16. { The one reason to using this unit directly is
  17.   developing non-VCL application, such as small console
  18.   program, so you don't want increase program size
  19.   with 'classes' and 'forms' units. }
  20. { This unit uses only headered units, such as Windows,
  21.   So including this unit to you uses list will increase
  22.   program size only with really used functions from this unit. }
  23.  
  24.  
  25. {$IFNDEF RAUTILS}
  26.  
  27. {$INCLUDE RA.INC}
  28.  
  29. unit RAUtilsW;
  30.  
  31. {╠εΣ≤δⁿ ∩≡ε±≥√⌡ ⌠≤φΩ÷ΦΘ}
  32.  
  33. {
  34.  ∞εΣ≤δⁿ φσ ±εΣσ≡µΦ≥ πδεßαδⁿφ√⌡ εß·σΩ≥εΓ Φ φσ Φ±∩εδⁿτ≤σ≥ ∞εΣ≤δΦ, ±εΣσ≡µα∙Φσ ≥αΩΦσ εß·σΩ≥√,
  35.  ∩≡Φ ∩εΣΩδ■≈σφΦΦ ²≥επε ∞εΣ≤δ  ß≤Σ≤≥ Φ±∩εδⁿτεΓαφ√ ≥εδⁿΩε φ≤µφ√σ ⌠≤φΩ÷ΦΦ Φ ∞εµφε
  36.  φσ ßσ±∩εΩεΦ≥ⁿ±  ε ßσ±∩εδστφε∞ ≤ΓσδΦ≈σφΦΦ Φ±∩εδφ σ∞επε ∞εΣ≤δ .
  37. }
  38.  
  39. interface
  40.  
  41. uses
  42.   Windows, SysUtils {$IFDEF RA_D3H}, ShlObj{$ENDIF};
  43.  
  44.   { φΦ ∩≡Φ ΩαΩΦ⌡ ≤±δεΓΦ ⌡ φσ ΣεßαΓδ ≥ⁿ Γ uses Forms, Controls, Graphics, FileCtrl Φ ≥.Σ.
  45.     ╘≤φΩ÷ΦΦ, Φ±∩εδⁿτ≤■∙Φσ ²≥Φ ∞εΣ≤δΦ ∩ε∞σ∙αΘ≥σ Γ RAUtils }
  46.  
  47.  {$DEFINE INTERFACE}
  48. {$ENDIF RAUTILS}
  49.  
  50. {$IFDEF INTERFACE}
  51.  
  52. {$IFNDEF RA_D4H}
  53. type
  54.   longword = integer;
  55. {$ENDIF}
  56.  
  57.  
  58.  {**** string handling routines - ±≥≡εΩεΓ√σ ⌠≤φΩ÷ΦΦ}
  59.  
  60. const
  61.   Separators : set of char = [#00,' ','-',#13, #10,'.',',','/','\',':','+','%','*','(',')',';','=','{','}','[',']'];
  62.  {const Separators Φ±∩εδⁿτ≤σ≥±  Γ ⌠≤φΩ÷Φ ⌡ GetWordOnPos, RAUtils.ReplaceSokr Φ SubWord}
  63.  
  64. {$IFDEF RA_D}
  65. type
  66.   TSetOfChar = set of char;
  67. {$ENDIF RA_D}
  68. {$IFDEF RA_B}
  69. type
  70.   TSetOfChar = string;
  71. {$ENDIF RA_B}
  72.  
  73.   { GetWordOnPos returns word from string, S,
  74.     on the cursor position, P}
  75.  
  76.   function GetWordOnPos(const S : string; const P : integer) : string;
  77.  
  78.   { GetWordOnPos working like GetWordOn function, but
  79.     also returns word position in iBeg, iEnd variables }
  80.  
  81.   function GetWordOnPosEx(const S : string; const P : integer; var iBeg, iEnd : integer) : string;
  82.  
  83.   { SubStr returns substring from string, S,
  84.     separated with Separator string}
  85.  
  86.   function SubStr(const S : string; const index : integer; const Separator : string) : string;
  87.  
  88.   { SubStrEnd same to previous function but index numerated
  89.     from the end of string }
  90.  
  91.   function SubStrEnd(const S : string; const index : integer; const Separator : string) : string;
  92.  
  93.   { SubWord returns next word from string, P, and
  94.     offsets pointer to the end of word, P2 }
  95.  
  96.   function SubWord(P : PChar; var P2 : PChar) : string;
  97.  
  98.   { NumberByWord returns the text representation of
  99.     the number, N, in normal russian language.
  100.     Was typed from Monitor magazine }
  101.  
  102.   function NumberByWord(const N : longint): string;
  103.  
  104.  
  105. //  function CurrencyByWord(Value : Currency) : string;
  106.  
  107.   { GetLineByPos returns the Line number, there
  108.     the symbol Pos is pointed.
  109.     Lines separated with #13 symbol }
  110.  
  111.   function GetLineByPos(const S : string; const Pos : integer) : integer;
  112.  
  113.   { GetXYByPos is same to previous function, but
  114.     returns X position in line too}
  115.  
  116.   procedure GetXYByPos(const S : string; const Pos : integer; var X, Y : integer);
  117.  
  118.   { ReplaceSokr1 searches for all substrings, Word,
  119.     in a string, S, and replaces them with Frase }
  120.  
  121.   function ReplaceSokr1(S : string; const Word, Frase : string) : string;
  122.  
  123.   { ConcatSep concatenate S and S2 strings with Separator.
  124.     if S = '', separator don't included }
  125.  
  126.   function ConcatSep(const S, S2, Separator : string) : string;
  127.  
  128.   { ConcatLeftSep is same to previous function, but
  129.     strings concatenate right to left }
  130.  
  131.   function ConcatLeftSep(const S, S2, Separator : string) : string;
  132.  
  133.   { MinimizeString trunactes long string, S, and appends
  134.     '...' symbols, if length of S is more than MaxLen }
  135.  
  136.   function MinimizeString(const S : string; const MaxLen : integer) : string;
  137.  
  138.   { Next 4 function for russian chars transliterating.
  139.     This functions are needed because Oem2Ansi and Ansi2Oem functions
  140.     sometimes works sucks }
  141.  
  142.   procedure Dos2Win(var S : string);
  143.   procedure Win2Dos(var S : string);
  144.   function Dos2WinRes(const S : string) : string;
  145.   function Win2DosRes(const S : string) : string;
  146.  
  147.   { Spaces returns string consists on N space chars }
  148.  
  149.   function Spaces(const N : integer) : string;
  150.  
  151.   { AddSpaces add spaces to string, S, if it length is smaller than N }
  152.  
  153.   function AddSpaces(const S : string; const N : integer) : string;
  154.  
  155.   { function LastDate for russian users only }
  156.   { ┬ετΓ≡α∙ασ≥ ε∩Φ±αφΦσ Σα≥√ ε≥φε±Φ≥σδⁿφε ≥σΩ≤∙σΘ φα∩≡Φ∞σ≡: 'ΣΓα Σφ  φαταΣ' }
  157.  
  158.   function LastDate(const Dat : TDateTime) : string;
  159.  
  160.   { CurrencyToStr format currency, Cur, using ffCurrency float format}
  161.  
  162.   function CurrencyToStr(const Cur : currency): string;
  163.  
  164.   { Cmp compares two strings and returns true if they
  165.     are equal. Case-insensitive.}
  166.  
  167.   function Cmp(const S1, S2 : string) : boolean;
  168.  
  169.   { StringCat add S2 string to S1 and returns this string }
  170.  
  171.   function StringCat(var S1 : string; S2 : string) : string;
  172.  
  173.   { HasChar returns true, if char, Ch, contains in string, S }
  174.  
  175.   function HasChar(const Ch : Char; const S : string) : boolean;
  176.  
  177.   function HasAnyChar(const Chars : string; const S : string) : boolean;
  178.  
  179.   function CharInSet(const Ch : Char; const SetOfChar : TSetOfChar) : boolean;
  180.  
  181.  {#### string handling routines - ±≥≡εΩεΓ√σ ⌠≤φΩ÷ΦΦ}
  182.  
  183.  
  184.  {**** files routines - ⌠αΘδεΓ√σ ⌠≤φΩ÷ΦΦ}
  185.  
  186.   { GetWinDir returns Windows folder name }
  187.  
  188.   function GetWinDir : TFileName;
  189.  
  190.   { GetTempDir returns Windows temporary folder name }
  191.  
  192.   function GetTempDir : string;
  193.  
  194.   { GenTempFileName returns temporary file name on
  195.     drive, there FileName is placed }
  196.  
  197.   function GenTempFileName(FileName : string) : string;
  198.  
  199.   { GenTempFileNameExt same to previous function, but
  200.     returning filename has given extension, FileExt }
  201.  
  202.   function GenTempFileNameExt(FileName : string; const FileExt : string) : string;
  203.  
  204.   { ClearDir clears folder Dir }
  205.  
  206.   function ClearDir(const Dir : string) : boolean;
  207.  
  208.   { DeleteDir clears and than delete folder Dir }
  209.  
  210.   function DeleteDir(const Dir : string) : boolean;
  211.  
  212.   { FileEquMask returns true if file, FileName,
  213.     is compatible with given dos file mask, Mask }
  214.  
  215.   function FileEquMask(FileName, Mask : TFileName) : boolean;
  216.  
  217.   { FileEquMasks returns true if file, FileName,
  218.     is compatible with given Masks.
  219.     Masks must be separated with comma (';') }
  220.  
  221.   function FileEquMasks(FileName, Masks : TFileName) : boolean;
  222.  
  223.  
  224.   procedure DeleteFiles(const Folder : TFileName; const Masks : string);
  225.  
  226.   { LZFileExpand expand file, FileSource,
  227.     into FileDest. Given file must be compressed, used MS Compress program }
  228.  
  229.   function LZFileExpand(const FileSource, FileDest : string) : boolean;
  230.  
  231.   { FileGetInfo fills SearchRec record for specified file attributes}
  232.  
  233.   function FileGetInfo(FileName : TFileName; var SearchRec : TSearchRec) : boolean;
  234.  
  235.   { HasSubFolder returns true, if folder APath contains other folders }
  236.  
  237.   function HasSubFolder(APath : TFileName) : boolean;
  238.  
  239.   { IsEmptyFolder returns true, if there are no files or
  240.     folders in given folder, APath}
  241.  
  242.   function IsEmptyFolder(APath : TFileName) : boolean;
  243.  
  244.   { AddSlash add slash char to Dir parameter, if needed }
  245.  
  246.   procedure AddSlash(var Dir : TFileName);
  247.  
  248.   { AddSlash returns string with added slash char to Dir parameter, if needed }
  249.  
  250.   function AddSlash2(const Dir : TFileName) : string;
  251.  
  252.   { AddPath returns FileName with Path, if FileName not contain any path }
  253.  
  254.   function AddPath(const FileName, Path : TFileName) : TFileName;
  255.  
  256.  {$IFNDEF RA_B1}
  257.  
  258.   { BrowseForFolder displays Browse For Folder dialog }
  259.  
  260.   function BrowseForFolder(const Handle : HWnd; const Title : string; var Folder : string) : boolean;
  261.  
  262.  {$ENDIF RA_B1}
  263.  
  264.   { DeleteReadOnlyFile clears R/O file attribute and delete file }
  265.  
  266.   function DeleteReadOnlyFile(const FileName : TFileName) : boolean;
  267.  
  268.   { HasParam returns true, if program running with
  269.     specified parameter, Param }
  270.  
  271.   function HasParam(const Param : string) : boolean;
  272.  
  273.   function HasSwitch(const Param : string) : boolean;
  274.   function Switch(const Param : string) : string;
  275.  
  276.   { ExePath returns ExtractFilePath(ParamStr(0)) }
  277.  
  278.   function ExePath : TFileName;
  279.  
  280.  {#### files routines - ⌠αΘδεΓ√σ ⌠≤φΩ÷ΦΦ}
  281.  
  282.  
  283.  {**** Graphic routines - π≡α⌠Φ≈σ±ΩΦσ ⌠≤φΩ÷ΦΦ}
  284.  
  285.   { TTFontSelected returns true, if True Type font
  286.     is selected in specified device context }
  287.  
  288.   function TTFontSelected(const DC : HDC) : boolean;
  289.  
  290.   { TrueInflateRect inflates rect in other
  291.     method, than InflateRect API function }
  292.  
  293.   function TrueInflateRect(const R : TRect; const I : integer) : TRect;
  294.  
  295.  {#### Graphic routines - π≡α⌠Φ≈σ±ΩΦσ ⌠≤φΩ÷ΦΦ}
  296.  
  297.  
  298.  
  299.  {**** Windows routines - εΩεφφ√σ ⌠≤φΩ÷ΦΦ}
  300.  
  301.   { SetWindowTop put window to top without recreating window }
  302.  
  303.   procedure SetWindowTop(const Handle : HWND; const Top : boolean);
  304.  
  305.  {#### Windows routines - εΩεφφ√σ ⌠≤φΩ÷ΦΦ}
  306.  
  307.  
  308.  
  309.  {**** other routines - ∩≡ε≈Φσ ⌠≤φΩ÷ΦΦ}
  310.  
  311.   { KeyPressed returns true, if Key VK is now pressed }
  312.  
  313.   function KeyPressed(VK : integer) : boolean;
  314.  
  315.   { functions Max and Min not need comments }
  316.  
  317.   function Max(x, y :integer):integer;
  318.  
  319.   function Min(x, y :integer):integer;
  320.  
  321.   function IntPower(Base, Exponent : integer) : integer;
  322.   
  323.   procedure ChangeTopException(E : Exception);
  324.  
  325.   function MakeValidFileName(const FileName : TFileName;
  326.     const ReplaceBadChar : Char) : TFileName;
  327.  {#### other routines - ∩≡ε≈Φσ ⌠≤φΩ÷ΦΦ}
  328.  
  329.  
  330.  
  331.  {$IFDEF RA_D2} 
  332.  
  333. { AnsiStrLIComp compares S1 to S2, without case-sensitivity, up to a maximum
  334.   length of MaxLen bytes. The compare operation is controlled by the
  335.   current Windows locale. The return value is the same as for CompareStr. }
  336.  
  337.   function AnsiStrLIComp(S1, S2: PChar; MaxLen: Cardinal): Integer;
  338.  
  339.  {$ENDIF RA_D2}
  340.  
  341.  
  342.  { following functions are not documented
  343.    because they are don't work properly sometimes,
  344.    so don't use them }
  345.  
  346.   { GetSubStr is full equal to SubStr function
  347.     - only for compatibility - don't use }
  348.   { GetSubStr - ≤±≥α≡σΓ°α , Φ±∩εδⁿτ≤Θ≥σ SubStr }
  349.  
  350.   function GetSubStr(const S : string; const index : integer; const Separator : Char) : string;
  351.  
  352.   function GetParameter : string;
  353.   function GetLongFileName(FileName : string) : string;
  354.   {* from unit FileCtrl}
  355.   function DirectoryExists(const Name: string): Boolean;
  356.   procedure ForceDirectories(Dir: string);
  357.   {# from unit FileCtrl}
  358.   function FileNewExt(const FileName, NewExt : TFileName) : TFileName;
  359.   function GetComputerID : string;
  360.  
  361. {$ENDIF INTERFACE}
  362.  
  363. {$IFNDEF RAUTILS}
  364. implementation
  365.  {$DEFINE IMPLEMENTATION}
  366. {$ENDIF RAUTILS}
  367.  
  368.  
  369. {$IFDEF IMPLEMENTATION}
  370.  
  371. function GetLineByPos(const S : string; const Pos : integer) : integer;
  372. var
  373.   i : integer;
  374. begin
  375.   if Length(S) < Pos then Result := -1
  376.   else begin
  377.     i := 0;
  378.     Result := 0;
  379.     while (i <= Pos) do begin
  380.       if S[i] = #13 then inc(Result);
  381.       inc(i);
  382.     end;
  383.   end;
  384. end;
  385.  
  386. procedure GetXYByPos(const S : string; const Pos : integer; var X, Y : integer);
  387. {ΓετΓ≡α∙ασ≥ ∩ε ΦφΣσΩ±≤ Pos - φε∞σ≡≤ ±Φ∞Γεδα - σπε Ωεε≡ΣΦφα≥√}
  388. var
  389.   i, iB : integer;
  390. begin
  391.   X := -1; Y := -1; iB := 0;
  392.   if (Length(S) >= Pos) and (Pos >= 0) then begin
  393.     i := 1;
  394.     Y := 0;
  395.     while (i <= Pos) do begin
  396.       if S[i] = #13 then begin inc(Y); iB := i+1 end;
  397.       inc(i);
  398.     end;
  399.     X := Pos - iB;
  400.   end;
  401. end;
  402.  
  403. function GetWordOnPos(const S : string; const P : integer) : string;
  404. var
  405.   i, Beg : integer;
  406. begin
  407.   Result := '';
  408.   if (P > Length(S)) or (P < 1) then exit;
  409.   for i := P downto 1 do
  410.     if S[i] in Separators then break;
  411.   Beg := i + 1;
  412.   for i := P to Length(S) do
  413.     if S[i] in Separators then break;
  414.   if i > Beg then
  415.     Result := Copy(S, Beg, i-Beg) else
  416.     Result := S[P];
  417. end;
  418.  
  419. function GetWordOnPosEx(const S : string; const P : integer; var iBeg, iEnd : integer) : string;
  420. begin
  421.   Result := '';
  422.   if (P > Length(S)) or (P < 1) then exit;
  423.   iBeg := P;
  424.   if (S[P] in Separators) and ((P < 1) or (S[P-1] in Separators)) then inc(iBeg);
  425.   while iBeg >= 1 do
  426.     if S[iBeg] in Separators then break else dec(iBeg);
  427.   inc(iBeg);
  428.   iEnd := P;
  429.   while iEnd <= Length(S) do
  430.     if S[iEnd] in Separators then break else inc(iEnd);
  431.   if iEnd > iBeg then
  432.     Result := Copy(S, iBeg, iEnd - iBeg) else
  433.     Result := S[P];
  434. end;
  435.  
  436. function GetWinDir : TFileName;
  437. var
  438.   WinDir  : array[0..MAX_PATH] of char;
  439. begin
  440.   WinDir[GetWindowsDirectory(WinDir, MAX_PATH)] := #0;
  441.   Result := WinDir;
  442. end;
  443.  
  444. function GenTempFileName(FileName : string) : string;
  445. {⌠≤φΩ÷Φ  πσφσ≡Φ≡≤σ≥ Φ∞  Σδ  Γ≡σ∞σφφεπε ⌠αΘδα φα ≥ε∞ µσ ΣΦ±Ωσ, πΣσ Φ ⌠αΘδ FileName
  446.  σ±δΦ ΣΦ±Ω φσ Φ∞σσ≥ τφα≈σφΦ  ∞εµφε ∩σ≡σΣα≥ⁿ FileName = ''}
  447. var
  448.   TempDir  : array[0..MAX_PATH] of char;
  449.   TempFile : array[0..MAX_PATH] of char;
  450.   STempDir : TFileName;
  451.   Res : integer;
  452. begin
  453.   TempDir[GetTempPath(260, TempDir)] := #0;
  454.   if FileName <> '' then begin
  455.     if Length(FileName) < 4 then FileName := ExpandFileName(FileName);
  456.     if (Length(FileName) > 4) and (FileName[2] = ':')
  457.         and (StrLen(@TempDir[0]) > 4)
  458.         and (ANSICompareText(TempDir[0], FileName[1]) <> 0)
  459.     then begin
  460.       STempDir := ExtractFilePath(FileName);
  461.       Move(STempDir[1], TempDir, Length(STempDir)+1);
  462.     end;
  463.   end;
  464.   Res := GetTempFileName(
  465.     TempDir, { address of directory name for temporary file}
  466.     '~RA',   { address of filename prefix}
  467.     0,       { number used to create temporary filename}
  468.     TempFile { address of buffer that receives the new filename}
  469.    );
  470.   if Res <> 0 then Result := TempFile else Result := '~R&ATemp.tmp';
  471.   DeleteFile(Result);
  472. end;
  473.  
  474. function GenTempFileNameExt(FileName : string; const FileExt : string) : string;
  475. begin
  476.   Result := ChangeFileExt(GenTempFileName(FileName), FileExt);
  477. end;
  478.  
  479. function GetTempDir : string;
  480. var
  481.   TempDir  : array[0..MAX_PATH] of char;
  482. begin
  483.   TempDir[GetTempPath(260, TempDir)] := #0;
  484.   Result := TempDir;
  485. end;
  486.  
  487. function ClearDir(const Dir : string) : boolean;
  488. var
  489.   SearchRec : TSearchRec;
  490.   DosError  : integer;
  491.   Path : TFileName;
  492. begin
  493.   Result := false;
  494.   Path := Dir;
  495.   AddSlash(Path);
  496.   DosError := FindFirst(Path+'*.*', faAnyFile, SearchRec);
  497.   while DosError = 0 do
  498.   begin
  499.     if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
  500.     begin
  501.       if ((SearchRec.Attr and faDirectory) = faDirectory)then
  502.         Result := DeleteDir(Path+SearchRec.Name)
  503.       else
  504.         Result := DeleteFile(Path+SearchRec.Name);
  505.       if not Result then exit;
  506.     end;
  507.     DosError := FindNext(SearchRec);
  508.   end;
  509.   FindClose(SearchRec);
  510. end;
  511.  
  512. function DeleteDir(const Dir : string) : boolean;
  513. begin
  514.   ClearDir(Dir);
  515. {  if Dir[Length(Dir)] = '\' then Dir[Length(Dir)] := #0;}
  516.   Result := RemoveDir(Dir);
  517. end;
  518.  
  519. procedure DeleteFiles(const Folder : TFileName; const Masks : string);
  520. var
  521.   SearchRec : TSearchRec;
  522.   DosError  : integer;
  523.   Path : TFileName;
  524. begin
  525.   Path := AddSlash2(Folder);
  526.   DosError := FindFirst(Path + '*.*', faAnyFile and not faDirectory, SearchRec);
  527.   while DosError = 0 do
  528.   begin
  529.     if FileEquMasks(Path + SearchRec.Name, Masks) then
  530.       DeleteFile(Path + SearchRec.Name);
  531.     DosError := FindNext(SearchRec);
  532.   end;
  533.   FindClose(SearchRec);
  534. end;
  535.  
  536.  
  537. {┬ετΓ≡α∙ασ≥ ∩α≡α∞σ≥≡ Ωε∞αφΣφεΘ ±≥≡εΩΦ ΩαΩ ΣδΦφφεσ Φ∞  ⌠αΘδα}
  538. function GetParameter : string;
  539. var
  540.   FN, FN1 : PChar;
  541. begin
  542.   if ParamCount = 0 then begin Result := ''; exit end;
  543.   FN := cmdLine;
  544.   if FN[0] = '"' then begin
  545.     FN := StrScan(FN+1, '"');
  546.     if (FN[0] = #00) or (FN[1] = #00)
  547.     then Result := ''
  548.     else begin
  549.       inc(FN, 2);
  550.       if FN[0] = '"' then begin
  551.         inc(FN, 1);
  552.         FN1 := StrScan(FN+1, '"');
  553.         if FN1[0] <> #00 then FN1[0] := #00;
  554.       end;
  555.       Result := FN;
  556.     end;
  557.   end else Result := Copy(CmdLine, Length(ParamStr(0))+1, 260);{═σ ≡αßε≥ασ≥ Σδ  ΣδΦφφ√⌡ Φ∞σφ ± ∩≡εßσδα∞Φ}
  558.   while (Length(Result)>0) and (Result[1] = ' ') do Delete(Result, 1, 1);
  559.   if FileExists(Result) then
  560.     Result := GetLongFileName(Result);
  561. end;
  562.  
  563.  
  564. function GetLongFileName(FileName : string) : string;
  565. var
  566.   SearchRec : TSearchRec;
  567. begin
  568.   if FileGetInfo(FileName, SearchRec) then
  569.     Result := ExtractFilePath(ExpandFileName(FileName))+SearchRec.FindData.cFileName
  570.   else
  571.     Result := FileName;
  572. end;
  573.  
  574. {∩≡εΓσ≡ σ≥ ∩εΣ⌡εΣΦ≥ δΦ ∞α±Ωα Mask Ω Φ∞σφΦ ⌠αΘδα FN}
  575. function FileEquMask(FileName, Mask : TFileName) : boolean;
  576. var
  577.   i : integer;
  578.   C : char;
  579.   P : PChar;
  580. begin
  581.   FileName := ANSIUpperCase(ExtractFileName(FileName));
  582.   Mask := ANSIUpperCase(Mask);
  583.   Result := false;
  584.   if Pos('.', FileName) = 0 then FileName := FileName+'.';
  585.   i := 1; P := PChar(FileName);
  586.   while (i <= length(Mask)) do begin
  587.     C := Mask[i];
  588.     if (P[0] = #0) and (C <> '*') then exit;
  589.     case C of
  590.       '*' :
  591.         if i = length(Mask) then begin
  592.           Result := true;
  593.           exit;
  594.         end else begin
  595.           P := StrScan(P, Mask[i+1]);
  596.           if P = nil then exit;
  597.         end;
  598.       '?' : inc(P);
  599.       else if C = P[0] then inc(P) else exit;
  600.     end;
  601.     inc(i);
  602.   end;
  603.   if P[0] = #0 then Result := true;
  604. end;
  605.  
  606. function FileEquMasks(FileName, Masks : TFileName) : boolean;
  607. var
  608.   i : integer;
  609.   Mask : string;
  610. begin
  611.   Result := false;
  612.   i := 0;
  613.   Mask := Trim(GetSubStr(Masks, i, ';'));
  614.   while Length(Mask) <> 0 do
  615.     if FileEquMask(FileName, Mask) then begin
  616.       Result := true;
  617.       break;
  618.     end else begin
  619.       inc(i);
  620.       Mask := Trim(GetSubStr(Masks, i, ';'));
  621.     end;
  622. end;
  623.  
  624. function NumberByWord(const N : longint): string;
  625. const
  626.   Ten : array[0..9] of string = ('φεδⁿ',  'εΣΦφ',  'ΣΓα',    '≥≡Φ', '≈σ≥√≡σ',
  627.                                  '∩ ≥ⁿ', '°σ±≥ⁿ', '±σ∞ⁿ', 'Γε±σ∞ⁿ', 'ΣσΓ ≥ⁿ');
  628.   Hun : array[1..9] of string = ('±≥ε', 'ΣΓσ±≥Φ', '≥≡Φ±≥α', '≈σ≥√≡σ±≥α', '∩ ≥ⁿ±ε≥',
  629.                                  '°σ±≥ⁿ±ε≥', '±σ∞ⁿ±ε≥', 'Γε±σ∞ⁿ±ε≥', 'ΣσΓ ≥ⁿ±ε≥');
  630.   OnTen : array[10..19] of string = ('Σσ± ≥ⁿ', 'εΣΦφφαΣ÷α≥ⁿ', 'ΣΓσφαΣ÷α≥ⁿ', '≥≡ΦφαΣ÷α≥ⁿ',
  631.                                      '≈σ≥√≡φαΣ÷α≥ⁿ', '∩ ≥φαΣ÷α≥ⁿ', '°σ±≥φαΣ÷α≥ⁿ',
  632.                                      '±σ∞φαΣ÷α≥ⁿ', 'Γε±σ∞φαΣ÷α≥ⁿ', 'ΣσΓ ≥φαΣ÷α≥ⁿ');
  633.   HunIn : array[2..9] of string = ('ΣΓαΣ÷α≥ⁿ', '≥≡ΦΣ÷α≥ⁿ', '±ε≡εΩ', '∩ ≥ⁿΣσ± ≥',
  634.                                    '°σ±≥ⁿΣσ± ≥', '±σ∞ⁿΣσ± ≥', 'Γε±σ∞ⁿΣσ± ≥', 'ΣσΓ φε±≥ε');
  635.  
  636. var
  637.   StrVsp  : string;
  638.   NumStr  : string;
  639.   StrVsp2 : string;
  640.   i       : byte;
  641.  
  642.   function IndNumber(Stri : string; Place : byte) : byte;
  643.   begin
  644.     IndNumber := Ord(Stri[Place]) - 48;
  645.   end;
  646.  
  647.   function Back(Stri : string) : longint;
  648.   var
  649.     code : integer;
  650.     LI   : longint;
  651.   begin
  652.     Result := 0;
  653.     Val(Stri, LI, code);
  654.     if (code = 0) then Result := LI;
  655.   end;
  656.  
  657. begin
  658.   NumStr := IntToStr(N);
  659.   if (Length(NumStr) > 9) then begin
  660.     Result := '*****';
  661.     Exit;
  662.   end;
  663.   case Length(NumStr) of
  664.     1 : StrVsp := Ten[N];
  665.     2 : case NumStr[1] of
  666.           '1'      :   StrVsp := OnTen[N];
  667.           '0'      :   StrVsp := NumberByWord(IndNumber(NumStr, 2));
  668.           '2'..'9' : begin
  669.             StrVsp := HunIn[IndNumber(NumStr, 1)];
  670.             if NumStr[2] <> '0' then
  671.               StrVsp := StrVsp + ' ' + NumberByWord(IndNumber(NumStr, 2));
  672.           end;
  673.         end;
  674.     3 : begin
  675.           StrVsp := Hun[IndNumber(NumStr, 1)];
  676.           StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 2, 2)));
  677.         end;
  678.     4 : begin
  679.           StrVsp := Ten[IndNumber(NumStr, 1)];
  680.           case NumStr[1] of
  681.             '1'      : StrVsp := 'εΣφα ≥√± ≈α';
  682.             '2'      : StrVsp := 'ΣΓσ ≥√± ≈Φ';
  683.             '3', '4' : StrVsp := StrVsp + ' ≥√± ≈Φ';
  684.             '5'..'9' : StrVsp := StrVsp + ' ≥√± ≈';
  685.           end;
  686.           StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 2, 3)));
  687.         end;
  688.     5 : begin
  689.           StrVsp2 := NumberByWord(Back(Copy(NumStr, 1, 2)));
  690.           i := Pos(' ΣΓα', StrVsp2);
  691.           if (Pos(' ΣΓα', StrVsp2) = i) then i := 0;
  692.           if (i <> 0) then StrVsp2[i+3] := 'e';
  693.           i := Pos(' εΣΦφ', StrVsp2);
  694.           if (Pos(' εΣΦφφ', StrVsp2) = i) then i := 0;
  695.           if (i <> 0) then begin
  696.             StrVsp2[i+3] := 'φ';
  697.             StrVsp2[i+4] := 'α';
  698.           end;
  699.           if NumStr[1] <> '1' then case NumStr[2] of
  700.             '1'      : StrVsp := ' ≥√± ≈α ';
  701.             '2'..'4' : StrVsp := ' ≥√± ≈Φ ';
  702.             '5'..'9' : StrVsp := ' ≥√± ≈ ';
  703.           end else StrVsp := ' ≥√± ≈ ';
  704.           StrVsp := StrVsp2 + StrVsp + NumberByWord(Back(Copy(NumStr, 3, 3)));
  705.         end;
  706.     6 : begin
  707.           StrVsp2 :=NumberByWord(Back(Copy(NumStr, 1, 3)));
  708.           i := Pos(' ΣΓα', StrVsp2);
  709.           if (Pos(' ΣΓαΣ', StrVsp2) = i) then i := 0;
  710.           if (i <> 0) then StrVsp2[i+3] := 'σ';
  711.           i := Pos(' εΣΦφ', Strvsp2);
  712.           if (Pos(' εΣΦφφ', StrVsp2) = i) then i := 0;
  713.           if (i <> 0) then begin
  714.             StrVsp2[i+3] := 'φ';
  715.             StrVsp2[i+4] := 'α';
  716.           end;
  717.           if NumStr[2] <> '1' then case numStr[3] of
  718.             '1'      : StrVsp := ' ≥√± ≈α ';
  719.             '2'..'4' : StrVsp := ' ≥√± ≈Φ ';
  720.             '5'..'9' : StrVsp := ' ≥√± ≈ ';
  721.           end else StrVsp := ' ≥√± ≈ ';
  722.           StrVsp := StrVsp2 + StrVsp + NumberByWord(Back(Copy(NumStr, 4, 3)));
  723.         end;
  724.     7 : begin
  725.           StrVsp := Ten[IndNumber(NumStr, 1)];
  726.           case NumStr[1] of
  727.             '1'      : StrVsp := 'εΣΦφ ∞ΦδδΦεφ';
  728.             '2'..'4' : StrVsp := StrVsp + ' ∞ΦδδΦεφα';
  729.             '5'..'9' : StrVsp := StrVsp + ' ∞ΦδδΦεφεΓ';
  730.           end;
  731.           StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 2, 6)));
  732.         end;
  733.     8 : begin
  734.           StrVsp := NumberByWord(Back(Copy(NumStr, 1, 2)));
  735.           StrVsp := StrVsp + ' ∞ΦδδΦεφ';
  736.           if (NumStr[1] <> '1') then case NumStr[2] of
  737.             '2'..'4'     : StrVsp := StrVsp + 'α';
  738.             '0','5'..'9' : StrVsp := StrVsp + 'εΓ';
  739.           end else StrVsp := StrVsp + 'εΓ';
  740.           StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 3, 6)));
  741.         end;
  742.     9 : begin
  743.           StrVsp := NumberByWord(Back(Copy(Numstr, 1, 3)));
  744.           StrVsp := StrVsp + ' ∞ΦδδΦεφ';
  745.           if (NumStr[2] <> '1') then case NumStr[3] of
  746.             '2'..'4'      : StrVsp := StrVsp + 'α';
  747.             '0', '5'..'9' : StrVsp := StrVsp + 'εΓ';
  748.           end else StrVsp := StrVsp + 'εΓ';
  749.           StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 4, 6)));
  750.         end;
  751.   end;
  752.   if ((Length(StrVsp) > 4) and (Copy(StrVsp, Length(StrVsp)-3, 4) = Ten[0])) then
  753.     StrVsp := Copy(StrVsp, 1, Length(StrVsp) - 4);
  754.   Result := StrVsp;
  755. end;
  756.  
  757. {
  758. function CurrencyByWord(Value : Currency) : string;
  759. var
  760.  Int : longint;
  761.  SInt : string;
  762.  L : integer;
  763. begin
  764.   Int := Trunc(Value);
  765.   Result := NumberByWord(Int);
  766.   Result[1] := AnsiUpperCase(Result[1]);
  767.   SInt := IntToStr(Int);
  768.   L := Length(SInt);
  769.   if SInt[L] = '1' then
  770.     if (L > 1) and (SInt[L-1] = '1') then
  771.       R := '≡≤ßδⁿ'
  772.       
  773. end;
  774. }
  775.  
  776. function GetSubStr(const S : string; const index : integer; const Separator : Char) : string;
  777. begin
  778.   Result := SubStr(S, index, Separator);
  779. end;
  780.  
  781. (*
  782. function SubStr(const S : string; const index : integer; const Separator : Char) : string;
  783.  {┬√≡στασ≥ ∩εΣ±≥≡εΩ≤. ╧εΣ±≥≡εΩΦ ≡ατΣσδ ■≥±  ±Φ∞Γεδε∞ Sep}
  784. var
  785.   i : integer;
  786.   pB, pE : PChar;
  787. begin
  788.   Result := '';
  789.   if (index < 0) or ((index = 0) and (Length(S) > 0) and (S[1] = Separator)) then exit;
  790.   pB := PChar(S);
  791.   for i := 1 to index do begin
  792.     pB := StrScan(pB, Separator);
  793.     if pB = nil then exit;
  794.     pB := pB+1;
  795.   end;
  796.   pE := StrScan(pB+1, Separator);
  797.   if pE = nil then pE := PChar(S)+Length(S);
  798.   SetString(Result, pB, pE-pB);
  799. end;*)
  800.  
  801. function SubStr(const S : string; const index : integer; const Separator : string) : string;
  802.  {┬√≡στασ≥ ∩εΣ±≥≡εΩ≤. ╧εΣ±≥≡εΩΦ ≡ατΣσδ ■≥±  ±Φ∞Γεδε∞ Sep}
  803. var
  804.   i : integer;
  805.   pB, pE : PChar;
  806. begin
  807.   Result := '';
  808.   if (index < 0) or ((index = 0) and (Length(S) > 0) and (S[1] = Separator)) then exit;
  809.   pB := PChar(S);
  810.   for i := 1 to index do begin
  811.     pB := StrPos(pB, PChar(Separator));
  812.     if pB = nil then exit;
  813.     pB := pB+Length(Separator);
  814.   end;
  815.   pE := StrPos(pB+1, PChar(Separator));
  816.   if pE = nil then pE := PChar(S)+Length(S);
  817.   if not (ANSIStrLIComp(pB, PChar(Separator), Length(Separator)) = 0) then
  818.     SetString(Result, pB, pE-pB);
  819. end;
  820.  
  821. function SubStrEnd(const S : string; const index : integer; const Separator : string) : string;
  822.  {≥ε µσ ≈≥ε Φ SubStr, φε ∩εΣ±≥≡εΩΦ φ≤∞σ≡≤■≥±  ± Ωεφ÷α}
  823. var
  824.   MaxIndex : integer;
  825.   pB : PChar;
  826. begin
  827.  {Γ≡σ∞σφφα  ≡σαδΦτα÷Φ  - φσε∩≥Φ∞αδⁿφα }
  828.   MaxIndex := 0;
  829.   pB := StrPos(PChar(S), PChar(Separator));
  830.   while pB <> nil do begin
  831.     inc(MaxIndex);
  832.     pB := StrPos(pB+Length(Separator), PChar(Separator));
  833.   end;
  834.   Result := SubStr(S, MaxIndex - index, Separator);
  835. end;
  836.  
  837. function FileGetInfo(FileName : TFileName; var SearchRec : TSearchRec) : boolean;
  838. var
  839.   DosError  : integer;
  840.   Path : TFileName;
  841. begin
  842.   Result := false;
  843.   Path := ExtractFilePath(ExpandFileName(FileName))+'*.*';
  844.   FileName := ANSIUpperCase(ExtractFileName(FileName));
  845.   DosError := FindFirst(Path, faAnyFile, SearchRec);
  846.   while DosError = 0 do begin
  847.     if (ANSICompareText(SearchRec.FindData.cFileName, FileName) = 0)
  848.     or (ANSICompareText(SearchRec.FindData.cAlternateFileName, FileName) = 0)
  849.     then begin
  850.       Result := true;
  851.       break;
  852.     end;
  853.     DosError := FindNext(SearchRec);
  854.   end;
  855.   FindClose(SearchRec);
  856. end;
  857.  
  858. function HasSubFolder(APath : TFileName) : boolean;
  859. var
  860.   SearchRec : TSearchRec;
  861.   DosError  : integer;
  862. begin
  863.   Result := false;
  864.   AddSlash(APath);
  865.   APath := Concat(APath, '*.*');
  866.   DosError := FindFirst(APath, faDirectory, SearchRec);
  867.   while DosError = 0 do begin
  868.     if (SearchRec.Attr and faDirectory = faDirectory) and (SearchRec.Name[1] <> '.') then begin
  869.       Result := true;
  870.       break;
  871.     end;
  872.     DosError := FindNext(SearchRec);
  873.   end;
  874.   FindClose(SearchRec);
  875. end;
  876.  
  877. function IsEmptyFolder(APath : TFileName) : boolean;
  878. var
  879.   SearchRec : TSearchRec;
  880.   DosError  : integer;
  881. begin
  882.   Result := true;
  883.   AddSlash(APath);
  884.   APath := Concat(APath, '*.*');
  885.   DosError := FindFirst(APath, faDirectory, SearchRec);
  886.   while DosError = 0 do begin
  887.     if SearchRec.Name[1] <> '.' then begin
  888.       Result := false;
  889.       break;
  890.     end;
  891.     DosError := FindNext(SearchRec);
  892.   end;
  893.   FindClose(SearchRec);
  894. end;
  895.  
  896. function TTFontSelected(const DC : HDC) : boolean;
  897. var
  898.   TM : TTEXTMETRIC;
  899. begin
  900.   GetTextMetrics(DC, TM);
  901.   Result := TM.tmPitchAndFamily and TMPF_TRUETYPE <> 0;
  902. end;
  903.  
  904. function SubWord(P : PChar; var P2 : PChar) : string;
  905. {ΓετΓ≡α∙ασ≥ ±δεΓε}
  906. var
  907.   i : integer;
  908. begin
  909.   i := 0;
  910.   while not (P[i] in Separators) do inc(i);
  911.   SetString(Result, P, i);
  912.   P2 := P+i;
  913. end;
  914.  
  915. function ReplaceSokr1(S : string; const Word, Frase : string) : string;
  916. var
  917.   LW : integer;
  918.   P : PChar;
  919.   Sm : integer;
  920. begin
  921.   LW := Length(Word);
  922.   P := StrPos(PChar(S), PChar(Word));
  923.   while P <> nil do begin
  924.     Sm := P-PChar(S);
  925.     S := Copy(S, 1, Sm)+Frase+Copy(S, Sm+LW+1, Length(S));
  926.     P := StrPos(PChar(S)+Sm+Length(Frase), PChar(Word));
  927.   end;
  928.   Result := S;
  929. end;
  930.  
  931. function ConcatSep(const S, S2, Separator : string) : string;
  932. begin
  933.   Result := S;
  934.   if Result <> '' then Result := Result + Separator;
  935.   Result := Result + S2;
  936. end;
  937.  
  938. function ConcatLeftSep(const S, S2, Separator : string) : string;
  939. begin
  940.   Result := S;
  941.   if Result <> '' then Result := Separator + Result;
  942.   Result := S2 + Result;
  943. end;
  944.  
  945. function MinimizeString(const S : string; const MaxLen : integer) : string;
  946. begin
  947.   if Length(S) > MaxLen then
  948.     if MaxLen < 3 then
  949.       Result := Copy(S, 1, MaxLen)
  950.     else
  951.       Result := Copy(S, 1, MaxLen-3) + '...'
  952.   else
  953.     Result := S;
  954. end;
  955.  
  956. function TrueInflateRect(const R : TRect; const I : integer) : TRect;
  957. begin
  958.   with R do SetRect(Result, Left - I, Top - I, Right + I, Bottom + I);
  959. end;
  960.  
  961. procedure SetWindowTop(const Handle : HWND; const Top : boolean);
  962. const
  963.   TopFlag : array[boolean] of longword = (HWND_NOTOPMOST, HWND_TOPMOST);
  964. begin
  965.   SetWindowPos(Handle, TopFlag[Top], 0, 0, 0, 0, SWP_NOMOVE or
  966.     SWP_NOSIZE or SWP_NOACTIVATE);
  967. end;
  968.  
  969. {* from unit FileCtrl}
  970.  
  971. function DirectoryExists(const Name: string): Boolean;
  972. var
  973.   Code: integer;
  974. begin
  975.   Code := GetFileAttributes(PChar(Name));
  976.   Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
  977. end;
  978.  
  979. procedure ForceDirectories(Dir: string);
  980. begin
  981.   if Dir[Length(Dir)] = '\' then
  982.     Delete(Dir, Length(Dir), 1);
  983.   if (Length(Dir) < 3) or DirectoryExists(Dir)
  984.     or (ExtractFilePath(Dir) = Dir) then Exit; { avoid 'xyz:\' problem.}
  985.   ForceDirectories(ExtractFilePath(Dir));
  986.   CreateDir(Dir);
  987. end;
  988.  
  989. {# from unit FileCtrl}
  990.  
  991. function LZFileExpand(const FileSource, FileDest : string) : boolean;
  992. type
  993.   TLZCopy     = function (Source, Dest: Integer): Longint; stdcall;
  994.   TLZOpenFile = function (Filename: PChar; var ReOpenBuff: TOFStruct; Style: Word): Integer; stdcall;
  995.   TLZClose    = procedure (hFile: Integer); stdcall;
  996. var
  997.   Source, Dest : integer;
  998.   OSSource, OSDest : TOFSTRUCT;
  999.   Res : integer;
  1000.   Ins : integer;
  1001.   LZCopy     : TLZCopy;
  1002.   LZOpenFile : TLZOpenFile;
  1003.   LZClose    : TLZClose;
  1004. begin
  1005.   Result := false;
  1006.   Ins := LoadLibrary('LZ32.dll');
  1007.   try
  1008.     LZCopy     := GetProcAddress(Ins, 'LZCopy');
  1009.     LZOpenFile := GetProcAddress(Ins, 'LZOpenFileA');
  1010.     LZClose    := GetProcAddress(Ins, 'LZClose');
  1011.     OSSource.cBytes := sizeof(TOFSTRUCT);
  1012.     OSDest.cBytes := sizeof(TOFSTRUCT);
  1013.     Source := LZOpenFile(
  1014.       PChar(FileSource), // address of name of file to be opened
  1015.       OSSource, // address of open file structure
  1016.       OF_READ or OF_SHARE_DENY_NONE// action to take
  1017.      );
  1018.     if Source < 0 then begin
  1019.       DeleteFile(FileDest);
  1020.       Dest := LZOpenFile(
  1021.         PChar(FileDest), // address of name of file to be opened
  1022.         OSDest, // address of open file structure
  1023.         OF_CREATE or OF_WRITE or OF_SHARE_EXCLUSIVE// action to take
  1024.        );
  1025.       if Dest >= 0 then begin
  1026.         Res := LZCopy(Source, Dest);
  1027.         if Res >= 0 then Result := true;
  1028.       end;
  1029.       LZClose(Source);
  1030.       LZClose(Dest);
  1031.     end;
  1032.   finally
  1033.     FreeLibrary(Ins);
  1034.   end;
  1035. end;
  1036.  
  1037. procedure Dos2Win(var S : string);
  1038. var
  1039.   i : integer;
  1040. begin
  1041.   for i := 1 to Length(S) do
  1042.     case S[i] of
  1043.       #$80..#$AF : S[i] := char(byte(S[i])+(192-$80));
  1044.       #$E0..#$EF : S[i] := char(byte(S[i])+(240-$E0));
  1045.     end;
  1046. end;
  1047.  
  1048. procedure Win2Dos(var S : string);
  1049. var
  1050.   i : integer;
  1051. begin
  1052.   for i := 1 to Length(S) do
  1053.     case S[i] of
  1054.       '└'..'∩' : S[i] := char(byte(S[i])-(192-$80));
  1055.       '≡'..' ' : S[i] := char(byte(S[i])-(240-$E0));
  1056.     end;
  1057. end;
  1058.  
  1059. function Dos2WinRes(const S : string) : string;
  1060. begin
  1061.   Result := S;
  1062.   Dos2Win(Result);
  1063. end;
  1064.  
  1065. function Win2DosRes(const S : string) : string;
  1066. begin
  1067.   Result := S;
  1068.   Win2Dos(Result);
  1069. end;
  1070.  
  1071.  
  1072. function Spaces(const N : integer) : string;
  1073. var
  1074.   i : integer;
  1075. begin
  1076.   Result := '';
  1077.   for i := 1 to N do Result := Result+' ';
  1078. end;
  1079.  
  1080. function AddSpaces(const S : string; const N : integer) : string;
  1081. begin
  1082.   Result := S;
  1083.   while Length(Result) < N do Result := Result+' ';
  1084. end;
  1085.  
  1086. function KeyPressed(VK : integer) : boolean;
  1087. begin
  1088.   Result := GetKeyState(VK) and $8000 = $8000;
  1089. end;
  1090.  
  1091. {$IFNDEF RA_B1}
  1092. function BrowseForFolder(const Handle : HWnd; const Title : string; var Folder : string) : boolean;
  1093. {$IFDEF RA_D2}
  1094. type
  1095.   TSHItemID = packed record           { mkid }
  1096.     cb: Word;                         { Size of the ID (including cb itself) }
  1097.     abID: array[0..0] of Byte;        { The item ID (variable length) }
  1098.   end;
  1099.   PItemIDList = ^TItemIDList;
  1100.   TItemIDList = packed record         { idl }
  1101.      mkid: TSHItemID;
  1102.    end;
  1103.   TFNBFFCallBack = function(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer stdcall;
  1104.   TBrowseInfo = packed record
  1105.     hwndOwner: HWND;
  1106.     pidlRoot: PItemIDList;
  1107.     pszDisplayName: PAnsiChar;  { Return display name of item selected. }
  1108.     lpszTitle: PAnsiChar;      { text to go in the banner over the tree. }
  1109.     ulFlags: UINT;           { Flags that control the return stuff }
  1110.     lpfn: TFNBFFCallBack;
  1111.     lParam: LPARAM;          { extra info that's passed back in callbacks }
  1112.     iImage: Integer;         { output var: where to return the Image index. }
  1113.   end;
  1114.   function SHBrowseForFolder(var lpbi: TBrowseInfo): PItemIDList; stdcall; external 'shell32.dll' name 'SHBrowseForFolderA';
  1115.   function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL; stdcall external 'shell32.dll' name 'SHGetPathFromIDListA';
  1116. {$ENDIF}
  1117. var
  1118.   browseinfo : TBrowseinfo;
  1119.   Id : PItemIDList;
  1120.   FN : array[0..MAX_PATH] of char;
  1121. begin
  1122.   with browseinfo do begin
  1123.     hwndOwner := Handle;
  1124.     pidlRoot  := nil;
  1125.     pszDisplayName := FN;
  1126.     lpszTitle := PChar(Title);
  1127.     ulFlags := 0;
  1128.     lpfn := nil;
  1129.   end;
  1130.   Id := SHBrowseForFolder(browseinfo);
  1131.   Result := Id <> nil;
  1132.   if Result then begin
  1133.     SHGetPathFromIDList(Id, FN);
  1134.     Folder := FN;
  1135.   end;
  1136. end;
  1137. {$ENDIF RA_B1}
  1138.  
  1139. function LastDate(const Dat : TDateTime) : string;
  1140. const
  1141.   D2D : array [0..9] of 1..3 = (3, 1, 2, 2, 2, 3, 3, 3, 3, 3);
  1142.   Day   : array [1..3] of string = ('Σσφⁿ', 'Σφ ', 'ΣφσΘ');
  1143.   Month : array [1..3] of string = ('∞σ± ÷', '∞σ± ÷α', '∞σ± ÷σΓ');
  1144.   Year  : array [1..3] of string = ('πεΣ', 'πεΣα', 'δσ≥');
  1145.   Week  : array [1..4] of string = ('φσΣσδ■', '2 φσΣσδΦ', '3 φσΣσδΦ', '∞σ± ÷');
  1146. var
  1147.   Y, M, D : integer;
  1148. begin
  1149.   if Date = Dat then Result := '±σπεΣφ '
  1150.   else if Dat = Date - 1 then Result := 'Γ≈σ≡α'
  1151.   else if Dat = Date - 2 then Result := '∩εταΓ≈σ≡α'
  1152.   else if Dat > Date then Result := 'Γ ß≤Σ≤∙σ∞'
  1153.   else begin
  1154.     D := Trunc(Date - Dat);
  1155.     Y := Round(D / 365);
  1156.     M := Round(D / 30);
  1157.     if Y > 0 then
  1158.       Result := IntToStr(Y)+' '+Year[D2D[StrToInt(IntToStr(Y)[Length(IntToStr(Y))])]]+' φαταΣ'
  1159.     else if M > 0 then
  1160.       Result := IntToStr(M)+' '+Month[D2D[StrToInt(IntToStr(M)[Length(IntToStr(M))])]]+' φαταΣ'
  1161.     else if D > 6 then
  1162.       Result := Week[D div 7]+' φαταΣ'
  1163.     else if D > 0 then
  1164.       Result := IntToStr(D)+' '+Day[D2D[StrToInt(IntToStr(D)[Length(IntToStr(D))])]]+' φαταΣ'
  1165.   end;
  1166. end;
  1167.  
  1168. procedure AddSlash(var Dir : TFileName);
  1169. begin
  1170.   if (Length(Dir) > 0) and (Dir[Length(Dir)] <> '\') then
  1171.     Dir := Dir +'\';
  1172. end;
  1173.  
  1174. function AddSlash2(const Dir : TFileName) : string;
  1175. begin
  1176.   Result := Dir;
  1177.   if (Length(Dir) > 0) and (Dir[Length(Dir)] <> '\') then
  1178.     Result := Dir +'\';
  1179. end;
  1180.  
  1181. function AddPath(const FileName, Path : TFileName) : TFileName;
  1182. begin
  1183.   if ExtractFileDrive(FileName) = '' then
  1184.     Result := Path + FileName
  1185.   else
  1186.     Result := FileName;
  1187. end;
  1188.  
  1189.  
  1190. function GetComputerID : string;
  1191. var
  1192.   SN  : DWORD;
  1193.   Nul : DWORD;
  1194.   WinDir  : array[0..MAX_PATH] of char;
  1195. begin
  1196.   GetWindowsDirectory(WinDir, MAX_PATH);
  1197.   WinDir[3] := #0;
  1198.   if GetVolumeInformation(
  1199.     WinDir,   // address of root directory of the file system
  1200.     nil,   // address of name of the volume
  1201.     0,     // length of lpVolumeNameBuffer
  1202.     @SN,    // address of volume serial number
  1203.     Nul,   // address of system's maximum filename length
  1204.     Nul,   // address of file system flags
  1205.     nil,   // address of name of file system
  1206.     0      // length of lpFileSystemNameBuffer
  1207.    )
  1208.   then
  1209.     Result := IntToHex(SN, 8)
  1210.   else
  1211.     Result := 'None';
  1212. end;
  1213.  
  1214. function CurrencyToStr(const Cur : currency): string;
  1215. begin
  1216.   Result := CurrToStrF(Cur, ffCurrency, CurrencyDecimals)
  1217. end;
  1218.  
  1219. function Cmp(const S1, S2 : string) : boolean;
  1220. begin
  1221.   Result := ANSICompareText(S1, S2) = 0;
  1222. end;
  1223.  
  1224. function StringCat(var S1 : string; S2 : string) : string;
  1225. begin
  1226.   S1 := S1 + S2;
  1227.   Result := S1;
  1228. end;
  1229.  
  1230. function HasChar(const Ch : Char; const S : string) : boolean;
  1231. begin
  1232.   Result := Pos(Ch, S) > 0;
  1233. end;
  1234.  
  1235. function HasAnyChar(const Chars : string; const S : string) : boolean;
  1236. var
  1237.   i : integer;
  1238. begin
  1239.   for i := 1 to Length(Chars) do
  1240.     if HasChar(Chars[i], S) then
  1241.     begin
  1242.       Result := true;
  1243.       exit;
  1244.     end;
  1245.   Result := false;
  1246. end;
  1247.  
  1248. function Max(x,y:integer):integer;
  1249. begin
  1250.   if x > y then Result := x else Result := y;
  1251. end;
  1252.  
  1253. function Min(x,y:integer):integer;
  1254. begin
  1255.   if x < y then Result := x else Result := y;
  1256. end;
  1257.  
  1258. function DeleteReadOnlyFile(const FileName : TFileName) : boolean;
  1259. begin
  1260.   FileSetAttr(FileName, 0); {clear Read Only Flag}
  1261.   Result := DeleteFile(FileName);
  1262. end;
  1263.  
  1264. function HasParam(const Param : string) : boolean;
  1265. var
  1266.   i : integer;
  1267. begin
  1268.   Result := false;
  1269.   for i := 1 to ParamCount do begin
  1270.     Result := Cmp(ParamStr(i), Param);
  1271.     if Result then exit;
  1272.   end;
  1273. end;
  1274.  
  1275. function HasSwitch(const Param : string) : boolean;
  1276. var
  1277.   i : integer;
  1278. begin
  1279.   Result := false;
  1280.   for i := 1 to ParamCount do
  1281.     if HasChar(ParamStr(i)[1], '-/') then
  1282.     begin
  1283.       Result := Cmp(Copy(ParamStr(i), 2, Length(Param)), Param);
  1284.       if Result then exit;
  1285.     end;
  1286. end;
  1287.  
  1288. function Switch(const Param : string) : string;
  1289. var
  1290.   i : integer;
  1291. begin
  1292.   Result := '';
  1293.   for i := 1 to ParamCount do
  1294.     if HasChar(ParamStr(i)[1], '-/\') and
  1295.        Cmp(Copy(ParamStr(i), 2, Length(Param)), Param) then
  1296.     begin
  1297.       Result := Copy(ParamStr(i), 2 + Length(Param), 260);
  1298.       exit;
  1299.     end;
  1300. end;
  1301.  
  1302. function ExePath : TFileName;
  1303. begin
  1304.   Result := ExtractFilePath(ParamStr(0));
  1305. end;
  1306.  
  1307. function FileNewExt(const FileName, NewExt : TFileName) : TFileName;
  1308. begin
  1309.   Result := Copy(FileName, 1, Length(FileName) - Length(ExtractFileExt(FileName))) + NewExt;
  1310. end;
  1311.  
  1312. {$IFDEF RA_D2}
  1313. function AnsiStrLIComp(S1, S2: PChar; MaxLen: Cardinal): Integer;
  1314. begin
  1315.   Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1316.     S1, MaxLen, S2, MaxLen) - 2;
  1317. end;
  1318. {$ENDIF RA_D2}
  1319.  
  1320. function CharInSet(const Ch : Char; const SetOfChar : TSetOfChar) : boolean;
  1321. begin
  1322. {$IFDEF RA_D}
  1323.   Result := Ch in SetOfChar;
  1324. {$ENDIF RA_D}
  1325. {$IFDEF RA_B}
  1326.   Result := Pos(Ch, SetOfChar) > 0;
  1327. {$ENDIF RA_B}
  1328. end;
  1329.  
  1330. function IntPower(Base, Exponent : integer) : integer;
  1331. begin
  1332.   if Exponent > 0 then
  1333.   begin
  1334.     Result := Base;
  1335.     dec(Exponent);
  1336.     while Exponent > 0 do
  1337.     begin
  1338.       Result := Result * Base;
  1339.       dec(Exponent);
  1340.     end;
  1341.   end else
  1342.   if Exponent < 0 then
  1343.   begin
  1344.     Result := 1;
  1345.     inc(Exponent);
  1346.     while Exponent < 0 do
  1347.     begin
  1348.       Result := Result div Base;
  1349.       inc(Exponent);
  1350.     end;
  1351.   end else
  1352.     Result := Base;
  1353. end;
  1354.  
  1355. procedure ChangeTopException(E : Exception);
  1356. type
  1357.   PRaiseFrame = ^TRaiseFrame;
  1358.   TRaiseFrame = record
  1359.     NextRaise: PRaiseFrame;
  1360.     ExceptAddr: Pointer;
  1361.     ExceptObject: TObject;
  1362.     ExceptionRecord: PExceptionRecord;
  1363.   end;
  1364. begin
  1365.   if RaiseList <> nil then
  1366.     PRaiseFrame(RaiseList)^.ExceptObject := E
  1367.   else
  1368.     raise Exception.Create('Not in exception');
  1369. end;
  1370.  
  1371. function MakeValidFileName(const FileName : TFileName;
  1372.     const ReplaceBadChar : Char) : TFileName;
  1373. var
  1374.   i : Integer;
  1375. begin
  1376.   Result := FileName;
  1377.   for i := 1 to Length(Result) do
  1378.     if HasChar(Result[i], '''":?*\/') then
  1379.       Result[i] := ReplaceBadChar;
  1380. end;
  1381.  
  1382. {$ENDIF IMPLEMENTATION}
  1383.  
  1384. {$IFNDEF RAUTILS}
  1385. end.
  1386. {$ENDIF RAUTILS}
  1387.  
  1388.