428 lines
11 KiB
ObjectPascal
428 lines
11 KiB
ObjectPascal
{ rxapputils unit
|
|
|
|
Copyright (C) 2005-2017 Lagunov Aleksey alexs75@yandex.ru and Lazarus team
|
|
original conception from rx library for Delphi (c)
|
|
|
|
This library is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU Library General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or (at your
|
|
option) any later version with the following modification:
|
|
|
|
As a special exception, the copyright holders of this library give you
|
|
permission to link this library with independent modules to produce an
|
|
executable, regardless of the license terms of these independent modules,and
|
|
to copy and distribute the resulting executable under terms of your choice,
|
|
provided that you also meet, for each linked independent module, the terms
|
|
and conditions of the license of that module. An independent module is a
|
|
module which is not derived from or based on this library. If you modify
|
|
this library, you may extend this exception to your version of the library,
|
|
but you are not obligated to do so. If you do not wish to do so, delete this
|
|
exception statement from your version.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; if not, write to the Free Software Foundation,
|
|
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
}
|
|
|
|
unit rxAppUtils;
|
|
|
|
{$I rx.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Controls, IniFiles;
|
|
|
|
const
|
|
{$IFNDEF LINUX}
|
|
AllMask = '*.*';
|
|
{$ELSE}
|
|
AllMask = '*';
|
|
{$ENDIF}
|
|
|
|
var
|
|
DefCompanyName: string = '';
|
|
RegUseAppTitle: Boolean = False;
|
|
|
|
|
|
function GetDefaultSection(Component: TComponent): string;
|
|
procedure GetDefaultIniData(Control: TControl; var IniFileName,
|
|
Section: string; UseRegistry: Boolean = false);
|
|
function GetDefaultIniName: string;
|
|
|
|
type
|
|
TOnGetDefaultIniName = function: string;
|
|
TRxLoggerEvent = procedure( ALogType:TEventType; const ALogMessage:string);
|
|
|
|
const
|
|
OnGetDefaultIniName: TOnGetDefaultIniName = nil;
|
|
OnRxLoggerEvent:TRxLoggerEvent = nil;
|
|
|
|
//Save to IniFile or TRegIniFile string value
|
|
procedure IniWriteString(IniFile: TObject; const Section, Ident,
|
|
Value: string);
|
|
function IniReadString(IniFile: TObject; const Section, Ident,
|
|
Value: string):string;
|
|
|
|
//Save to IniFile or TRegIniFile integer value
|
|
procedure IniWriteInteger(IniFile: TObject; const Section, Ident:string;
|
|
const Value: integer);
|
|
function IniReadInteger(IniFile: TObject; const Section, Ident:string;
|
|
const Value: integer):integer;
|
|
|
|
function GetDefaultIniRegKey: string;
|
|
function RxGetAppConfigDir(Global : Boolean) : String;
|
|
|
|
|
|
procedure InfoBox(const S:string); overload;
|
|
procedure InfoBox(const S:string; Params:array of const); overload;
|
|
|
|
procedure WarningBox(const S:string); overload;
|
|
procedure WarningBox(const S:string; Params:array of const); overload;
|
|
|
|
procedure ErrorBox(const S:string);
|
|
procedure ErrorBox(const S:string; Params:array of const);
|
|
|
|
procedure RxDefaultWriteLog( ALogType:TEventType; const ALogMessage:string);
|
|
function RxDefaultLogFileName:string;
|
|
procedure InitRxLogs;
|
|
|
|
function RxGetKeyboardLayoutName:string;
|
|
|
|
implementation
|
|
uses
|
|
{$IFDEF WINDOWS}
|
|
Windows, windirs,
|
|
{$ENDIF}
|
|
{$IFDEF LINUX}
|
|
X, XKB, xkblib, xlib,
|
|
{$ENDIF}
|
|
Registry, Forms, FileUtil, LazUTF8, LazFileUtils, Dialogs;
|
|
|
|
function RxGetAppConfigDir(Global: Boolean): String;
|
|
{$IFDEF WINDOWS}
|
|
begin
|
|
If Global then
|
|
Result:=GetWindowsSpecialDir(CSIDL_COMMON_APPDATA)
|
|
else
|
|
Result:=GetWindowsSpecialDir(CSIDL_LOCAL_APPDATA);
|
|
If (Result<>'') then
|
|
begin
|
|
if VendorName<>'' then
|
|
Result:=IncludeTrailingPathDelimiter(Result+ UTF8ToSys(VendorName));
|
|
Result:=IncludeTrailingPathDelimiter(Result+UTF8ToSys(ApplicationName));
|
|
end
|
|
else
|
|
Result:=ExcludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))); //IncludeTrailingPathDelimiter(DGetAppConfigDir(Global));
|
|
end;
|
|
{$ELSE}
|
|
begin
|
|
Result:=GetAppConfigDir(Global);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
procedure DoWriteLog(ALogType:TEventType; const ALogMessage:string);
|
|
begin
|
|
if Assigned(OnRxLoggerEvent) then
|
|
OnRxLoggerEvent(ALogType, ALogMessage)
|
|
end;
|
|
|
|
procedure InfoBox(const S: string);
|
|
begin
|
|
MessageDlg(S, mtInformation, [mbOK], 0);
|
|
DoWriteLog(etInfo, S);
|
|
Application.Log(etInfo, S);
|
|
end;
|
|
|
|
procedure InfoBox(const S: string; Params: array of const);
|
|
begin
|
|
InfoBox(Format(S, Params));
|
|
end;
|
|
|
|
procedure WarningBox(const S: string);
|
|
begin
|
|
MessageDlg(S, mtWarning, [mbOK], 0);
|
|
DoWriteLog(etWarning, S);
|
|
Application.Log(etWarning, S);
|
|
end;
|
|
|
|
procedure WarningBox(const S: string; Params: array of const);
|
|
begin
|
|
WarningBox(Format(S, Params));
|
|
end;
|
|
|
|
procedure ErrorBox(const S: string);
|
|
begin
|
|
MessageDlg(S, mtError, [mbOK], 0);
|
|
DoWriteLog(etError, S);
|
|
Application.Log(etError, S);
|
|
end;
|
|
|
|
procedure ErrorBox(const S: string; Params: array of const);
|
|
begin
|
|
ErrorBox(Format(S, Params));
|
|
end;
|
|
|
|
procedure RxDefaultWriteLog(ALogType: TEventType; const ALogMessage: string);
|
|
var
|
|
F: Text;
|
|
S: String;
|
|
const
|
|
sEventNames : array [TEventType] of string =
|
|
('CUSTOM','INFO','WARNING','ERROR','DEBUG');
|
|
begin
|
|
S:=RxDefaultLogFileName;
|
|
if S<>'' then
|
|
begin
|
|
Assign(F, S);
|
|
if FileExists(S) then
|
|
Append(F)
|
|
else
|
|
Rewrite(F);
|
|
|
|
Writeln(F,Format( '|%s| %20s |%s', [sEventNames[ALogType], DateTimeToStr(Now), ALogMessage]));
|
|
CloseFile(F);
|
|
end;
|
|
end;
|
|
|
|
function RxDefaultLogFileName: string;
|
|
begin
|
|
Result:=AppendPathDelim(GetTempDir) + ExtractFileNameOnly(ParamStr(0)) + '.log';
|
|
end;
|
|
|
|
procedure InitRxLogs;
|
|
begin
|
|
OnRxLoggerEvent:=@RxDefaultWriteLog;
|
|
end;
|
|
|
|
{$IFDEF LINUX}
|
|
function getKeyboardLang(dpy:PDisplay; AGroup:Integer):string;
|
|
var
|
|
baseEventCode, baseErrorCode, opcode:integer;
|
|
groupCount:integer;
|
|
major:integer;
|
|
minor:integer;
|
|
kbdDescPtr: PXkbDescPtr;
|
|
tmpGroupSource: TAtom;
|
|
begin
|
|
major:=0;
|
|
minor:=0;
|
|
XkbQueryExtension(dpy, @opcode, @baseEventCode, @baseErrorCode, @major, @minor);
|
|
|
|
kbdDescPtr := XkbAllocKeyboard();
|
|
|
|
if not Assigned(kbdDescPtr) then
|
|
begin
|
|
Result:='Failed to get keyboard description.';
|
|
exit;
|
|
end;
|
|
|
|
kbdDescPtr^.dpy := dpy;
|
|
kbdDescPtr^.device_spec := XkbUseCoreKbd;
|
|
|
|
XkbGetControls(dpy, XkbAllControlsMask, kbdDescPtr);
|
|
XkbGetNames(dpy, XkbSymbolsNameMask, kbdDescPtr);
|
|
XkbGetNames(dpy, XkbGroupNamesMask, kbdDescPtr);
|
|
|
|
if (not Assigned(kbdDescPtr^.names)) then
|
|
begin
|
|
Result:='Failed to get keyboard description.';
|
|
exit;
|
|
end;
|
|
|
|
if AGroup in [0 .. XkbNumKbdGroups -1] then
|
|
begin
|
|
tmpGroupSource := kbdDescPtr^.names^.groups[AGroup];
|
|
Result:=XGetAtomName(dpy, tmpGroupSource);
|
|
end
|
|
else
|
|
Result:='';
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
function RxGetKeyboardLayoutName: string;
|
|
{$IFDEF WINDOWS}
|
|
var
|
|
LayoutName:array [0..KL_NAMELENGTH + 1] of char;
|
|
LangName: array [0 .. 1024] of Char;
|
|
{$ENDIF}
|
|
{$IFDEF LINUX}
|
|
var
|
|
Disp: PDisplay;
|
|
RtrnState: TXkbStateRec;
|
|
{$ENDIF}
|
|
begin
|
|
{$IFDEF WINDOWS}
|
|
GetKeyboardLayoutName(@LayoutName);
|
|
if GetLocaleInfo(StrToInt('$' + StrPas(LayoutName)), LOCALE_SABBREVLANGNAME, @LangName, SizeOf(LangName) - 1) <> 0 then
|
|
Result := StrPas(LangName);
|
|
// end;
|
|
// Result := AnsiUpperCase(Copy(Result, 1, 2));
|
|
{$ELSE}
|
|
{$IFDEF LINUX}
|
|
Disp := XOpenDisplay(nil);
|
|
if Assigned(Disp) then
|
|
begin
|
|
XkbGetState(Disp, XkbUseCoreKbd, @RtrnState);
|
|
Result:=getKeyboardLang(Disp, RtrnState.group);
|
|
XCloseDisplay(Disp);
|
|
end
|
|
else
|
|
Result:='';
|
|
{$ELSE}
|
|
//Other system - maybe in future?
|
|
Result:='';
|
|
{$ENDIF LINUX}
|
|
{$ENDIF WINDOWS}
|
|
end;
|
|
|
|
|
|
function GetDefaultSection(Component: TComponent): string;
|
|
var
|
|
F: TCustomForm;
|
|
Owner: TComponent;
|
|
begin
|
|
if Component <> nil then begin
|
|
if Component is TCustomForm then Result := Component.ClassName
|
|
else begin
|
|
Result := Component.Name;
|
|
if Component is TControl then begin
|
|
F := GetParentForm(TControl(Component));
|
|
if F <> nil then Result := F.ClassName + Result
|
|
else begin
|
|
if TControl(Component).Parent <> nil then
|
|
Result := TControl(Component).Parent.Name + Result;
|
|
end;
|
|
end
|
|
else begin
|
|
Owner := Component.Owner;
|
|
if Owner is TForm then
|
|
Result := Format('%s.%s', [Owner.ClassName, Result]);
|
|
end;
|
|
end;
|
|
end
|
|
else Result := '';
|
|
end;
|
|
|
|
function GetDefaultIniName: string;
|
|
var
|
|
S:string;
|
|
begin
|
|
if Assigned(OnGetDefaultIniName) then
|
|
Result:= OnGetDefaultIniName()
|
|
else
|
|
begin
|
|
Result := ExtractFileName(ChangeFileExt(Application.ExeName, '.ini'));
|
|
S:=RxGetAppConfigDir(false);
|
|
S:=SysToUTF8(S);
|
|
ForceDirectoriesUTF8(S);
|
|
Result:=S+Result;
|
|
end;
|
|
end;
|
|
|
|
procedure GetDefaultIniData(Control: TControl; var IniFileName,
|
|
Section: string; UseRegistry: Boolean );
|
|
var
|
|
I: Integer;
|
|
begin
|
|
IniFileName := EmptyStr;
|
|
{ with Control do
|
|
if Owner is TCustomForm then
|
|
for I := 0 to Owner.ComponentCount - 1 do
|
|
if (Owner.Components[I] is TFormPropertyStorage) then
|
|
begin
|
|
IniFileName := TFormPropertyStorage(Owner.Components[I]).IniFileName;
|
|
Break;
|
|
end;}
|
|
Section := GetDefaultSection(Control);
|
|
if IniFileName = EmptyStr then
|
|
if UseRegistry then IniFileName := GetDefaultIniRegKey
|
|
else
|
|
IniFileName := GetDefaultIniName;
|
|
end;
|
|
|
|
procedure IniWriteString(IniFile: TObject; const Section, Ident,
|
|
Value: string);
|
|
var
|
|
S: string;
|
|
begin
|
|
if IniFile is TRegIniFile then
|
|
TRegIniFile(IniFile).WriteString(Section, Ident, Value)
|
|
else
|
|
begin
|
|
S := Value;
|
|
if S <> '' then
|
|
begin
|
|
if ((S[1] = '"') and (S[Length(S)] = '"')) or
|
|
((S[1] = '''') and (S[Length(S)] = '''')) then
|
|
S := '"' + S + '"';
|
|
end;
|
|
if IniFile is TIniFile then
|
|
TIniFile(IniFile).WriteString(Section, Ident, S);
|
|
end;
|
|
end;
|
|
|
|
function IniReadString(IniFile: TObject; const Section, Ident, Value: string
|
|
): string;
|
|
var
|
|
S: string;
|
|
begin
|
|
if IniFile is TRegIniFile then
|
|
Result:=TRegIniFile(IniFile).ReadString(Section, Ident, Value)
|
|
else
|
|
begin
|
|
S := Value;
|
|
if S <> '' then begin
|
|
if ((S[1] = '"') and (S[Length(S)] = '"')) or
|
|
((S[1] = '''') and (S[Length(S)] = '''')) then
|
|
S := '"' + S + '"';
|
|
end;
|
|
if IniFile is TIniFile then
|
|
Result:=TIniFile(IniFile).ReadString(Section, Ident, S);
|
|
end;
|
|
end;
|
|
|
|
procedure IniWriteInteger(IniFile: TObject; const Section, Ident: string;
|
|
const Value: integer);
|
|
begin
|
|
if IniFile is TRegIniFile then
|
|
TRegIniFile(IniFile).WriteInteger(Section, Ident, Value)
|
|
else
|
|
begin
|
|
if IniFile is TIniFile then
|
|
TIniFile(IniFile).WriteInteger(Section, Ident, Value);
|
|
end;
|
|
end;
|
|
|
|
function IniReadInteger(IniFile: TObject; const Section, Ident: string;
|
|
const Value: integer): integer;
|
|
begin
|
|
if IniFile is TRegIniFile then
|
|
Result:=TRegIniFile(IniFile).ReadInteger(Section, Ident, Value)
|
|
else
|
|
begin
|
|
if IniFile is TIniFile then
|
|
Result:=TIniFile(IniFile).ReadInteger(Section, Ident, Value);
|
|
end;
|
|
end;
|
|
|
|
function GetDefaultIniRegKey: string;
|
|
begin
|
|
if RegUseAppTitle and (Application.Title <> '') then
|
|
Result := Application.Title
|
|
else Result := ExtractFileName(ChangeFileExt(Application.ExeName, ''));
|
|
if DefCompanyName <> '' then
|
|
Result := DefCompanyName + '\' + Result;
|
|
Result := 'Software\' + Result;
|
|
end;
|
|
|
|
|
|
end.
|
|
|