Componentes.Terceros.jvcl/official/3.32/archive/JvUtils.pas

3100 lines
86 KiB
ObjectPascal
Raw Blame History

{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvUtils.PAS, released on 2002-07-04.
The Initial Developers of the Original Code are: Andrei Prygounkov <a dott prygounkov att gmx dott de>
Roman Tkachev <whiteman@infa.ru>
Copyright (c) 1999, 2002 Andrei Prygounkov, Roman Tkachev
All Rights Reserved.
Contributor(s):
Last Modified: 2002-07-04
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.sourceforge.net
Description : common routines
Known Issues:
* Some functions are also in JvStrUtil
* Some russian comments were translated to english; these comments are marked
with [translated]
-----------------------------------------------------------------------------}
{$I JVCL.INC}
{$I WINDOWSONLY.INC}
unit JvUtils;
interface
{$DEFINE INCLUDE_RAUTILSW}
uses
Windows, Forms, Controls, Graphics, SysUtils, Classes,
StdCtrls, ExtCtrls, Dialogs, Menus, Clipbrd,
{$IFDEF COMPILER3_UP}
ShlObj,
{$ENDIF}
{$IFDEF COMPILER3_UP}
ActiveX,
{$ELSE}
Ole2,
{$ENDIF}
{$IFDEF COMPILER6_UP}
Variants,
{$ENDIF}
TypInfo;
{$IFNDEF COMPILER4_UP}
type
Longword = Integer;
{$ENDIF}
type
TTickCount = Cardinal;
{**** string handling routines}
const
Separators: set of Char = [#00, ' ', '-', #13, #10, '.', ',', '/', '\', '#', '"', '''',
':', '+', '%', '*', '(', ')', ';', '=', '{', '}', '[', ']', '{', '}', '<', '>'];
{const Separators is used in GetWordOnPos, JvUtils.ReplaceStrings and SubWord}
{$IFDEF DELPHI}
type
TSetOfChar = set of Char;
{$ENDIF DELPHI}
{$IFDEF BCB}
type
TSetOfChar = string;
{$ENDIF BCB}
{ GetWordOnPos returns Word from string, S, on the cursor position, P}
function GetWordOnPos(const S: string; const P: Integer): string;
{ GetWordOnPosEx working like GetWordOnPos function, but
also returns Word position in iBeg, iEnd variables }
function GetWordOnPosEx(const S: string; const P: Integer; var iBeg, iEnd: Integer): string;
{ SubStr returns substring from string, S, separated with Separator string}
function SubStr(const S: string; const Index: Integer; const Separator: string): string;
{ SubStrEnd same to previous function but Index numerated from the end of string }
function SubStrEnd(const S: string; const Index: Integer; const Separator: string): string;
{ SubWord returns next Word from string, P, and offsets Pointer to the end of Word, P2 }
function SubWord(P: PChar; var P2: PChar): string;
{ NumberByWord returns the text representation of
the number, N, in normal russian language. Was typed from Monitor magazine }
function NumberByWord(const N: Longint): string;
// function CurrencyByWord(Value : Currency) : string;
{ GetLineByPos returns the Line number, there
the symbol Pos is pointed. Lines separated with #13 symbol }
function GetLineByPos(const S: string; const Pos: Integer): Integer;
{ GetXYByPos is same to previous function, but returns X position in line too}
procedure GetXYByPos(const S: string; const Pos: Integer; var X, Y: Integer);
{ ReplaceString searches for all substrings, OldPattern,
in a string, S, and replaces them with NewPattern }
function ReplaceString(S: string; const OldPattern, NewPattern: string): string;
{ ConcatSep concatenate S and S2 strings with Separator.
if S = '', separator don't included }
function ConcatSep(const S, S2, Separator: string): string;
{ ConcatLeftSep is same to previous function, but
strings concatenate right to left }
function ConcatLeftSep(const S, S2, Separator: string): string;
{ MinimizeString trunactes long string, S, and appends
'...' symbols, if Length of S is more than MaxLen }
function MinimizeString(const S: string; const MaxLen: Integer): string;
{ Next 4 function for russian chars transliterating.
This functions are needed because Oem2Ansi and Ansi2Oem functions
sometimes works sucks }
procedure Dos2Win(var S: string);
procedure Win2Dos(var S: string);
function Dos2WinRes(const S: string): string;
function Win2DosRes(const S: string): string;
function Win2Koi(const S: string): string;
{ Spaces returns string consists on N space chars }
function Spaces(const N: Integer): string;
{ AddSpaces add spaces to string, S, if it Length is smaller than N }
function AddSpaces(const S: string; const N: Integer): string;
{ function LastDate for russian users only }
// { returns date relative to current date: '<27><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>' }
function LastDate(const Dat: TDateTime): string;
{ CurrencyToStr format currency, Cur, using ffCurrency float format}
function CurrencyToStr(const Cur: currency): string;
{ Cmp compares two strings and returns True if they
are equal. Case-insensitive.}
function Cmp(const S1, S2: string): Boolean;
{ StringCat add S2 string to S1 and returns this string }
function StringCat(var S1: string; S2: string): string;
{ HasChar returns True, if Char, Ch, contains in string, S }
function HasChar(const Ch: Char; const S: string): Boolean;
function HasAnyChar(const Chars: string; const S: string): Boolean;
function CharInSet(const Ch: Char; const SetOfChar: TSetOfChar): Boolean;
function CountOfChar(const Ch: Char; const S: string): Integer;
function DefStr(const S: string; Default: string): string;
{**** files routines}
{ GetWinDir returns Windows folder name }
function GetWinDir: TFileName;
{ GetTempDir returns Windows temporary folder name }
function GetTempDir: string;
{ GenTempFileName returns temporary file name on
drive, there FileName is placed }
function GenTempFileName(FileName: string): string;
{ GenTempFileNameExt same to previous function, but
returning filename has given extension, FileExt }
function GenTempFileNameExt(FileName: string; const FileExt: string): string;
{ ClearDir clears folder Dir }
function ClearDir(const Dir: string): Boolean;
{ DeleteDir clears and than delete folder Dir }
function DeleteDir(const Dir: string): Boolean;
{ FileEquMask returns True if file, FileName,
is compatible with given dos file mask, Mask }
function FileEquMask(FileName, Mask: TFileName): Boolean;
{ FileEquMasks returns True if file, FileName,
is compatible with given Masks.
Masks must be separated with comma (';') }
function FileEquMasks(FileName, Masks: TFileName): Boolean;
procedure DeleteFiles(const Folder: TFileName; const Masks: string);
{ LZFileExpand expand file, FileSource,
into FileDest. Given file must be compressed, using MS Compress program }
function LZFileExpand(const FileSource, FileDest: string): Boolean;
{ FileGetInfo fills SearchRec record for specified file attributes}
function FileGetInfo(FileName: TFileName; var SearchRec: TSearchRec): Boolean;
{ HasSubFolder returns True, if folder APath contains other folders }
function HasSubFolder(APath: TFileName): Boolean;
{ IsEmptyFolder returns True, if there are no files or
folders in given folder, APath}
function IsEmptyFolder(APath: TFileName): Boolean;
{ AddSlash add slash Char to Dir parameter, if needed }
procedure AddSlash(var Dir: TFileName);
{ AddSlash returns string with added slash Char to Dir parameter, if needed }
function AddSlash2(const Dir: TFileName): string;
{ AddPath returns FileName with Path, if FileName not contain any path }
function AddPath(const FileName, Path: TFileName): TFileName;
function AddPaths(const PathList, Path: string): string;
function ParentPath(const Path: TFileName): TFileName;
function FindInPath(const FileName, PathList: string): TFileName;
{$IFNDEF BCB1}
{ BrowseForFolder displays Browse For Folder dialog }
function BrowseForFolder(const Handle: HWND; const Title: string; var Folder: string): Boolean;
{$ENDIF BCB1}
{ DeleteReadOnlyFile clears R/O file attribute and delete file }
function DeleteReadOnlyFile(const FileName: TFileName): Boolean;
{ HasParam returns True, if program running with specified parameter, Param }
function HasParam(const Param: string): Boolean;
function HasSwitch(const Param: string): Boolean;
function Switch(const Param: string): string;
{ ExePath returns ExtractFilePath(ParamStr(0)) }
function ExePath: TFileName;
function CopyDir(const SourceDir, DestDir: TFileName): Boolean;
function FileTimeToDateTime(const FT: TFileTime): TDateTime;
function MakeValidFileName(const FileName: TFileName; const ReplaceBadChar: Char): TFileName;
{**** Graphic routines }
{ TTFontSelected returns True, if True Type font
is selected in specified device context }
function TTFontSelected(const DC: HDC): Boolean;
{ TrueInflateRect inflates rect in other method, than InflateRect API function }
function TrueInflateRect(const R: TRect; const I: Integer): TRect;
{**** Windows routines }
{ SetWindowTop put window to top without recreating window }
procedure SetWindowTop(const Handle: HWND; const Top: Boolean);
{**** other routines }
{ KeyPressed returns True, if Key VK is now pressed }
function KeyPressed(VK: Integer): Boolean;
procedure SwapInt(var Int1, Int2: Integer);
function IntPower(Base, Exponent: Integer): Integer;
function ChangeTopException(E: TObject): TObject;
function StrToBool(const S: string): Boolean;
{$IFNDEF COMPILER3_UP}
{ AnsiStrLIComp compares S1 to S2, without case-sensitivity, up to a maximum
Length of MaxLen bytes. The compare operation is controlled by the
current Windows locale. The return value is the same as for CompareStr. }
function AnsiStrLIComp(S1, S2: PChar; MaxLen: Cardinal): Integer;
function AnsiStrIComp(S1, S2: PChar): Integer;
{$ENDIF}
function Var2Type(V: Variant; const VarType: Integer): Variant;
function VarToInt(V: Variant): Integer;
function VarToFloat(V: Variant): Double;
{ following functions are not documented
because they are don't work properly sometimes, so don't use them }
function ReplaceStrings1(S: string; const Word, Frase: string): string;
{ ReplaceStrings1 is full equal to ReplaceString function
- only for compatibility - don't use }
{ GetSubStr is full equal to SubStr function
- only for compatibility - don't use }
function GetSubStr(const S: string; const Index: Integer; const Separator: Char): string;
function GetParameter: string;
function GetLongFileName(FileName: string): string;
{* from unit FileCtrl}
function DirectoryExists(const Name: string): Boolean;
procedure ForceDirectories(Dir: string);
{# from unit FileCtrl}
function FileNewExt(const FileName, NewExt: TFileName): TFileName;
function GetComputerID: string;
function GetComputerName: string;
{**** string routines }
{ ReplaceAllStrings searches for all substrings, Words,
in a string, S, and replaces them with Frases with the same Index.
Also see RAUtilsW.ReplaceStrings1 function }
function ReplaceAllStrings(S: string; Words, Frases: TStrings): string;
{ ReplaceStrings searches the Word in a string, S, on PosBeg position,
in the list, Words, and if founds, replaces this Word
with string from another list, Frases, with the same Index,
and then update NewSelStart variable }
function ReplaceStrings(S: string; PosBeg, Len: Integer; Words, Frases: TStrings; var NewSelStart: Integer): string;
{ CountOfLines calculates the lines count in a string, S,
each line must be separated from another with CrLf sequence }
function CountOfLines(const S: string): Integer;
{ DeleteEmptyLines deletes all empty lines from strings, Ss.
Lines contained only spaces also deletes. }
procedure DeleteEmptyLines(Ss: TStrings);
{ SQLAddWhere addes or modifies existing where-statement, where,
to the strings, SQL.
Note: If strings SQL allready contains where-statement,
it must be started on the begining of any line }
procedure SQLAddWhere(SQL: TStrings; const Where: string);
{**** files routines - }
{ ResSaveToFile save resource named as Name with Typ type into file FileName.
Resource can be compressed using MS Compress program}
function ResSaveToFile(const Typ, Name: string; const Compressed: Boolean; const FileName: string): Boolean;
function ResSaveToFileEx(Instance: HINST; Typ, Name: PChar;
const Compressed: Boolean; const FileName: string): Boolean;
function ResSaveToString(Instance: HINST; const Typ, Name: string;
var S: string): Boolean;
{ Execute executes other program and waiting for it
terminating, then return its Exit Code }
function Execute(const CommandLine, WorkingDirectory: string): Integer;
{ IniReadSection read section, Section, from ini-file,
IniFileName, into strings, Ss.
This function reads ALL strings from specified section.
Note: TIninFile.ReadSection function reads only strings with '=' symbol.}
function IniReadSection(const IniFileName: TFileName; const Section: string; Ss: TStrings): Boolean;
{ LoadTextFile load text file, FileName, into string }
function LoadTextFile(const FileName: TFileName): string;
procedure SaveTextFile(const FileName: TFileName; const Source: string);
{ ReadFolder reads files list from disk folder, Folder,
that are equal to mask, Mask, into strings, FileList}
function ReadFolder(const Folder, Mask: TFileName; FileList: TStrings): Integer;
function ReadFolders(const Folder: TFileName; FolderList: TStrings): Integer;
{$IFDEF COMPILER3_UP}
{ TargetFileName - if FileName is ShortCut returns filename ShortCut linked to }
function TargetFileName(const FileName: TFileName): TFileName;
{ return filename ShortCut linked to }
function ResolveLink(const hWnd: HWND; const LinkFile: TFileName;
var FileName: TFileName): HRESULT;
{$ENDIF COMPILER3_UP}
{**** Graphic routines - }
{ LoadIcoToImage loads two icons from resource named NameRes,
into two image lists ALarge and ASmall}
procedure LoadIcoToImage(ALarge, ASmall: TImageList; const NameRes: string);
{ RATextOut same with TCanvas.TextOut procedure, but
can clipping drawing with rectangle, RClip. }
procedure RATextOut(Canvas: TCanvas; const R, RClip: TRect; const S: string);
{ RATextOutEx same with RATextOut function, but
can calculate needed height for correct output }
function RATextOutEx(Canvas: TCanvas; const R, RClip: TRect; const S: string; const CalcHeight: Boolean): Integer;
{ RATextCalcHeight calculate needed height for
correct output, using RATextOut or RATextOutEx functions }
function RATextCalcHeight(Canvas: TCanvas; const R: TRect; const S: string): Integer;
{ Cinema draws some visual effect }
procedure Cinema(Canvas: TCanvas; rS {Source}, rD {Dest}: TRect);
{ Roughed fills rect with special 3D pattern }
procedure Roughed(ACanvas: TCanvas; const ARect: TRect; const AVert: Boolean);
{ BitmapFromBitmap creates new small bitmap from part
of source bitmap, SrcBitmap, with specified width and height,
AWidth, AHeight and placed on a specified Index, Index in the
source bitmap }
function BitmapFromBitmap(SrcBitmap: TBitmap; const AWidth, AHeight, Index: Integer): TBitmap;
{ TextWidth calculate text with for writing using standard desktop font }
function TextWidth(AStr: string): Integer;
{ DefineCursor load cursor from resource, and return
available cursor number, assigned to it }
function DefineCursor(Identifier: PChar): TCursor;
{**** other routines - }
{ FindFormByClass returns first form with specified
class, FormClass, owned by Application global variable }
function FindFormByClass(FormClass: TFormClass): TForm;
function FindFormByClassName(FormClassName: string): TForm;
{ FindByTag returns the control with specified class,
ComponentClass, from WinContol.Controls property,
having Tag property value, equaled to Tag parameter }
function FindByTag(WinControl: TWinControl; ComponentClass: TComponentClass; const Tag: Integer): TComponent;
{ ControlAtPos2 equal to TWinControl.ControlAtPos function,
but works better }
function ControlAtPos2(Parent: TWinControl; X, Y: Integer): TControl;
{ RBTag searches WinControl.Controls for checked
RadioButton and returns its Tag property value }
function RBTag(Parent: TWinControl): Integer;
{ AppMinimized returns True, if Application is minimized }
function AppMinimized: Boolean;
{ MessageBox is Application.MessageBox with string (not PChar) parameters.
if Caption parameter = '', it replaced with Application.Title }
function MessageBox(const Msg: string; Caption: string;
const Flags: Integer): Integer;
function MsgDlg2(const Msg, ACaption: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; HelpContext: Integer; Control: TWinControl): Integer;
function MsgDlgDef(const Msg, ACaption: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; DefButton: TMsgDlgBtn; HelpContext: Integer;
Control: TWinControl): Integer;
{ Delay stop program execution to MSec msec }
procedure Delay(MSec: Longword);
procedure CenterHor(Parent: TControl; MinLeft: Integer; Controls: array of TControl);
procedure EnableControls(Control: TWinControl; const Enable: Boolean);
procedure EnableMenuItems(MenuItem: TMenuItem; const Tag: Integer; const Enable: Boolean);
procedure ExpandWidth(Parent: TControl; MinWidth: Integer; Controls: array of TControl);
function PanelBorder(Panel: TCustomPanel): Integer;
function Pixels(Control: TControl; APixels: Integer): Integer;
procedure SetChildPropOrd(Owner: TComponent; PropName: string; Value: Longint);
procedure Error(const Msg: string);
procedure ItemHtDrawEx(Canvas: TCanvas; Rect: TRect;
const State: TOwnerDrawState; const Text: string;
const HideSelColor: Boolean; var PlainItem: string;
var Width: Integer; CalcWidth: Boolean);
{ example for Text parameter :
'Item 1 <b>bold</b> <i>italic ITALIC <c:Red>red <c:Green>green <c:blue>blue </i>' }
function ItemHtDraw(Canvas: TCanvas; Rect: TRect;
const State: TOwnerDrawState; const Text: string;
const HideSelColor: Boolean): string;
function ItemHtWidth(Canvas: TCanvas; Rect: TRect;
const State: TOwnerDrawState; const Text: string;
const HideSelColor: Boolean): Integer;
function ItemHtPlain(const Text: string): string;
{ ClearList - clears list of TObject }
procedure ClearList(List: TList);
procedure MemStreamToClipBoard(MemStream: TMemoryStream; const Format: Word);
procedure ClipBoardToMemStream(MemStream: TMemoryStream; const Format: Word);
{ RTTI support }
function GetPropType(Obj: TObject; const PropName: string): TTypeKind;
function GetPropStr(Obj: TObject; const PropName: string): string;
function GetPropOrd(Obj: TObject; const PropName: string): Integer;
function GetPropMethod(Obj: TObject; const PropName: string): TMethod;
procedure PrepareIniSection(SS: TStrings);
{ following functions are not documented because
they are don't work properly, so don't use them }
{$IFDEF COMPILER2}
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
{$ENDIF}
type
TMenuAnimation = (maNone, maRandom, maUnfold, maSlide);
procedure ShowMenu(Form: TForm; MenuAni: TMenuAnimation);
type
TProcObj = procedure of object;
procedure ExecAfterPause(Proc: TProcObj; Pause: Integer);
const
NoHelp = 0; { for MsgDlg2 }
MsgDlgCharSet: Integer = DEFAULT_CHARSET;
// (rom) from JvBandWindows to make it obsolete
function PointL(const X, Y: Longint): TPointL;
// (rom) from JvBandUtils to make it obsolete
function iif(const Test: Boolean; const ATrue, AFalse: Variant): Variant;
implementation
uses
Math,
JvCtlConst;
function GetLineByPos(const S: string; const Pos: Integer): Integer;
var
I: Integer;
begin
if Length(S) < Pos then
Result := -1
else
begin
I := 1;
Result := 0;
while I <= Pos do
begin
if S[I] = #13 then
Inc(Result);
Inc(I);
end;
end;
end;
procedure GetXYByPos(const S: string; const Pos: Integer; var X, Y: Integer);
var
I, iB: Integer;
begin
X := -1;
Y := -1;
iB := 0;
if (Length(S) >= Pos) and (Pos >= 0) then
begin
I := 1;
Y := 0;
while I <= Pos do
begin
if S[I] = #13 then
begin
Inc(Y);
iB := I + 1;
end;
Inc(I);
end;
X := Pos - iB;
end;
end;
function GetWordOnPos(const S: string; const P: Integer): string;
var
I, Beg: Integer;
begin
Result := '';
if (P > Length(S)) or (P < 1) then
Exit;
for I := P downto 1 do
if S[I] in Separators then
Break;
Beg := I + 1;
for I := P to Length(S) do
if S[I] in Separators then
Break;
if I > Beg then
Result := Copy(S, Beg, I - Beg)
else
Result := S[P];
end;
function GetWordOnPosEx(const S: string; const P: Integer; var iBeg, iEnd: Integer): string;
begin
Result := '';
if (P > Length(S)) or (P < 1) then
Exit;
iBeg := P;
if P > 1 then
if S[P] in Separators then
if (P < 1) or ((P - 1 > 0) and (S[P - 1] in Separators)) then
Inc(iBeg)
else
if not ((P - 1 > 0) and (S[P - 1] in Separators)) then
Dec(iBeg);
while iBeg >= 1 do
if S[iBeg] in Separators then
Break
else
Dec(iBeg);
Inc(iBeg);
iEnd := P;
while iEnd <= Length(S) do
if S[iEnd] in Separators then
Break
else
Inc(iEnd);
if iEnd > iBeg then
Result := Copy(S, iBeg, iEnd - iBeg)
else
Result := S[P];
end;
function GetWinDir: TFileName;
var
WinDir: array [0..MAX_PATH] of Char;
begin
WinDir[GetWindowsDirectory(WinDir, MAX_PATH)] := #0;
Result := WinDir;
end;
function GenTempFileName(FileName: string): string;
var
TempDir: array [0..MAX_PATH] of Char;
TempFile: array [0..MAX_PATH] of Char;
STempDir: TFileName;
Res: Integer;
begin
TempDir[GetTempPath(260, TempDir)] := #0;
if FileName <> '' then
begin
if Length(FileName) < 4 then
FileName := ExpandFileName(FileName);
if (Length(FileName) > 4) and (FileName[2] = ':') and
(StrLen(@TempDir[0]) > 4) and
(AnsiCompareText(TempDir[0], FileName[1]) <> 0) then
begin
STempDir := ExtractFilePath(FileName);
Move(STempDir[1], TempDir, Length(STempDir) + 1);
end;
end;
Res := GetTempFileName(
TempDir, { address of directory name for temporary file}
'~RA', { address of filename prefix}
0, { number used to create temporary filename}
TempFile); { address of buffer that receives the new filename}
if Res <> 0 then
Result := TempFile
else
Result := '~JVCLTemp.tmp';
DeleteFile(Result);
end;
function GenTempFileNameExt(FileName: string; const FileExt: string): string;
begin
Result := ChangeFileExt(GenTempFileName(FileName), FileExt);
end;
function GetTempDir: string;
var
TempDir: array [0..MAX_PATH] of Char;
begin
TempDir[GetTempPath(260, TempDir)] := #0;
Result := TempDir;
end;
function ClearDir(const Dir: string): Boolean;
var
SearchRec: TSearchRec;
DosError: Integer;
Path: TFileName;
begin
Result := True;
Path := Dir;
AddSlash(Path);
DosError := FindFirst(Path + '*.*', faAnyFile, SearchRec);
while DosError = 0 do
begin
if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
begin
if (SearchRec.Attr and faDirectory) = faDirectory then
Result := Result and DeleteDir(Path + SearchRec.Name)
else
Result := Result and DeleteFile(Path + SearchRec.Name);
// if not Result then Exit;
end;
DosError := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
function DeleteDir(const Dir: string): Boolean;
begin
ClearDir(Dir);
{ if Dir[Length(Dir)] = '\' then Dir[Length(Dir)] := #0;}
Result := RemoveDir(Dir);
end;
procedure DeleteFiles(const Folder: TFileName; const Masks: string);
var
SearchRec: TSearchRec;
DosError: Integer;
Path: TFileName;
begin
Path := AddSlash2(Folder);
DosError := FindFirst(Path + '*.*', faAnyFile and not faDirectory, SearchRec);
while DosError = 0 do
begin
if FileEquMasks(Path + SearchRec.Name, Masks) then
DeleteFile(Path + SearchRec.Name);
DosError := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
function GetParameter: string;
var
FN, FN1: PChar;
begin
if ParamCount = 0 then
begin
Result := '';
Exit
end;
FN := cmdLine;
if FN[0] = '"' then
begin
FN := StrScan(FN + 1, '"');
if (FN[0] = #00) or (FN[1] = #00) then
Result := ''
else
begin
Inc(FN, 2);
if FN[0] = '"' then
begin
Inc(FN, 1);
FN1 := StrScan(FN + 1, '"');
if FN1[0] <> #00 then
FN1[0] := #00;
end;
Result := FN;
end;
end
else
Result := Copy(CmdLine, Length(ParamStr(0)) + 1, 260);
while (Length(Result) > 0) and (Result[1] = ' ') do
Delete(Result, 1, 1);
Result := ReplaceString(Result, '"', '');
if FileExists(Result) then
Result := GetLongFileName(Result);
end;
function GetLongFileName(FileName: string): string;
var
SearchRec: TSearchRec;
begin
if FileGetInfo(FileName, SearchRec) then
Result := ExtractFilePath(ExpandFileName(FileName)) + SearchRec.FindData.cFileName
else
Result := FileName;
end;
function FileEquMask(FileName, Mask: TFileName): Boolean;
var
I: Integer;
C: Char;
P: PChar;
begin
FileName := AnsiUpperCase(ExtractFileName(FileName));
Mask := AnsiUpperCase(Mask);
Result := False;
if Pos('.', FileName) = 0 then
FileName := FileName + '.';
I := 1;
P := PChar(FileName);
while I <= Length(Mask) do
begin
C := Mask[I];
if (P[0] = #0) and (C <> '*') then
Exit;
case C of
'*':
if I = Length(Mask) then
begin
Result := True;
Exit;
end
else
begin
P := StrScan(P, Mask[I + 1]);
if P = nil then
Exit;
end;
'?':
Inc(P);
else
if C = P[0] then
Inc(P)
else
Exit;
end;
Inc(I);
end;
if P[0] = #0 then
Result := True;
end;
function FileEquMasks(FileName, Masks: TFileName): Boolean;
var
I: Integer;
Mask: string;
begin
Result := False;
I := 0;
Mask := Trim(GetSubStr(Masks, I, ';'));
while Length(Mask) <> 0 do
if FileEquMask(FileName, Mask) then
begin
Result := True;
Break;
end
else
begin
Inc(I);
Mask := Trim(GetSubStr(Masks, I, ';'));
end;
end;
function NumberByWord(const N: Longint): string;
const
Ten: array [0..9] of string =
('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
Hun: array [1..9] of string =
('onehundred', 'twohundred', 'threehundred', 'fourhundred', 'fivehundred',
'sixhundred', 'sevenhundred', 'eighthundred', 'ninehundred');
OnTen: array [10..19] of string =
('ten', 'eleven', 'twelve', 'thirteen', 'fourteen',
'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen');
HunIn: array [2..9] of string =
('twothousand', 'threethousand', 'fourthousand', 'fivethousand',
'sixthousand', 'seventhousand', 'eightthousand', 'ninethousand');
var
StrVsp: string;
NumStr: string;
StrVsp2: string;
I: Byte;
function IndNumber(Stri: string; Place: Byte): Byte;
begin
IndNumber := Ord(Stri[Place]) - 48;
end;
function Back(Stri: string): Longint;
var
Code: Integer;
LI: Longint;
begin
Result := 0;
Val(Stri, LI, Code);
if Code = 0 then
Result := LI;
end;
begin
NumStr := IntToStr(N);
if Length(NumStr) > 9 then
begin
Result := '*****';
Exit;
end;
case Length(NumStr) of
1:
StrVsp := Ten[N];
2: case NumStr[1] of
'1':
StrVsp := OnTen[N];
'0':
StrVsp := NumberByWord(IndNumber(NumStr, 2));
'2'..'9':
begin
StrVsp := HunIn[IndNumber(NumStr, 1)];
if NumStr[2] <> '0' then
StrVsp := StrVsp + ' ' + NumberByWord(IndNumber(NumStr, 2));
end;
end;
3:
begin
StrVsp := Hun[IndNumber(NumStr, 1)];
StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 2, 2)));
end;
4:
begin
StrVsp := Ten[IndNumber(NumStr, 1)];
// (rom) needs translation
case NumStr[1] of
'1':
StrVsp := '<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
'2':
StrVsp := '<27><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
'3', '4':
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
'5'..'9':
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD>';
end;
StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 2, 3)));
end;
5:
begin
StrVsp2 := NumberByWord(Back(Copy(NumStr, 1, 2)));
I := Pos(' <20><><EFBFBD>', StrVsp2);
if Pos(' <20><><EFBFBD>', StrVsp2) = I then
I := 0;
if I <> 0 then
StrVsp2[I + 3] := 'e';
I := Pos(' <20><><EFBFBD><EFBFBD>', StrVsp2);
if Pos(' <20><><EFBFBD><EFBFBD><EFBFBD>', StrVsp2) = I then
I := 0;
if I <> 0 then
begin
StrVsp2[I + 3] := '<27>';
StrVsp2[I + 4] := '<27>';
end;
if NumStr[1] <> '1' then
case NumStr[2] of
'1':
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ';
'2'..'4':
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ';
'5'..'9':
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD> ';
end
else
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD> ';
StrVsp := StrVsp2 + StrVsp + NumberByWord(Back(Copy(NumStr, 3, 3)));
end;
6:
begin
StrVsp2 := NumberByWord(Back(Copy(NumStr, 1, 3)));
I := Pos(' <20><><EFBFBD>', StrVsp2);
if Pos(' <20><><EFBFBD><EFBFBD>', StrVsp2) = I then
I := 0;
if I <> 0 then
StrVsp2[I + 3] := '<27>';
I := Pos(' <20><><EFBFBD><EFBFBD>', Strvsp2);
if Pos(' <20><><EFBFBD><EFBFBD><EFBFBD>', StrVsp2) = I then
I := 0;
if I <> 0 then
begin
StrVsp2[I + 3] := '<27>';
StrVsp2[I + 4] := '<27>';
end;
if NumStr[2] <> '1' then
case NumStr[3] of
'1':
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ';
'2'..'4':
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ';
'5'..'9':
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD> ';
end
else
StrVsp := ' <20><><EFBFBD><EFBFBD><EFBFBD> ';
StrVsp := StrVsp2 + StrVsp + NumberByWord(Back(Copy(NumStr, 4, 3)));
end;
7:
begin
StrVsp := Ten[IndNumber(NumStr, 1)];
case NumStr[1] of
'1':
StrVsp := '<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
'2'..'4':
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
'5'..'9':
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
end;
StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 2, 6)));
end;
8:
begin
StrVsp := NumberByWord(Back(Copy(NumStr, 1, 2)));
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
if NumStr[1] <> '1' then
case NumStr[2] of
'2'..'4':
StrVsp := StrVsp + '<27>';
'0', '5'..'9':
StrVsp := StrVsp + '<27><>';
end
else
StrVsp := StrVsp + '<27><>';
StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 3, 6)));
end;
9:
begin
StrVsp := NumberByWord(Back(Copy(Numstr, 1, 3)));
StrVsp := StrVsp + ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
if NumStr[2] <> '1' then
case NumStr[3] of
'2'..'4':
StrVsp := StrVsp + '<27>';
'0', '5'..'9':
StrVsp := StrVsp + '<27><>';
end
else
StrVsp := StrVsp + '<27><>';
StrVsp := StrVsp + ' ' + NumberByWord(Back(Copy(NumStr, 4, 6)));
end;
end;
if (Length(StrVsp) > 4) and (Copy(StrVsp, Length(StrVsp) - 3, 4) = Ten[0]) then
StrVsp := Copy(StrVsp, 1, Length(StrVsp) - 4);
Result := StrVsp;
end;
function GetSubStr(const S: string; const Index: Integer; const Separator: Char): string;
begin
Result := SubStr(S, Index, Separator);
end;
function SubStr(const S: string; const Index: Integer; const Separator: string): string;
{ Returns a substring. Substrings are divided by Sep character [translated] }
var
I: Integer;
pB, pE: PChar;
begin
Result := '';
if ((Index < 0) or ((Index = 0) and (Length(S) > 0) and (S[1] = Separator))) or
(Length(S) = 0) then
Exit;
pB := PChar(S);
for I := 1 to Index do
begin
pB := StrPos(pB, PChar(Separator));
if pB = nil then
Exit;
pB := pB + Length(Separator);
if pB[0] = #0 then
Exit;
end;
pE := StrPos(pB + 1, PChar(Separator));
if pE = nil then
pE := PChar(S) + Length(S);
if not (AnsiStrLIComp(pB, PChar(Separator), Length(Separator)) = 0) then
SetString(Result, pB, pE - pB);
end;
function SubStrEnd(const S: string; const Index: Integer; const Separator: string): string;
{ The same as SubStr, but substrings are numbered from the end [translated]}
var
MaxIndex: Integer;
pB: PChar;
begin
{ Not optimal implementation [translated] }
MaxIndex := 0;
pB := StrPos(PChar(S), PChar(Separator));
while pB <> nil do
begin
Inc(MaxIndex);
pB := StrPos(pB + Length(Separator), PChar(Separator));
end;
Result := SubStr(S, MaxIndex - Index, Separator);
end;
function FileGetInfo(FileName: TFileName; var SearchRec: TSearchRec): Boolean;
var
DosError: Integer;
Path: TFileName;
begin
Result := False;
Path := ExtractFilePath(ExpandFileName(FileName)) + '*.*';
FileName := AnsiUpperCase(ExtractFileName(FileName));
DosError := FindFirst(Path, faAnyFile, SearchRec);
while DosError = 0 do
begin
if (AnsiCompareText(SearchRec.FindData.cFileName, FileName) = 0) or
(AnsiCompareText(SearchRec.FindData.cAlternateFileName, FileName) = 0) then
begin
Result := True;
Break;
end;
DosError := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
function HasSubFolder(APath: TFileName): Boolean;
var
SearchRec: TSearchRec;
DosError: Integer;
begin
Result := False;
AddSlash(APath);
APath := Concat(APath, '*.*');
DosError := FindFirst(APath, faDirectory, SearchRec);
while DosError = 0 do
begin
if (SearchRec.Attr and faDirectory = faDirectory) and (SearchRec.Name[1] <> '.') then
begin
Result := True;
Break;
end;
DosError := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
function IsEmptyFolder(APath: TFileName): Boolean;
var
SearchRec: TSearchRec;
DosError: Integer;
begin
Result := True;
AddSlash(APath);
APath := Concat(APath, '*.*');
DosError := FindFirst(APath, faDirectory, SearchRec);
while DosError = 0 do
begin
if SearchRec.Name[1] <> '.' then
begin
Result := False;
Break;
end;
DosError := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
function TTFontSelected(const DC: HDC): Boolean;
var
TM: TTEXTMETRIC;
begin
GetTextMetrics(DC, TM);
Result := TM.tmPitchAndFamily and TMPF_TRUETYPE <> 0;
end;
function SubWord(P: PChar; var P2: PChar): string;
var
I: Integer;
begin
I := 0;
while not (P[I] in Separators) do
Inc(I);
SetString(Result, P, I);
P2 := P + I;
end;
function ReplaceString(S: string; const OldPattern, NewPattern: string): string;
var
LW: Integer;
P: PChar;
Sm: Integer;
begin
LW := Length(OldPattern);
P := StrPos(PChar(S), PChar(OldPattern));
while P <> nil do
begin
Sm := P - PChar(S);
S := Copy(S, 1, Sm) + NewPattern + Copy(S, Sm + LW + 1, Length(S));
P := StrPos(PChar(S) + Sm + Length(NewPattern), PChar(OldPattern));
end;
Result := S;
end;
function ReplaceStrings1(S: string; const Word, Frase: string): string;
begin
Result := ReplaceString(S, Word, Frase);
end;
function ConcatSep(const S, S2, Separator: string): string;
begin
Result := S;
if Result <> '' then
Result := Result + Separator;
Result := Result + S2;
end;
function ConcatLeftSep(const S, S2, Separator: string): string;
begin
Result := S;
if Result <> '' then
Result := Separator + Result;
Result := S2 + Result;
end;
function MinimizeString(const S: string; const MaxLen: Integer): string;
begin
if Length(S) > MaxLen then
if MaxLen < 3 then
Result := Copy(S, 1, MaxLen)
else
Result := Copy(S, 1, MaxLen - 3) + '...'
else
Result := S;
end;
function TrueInflateRect(const R: TRect; const I: Integer): TRect;
begin
with R do
SetRect(Result, Left - I, Top - I, Right + I, Bottom + I);
end;
procedure SetWindowTop(const Handle: HWND; const Top: Boolean);
const
TopFlag: array [Boolean] of Longword = (HWND_NOTOPMOST, HWND_TOPMOST);
begin
SetWindowPos(Handle, TopFlag[Top], 0, 0, 0, 0, SWP_NOMOVE or
SWP_NOSIZE or SWP_NOACTIVATE);
end;
{* from unit FileCtrl}
function DirectoryExists(const Name: string): Boolean;
var
Code: Integer;
begin
Code := Integer(GetFileAttributes(PChar(Name)));
Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
end;
procedure ForceDirectories(Dir: string);
begin
if Dir[Length(Dir)] = '\' then
Delete(Dir, Length(Dir), 1);
if (Length(Dir) < 3) or DirectoryExists(Dir) or (ExtractFilePath(Dir) = Dir) then
Exit; { avoid 'xyz:\' problem.}
ForceDirectories(ExtractFilePath(Dir));
CreateDir(Dir);
end;
{# from unit FileCtrl}
function LZFileExpand(const FileSource, FileDest: string): Boolean;
type
TLZCopy = function(Source, Dest: Integer): Longint; stdcall;
TLZOpenFile = function(Filename: PChar; var ReOpenBuff: TOFStruct; Style: Word): Integer; stdcall;
TLZClose = procedure(hFile: Integer); stdcall;
var
Source, Dest: Integer;
OSSource, OSDest: TOFSTRUCT;
Res: Integer;
Ins: Integer;
LZCopy: TLZCopy;
LZOpenFile: TLZOpenFile;
LZClose: TLZClose;
begin
Result := False;
Ins := LoadLibrary('LZ32.dll');
try
LZCopy := GetProcAddress(Ins, 'LZCopy');
LZOpenFile := GetProcAddress(Ins, 'LZOpenFileA');
LZClose := GetProcAddress(Ins, 'LZClose');
OSSource.cBytes := SizeOf(TOFSTRUCT);
OSDest.cBytes := SizeOf(TOFSTRUCT);
Source := LZOpenFile(
PChar(FileSource), // address of name of file to be opened
OSSource, // address of open file structure
OF_READ or OF_SHARE_DENY_NONE);// action to take
if Source < 0 then
begin
DeleteFile(FileDest);
Dest := LZOpenFile(
PChar(FileDest), // address of name of file to be opened
OSDest, // address of open file structure
OF_CREATE or OF_WRITE or OF_SHARE_EXCLUSIVE); // action to take
if Dest >= 0 then
begin
Res := LZCopy(Source, Dest);
if Res >= 0 then
Result := True;
end;
LZClose(Source);
LZClose(Dest);
end;
finally
FreeLibrary(Ins);
end;
end;
procedure Dos2Win(var S: string);
var
I: Integer;
begin
for I := 1 to Length(S) do
case S[I] of
#$80..#$AF:
S[I] := Char(Byte(S[I]) + (192 - $80));
#$E0..#$EF:
S[I] := Char(Byte(S[I]) + (240 - $E0));
end;
end;
procedure Win2Dos(var S: string);
var
I: Integer;
begin
for I := 1 to Length(S) do
case S[I] of
#$C0..#$EF:
S[I] := Char(Byte(S[I]) - (192 - $80));
#$F0..#$FF:
S[I] := Char(Byte(S[I]) - (240 - $E0));
end;
end;
function Dos2WinRes(const S: string): string;
begin
Result := S;
Dos2Win(Result);
end;
function Win2DosRes(const S: string): string;
begin
Result := S;
Win2Dos(Result);
end;
function Win2Koi(const S: string): string;
const
W = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ũ<EFBFBD><C5A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
K = '<27><><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD><C5A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>';
var
I, J: Integer;
begin
Result := S;
for I := 1 to Length(Result) do
begin
J := Pos(Result[I], W);
if J > 0 then
Result[I] := K[J];
end;
end;
function Spaces(const N: Integer): string;
begin
// (rom) reimplemented
Result := AddSpaces('', N);
end;
function AddSpaces(const S: string; const N: Integer): string;
begin
// (rom) SLOOOOW implementation
Result := S;
while Length(Result) < N do
Result := Result + ' ';
end;
function KeyPressed(VK: Integer): Boolean;
begin
Result := GetKeyState(VK) and $8000 = $8000;
end;
{$IFNDEF BCB1}
function BrowseForFolder(const Handle: HWND; const Title: string; var Folder: string): Boolean;
{$IFDEF COMPILER2}
type
TSHItemID = packed record { mkid }
cb: Word; { Size of the ID (including cb itself) }
abID: array [0..0] of Byte; { The item ID (variable Length) }
end;
PItemIDList = ^TItemIDList;
TItemIDList = packed record { idl }
mkid: TSHItemID;
end;
TFNBFFCallBack = function(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer stdcall;
TBrowseInfo = packed record
hwndOwner: HWND;
pidlRoot: PItemIDList;
pszDisplayName: PAnsiChar; { Return display name of item selected. }
lpszTitle: PAnsiChar; { text to go in the banner over the tree. }
ulFlags: UINT; { Flags that control the return stuff }
lpfn: TFNBFFCallBack;
lParam: LPARAM; { extra info that's passed back in callbacks }
iImage: Integer; { output var: where to return the Image Index. }
end;
function SHBrowseForFolder(var lpbi: TBrowseInfo): PItemIDList; stdcall; external 'shell32.dll' name
'SHBrowseForFolderA';
function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL; stdcall external 'shell32.dll' name
'SHGetPathFromIDListA';
{$ENDIF}
var
BrowseInfo: TBrowseInfo;
Id: PItemIDList;
FN: array [0..MAX_PATH] of Char;
begin
with BrowseInfo do
begin
hwndOwner := Handle;
pidlRoot := nil;
pszDisplayName := FN;
lpszTitle := PChar(Title);
ulFlags := 0;
lpfn := nil;
end;
Id := SHBrowseForFolder(BrowseInfo);
Result := Id <> nil;
if Result then
begin
SHGetPathFromIDList(Id, FN);
Folder := FN;
end;
end;
{$ENDIF BCB1}
function LastDate(const Dat: TDateTime): string;
const
D2D: array [0..9] of 1..3 = (3, 1, 2, 2, 2, 3, 3, 3, 3, 3);
Day: array [1..3] of string = ('<27><><EFBFBD><EFBFBD>', '<27><><EFBFBD>', '<27><><EFBFBD><EFBFBD>');
Month: array [1..3] of string = ('<27><><EFBFBD><EFBFBD><EFBFBD>', '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>', '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>');
Year: array [1..3] of string = ('<27><><EFBFBD>', '<27><><EFBFBD><EFBFBD>', '<27><><EFBFBD>');
Week: array [1..4] of string = ('<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>', '2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>', '3 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>', '<27><><EFBFBD><EFBFBD><EFBFBD>');
var
Y, M, D: Integer;
begin
if Date = Dat then
Result := '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'
else
if Dat = Date - 1 then
Result := '<27><><EFBFBD><EFBFBD><EFBFBD>'
else
if Dat = Date - 2 then
Result := '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'
else
if Dat > Date then
Result := '<27> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'
else
begin
D := Trunc(Date - Dat);
Y := Round(D / 365);
M := Round(D / 30);
if Y > 0 then
Result := IntToStr(Y) + ' ' + Year[D2D[StrToInt(IntToStr(Y)[Length(IntToStr(Y))])]] + ' <20><><EFBFBD><EFBFBD><EFBFBD>'
else
if M > 0 then
Result := IntToStr(M) + ' ' + Month[D2D[StrToInt(IntToStr(M)[Length(IntToStr(M))])]] + ' <20><><EFBFBD><EFBFBD><EFBFBD>'
else
if D > 6 then
Result := Week[D div 7] + ' <20><><EFBFBD><EFBFBD><EFBFBD>'
else
if D > 0 then
Result := IntToStr(D) + ' ' + Day[D2D[StrToInt(IntToStr(D)[Length(IntToStr(D))])]] + ' <20><><EFBFBD><EFBFBD><EFBFBD>'
end;
end;
procedure AddSlash(var Dir: TFileName);
begin
if (Length(Dir) > 0) and (Dir[Length(Dir)] <> '\') then
Dir := Dir + '\';
end;
function AddSlash2(const Dir: TFileName): string;
begin
Result := Dir;
if (Length(Dir) > 0) and (Dir[Length(Dir)] <> '\') then
Result := Dir + '\';
end;
function AddPath(const FileName, Path: TFileName): TFileName;
begin
if ExtractFileDrive(FileName) = '' then
Result := AddSlash2(Path) + FileName
else
Result := FileName;
end;
function AddPaths(const PathList, Path: string): string;
var
I: Integer;
S: string;
begin
Result := '';
I := 0;
S := SubStr(PathList, I, ';');
while S <> '' do
begin
Result := ConcatSep(Result, AddPath(S, Path), ';');
Inc(I);
S := SubStr(PathList, I, ';');
end;
end;
function ParentPath(const Path: TFileName): TFileName;
begin
Result := Path;
if (Length(Result) > 0) and (Result[Length(Result)] = '\') then
Delete(Result, Length(Result), 1);
Result := ExtractFilePath(Result);
end;
function FindInPath(const FileName, PathList: string): TFileName;
var
I: Integer;
S: string;
begin
I := 0;
S := SubStr(PathList, I, ';');
while S <> '' do
begin
Result := AddSlash2(S) + FileName;
if FileExists(Result) then
Exit;
Inc(I);
S := SubStr(PathList, I, ';');
end;
Result := '';
end;
function GetComputerID: string;
var
SN: DWORD;
Nul: DWORD;
WinDir: array [0..MAX_PATH] of Char;
begin
GetWindowsDirectory(WinDir, MAX_PATH);
WinDir[3] := #0;
if GetVolumeInformation(
WinDir, // address of root directory of the file system
nil, // address of name of the volume
0, // Length of lpVolumeNameBuffer
@SN, // address of volume serial number
Nul, // address of system's maximum filename Length
Nul, // address of file system flags
nil, // address of name of file system
0) // Length of lpFileSystemNameBuffer
then
Result := IntToHex(SN, 8)
else
Result := 'None';
end;
function CurrencyToStr(const Cur: currency): string;
begin
Result := CurrToStrF(Cur, ffCurrency, CurrencyDecimals)
end;
function Cmp(const S1, S2: string): Boolean;
begin
//Result := AnsiCompareText(S1, S2) = 0;
Result := AnsiStrIComp(PChar(S1), PChar(S2)) = 0;
end;
function StringCat(var S1: string; S2: string): string;
begin
S1 := S1 + S2;
Result := S1;
end;
function HasChar(const Ch: Char; const S: string): Boolean;
begin
Result := Pos(Ch, S) > 0;
end;
function HasAnyChar(const Chars: string; const S: string): Boolean;
var
I: Integer;
begin
for I := 1 to Length(Chars) do
if HasChar(Chars[I], S) then
begin
Result := True;
Exit;
end;
Result := False;
end;
function CountOfChar(const Ch: Char; const S: string): Integer;
var
I: Integer;
begin
Result := 0;
for I := 1 to Length(S) do
if S[I] = Ch then
Inc(Result);
end;
procedure SwapInt(var Int1, Int2: Integer);
var
Tmp: Integer;
begin
Tmp := Int1;
Int1 := Int2;
Int2 := Tmp;
end;
function DeleteReadOnlyFile(const FileName: TFileName): Boolean;
begin
FileSetAttr(FileName, 0); {clear Read Only Flag}
Result := DeleteFile(FileName);
end;
function HasParam(const Param: string): Boolean;
var
I: Integer;
begin
Result := False;
for I := 1 to ParamCount do
begin
Result := Cmp(ParamStr(I), Param);
if Result then
Exit;
end;
end;
function HasSwitch(const Param: string): Boolean;
var
I: Integer;
begin
Result := False;
for I := 1 to ParamCount do
if HasChar(ParamStr(I)[1], '-/') then
begin
Result := Cmp(Copy(ParamStr(I), 2, Length(Param)), Param);
if Result then
Exit;
end;
end;
function Switch(const Param: string): string;
var
I: Integer;
begin
Result := '';
for I := 1 to ParamCount do
if HasChar(ParamStr(I)[1], '-/\') and
Cmp(Copy(ParamStr(I), 2, Length(Param)), Param) then
begin
Result := Copy(ParamStr(I), 2 + Length(Param), 260);
Exit;
end;
end;
function ExePath: TFileName;
begin
Result := ExtractFilePath(ParamStr(0));
end;
function FileNewExt(const FileName, NewExt: TFileName): TFileName;
begin
Result := Copy(FileName, 1, Length(FileName) - Length(ExtractFileExt(FileName))) + NewExt;
end;
{$IFNDEF COMPILER3_UP}
function AnsiStrLIComp(S1, S2: PChar; MaxLen: Cardinal): Integer;
begin
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
S1, MaxLen, S2, MaxLen) - 2;
end;
function AnsiStrIComp(S1, S2: PChar): Integer;
begin
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, S1, -1,
S2, -1) - 2;
end;
{$ENDIF}
function CharInSet(const Ch: Char; const SetOfChar: TSetOfChar): Boolean;
begin
{$IFDEF DELPHI}
Result := Ch in SetOfChar;
{$ENDIF DELPHI}
{$IFDEF BCB}
Result := Pos(Ch, SetOfChar) > 0;
{$ENDIF BCB}
end;
function IntPower(Base, Exponent: Integer): Integer;
begin
if Exponent > 0 then
begin
Result := Base;
Dec(Exponent);
while Exponent > 0 do
begin
Result := Result * Base;
Dec(Exponent);
end;
end
else
if Exponent < 0 then
begin
Result := 1;
Inc(Exponent);
while Exponent < 0 do
begin
Result := Result div Base;
Inc(Exponent);
end;
end
else
Result := Base;
end;
function ChangeTopException(E: TObject): TObject;
type
PRaiseFrame = ^TRaiseFrame;
TRaiseFrame = record
NextRaise: PRaiseFrame;
ExceptAddr: Pointer;
ExceptObject: TObject;
ExceptionRecord: PExceptionRecord;
end;
begin
{ CBuilder 3 Warning !}
{ if linker error occured with message "unresolved external 'System::RaiseList'" try
comment this function implementation, compile,
then uncomment and compile again. }
{$IFDEF COMPILER6_UP}
{$WARN SYMBOL_DEPRECATED OFF}
{$ENDIF}
if RaiseList <> nil then
begin
Result := PRaiseFrame(RaiseList)^.ExceptObject;
PRaiseFrame(RaiseList)^.ExceptObject := E
end
else
Result := nil;
// raise Exception.Create('Not in exception');
end;
function MakeValidFileName(const FileName: TFileName;
const ReplaceBadChar: Char): TFileName;
var
I: Integer;
begin
Result := FileName;
for I := 1 to Length(Result) do
if HasChar(Result[I], '''":?*\/') then
Result[I] := ReplaceBadChar;
end;
function Var2Type(V: Variant; const VarType: Integer): Variant;
begin
if TVarData(V).VType in [varEmpty, varNull] then
begin
case VarType of
varString, varOleStr:
Result := '';
varInteger, varSmallint, varByte:
Result := 0;
varBoolean:
Result := False;
varSingle, varDouble, varCurrency, varDate:
Result := 0.0;
varVariant:
Result := Null;
else
Result := VarAsType(V, VarType);
end;
end
else
Result := VarAsType(V, VarType);
if (VarType = varInteger) and (TVarData(V).VType = varBoolean) then
Result := Integer(V = True);
end;
function VarToInt(V: Variant): Integer;
begin
Result := Var2Type(V, varInteger);
end;
function VarToFloat(V: Variant): Double;
begin
Result := Var2Type(V, varDouble);
end;
function CopyDir(const SourceDir, DestDir: TFileName): Boolean;
var
SearchRec: TSearchRec;
DosError: Integer;
Path, DestPath: TFileName;
begin
Result := False;
if not CreateDir(DestDir) then
Exit;
Path := SourceDir;
DestPath := AddSlash2(DestDir);
AddSlash(Path);
DosError := FindFirst(Path + '*.*', faAnyFile, SearchRec);
while DosError = 0 do
begin
if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
begin
if (SearchRec.Attr and faDirectory) = faDirectory then
Result := CopyDir(Path + SearchRec.Name, AddSlash2(DestDir) + SearchRec.Name)
else
Result := CopyFile(PChar(Path + SearchRec.Name),
PChar(DestPath + SearchRec.Name), True);
if not Result then
Exit;
end;
DosError := FindNext(SearchRec);
end;
FindClose(SearchRec);
Result := True;
end;
function FileTimeToDateTime(const FT: TFileTime): TDateTime;
var
LocalFileTime: TFileTime;
FileDate: Integer;
begin
FileTimeToLocalFileTime(FT, LocalFileTime);
FileTimeToDosDateTime(LocalFileTime, LongRec(FileDate).Hi, LongRec(FileDate).Lo);
Result := FileDateToDateTime(FileDate);
end;
function DefStr(const S: string; Default: string): string;
begin
if S <> '' then
Result := S
else
Result := Default;
end;
function GetComputerName: string;
var
nSize: DWORD;
begin
nSize := MAX_COMPUTERNAME_LENGTH + 1;
SetLength(Result, nSize);
if Windows.GetComputerName(
PChar(Result), // address of name buffer
nSize) then // address of size of name buffer
SetLength(Result, nSize)
else
Result := '';
end;
function StrToBool(const S: string): Boolean;
begin
Result := (S = '1') or Cmp(S, 'True') or Cmp(S, 'yes');
end;
procedure LoadIcoToImage(ALarge, ASmall: TImageList; const NameRes: string);
var
Ico: TIcon;
begin
Ico := TIcon.Create;
if ALarge <> nil then
begin
Ico.Handle := LoadImage(hInstance, PChar(NameRes), IMAGE_ICON, 32, 32, 0);
ALarge.AddIcon(Ico);
end;
if ASmall <> nil then
begin
Ico.Handle := LoadImage(hInstance, PChar(NameRes), IMAGE_ICON, 16, 16, 0);
ASmall.AddIcon(Ico);
end;
Ico.Free;
end;
procedure WordBreak(Canvas: TCanvas; const S: string; Ss: TStrings);
begin
Ss.Text := S;
end;
procedure RATextOut(Canvas: TCanvas; const R, RClip: TRect; const S: string);
begin
RATextOutEx(Canvas, R, RClip, S, False);
end;
function RATextCalcHeight(Canvas: TCanvas; const R: TRect; const S: string): Integer;
begin
Result := RATextOutEx(Canvas, R, R, S, True);
end;
function RATextOutEx(Canvas: TCanvas; const R, RClip: TRect; const S: string; const CalcHeight: Boolean): Integer;
var
Ss: TStrings;
I: Integer;
H: Integer;
begin
Ss := TStringList.Create;
try
WordBreak(Canvas, S, Ss);
H := Canvas.TextHeight('A');
Result := H * Ss.Count;
if not CalcHeight then
for I := 0 to Ss.Count - 1 do
ExtTextOut(
Canvas.Handle, // handle of device context
R.Left, // X-coordinate of reference point
R.Top + H * I, // Y-coordinate of reference point
ETO_CLIPPED, // text-output options
@RClip, // optional clipping and/or opaquing rectangle
PChar(Ss[I]),
Length(Ss[I]), // number of characters in string
nil); // address of array of intercharacter spacing values
finally
Ss.Free;
end;
end;
procedure Cinema(Canvas: TCanvas; rS, rD: TRect);
const
Pause = 30; {milliseconds}
Steps = 7;
Width = 1;
var
R: TRect;
I: Integer;
PenOld: TPen;
procedure FrameR(R: TRect);
begin
with Canvas do
begin
MoveTo(R.Left, R.Top);
LineTo(R.Left, R.Bottom);
LineTo(R.Right, R.Bottom);
LineTo(R.Right, R.Top);
LineTo(R.Left, R.Top);
end;
end;
procedure Frame;
begin
FrameR(R);
with Canvas do
begin
MoveTo(rS.Left, rS.Top);
LineTo(R.Left, R.Top);
if R.Top <> rS.Top then
begin
MoveTo(rS.Right, rS.Top);
LineTo(R.Right, R.Top);
end;
if R.Left <> rS.Left then
begin
MoveTo(rS.Left, rS.Bottom);
LineTo(R.Left, R.Bottom);
end;
if (R.Bottom <> rS.Bottom) and (R.Right <> rS.Right) then
begin
MoveTo(rS.Right, rS.Bottom);
LineTo(R.Right, R.Bottom);
end;
end;
end;
begin
PenOld := TPen.Create;
PenOld.Assign(Canvas.Pen);
Canvas.Pen.Mode := pmNot;
Canvas.Pen.Width := Width;
Canvas.Pen.Style := psDot;
FrameR(rS);
R := rS;
for I := 1 to Steps do
begin
R.Left := rS.Left + (rD.Left - rS.Left) div Steps * I;
R.Top := rS.Top + (rD.Top - rS.Top) div Steps * I;
R.Bottom := rS.Bottom + (rD.Bottom - rS.Bottom) div Steps * I;
R.Right := rS.Right + (rD.Right - rS.Right) div Steps * I;
Frame;
Sleep(Pause);
Frame;
end;
FrameR(rS);
Canvas.Pen.Assign(PenOld);
end;
function FindFormByClass(FormClass: TFormClass): TForm;
var
I: Integer;
begin
Result := nil;
for I := 0 to Application.ComponentCount - 1 do
if Application.Components[I].ClassName = FormClass.ClassName then
begin
Result := Application.Components[I] as TForm;
Break;
end;
end;
function FindFormByClassName(FormClassName: string): TForm;
var
I: Integer;
begin
Result := nil;
for I := 0 to Application.ComponentCount - 1 do
if Application.Components[I].ClassName = FormClassName then
begin
Result := Application.Components[I] as TForm;
Break;
end;
end;
function FindByTag(WinControl: TWinControl; ComponentClass: TComponentClass; const Tag: Integer): TComponent;
var
I: Integer;
begin
for I := 0 to WinControl.ControlCount - 1 do
begin
Result := WinControl.Controls[I];
if (Result is ComponentClass) and (Result.Tag = Tag) then
Exit;
end;
Result := nil;
end;
function ControlAtPos2(Parent: TWinControl; X, Y: Integer): TControl;
var
I: Integer;
P: TPoint;
begin
P := Point(X, Y);
for I := Parent.ControlCount - 1 downto 0 do
begin
Result := Parent.Controls[I];
with Result do
if PtInRect(BoundsRect, P) then
Exit;
end;
Result := nil;
end;
function RBTag(Parent: TWinControl): Integer;
var
RB: TRadioButton;
I: Integer;
begin
RB := nil;
with Parent do
for I := 0 to ControlCount - 1 do
if (Controls[I] is TRadioButton) and
(Controls[I] as TRadioButton).Checked then
begin
RB := Controls[I] as TRadioButton;
Break;
end;
if RB <> nil then
Result := RB.Tag
else
Result := 0;
end;
function IniReadSection(const IniFileName: TFileName; const Section: string; Ss: TStrings): Boolean;
var
F: Integer;
S: string;
begin
with TStringList.Create do
try
LoadFromFile(IniFileName);
F := IndexOf('[' + Section + ']');
Result := F > -1;
if Result then
begin
Ss.Clear;
Inc(F);
while F < Count do
begin
S := Strings[F];
if (Length(S) > 0) and (Trim(S[1]) = '[') then
Break;
Ss.Add(S);
Inc(F);
end;
end;
finally
Free;
end;
end;
procedure SaveTextFile(const FileName: TFileName; const Source: string);
begin
with TStringList.Create do
try
Text := Source;
SaveToFile(FileName);
finally
Free;
end;
end;
function LoadTextFile(const FileName: TFileName): string;
begin
with TStringList.Create do
try
LoadFromFile(FileName);
Result := Text;
finally
Free;
end;
end;
function ReadFolder(const Folder, Mask: TFileName; FileList: TStrings): Integer;
var
SearchRec: TSearchRec;
DosError: Integer;
begin
FileList.Clear;
Result := FindFirst(AddSlash2(Folder) + Mask, faAnyFile, SearchRec);
DosError := Result;
while DosError = 0 do
begin
if not ((SearchRec.Attr and faDirectory) = faDirectory) then
FileList.Add(SearchRec.Name);
DosError := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
function ReadFolders(const Folder: TFileName; FolderList: TStrings): Integer;
var
SearchRec: TSearchRec;
DosError: Integer;
begin
FolderList.Clear;
Result := FindFirst(AddSlash2(Folder) + '*.*', faAnyFile, SearchRec);
DosError := Result;
while DosError = 0 do
begin
if ((SearchRec.Attr and faDirectory) = faDirectory) and
(SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
FolderList.Add(SearchRec.Name);
DosError := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
{$IFDEF COMPILER3_UP}
function TargetFileName(const FileName: TFileName): TFileName;
begin
Result := FileName;
if Cmp(ExtractFileExt(FileName), '.lnk') then
if ResolveLink(Application.Handle, FileName, Result) <> 0 then
raise Exception.CreateFmt(SCantGetShortCut, [FileName]);
end;
function ResolveLink(const hWnd: HWND; const LinkFile: TFileName;
var FileName: TFileName): HRESULT;
var
psl: IShellLink;
WLinkFile: array [0..MAX_PATH] of WideChar;
wfd: TWIN32FINDDATA;
ppf: IPersistFile;
begin
Pointer(psl) := nil;
Pointer(ppf) := nil;
Result := CoInitialize(nil);
if SUCCEEDED(Result) then
begin
// Get a Pointer to the IShellLink interface.
Result := CoCreateInstance(CLSID_ShellLink, nil,
CLSCTX_INPROC_SERVER, IShellLink, psl);
if SUCCEEDED(Result) then
begin
// Get a Pointer to the IPersistFile interface.
Result := psl.QueryInterface(IPersistFile, ppf);
if SUCCEEDED(Result) then
begin
StringToWideChar(LinkFile, WLinkFile, SizeOf(WLinkFile) - 1);
// Load the shortcut.
Result := ppf.Load(WLinkFile, STGM_READ);
if SUCCEEDED(Result) then
begin
// Resolve the link.
Result := psl.Resolve(hWnd, SLR_ANY_MATCH);
if SUCCEEDED(Result) then
begin
// Get the path to the link target.
SetLength(FileName, MAX_PATH);
Result := psl.GetPath(PChar(FileName), MAX_PATH, wfd,
SLGP_UNCPRIORITY);
if not SUCCEEDED(Result) then
Exit;
SetLength(FileName, Length(PChar(FileName)));
end;
end;
// Release the Pointer to the IPersistFile interface.
ppf._Release;
end;
// Release the Pointer to the IShellLink interface.
psl._Release;
end;
CoUnInitialize;
end;
Pointer(psl) := nil;
Pointer(ppf) := nil;
end;
{$ENDIF COMPILER3_UP}
{
with memEdit do begin
Text := ReplaceStrings(Text, SelStart+1, SelLength, memWords.Lines, memFrases.Lines, NewSelStart);
SelStart := NewSelStart-1;
end; }
function ReplaceStrings(S: string; PosBeg, Len: Integer; Words, Frases: TStrings;
var NewSelStart: Integer): string;
var
I, Beg, Ent, LS, F: Integer;
Word: string;
begin
NewSelStart := PosBeg;
Result := S;
LS := Length(S);
if Len = 0 then
begin
if PosBeg < 1 then
Exit;
if PosBeg = 1 then
PosBeg := 2;
for I := PosBeg - 1 downto 1 do
if S[I] in Separators then
Break;
Beg := I + 1;
for Ent := PosBeg to LS do
if S[Ent] in Separators then
Break;
if Ent > Beg then
Word := Copy(S, Beg, Ent - Beg)
else
Word := S[PosBeg];
end
else
begin
Word := Copy(S, PosBeg, Len);
Beg := PosBeg;
Ent := PosBeg + Len;
end;
if Word = '' then
Exit;
F := Words.IndexOf(Word);
if (F > -1) and (F < Frases.Count) then
begin
Result := Copy(S, 1, Beg - 1) + Frases[F] + Copy(S, Ent, LS);
NewSelStart := Beg + Length(Frases[F]);
end;
end;
{
with memEdit do
Text := ReplaceAllStrings(Text, memWords.Lines, memFrases.Lines);
}
function ReplaceAllStrings(S: string; Words, Frases: TStrings): string;
var
I, LW: Integer;
P: PChar;
Sm: Integer;
begin
for I := 0 to Words.Count - 1 do
begin
LW := Length(Words[I]);
P := StrPos(PChar(S), PChar(Words[I]));
while P <> nil do
begin
Sm := P - PChar(S);
S := Copy(S, 1, Sm) + Frases[I] + Copy(S, Sm + LW + 1, Length(S));
P := StrPos(PChar(S) + Sm + Length(Frases[I]), PChar(Words[I]));
end;
end;
Result := S;
end;
function CountOfLines(const S: string): Integer;
begin
with TStringList.Create do
try
Text := S;
Result := Count;
finally
Free;
end;
end;
procedure DeleteEmptyLines(Ss: TStrings);
var
I: Integer;
begin
I := 0;
while I < Ss.Count do
if Trim(Ss[I]) = '' then
Ss.Delete(I)
else
Inc(I);
end;
procedure SQLAddWhere(SQL: TStrings; const Where: string);
var
I, J: Integer;
begin
J := SQL.Count - 1;
for I := 0 to SQL.Count - 1 do
// (rom) does this always work? Think of a fieldname "grouporder"
if StrLIComp(PChar(SQL[I]), 'where ', 6) = 0 then
begin
J := I + 1;
while J < SQL.Count do
begin
if (StrLIComp(PChar(SQL[J]), 'order ', 6) = 0) or
(StrLIComp(PChar(SQL[J]), 'group ', 6) = 0) then
Break;
Inc(J);
end;
end;
SQL.Insert(J, 'and ' + Where);
end;
var
ProcList: TList = nil;
type
TJvProcItem = class(TObject)
private
FProcObj: TProcObj;
public
constructor Create(AProcObj: TProcObj);
end;
constructor TJvProcItem.Create(AProcObj: TProcObj);
begin
FProcObj := AProcObj;
end;
procedure TmrProc(hWnd: HWND; uMsg: Integer; idEvent: Integer; dwTime: Integer); stdcall;
var
Pr: TProcObj;
begin
if ProcList[idEvent] <> nil then
begin
Pr := TJvProcItem(ProcList[idEvent]).FProcObj;
TJvProcItem(ProcList[idEvent]).Free;
end
else
Pr := nil;
ProcList.Delete(idEvent);
KillTimer(hWnd, idEvent);
if ProcList.Count <= 0 then
begin
ProcList.Free;
ProcList := nil;
end;
if Assigned(Pr) then
Pr;
end;
procedure ExecAfterPause(Proc: TProcObj; Pause: Integer);
var
Num: Integer;
I: Integer;
begin
if ProcList = nil then
ProcList := TList.Create;
Num := -1;
for I := 0 to ProcList.Count - 1 do
if @TJvProcItem(ProcList[I]).FProcObj = @Proc then
begin
Num := I;
Break;
end;
if Num <> -1 then
KillTimer(Application.Handle, Num)
else
Num := ProcList.Add(TJvProcItem.Create(Proc));
SetTimer(Application.Handle, Num, Pause, @TmrProc);
end;
procedure Roughed(ACanvas: TCanvas; const ARect: TRect; const AVert: Boolean);
var
I: Integer;
J: Integer;
R: TRect;
V: Boolean;
H: Boolean;
begin
H := True;
V := True;
for I := 0 to (ARect.Right - ARect.Left) div 4 do
begin
for J := 0 to (ARect.Bottom - ARect.Top) div 4 do
begin
if AVert then
begin
if V then
R := Bounds(ARect.Left + I * 4 + 2, ARect.Top + J * 4, 2, 2)
else
R := Bounds(ARect.Left + I * 4, ARect.Top + J * 4, 2, 2);
end
else
begin
if H then
R := Bounds(ARect.Left + I * 4, ARect.Top + J * 4 + 2, 2, 2)
else
R := Bounds(ARect.Left + I * 4, ARect.Top + J * 4, 2, 2);
end;
Frame3D(ACanvas, R, clBtnHighlight, clBtnShadow, 1);
V := not V;
end;
H := not H;
end;
end;
function BitmapFromBitmap(SrcBitmap: TBitmap; const AWidth, AHeight, Index: Integer): TBitmap;
begin
Result := TBitmap.Create;
Result.Width := AWidth;
Result.Height := AHeight;
Result.Canvas.CopyRect(Rect(0, 0, AWidth, AHeight), SrcBitmap.Canvas, Bounds(AWidth * Index, 0, AWidth, AHeight));
end;
procedure ShowMenu(Form: TForm; MenuAni: TMenuAnimation);
var
I: Integer;
h: Integer;
w: Integer;
begin
case MenuAni of
maNone:
Form.Show;
maRandom:
;
maUnfold:
begin
h := Form.Height;
Form.Height := 0;
Form.Show;
for I := 0 to h div 10 do
if Form.Height < h then
Form.Height := Form.Height + 10;
end;
maSlide:
begin
h := Form.Height;
w := Form.Width;
Form.Height := 0;
Form.Width := 0;
Form.Show;
for I := 0 to Max(h div 5, w div 5) do
begin
if Form.Height < h then
Form.Height := Form.Height + 5;
if Form.Width < w then
Form.Width := Form.Width + 5;
end;
// CS_SAVEBITS
end;
end;
end;
function ResSaveToFileEx(Instance: HINST; Typ, Name: PChar;
const Compressed: Boolean; const FileName: string): Boolean;
var
RhRsrc: HRSRC;
RhGlobal: HGLOBAL;
RAddr: Pointer;
RLen: DWORD;
Stream: TFileStream;
FileDest: string;
begin
Result := False;
RhRsrc := FindResource(
Instance, // resource-module handle
Name, // address of resource name
Typ); // address of resource type
if RhRsrc = 0 then
Exit;
RhGlobal := LoadResource(
Instance, // resource-module handle
RhRsrc); // resource handle
if RhGlobal = 0 then
Exit;
RAddr := LockResource(
RhGlobal); // handle to resource to lock
FreeResource(RhGlobal);
if RAddr = nil then
Exit;
RLen := SizeofResource(
Instance, // resource-module handle
RhRsrc); // resource handle
if RLen = 0 then
Exit;
{ And now it is possible to duplicate [translated] }
Stream := nil; { for Free [translated] }
if Compressed then
FileDest := GenTempFileName(FileName)
else
FileDest := FileName;
try
try
Stream := TFileStream.Create(FileDest, fmCreate or fmOpenWrite or fmShareExclusive);
Stream.WriteBuffer(RAddr^, RLen);
finally
Stream.Free;
end;
if Compressed then
begin
Result := LZFileExpand(FileDest, FileName);
DeleteFile(FileDest);
end
else
Result := True;
except
end;
end;
function ResSaveToFile(const Typ, Name: string; const Compressed: Boolean;
const FileName: string): Boolean;
begin
Result := ResSaveToFileEx(hInstance, PChar(Typ), PChar(Name), Compressed, FileName);
end;
function ResSaveToString(Instance: HINST; const Typ, Name: string;
var S: string): Boolean;
var
RhRsrc: HRSRC;
RhGlobal: HGLOBAL;
RAddr: Pointer;
RLen: DWORD;
begin
Result := False;
RhRsrc := FindResource(
Instance, // resource-module handle
PChar(Name), // address of resource name
PChar(Typ)); // address of resource type
if RhRsrc = 0 then
Exit;
RhGlobal := LoadResource(
Instance, // resource-module handle
RhRsrc); // resource handle
if RhGlobal = 0 then
Exit;
RAddr := LockResource(
RhGlobal); // handle to resource to lock
FreeResource(RhGlobal);
if RAddr = nil then
Exit;
RLen := SizeofResource(
Instance, // resource-module handle
RhRsrc); // resource handle
if RLen = 0 then
Exit;
{ And now it is possible to duplicate [translated] }
SetString(S, PChar(RAddr), RLen);
end;
// (rom) a thread to wait would be more elegant, also JCL function available
function Execute(const CommandLine, WorkingDirectory: string): Integer;
var
R: Boolean;
ProcessInformation: TProcessInformation;
StartupInfo: TStartupInfo;
{$IFDEF COMPILER4_UP}
ExCode: Cardinal;
{$ELSE}
ExCode: Integer;
{$ENDIF}
begin
Result := 0;
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
with StartupInfo do
begin
cb := SizeOf(TStartupInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := SW_SHOW;
end;
R := CreateProcess(
nil, // Pointer to name of executable module
PChar(CommandLine), // Pointer to command line string
nil, // Pointer to process security attributes
nil, // Pointer to thread security attributes
False, // handle inheritance flag
0, // creation flags
nil, // Pointer to new environment block
PChar(WorkingDirectory), // Pointer to current directory name
StartupInfo, // Pointer to STARTUPINFO
ProcessInformation); // Pointer to PROCESS_INFORMATION
if R then
while (GetExitCodeProcess(ProcessInformation.hProcess, ExCode) and
(ExCode = STILL_ACTIVE)) do
Application.ProcessMessages
else
Result := GetLastError;
end;
function TextWidth(AStr: string): Integer;
var
Canvas: TCanvas;
DC: HDC;
begin
DC := GetDC(HWND_DESKTOP);
Canvas := TCanvas.Create;
// (rom) secured
try
Canvas.Handle := DC;
Result := Canvas.TextWidth(AStr);
Canvas.Handle := 0;
Canvas.Free;
finally
ReleaseDC(HWND_DESKTOP, DC);
end;
end;
function AppMinimized: Boolean;
begin
Result := IsIconic(Application.Handle);
end;
function MessageBox(const Msg: string; Caption: string; const Flags: Integer): Integer;
begin
if Caption = '' then
Caption := Application.Title;
Result := Application.MessageBox(PChar(Msg), PChar(Caption), Flags);
end;
function MsgDlgDef1(const Msg, ACaption: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; DefButton: TMsgDlgBtn; UseDefButton: Boolean;
AHelpContext: Integer; Control: TWinControl): Integer;
const
{$IFNDEF COMPILER2}
ButtonNames: array [TMsgDlgBtn] of PChar =
('Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'NoToAll',
'YesToAll', 'Help');
{$ELSE}
ButtonNames: array [TMsgDlgBtn] of string =
('Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All', 'Help');
{$ENDIF COMPILER2}
var
P: TPoint;
I: Integer;
Btn: TButton;
StayOnTop: Boolean;
begin
if AHelpContext <> 0 then
Buttons := Buttons + [mbHelp];
StayOnTop := False;
with CreateMessageDialog(Msg, DlgType, Buttons) do
try
{$IFDEF COMPILER3_UP}
Font.CharSet := MsgDlgCharSet;
{$ENDIF COMPILER3_UP}
if (Screen.ActiveForm <> nil) and
(Screen.ActiveForm.FormStyle = fsStayOnTop) then
begin
StayOnTop := True;
SetWindowTop(Screen.ActiveForm.Handle, False);
end;
if ACaption <> '' then
Caption := ACaption;
if Control = nil then
begin
Left := (Screen.Width - Width) div 2;
Top := (Screen.Height - Height) div 2;
end
else
begin
P := Point((Control.Width - Width) div 2,
(Control.Height - Height) div 2);
P := Control.ClientToScreen(P);
Left := P.X;
Top := P.Y
end;
if Left < 0 then
Left := 0
else
if Left > Screen.Width then
Left := Screen.Width - Width;
if Top < 0 then
Top := 0
else
if Top > Screen.Height then
Top := Screen.Height - Height;
HelpContext := AHelpContext;
Btn := FindComponent(ButtonNames[DefButton]) as TButton;
if UseDefButton and (Btn <> nil) then
begin
for I := 0 to ComponentCount - 1 do
if Components[I] is TButton then
(Components[I] as TButton).Default := False;
Btn.Default := True;
ActiveControl := Btn;
end;
Btn := FindComponent(ButtonNames[mbIgnore]) as TButton;
if Btn <> nil then
begin
// Btn.Width := Btn.Width * 5 div 4; {To shift the Help button Help [translated] }
end;
Result := ShowModal;
finally
Free;
if (Screen.ActiveForm <> nil) and StayOnTop then
SetWindowTop(Screen.ActiveForm.Handle, True);
end;
end;
function MsgDlgDef(const Msg, ACaption: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; DefButton: TMsgDlgBtn; HelpContext: Integer;
Control: TWinControl): Integer;
begin
Result := MsgDlgDef1(Msg, ACaption, DlgType, Buttons, DefButton, True, HelpContext, Control);
end;
function MsgDlg2(const Msg, ACaption: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; HelpContext: Integer;
Control: TWinControl): Integer;
begin
Result := MsgDlgDef1(Msg, ACaption, DlgType, Buttons, mbHelp, False, HelpContext, Control);
end;
procedure CenterHor(Parent: TControl; MinLeft: Integer; Controls: array of TControl);
var
I: Integer;
begin
for I := Low(Controls) to High(Controls) do
Controls[I].Left := Max(MinLeft, (Parent.Width - Controls[I].Width) div 2)
end;
procedure EnableControls(Control: TWinControl; const Enable: Boolean);
var
I: Integer;
begin
for I := 0 to Control.ControlCount - 1 do
Control.Controls[I].Enabled := Enable;
end;
procedure EnableMenuItems(MenuItem: TMenuItem; const Tag: Integer; const Enable: Boolean);
var
I: Integer;
begin
for I := 0 to MenuItem.Count - 1 do
if MenuItem[I].Tag <> Tag then
MenuItem[I].Enabled := Enable;
end;
procedure ExpandWidth(Parent: TControl; MinWidth: Integer; Controls: array of TControl);
var
I: Integer;
begin
for I := Low(Controls) to High(Controls) do
Controls[I].Width := Max(MinWidth, Parent.ClientWidth - 2 * Controls[I].Left);
end;
function PanelBorder(Panel: TCustomPanel): Integer;
begin
Result := TPanel(Panel).BorderWidth;
if TPanel(Panel).BevelOuter <> bvNone then
Inc(Result, TPanel(Panel).BevelWidth);
if TPanel(Panel).BevelInner <> bvNone then
Inc(Result, TPanel(Panel).BevelWidth);
end;
{$IFDEF COMPILER2}
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
asm
PUSH ESI
PUSH EDI
MOV ESI,P1
MOV EDI,P2
MOV EDX,ECX
XOR EAX,EAX
AND EDX,3
SHR ECX,1
SHR ECX,1
REPE CMPSD
JNE @@2
MOV ECX,EDX
REPE CMPSB
JNE @@2
@@1: Inc EAX
@@2: POP EDI
POP ESI
end;
{$ENDIF COMPILER2}
{ function DefineCursor was typed from
book "Secrets of Delphi 2" by Ray Lischner }
function DefineCursor(Identifier: PChar): TCursor;
var
Handle: HCursor;
begin
Handle := LoadCursor(hInstance, Identifier);
if Handle = 0 then
raise EOutOfResources.Create('Cannot load cursor resource');
for Result := 1 to High(TCursor) do
if Screen.Cursors[Result] = Screen.Cursors[crDefault] then
begin
Screen.Cursors[Result] := Handle;
Exit;
end;
raise EOutOfResources.Create('Too many user-defined cursors');
end;
procedure Delay(MSec: Longword);
var
T: Longword;
begin
T := GetTickCount;
while GetTickCount - T < MSec do
Application.ProcessMessages;
end;
function Pixels(Control: TControl; APixels: Integer): Integer;
var
Form: TForm;
begin
Result := APixels;
if Control is TForm then
Form := TForm(Control)
else
Form := TForm(GetParentForm(Control));
if Form.Scaled then
Result := Result * Form.PixelsPerInch div 96;
end;
procedure SetChildPropOrd(Owner: TComponent; PropName: string; Value: Longint);
var
I: Integer;
PropInfo: PPropInfo;
begin
for I := 0 to Owner.ComponentCount - 1 do
begin
PropInfo := GetPropInfo(Owner.Components[I].ClassInfo, PropName);
if PropInfo <> nil then
SetOrdProp(Owner.Components[I], PropInfo, Value);
end;
end;
procedure Error(const Msg: string);
begin
raise Exception.Create(Msg);
end;
procedure ItemHtDrawEx(Canvas: TCanvas; Rect: TRect;
const State: TOwnerDrawState; const Text: string;
const HideSelColor: Boolean; var PlainItem: string;
var Width: Integer; CalcWidth: Boolean);
var
CL: string;
I: Integer;
M1: string;
OriRect: TRect; // it's added
oldFontStyles: TFontStyles;
oldFontColor: TColor;
function Cmp(M1: string): Boolean;
begin
Result := AnsiStrLIComp(PChar(Text) + I, PChar(M1), Length(M1)) = 0;
end;
function Cmp1(M1: string): Boolean;
begin
Result := AnsiStrLIComp(PChar(Text) + I, PChar(M1), Length(M1)) = 0;
if Result then
Inc(I, Length(M1));
end;
function CmpL(M1: string): Boolean;
begin
Result := Cmp(M1 + '>');
end;
function CmpL1(M1: string): Boolean;
begin
Result := Cmp1(M1 + '>');
end;
procedure Draw(const M: string);
begin
if not Assigned(Canvas) then
Exit;
if not CalcWidth then
Canvas.TextOut(Rect.Left, Rect.Top, M);
Rect.Left := Rect.Left + Canvas.TextWidth(M);
end;
procedure Style(const Style: TFontStyle; const Include: Boolean);
begin
if not Assigned(Canvas) then
Exit;
if Include then
Canvas.Font.Style := Canvas.Font.Style + [Style]
else
Canvas.Font.Style := Canvas.Font.Style - [Style];
end;
begin
PlainItem := '';
oldFontColor := 0; { satisfy compiler }
if Canvas <> nil then
begin
oldFontStyles := Canvas.Font.Style;
oldFontColor := Canvas.Font.Color;
end;
try
if HideSelColor and Assigned(Canvas) then
begin
Canvas.Brush.Color := clWindow;
Canvas.Font.Color := clWindowText;
end;
if Assigned(Canvas) then
Canvas.FillRect(Rect);
Width := Rect.Left;
Rect.Left := Rect.Left + 2;
OriRect := Rect; //save origin rectangle
M1 := '';
I := 1;
while I <= Length(Text) do
begin
if (Text[I] = '<') and
(CmpL('b') or CmpL('/b') or
CmpL('i') or CmpL('/i') or
CmpL('u') or CmpL('/u') or
Cmp('c:')) then
begin
Draw(M1);
PlainItem := PlainItem + M1;
if CmpL1('b') then
Style(fsBold, True)
else
if CmpL1('/b') then
Style(fsBold, False)
else
if CmpL1('i') then
Style(fsItalic, True)
else
if CmpL1('/i') then
Style(fsItalic, False)
else
if CmpL1('u') then
Style(fsUnderline, True)
else
if CmpL1('/u') then
Style(fsUnderline, False)
else
if Cmp1('c:') then
begin
CL := SubStr(PChar(Text) + I, 0, '>');
if (HideSelColor or not (odSelected in State)) and Assigned(Canvas) then
try
if (Length(CL) > 0) and (CL[1] <> '$') then
Canvas.Font.Color := StringToColor('cl' + CL)
else
Canvas.Font.Color := StringToColor(CL);
except
end;
Inc(I, Length(CL) + 1 {'>'});
end;
M1 := '';
end
else
// next lines were added
if (Text[I] = Chr(13)) and Cmp1(string(Chr(10))) then
begin
// new line
Draw(M1);
PlainItem := PlainItem + M1;
Rect.Left := OriRect.Left;
Rect.Top := Rect.Top + Canvas.TextHeight(M1);
M1 := '';
end
else
// add text
M1 := M1 + Text[I];
Inc(I);
end; { for }
Draw(M1);
PlainItem := PlainItem + M1;
finally
if Canvas <> nil then
begin
Canvas.Font.Style := oldFontStyles;
Canvas.Font.Color := oldFontColor;
end;
end;
Width := Rect.Left - Width + 2;
end;
function ItemHtDraw(Canvas: TCanvas; Rect: TRect;
const State: TOwnerDrawState; const Text: string;
const HideSelColor: Boolean): string;
var
S: string;
W: Integer;
begin
ItemHtDrawEx(Canvas, Rect, State, Text, HideSelColor, S, W, False);
end;
function ItemHtPlain(const Text: string): string;
var
S: string;
W: Integer;
begin
ItemHtDrawEx(nil, Rect(0, 0, -1, -1), [], Text, False, S, W, False);
Result := S;
end;
function ItemHtWidth(Canvas: TCanvas; Rect: TRect;
const State: TOwnerDrawState; const Text: string;
const HideSelColor: Boolean): Integer;
var
S: string;
W: Integer;
begin
ItemHtDrawEx(Canvas, Rect, State, Text, HideSelColor, S, W, True);
Result := W;
end;
procedure ClearList(List: TList);
var
I: Integer;
begin
if not Assigned(List) then
Exit;
for I := 0 to List.Count - 1 do
TObject(List[I]).Free;
List.Clear;
end;
procedure MemStreamToClipBoard(MemStream: TMemoryStream; const Format: Word);
var
Data: THandle;
DataPtr: Pointer;
begin
Clipboard.Open;
try
Data := GlobalAlloc(GMEM_MOVEABLE, MemStream.Size);
try
DataPtr := GlobalLock(Data);
try
Move(MemStream.Memory^, DataPtr^, MemStream.Size);
Clipboard.Clear;
SetClipboardData(Format, Data);
finally
GlobalUnlock(Data);
end;
except
GlobalFree(Data);
raise;
end;
finally
Clipboard.Close;
end;
end;
procedure ClipBoardToMemStream(MemStream: TMemoryStream; const Format: Word);
var
Data: THandle;
DataPtr: Pointer;
begin
Clipboard.Open;
try
Data := GetClipboardData(Format);
if Data = 0 then
Exit;
DataPtr := GlobalLock(Data);
if DataPtr = nil then
Exit;
try
MemStream.WriteBuffer(DataPtr^, GlobalSize(Data));
MemStream.Position := 0;
finally
GlobalUnlock(Data);
end;
finally
Clipboard.Close;
end;
end;
function GetPropType(Obj: TObject; const PropName: string): TTypeKind;
var
PropInf: PPropInfo;
begin
PropInf := GetPropInfo(Obj.ClassInfo, PropName);
if PropInf = nil then
Result := tkUnknown
else
Result := PropInf^.PropType^.Kind;
end;
function GetPropStr(Obj: TObject; const PropName: string): string;
var
PropInf: PPropInfo;
begin
PropInf := GetPropInfo(Obj.ClassInfo, PropName);
if PropInf = nil then
raise Exception.CreateFmt(SPropertyNotExists, [PropName]);
if not (PropInf^.PropType^.Kind in
[tkString, tkLString {$IFDEF COMPILER3_UP}, tkWString {$ENDIF COMPILER3_UP}]) then
raise Exception.CreateFmt(SInvalidPropertyType, [PropName]);
Result := GetStrProp(Obj, PropInf);
end;
function GetPropOrd(Obj: TObject; const PropName: string): Integer;
var
PropInf: PPropInfo;
begin
PropInf := GetPropInfo(Obj.ClassInfo, PropName);
if PropInf = nil then
raise Exception.CreateFmt(SPropertyNotExists, [PropName]);
if not (PropInf^.PropType^.Kind in
[tkInteger, tkChar, tkWChar, tkEnumeration, tkClass]) then
raise Exception.CreateFmt(SInvalidPropertyType, [PropName]);
Result := GetOrdProp(Obj, PropInf);
end;
function GetPropMethod(Obj: TObject; const PropName: string): TMethod;
var
PropInf: PPropInfo;
begin
PropInf := GetPropInfo(Obj.ClassInfo, PropName);
if PropInf = nil then
raise Exception.CreateFmt(SPropertyNotExists, [PropName]);
if not (PropInf^.PropType^.Kind = tkMethod) then
raise Exception.CreateFmt(SInvalidPropertyType, [PropName]);
Result := GetMethodProp(Obj, PropInf);
end;
procedure PrepareIniSection(SS: TStrings);
var
I: Integer;
S: string;
begin
I := 0;
while I < Ss.Count do
begin
S := Trim(Ss[I]);
if (Length(S) = 0) or (S[1] in [';', '#']) then
Ss.Delete(I)
else
Inc(I);
end;
end;
{:Creates a TPointL structure from a pair of coordinates.
Call PointL to create a TPointL structure that represents the specified
coordinates. Use PointL to construct parameters for functions
that require a TPointL, rather than setting up local variables
for each parameter.
@param X The X coordinate.
@param Y The Y coordinate.
@return A TPointL structure for coordinates X and Y.
@example <Code>
var
p: TPointL;
begin
p := PointL(100, 100);
end;
</Code>
}
function PointL(const X, Y: Longint): TPointL;
begin
Result.X := X;
Result.Y := Y;
end;
{:Conditional assignment.
Returns the value in True or False depending on the condition Test.
@param Test The test condition.
@param True Returns this value if Test is True.
@param False Returns this value if Test is False.
@return Value in True or False depending on Test.
@example <Code>
bar := iif(foo, 1, 0);
</Code>
<br>has the same effects as:<br>
<Code>
if foo then
bar := 1
else
bar := 0;
</Code>
}
function iif(const Test: Boolean; const ATrue, AFalse: Variant): Variant;
begin
if Test then
Result := ATrue
else
Result := AFalse;
end;
end.