doublecmd/src/ufilefunctions.pas
2015-05-01 09:00:00 +00:00

436 lines
13 KiB
ObjectPascal

{
Double Commander
-------------------------------------------------------------------------
Filepanel columns implementation unit
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 uFileFunctions;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Menus, uFile, uFileProperty, uFileSource;
type
TFileFunction = (fsfName,
fsfExtension,
fsfSize,
fsfAttr,
fsfPath,
fsfGroup,
fsfOwner,
fsfModificationTime,
fsfCreationTime,
fsfLastAccessTime,
fsfLinkTo,
fsfNameNoExtension,
fsfType,
fsfComment,
fsfCompressedSize,
fsfInvalid);
TFileFunctions = array of TFileFunction;
const TFileFunctionStrings: array [TFileFunction] of string
= ('GETFILENAME',
'GETFILEEXT',
'GETFILESIZE',
'GETFILEATTR',
'GETFILEPATH',
'GETFILEGROUP',
'GETFILEOWNER',
'GETFILETIME',
'GETFILECREATIONTIME',
'GETFILELASTACCESSTIME',
'GETFILELINKTO',
'GETFILENAMENOEXT',
'GETFILETYPE',
'GETFILECOMMENT',
'GETFILECOMPRESSEDSIZE',
'' // fsfInvalid
);
// Which file properties must be supported for each file function to work.
const TFileFunctionToProperty: array [TFileFunction] of TFilePropertiesTypes
= ([fpName],
[fpName],
[fpSize],
[fpAttributes],
[] { path },
[fpOwner],
[fpOwner],
[fpModificationTime],
[fpCreationTime],
[fpLastAccessTime],
[fpLink],
[fpName],
[fpType],
[fpComment],
[fpCompressedSize],
[] { invalid });
function FormatFileFunction(FuncS: string; AFile: TFile; const AFileSource: IFileSource; RetrieveProperties: Boolean = False): string;
function FormatFileFunctions(FuncS: String; AFile: TFile; const AFileSource: IFileSource): String;
function GetFileFunctionByName(FuncS: string): TFileFunction;
procedure FillContentFieldMenu(MenuItem: TMenuItem; OnMenuItemClick: TNotifyEvent);
procedure FillFileFuncList;
const
sFuncTypeDC = 'DC';
sFuncTypePlugin = 'PLUGIN';
var
FileFunctionsStr: TStringList;
implementation
uses
StrUtils, WdxPlugin, uWdxModule, uGlobs, uLng, uDefaultFilePropertyFormatter, uFileSourceProperty;
//Return type (Script or DC or Plugin etc)
function GetModType(str: String): String;
begin
if pos('(', Str) > 0 then
Result := Copy(Str, 1, pos('(', Str) - 1)
else
Result := EmptyStr;
end;
//Return name in (). (SriptName or PluginName etc)
function GetModName(str: String): String;
var
s: String;
begin
s := str;
if pos('(', S) > 0 then
Delete(s, 1, pos('(', S))
else
Exit(EmptyStr);
if pos(')', s) > 0 then
Result := Copy(s, 1, pos(')', s) - 1);
end;
//Return function name (DCFunction,PluginFunction etc)
function GetModFunctionName(str: String): String;
var
s: String;
begin
s := str;
if pos('.', S) > 0 then
Delete(s, 1, pos('.', S))
else
Exit(EmptyStr);
if pos('{', S) > 0 then
Result := Copy(s, 1, pos('{', S) - 1);
end;
// Return function parameters
function GetModFunctionParams(str: String): String;
var
I: Integer;
S: String;
begin
S := str;
I := pos('{', S);
if I < 0 then
Exit(EmptyStr);
Delete(S, 1, I);
I := pos('}', S);
if I < 0 then
Exit(EmptyStr);
Result := Copy(S, 1, I - 1);
end;
function FormatFileFunction(FuncS: String; AFile: TFile; const AFileSource: IFileSource; RetrieveProperties: Boolean = False): String;
var
AIndex: Integer;
AType, AName, AFunc, AParam: String;
FileFunction: TFileFunction;
FilePropertiesNeeded: TFilePropertiesTypes;
begin
Result := EmptyStr;
//---------------------
AType := upcase(GetModType(FuncS));
AName := upcase(GetModName(FuncS));
AFunc := upcase(GetModFunctionName(FuncS));
AParam := upcase(GetModFunctionParams(FuncS));
//---------------------
//Internal doublecmd function
//------------------------------------------------------
if AType = sFuncTypeDC then
begin
AIndex:= FileFunctionsStr.IndexOfName(AFunc);
if AIndex < 0 then Exit;
FileFunction:= TFileFunction(AIndex);
// Retrieve additional properties if needed
if RetrieveProperties then
begin
FilePropertiesNeeded:= TFileFunctionToProperty[FileFunction];
if aFileSource.CanRetrieveProperties(AFile, FilePropertiesNeeded) then
aFileSource.RetrieveProperties(AFile, FilePropertiesNeeded);
end;
case FileFunction of
fsfName:
begin
// Show square brackets around directories
if gDirBrackets and (AFile.IsDirectory or
AFile.IsLinkToDirectory) then
Result := '[' + AFile.Name + ']'
else
Result := AFile.Name;
end;
fsfExtension:
begin
Result := AFile.Extension;
end;
fsfSize:
begin
if (AFile.IsDirectory or AFile.IsLinkToDirectory) and
((not (fpSize in AFile.SupportedProperties)) or (AFile.Size = 0))
then
Result := '<DIR>'
else if fpSize in AFile.SupportedProperties then
Result := AFile.Properties[fpSize].Format(DefaultFilePropertyFormatter);
end;
fsfAttr:
if fpAttributes in AFile.SupportedProperties then
Result := AFile.Properties[fpAttributes].Format(DefaultFilePropertyFormatter);
fsfPath:
Result := AFile.Path;
fsfGroup:
if fpOwner in AFile.SupportedProperties then
Result := AFile.OwnerProperty.GroupStr;
fsfOwner:
if fpOwner in AFile.SupportedProperties then
Result := AFile.OwnerProperty.OwnerStr;
fsfModificationTime:
if fpModificationTime in AFile.SupportedProperties then
Result := AFile.Properties[fpModificationTime].Format(
DefaultFilePropertyFormatter);
fsfCreationTime:
if fpCreationTime in AFile.SupportedProperties then
Result := AFile.Properties[fpCreationTime].Format(
DefaultFilePropertyFormatter);
fsfLastAccessTime:
if fpLastAccessTime in AFile.SupportedProperties then
Result := AFile.Properties[fpLastAccessTime].Format(
DefaultFilePropertyFormatter);
fsfLinkTo:
if fpLink in AFile.SupportedProperties then
Result := AFile.LinkProperty.LinkTo;
fsfNameNoExtension:
begin
// Show square brackets around directories
if gDirBrackets and (AFile.IsDirectory or
AFile.IsLinkToDirectory) then
Result := '[' + AFile.NameNoExt + ']'
else
Result := AFile.NameNoExt;
end;
fsfType:
if fpType in AFile.SupportedProperties then
Result := AFile.TypeProperty.Format(DefaultFilePropertyFormatter);
fsfComment:
if fpComment in AFile.SupportedProperties then
Result := AFile.CommentProperty.Format(DefaultFilePropertyFormatter);
fsfCompressedSize:
begin
if (AFile.IsDirectory or AFile.IsLinkToDirectory) and
((not (fpCompressedSize in AFile.SupportedProperties)) or (AFile.CompressedSize = 0))
then
Result := '<DIR>'
else if fpCompressedSize in AFile.SupportedProperties then
Result := AFile.Properties[fpCompressedSize].Format(DefaultFilePropertyFormatter);
end;
end;
end
//------------------------------------------------------
//Plugin function
//------------------------------------------------------
else if AType = sFuncTypePlugin then
begin
if fspDirectAccess in AFileSource.Properties then
begin
if not gWdxPlugins.IsLoaded(AName) then
if not gWdxPlugins.LoadModule(AName) then
Exit;
if gWdxPlugins.GetWdxModule(AName).FileParamVSDetectStr(AFile) then
begin
Result := gWdxPlugins.GetWdxModule(AName).CallContentGetValue(
AFile.FullPath, AFunc, AParam, 0);
end;
end;
end;
//------------------------------------------------------
end;
function FormatFileFunctions(FuncS: String; AFile: TFile; const AFileSource: IFileSource): String;
var
P: Integer;
begin
Result:= EmptyStr;
while True do
begin
P := Pos('[', FuncS);
if P = 0 then
Break
else if P > 1 then
Result:= Result + Copy(FuncS, 1, P - 1);
Delete(FuncS, 1, P);
P := Pos(']', FuncS);
if P = 0 then
Break
else if P > 1 then
Result:= Result + FormatFileFunction(Copy(FuncS, 1, P - 1), AFile, AFileSource, True);
Delete(FuncS, 1, P);
end;
if Length(FuncS) <> 0 then
Result:= Result + FuncS;
end;
function GetFileFunctionByName(FuncS: String): TFileFunction;
var
AIndex: Integer;
AType, AFunc: String;
begin
AType := UpCase(GetModType(FuncS));
AFunc := UpCase(GetModFunctionName(FuncS));
// Only internal DC functions.
if AType = sFuncTypeDC then
begin
AIndex := FileFunctionsStr.IndexOfName(AFunc);
if AIndex >= 0 then Exit(TFileFunction(AIndex));
end;
Result := fsfInvalid;
end;
procedure FillContentFieldMenu(MenuItem: TMenuItem; OnMenuItemClick: TNotifyEvent);
var
I, J: Integer;
sUnits: String;
Module: TWDXModule;
Mi, mi2: TMenuItem;
begin
MenuItem.Clear;
// DC commands
MI:= TMenuItem.Create(MenuItem);
MI.Caption:= 'DC';
MenuItem.Add(MI);
for I:= 0 to FileFunctionsStr.Count - 1 do
begin
MI:= TMenuItem.Create(MenuItem);
MI.Tag:= 0;
MI.Hint:= FileFunctionsStr.Names[I];
MI.Caption:= FileFunctionsStr.ValueFromIndex[I] + ' (' + MI.Hint + ')';
MI.OnClick:= OnMenuItemClick;
MenuItem.Items[0].Add(MI);
end;
// Plugins
MI:= TMenuItem.Create(MenuItem);
MI.Caption:= 'Plugins';
MenuItem.Add(MI);
for I:= 0 to gWdxPlugins.Count - 1 do
begin
Module:= gWdxPlugins.GetWdxModule(I);
if not (Module.IsLoaded or Module.LoadModule) then
Continue;
MI:= TMenuItem.Create(MenuItem);
MI.Caption:= Module.Name;
MenuItem.Items[1].Add(MI);
// Load fields list
for J:= 0 to Module.FieldList.Count - 1 do
begin
MI:= TMenuItem.Create(MenuItem);
MI.Tag:= 1;
MI.Caption:= Module.FieldList[J];
MI.OnClick:= OnMenuItemClick;
MenuItem.Items[1].Items[MenuItem.Items[1].Count - 1].Add(MI);
with TWdxField(Module.FieldList.Objects[J]) do
if FType <> ft_multiplechoice then
begin
sUnits:= FUnits;
while sUnits <> EmptyStr do
begin
MI2:=TMenuItem.Create(MenuItem);
MI2.Tag:= 2;
MI2.Caption:= Copy2SymbDel(sUnits, '|');
MI2.OnClick:= OnMenuItemClick;
MI.Add(MI2);
end;
end;
end;
end;
end;
procedure FillFileFuncList;
begin
with FileFunctionsStr do
begin
Add(TFileFunctionStrings[fsfName] + '=' + rsFuncName);
Add(TFileFunctionStrings[fsfExtension] + '=' + rsFuncExt);
Add(TFileFunctionStrings[fsfSize] + '=' + rsFuncSize);
Add(TFileFunctionStrings[fsfAttr] + '=' + rsFuncAttr);
Add(TFileFunctionStrings[fsfPath] + '=' + rsFuncPath);
Add(TFileFunctionStrings[fsfGroup] + '=' + rsFuncGroup);
Add(TFileFunctionStrings[fsfOwner] + '=' + rsFuncOwner);
Add(TFileFunctionStrings[fsfModificationTime] + '=' + rsFuncMTime);
Add(TFileFunctionStrings[fsfCreationTime] + '=' + rsFuncCTime);
Add(TFileFunctionStrings[fsfLastAccessTime] + '=' + rsFuncATime);
Add(TFileFunctionStrings[fsfLinkTo] + '=' + rsFuncLinkTo);
Add(TFileFunctionStrings[fsfNameNoExtension] + '=' + rsFuncNameNoExt);
Add(TFileFunctionStrings[fsfType] + '=' + rsFuncType);
Add(TFileFunctionStrings[fsfComment] + '=' + rsFuncComment);
Add(TFileFunctionStrings[fsfCompressedSize] + '=' + rsFuncCompressedSize);
end;
end;
initialization
FileFunctionsStr := TStringList.Create;
finalization
FreeAndNil(FileFunctionsStr);
end.