mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
413 lines
No EOL
11 KiB
ObjectPascal
413 lines
No EOL
11 KiB
ObjectPascal
{
|
|
Double Commander
|
|
-------------------------------------------------------------------------
|
|
(DSX) Search plugin API implementation.
|
|
DSX - Double commander Search eXtentions.
|
|
|
|
Copyright (C) 2008 Dmitry Kolomiets (B4rr4cuda@rambler.ru)
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
}
|
|
|
|
unit uDsxModule;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, dynlibs, LCLProc, DsxPlugin, uClassesEx, uDCUtils,
|
|
uOSUtils, uXmlConfig;
|
|
|
|
type
|
|
|
|
{ TDsxModule }
|
|
|
|
TDsxModule = class
|
|
protected
|
|
SStartSearch: TSStartSearch;
|
|
SStopSearch: TSStopSearch;
|
|
SAddFileProc: TSAddFileProc;
|
|
SUpdateStatusProc: TSUpdateStatusProc;
|
|
SInit: TSInit;
|
|
SFinalize: TSFinalize;
|
|
private
|
|
FPluginNr: integer;
|
|
FModuleHandle: TLibHandle; // Handle to .DLL or .so
|
|
function GIsLoaded: boolean;
|
|
public
|
|
Name: string;
|
|
FileName: string;
|
|
Descr: string;
|
|
//---------------------
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
//---------------------
|
|
function LoadModule: boolean;
|
|
procedure UnloadModule;
|
|
//---------------------
|
|
function CallInit(pAddFileProc: TSAddFileProc; pUpdateStatus: TSUpdateStatusProc): integer;
|
|
procedure CallStartSearch(SearchRec: TDsxSearchRecord);
|
|
procedure CallStopSearch;
|
|
procedure CallFinalize;
|
|
//---------------------
|
|
property IsLoaded: boolean read GIsLoaded;
|
|
property ModuleHandle: TLibHandle read FModuleHandle write FModuleHandle;
|
|
end;
|
|
|
|
{ TDSXModuleList }
|
|
|
|
TDSXModuleList = class
|
|
private
|
|
Flist: TStringList;
|
|
function GetCount: integer;
|
|
public
|
|
//---------------------
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
//---------------------
|
|
procedure Clear;
|
|
procedure Load(Ini: TIniFileEx); overload;
|
|
procedure Load(AConfig: TXmlConfig; ANode: TXmlNode); overload;
|
|
procedure Save(Ini: TIniFileEx); overload;
|
|
procedure Save(AConfig: TXmlConfig; ANode: TXmlNode); overload;
|
|
procedure DeleteItem(Index: integer);
|
|
//---------------------
|
|
function Add(Item: TDSXModule): integer; overload;
|
|
function Add(FileName: string): integer; overload;
|
|
function Add(AName, FileName, Descr: string): integer; overload;
|
|
//---------------------
|
|
procedure Assign(OtherList: TDSXModuleList);
|
|
//---------------------
|
|
function IsLoaded(AName: string): boolean; overload;
|
|
function IsLoaded(Index: integer): boolean; overload;
|
|
function LoadModule(AName: string): boolean; overload;
|
|
function LoadModule(Index: integer): boolean; overload;
|
|
//---------------------
|
|
function GetDSXModule(Index: integer): TDSXModule; overload;
|
|
function GetDSXModule(AName: string): TDSXModule; overload;
|
|
//---------------------
|
|
property Count: integer read GetCount;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
uGlobs, uGlobsPaths;
|
|
|
|
const
|
|
DsxIniFileName = 'dsx.ini';
|
|
|
|
{ TDsxModule }
|
|
|
|
function TDsxModule.GIsLoaded: boolean;
|
|
begin
|
|
Result := FModuleHandle <> 0;
|
|
end;
|
|
|
|
constructor TDsxModule.Create;
|
|
begin
|
|
FModuleHandle := 0;
|
|
inherited Create;
|
|
end;
|
|
|
|
destructor TDsxModule.Destroy;
|
|
begin
|
|
if GIsLoaded then
|
|
UnloadModule;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TDsxModule.LoadModule: boolean;
|
|
begin
|
|
FModuleHandle := mbLoadLibrary(Self.FileName);
|
|
Result := (FModuleHandle <> 0);
|
|
if FModuleHandle = 0 then
|
|
exit;
|
|
|
|
SStopSearch := TSStopSearch(GetProcAddress(FModuleHandle, 'StopSearch'));
|
|
SStartSearch := TSStartSearch(GetProcAddress(FModuleHandle, 'StartSearch'));
|
|
SInit := TSInit(GetProcAddress(FModuleHandle, 'Init'));
|
|
SFinalize := TSFinalize(GetProcAddress(FModuleHandle, 'Finalize'));
|
|
end;
|
|
|
|
procedure TDsxModule.UnloadModule;
|
|
begin
|
|
if Assigned(SFinalize) then
|
|
SFinalize(FPluginNr);
|
|
|
|
if FModuleHandle <> 0 then
|
|
FreeLibrary(FModuleHandle);
|
|
FModuleHandle := 0;
|
|
|
|
SStartSearch := nil;
|
|
SStopSearch := nil;
|
|
SInit := nil;
|
|
SFinalize := nil;
|
|
end;
|
|
|
|
function TDsxModule.CallInit(pAddFileProc: TSAddFileProc; pUpdateStatus: TSUpdateStatusProc): integer;
|
|
var
|
|
dps: TDsxDefaultParamStruct;
|
|
begin
|
|
if Assigned(SInit) then
|
|
begin
|
|
dps.DefaultIniName := gpCfgDir + DsxIniFileName;
|
|
dps.PluginInterfaceVersionHi := 0;
|
|
dps.PluginInterfaceVersionLow := 10;
|
|
dps.size := SizeOf(TDsxDefaultParamStruct);
|
|
FPluginNr := Sinit(@dps, pAddFileProc, pUpdateStatus);
|
|
Result := FPluginNr;
|
|
end;
|
|
end;
|
|
|
|
procedure TDsxModule.CallStartSearch(SearchRec: TDsxSearchRecord);
|
|
begin
|
|
if Assigned(SStartSearch) then
|
|
SStartSearch(FPluginNr, @SearchRec);
|
|
end;
|
|
|
|
procedure TDsxModule.CallStopSearch;
|
|
begin
|
|
if Assigned(SStopSearch) then
|
|
SStopSearch(FPluginNr);
|
|
end;
|
|
|
|
procedure TDsxModule.CallFinalize;
|
|
begin
|
|
if Assigned(SFinalize) then
|
|
SFinalize(FPluginNr);
|
|
end;
|
|
|
|
{ TDSXModuleList }
|
|
|
|
function TDSXModuleList.GetCount: integer;
|
|
begin
|
|
if Assigned(Flist) then
|
|
Result := Flist.Count
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
constructor TDSXModuleList.Create;
|
|
begin
|
|
Flist := TStringList.Create;
|
|
end;
|
|
|
|
destructor TDSXModuleList.Destroy;
|
|
begin
|
|
Clear;
|
|
FreeAndNil(Flist);
|
|
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TDSXModuleList.Clear;
|
|
begin
|
|
while Flist.Count > 0 do
|
|
begin
|
|
TDSXModule(Flist.Objects[0]).Free;
|
|
Flist.Delete(0);
|
|
end;
|
|
end;
|
|
|
|
procedure TDSXModuleList.Load(Ini: TIniFileEx);
|
|
var
|
|
xCount, I: integer;
|
|
tmp: string;
|
|
begin
|
|
Self.Clear;
|
|
xCount := Ini.ReadInteger('Search Plugins', 'PluginCount', 0);
|
|
if xCount = 0 then
|
|
Exit;
|
|
|
|
for i := 0 to xCount - 1 do
|
|
begin
|
|
tmp := Ini.ReadString('Search Plugins', 'Plugin' + IntToStr(I + 1) + 'Name', '');
|
|
Flist.AddObject(UpCase(tmp), TDSXModule.Create);
|
|
TDSXModule(Flist.Objects[I]).Name := tmp;
|
|
TDSXModule(Flist.Objects[I]).Descr :=
|
|
Ini.ReadString('Search Plugins', 'Plugin' + IntToStr(I + 1) + 'Description', '');
|
|
TDSXModule(Flist.Objects[I]).FileName :=
|
|
GetCmdDirFromEnvVar(Ini.ReadString('Search Plugins', 'Plugin' + IntToStr(I + 1) + 'Path', ''));
|
|
end;
|
|
end;
|
|
|
|
procedure TDSXModuleList.Load(AConfig: TXmlConfig; ANode: TXmlNode);
|
|
var
|
|
AName, APath: String;
|
|
ADsxModule: TDSXModule;
|
|
begin
|
|
Clear;
|
|
|
|
ANode := ANode.FindNode('DsxPlugins');
|
|
if Assigned(ANode) then
|
|
begin
|
|
ANode := ANode.FirstChild;
|
|
while Assigned(ANode) do
|
|
begin
|
|
if ANode.CompareName('DsxPlugin') = 0 then
|
|
begin
|
|
if AConfig.TryGetValue(ANode, 'Name', AName) and
|
|
AConfig.TryGetValue(ANode, 'Path', APath) then
|
|
begin
|
|
ADsxModule := TDsxModule.Create;
|
|
Flist.AddObject(UpCase(AName), ADsxModule);
|
|
ADsxModule.Name := AName;
|
|
ADsxModule.FileName := GetCmdDirFromEnvVar(APath);
|
|
ADsxModule.Descr := AConfig.GetValue(ANode, 'Description', '');
|
|
end
|
|
else
|
|
DebugLn('Invalid entry in configuration: ' + AConfig.GetPathFromNode(ANode) + '.');
|
|
end;
|
|
ANode := ANode.NextSibling;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TDSXModuleList.Save(Ini: TIniFileEx);
|
|
var
|
|
i: integer;
|
|
begin
|
|
Ini.EraseSection('Search Plugins');
|
|
Ini.WriteInteger('Search Plugins', 'PluginCount', Flist.Count);
|
|
for i := 0 to Flist.Count - 1 do
|
|
begin
|
|
Ini.WriteString('Search Plugins', 'Plugin' + IntToStr(I + 1) + 'Name',
|
|
TDSXModule(Flist.Objects[I]).Name);
|
|
Ini.WriteString('Search Plugins', 'Plugin' + IntToStr(I + 1) +
|
|
'Description', TDSXModule(Flist.Objects[I]).Descr);
|
|
Ini.WriteString('Search Plugins', 'Plugin' + IntToStr(I + 1) + 'Path',
|
|
SetCmdDirAsEnvVar(TDSXModule(Flist.Objects[I]).FileName));
|
|
end;
|
|
end;
|
|
|
|
procedure TDSXModuleList.Save(AConfig: TXmlConfig; ANode: TXmlNode);
|
|
var
|
|
i: Integer;
|
|
SubNode: TXmlNode;
|
|
begin
|
|
ANode := AConfig.FindNode(ANode, 'DsxPlugins', True);
|
|
AConfig.ClearNode(ANode);
|
|
|
|
for i := 0 to Flist.Count - 1 do
|
|
begin
|
|
SubNode := AConfig.AddNode(ANode, 'DsxPlugin');
|
|
AConfig.AddValue(SubNode, 'Name', TDSXModule(Flist.Objects[I]).Name);
|
|
AConfig.AddValue(SubNode, 'Path', SetCmdDirAsEnvVar(TDSXModule(Flist.Objects[I]).FileName));
|
|
AConfig.AddValue(SubNode, 'Description', TDSXModule(Flist.Objects[I]).Descr);
|
|
end;
|
|
end;
|
|
|
|
procedure TDSXModuleList.DeleteItem(Index: integer);
|
|
begin
|
|
if (Index > -1) and (Index < Flist.Count) then
|
|
begin
|
|
TDSXModule(Flist.Objects[Index]).Free;
|
|
Flist.Delete(Index);
|
|
end;
|
|
end;
|
|
|
|
function TDSXModuleList.Add(Item: TDSXModule): integer;
|
|
begin
|
|
Result := Flist.AddObject(UpCase(item.Name), Item);
|
|
end;
|
|
|
|
function TDSXModuleList.Add(FileName: string): integer;
|
|
var
|
|
s: string;
|
|
begin
|
|
s := ExtractFileName(FileName);
|
|
if pos('.', s) > 0 then
|
|
Delete(s, pos('.', s), length(s));
|
|
Result := Flist.AddObject(UpCase(s), TDSXModule.Create);
|
|
TDSXModule(Flist.Objects[Result]).Name := s;
|
|
TDSXModule(Flist.Objects[Result]).FileName := FileName;
|
|
end;
|
|
|
|
function TDSXModuleList.Add(AName, FileName, Descr: string): integer;
|
|
begin
|
|
Result := Flist.AddObject(UpCase(AName), TDSXModule.Create);
|
|
TDSXModule(Flist.Objects[Result]).Name := AName;
|
|
TDSXModule(Flist.Objects[Result]).Descr := Descr;
|
|
TDSXModule(Flist.Objects[Result]).FileName := FileName;
|
|
end;
|
|
|
|
procedure TDSXModuleList.Assign(OtherList: TDSXModuleList);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Clear;
|
|
for i := 0 to OtherList.Flist.Count - 1 do
|
|
begin
|
|
with TDSXModule(OtherList.Flist.Objects[I]) do
|
|
Add(Name, FileName, Descr);
|
|
end;
|
|
end;
|
|
|
|
function TDSXModuleList.IsLoaded(AName: string): boolean;
|
|
var
|
|
x: integer;
|
|
begin
|
|
x := Flist.IndexOf(AName);
|
|
if x = -1 then
|
|
Result := False
|
|
else
|
|
begin
|
|
Result := GetDSXModule(x).IsLoaded;
|
|
end;
|
|
end;
|
|
|
|
function TDSXModuleList.IsLoaded(Index: integer): boolean;
|
|
begin
|
|
Result := GetDSXModule(Index).IsLoaded;
|
|
end;
|
|
|
|
function TDSXModuleList.LoadModule(AName: string): boolean;
|
|
var
|
|
x: integer;
|
|
begin
|
|
x := Flist.IndexOf(UpCase(AName));
|
|
if x = -1 then
|
|
Result := False
|
|
else
|
|
begin
|
|
Result := GetDSXModule(x).LoadModule;
|
|
end;
|
|
end;
|
|
|
|
function TDSXModuleList.LoadModule(Index: integer): boolean;
|
|
begin
|
|
Result := GetDSXModule(Index).LoadModule;
|
|
end;
|
|
|
|
function TDSXModuleList.GetDSXModule(Index: integer): TDSXModule;
|
|
begin
|
|
Result := TDSXModule(Flist.Objects[Index]);
|
|
end;
|
|
|
|
function TDSXModuleList.GetDSXModule(AName: string): TDSXModule;
|
|
var
|
|
tmp: integer;
|
|
begin
|
|
tmp := Flist.IndexOf(upcase(AName));
|
|
if tmp > -1 then
|
|
Result := TDSXModule(Flist.Objects[tmp]);
|
|
end;
|
|
|
|
end.
|
|
|