unit iac_program;
interface
implementation
uses
editwrapper,
windows, messages, commctrl,
global, iac_global, m_api, wrapper, syswin,
mirutils, mircontacts, common, dbsettings;
{$include i_cnst_program.inc}
{$resource iac_program.res}
const
ACF_CURPATH = $00000001; // Current (not program) path
ACF_PRTHREAD = $00000002; // parallel Program
ACF_PRG_PRG = $00000004; // script for program path
ACF_PRG_ARG = $00000008; // script for program args
const // V2
ACF_OLD_CURPATH = $00000002;
ACF_OLD_PRTHREAD = $00000004;
ACF2_PRG_PRG = $00000001;
ACF2_PRG_ARG = $00000002;
const
opt_prg = 'program';
opt_args = 'arguments';
opt_time = 'time';
opt_show = 'show';
const
ioArgs = 'args';
ioProgram = 'program';
ioCurrent = 'current';
ioParallel = 'parallel';
ioWait = 'wait';
ioFileVariable = 'modvariables';
ioArgVariable = 'argvariables';
ioWindow = 'window';
ioHidden = 'hidden';
ioMinimized = 'minimized';
ioMaximized = 'maximized';
type
tProgramAction = class(tBaseAction)
private
prgname:pWideChar;
args :pWideChar;
show :dword;
time :dword;
public
constructor Create(uid:dword);
destructor Destroy; override;
// function Clone:tBaseAction; override;
function DoAction(var WorkData:tWorkData):LRESULT; override;
procedure Save(node:pointer;fmt:integer); override;
procedure Load(node:pointer;fmt:integer); override;
end;
//----- Support functions -----
function replany(var str:pWideChar;aparam:LPARAM;alast:pWideChar):boolean;
var
buf:array [0..31] of WideChar;
tmp:pWideChar;
begin
if StrScanW(str,'<')<>nil then
begin
result:=true;
mGetMem(tmp,2048);
StrCopyW(tmp,str);
StrReplaceW(tmp,'',IntToStr(buf,aparam));
StrReplaceW(tmp,'' ,alast);
str:=tmp;
end
else
result:=false;
end;
//----- Object realization -----
constructor tProgramAction.Create(uid:dword);
begin
inherited Create(uid);
show :=0;
time :=0;
prgname:=nil;
args :=nil;
end;
destructor tProgramAction.Destroy;
begin
mFreeMem(prgname);
mFreeMem(args);
inherited Destroy;
end;
{
function tProgramAction.Clone:tBaseAction;
begin
result:=tProgramAction.Create(0);
Duplicate(result);
tProgramAction(result).show :=show;
tProgramAction(result).time :=time;
StrDupW(tProgramAction(result).prgname,prgname);
StrDupW(tProgramAction(result).args ,args);
end;
}
function tProgramAction.DoAction(var WorkData:tWorkData):LRESULT;
var
tmp,tmpp,lpath:PWideChar;
replPrg ,replArg :PWideChar;
replPrg1,replArg1:PWideChar;
pd:LPARAM;
vars1,vars2,prgs,argss:boolean;
buf:array [0..31] of WideChar;
begin
result:=0;
if WorkData.ResultType=rtInt then
begin
StrDupW(pWideChar(WorkData.LastResult),IntToStr(buf,WorkData.LastResult));
WorkData.ResultType:=rtWide;
end;
replPrg:=prgname;
prgs :=replany(replPrg,WorkData.Parameter,pWideChar(WorkData.LastResult));
replArg:=args;
argss :=replany(replArg,WorkData.Parameter,pWideChar(WorkData.LastResult));
if ((flags and ACF_PRG_PRG)<>0) or
((flags and ACF_PRG_ARG)<>0) then
begin
if db_is_contact(WorkData.Parameter)<>0 then
pd:=WorkData.Parameter
else
pd:=WndToContact(WaitFocusedWndChild(GetForegroundwindow){GetFocus});
if (pd=0) and (WorkData.Parameter<>0) then
pd:=WorkData.Parameter;
end;
if (flags and ACF_PRG_ARG)<>0 then
begin
vars2:=true;
tmp :=ParseVarString(replArg,pd,pWideChar(WorkData.LastResult));
end
else
begin
vars2:=false;
tmp :=replArg;
end;
if (flags and ACF_PRG_PRG)<>0 then
begin
vars1:=true;
tmpp :=ParseVarString(replPrg,pd,pWideChar(WorkData.LastResult));
end
else
begin
vars1:=false;
tmpp:=replPrg;
end;
if StrScanW(tmpp,'%')<>nil then
begin
mGetMem(replPrg1,8192*SizeOf(WideChar));
ExpandEnvironmentStringsW(tmpp,replPrg1,8191);
if vars1 then mFreeMem(tmpp);
if prgs then mFreeMem(replPrg);
tmpp :=replPrg1;
prgs :=false;
vars1:=true;
end;
if StrScanW(tmp,'%')<>nil then
begin
mGetMem(replArg1,8192*SizeOf(WideChar));
ExpandEnvironmentStringsW(tmp,replArg1,8191);
if vars2 then mFreeMem(tmp);
if argss then mFreeMem(replArg);
tmp :=replArg1;
argss:=false;
vars2:=true;
end;
if (flags and ACF_CURPATH)=0 then
lpath:=ExtractW(tmpp,false)
else
lpath:=nil;
if (flags and ACF_PRTHREAD)<>0 then
time:=0
else if time=0 then
time:=INFINITE;
WorkData.LastResult:=ExecuteWaitW(tmpp,tmp,lpath,show,time,@pd);
WorkData.ResultType:=rtInt;
if vars2 then mFreeMem(tmp);
if vars1 then mFreeMem(tmpp);
if prgs then mFreeMem(replPrg);
if argss then mFreeMem(replArg);
mFreeMem(lpath);
end;
procedure tProgramAction.Load(node:pointer;fmt:integer);
var
section: array [0..127] of AnsiChar;
pc:pAnsiChar;
tmp:pWideChar;
flags2,lflags:dword;
begin
inherited Load(node,fmt);
case fmt of
0: begin
pc:=StrCopyE(section,pAnsiChar(node));
StrCopy(pc,opt_prg ); prgname:=DBReadUnicode(0,DBBranch,section,nil);
StrCopy(pc,opt_args); args :=DBReadUnicode(0,DBBranch,section,nil);
StrCopy(pc,opt_time); time :=DBReadDWord (0,DBBranch,section,0);
StrCopy(pc,opt_show); show :=DBReadDWord (0,DBBranch,section,SW_SHOW);
end;
100: begin
pc:=StrCopyE(section,pAnsiChar(node));
StrCopy(pc,opt_prg ); prgname:=DBReadUnicode(0,DBBranch,section,nil);
StrCopy(pc,opt_args); args :=DBReadUnicode(0,DBBranch,section,nil);
StrCopy(pc,opt_time); time :=DBReadDWord (0,DBBranch,section,0);
StrCopy(pc,opt_show); show :=DBReadDWord (0,DBBranch,section,SW_SHOW);
StrCopy(pc,'flags2'); flags2:=DBReadDWord(0,DBBranch,section,0);
lflags:=flags;
flags:=flags and not ACF_MASK;
if (lflags and ACF_OLD_CURPATH )<>0 then flags:=flags or ACF_CURPATH;
if (lflags and ACF_OLD_PRTHREAD)<>0 then flags:=flags or ACF_PRTHREAD;
if (flags2 and ACF2_PRG_PRG)<>0 then flags:=flags or ACF_PRG_PRG;
if (flags2 and ACF2_PRG_ARG)<>0 then flags:=flags or ACF_PRG_ARG;
end;
1: begin
StrDupW(prgname,xmlGetText(HXML(node)));
StrDupW(args,xmlGetAttrValue(HXML(node),ioArgs));
if StrToInt(xmlGetAttrValue(HXML(node),ioCurrent))=1 then
flags:=flags or ACF_CURPATH;
if StrToInt(xmlGetAttrValue(HXML(node),ioParallel))=1 then
flags:=flags or ACF_PRTHREAD
else
time:=StrToInt(xmlGetAttrValue(HXML(node),ioWait));
if StrToInt(xmlGetAttrValue(HXML(node),ioFileVariable))=1 then
flags:=flags or ACF_PRG_PRG;
if StrToInt(xmlGetAttrValue(HXML(node),ioArgVariable))=1 then
flags:=flags or ACF_PRG_ARG;
tmp:=xmlGetAttrValue(HXML(node),ioWindow);
if lstrcmpiw(tmp,ioHidden )=0 then show:=SW_HIDE
else if lstrcmpiw(tmp,ioMinimized)=0 then show:=SW_SHOWMINIMIZED
else if lstrcmpiw(tmp,ioMaximized)=0 then show:=SW_SHOWMAXIMIZED
else show:=SW_SHOWNORMAL;
end;
{
2: begin
UTF8ToWide(GetParamSectionStr(node,ioProgram),prgname);
UTF8ToWide(GetParamSectionStr(node,ioArgs ),args);
if GetParamSectionInt(node,ioCurrent)=1 then
flags:=flags or ACF_CURPATH;
if GetParamSectionInt(node,ioParallel)=1 then
flags:=flags or ACF_PRTHREAD
else
time:=GetParamSectionInt(node,ioWait);
if GetParamSectionInt(node,ioFileVariable)=1 then
flags:=flags or ACF_PRG_PRG;
if GetParamSectionInt(node,ioArgVariable)=1 then
flags:=flags or ACF_PRG_ARG;
pc:=GetParamSectionStr(node,ioWindow);
if lstrcmpi(pc,ioHidden )=0 then show:=SW_HIDE
else if lstrcmpi(pc,ioMinimized)=0 then show:=SW_SHOWMINIMIZED
else if lstrcmpi(pc,ioMaximized)=0 then show:=SW_SHOWMAXIMIZED
else show:=SW_SHOWNORMAL;
end;
}
end;
end;
procedure tProgramAction.Save(node:pointer;fmt:integer);
var
section: array [0..127] of AnsiChar;
pc:pAnsiChar;
begin
inherited Save(node,fmt);
case fmt of
0: begin
pc:=StrCopyE(section,pAnsiChar(node));
StrCopy(pc,opt_prg ); DBWriteUnicode(0,DBBranch,section,prgname);
StrCopy(pc,opt_args); DBWriteUnicode(0,DBBranch,section,args);
StrCopy(pc,opt_time); DBWriteDWord (0,DBBranch,section,time);
StrCopy(pc,opt_show); DBWriteDWord (0,DBBranch,section,show);
end;
{
1: begin
end;
}
13: begin
end;
end;
end;
//----- Dialog realization -----
procedure MakeFileEncList(wnd:HWND);
begin
SendMessage(wnd,CB_RESETCONTENT,0,0);
{
InsertString(wnd,0,'Ansi');
InsertString(wnd,1,'UTF8');
InsertString(wnd,2,'UTF8+sign');
InsertString(wnd,3,'UTF16');
InsertString(wnd,4,'UTF16+sign');
}
SendMessage(wnd,CB_SETCURSEL,0,0);
end;
procedure ClearFields(Dialog:HWND);
begin
CheckDlgButton(Dialog,IDC_FLAG_NORMAL,BST_UNCHECKED);
CheckDlgButton(Dialog,IDC_FLAG_HIDDEN,BST_UNCHECKED);
CheckDlgButton(Dialog,IDC_FLAG_MINIMIZE,BST_UNCHECKED);
CheckDlgButton(Dialog,IDC_FLAG_MAXIMIZE,BST_UNCHECKED);
CheckDlgButton(Dialog,IDC_FLAG_CURPATH,BST_UNCHECKED);
CheckDlgButton(Dialog,IDC_FLAG_CONTINUE,BST_UNCHECKED);
CheckDlgButton(Dialog,IDC_FLAG_PARALLEL,BST_UNCHECKED);
end;
function FillFileName(Dialog:HWND;idc:integer):boolean;
var
pw,ppw:pWideChar;
begin
mGetMem(pw,1024*SizeOf(WideChar));
ppw:=GetDlgText(Dialog,idc);
result:=ShowDlgW(pw,ppw);
if result then
begin
SetDlgItemTextW(Dialog,idc,pw);
SetEditFlags(Dialog,idc,EF_SCRIPT,0);
end;
mFreeMem(ppw);
mFreeMem(pw);
end;
function DlgProc(Dialog:HWND;hMessage:uint;wParam:WPARAM;lParam:LPARAM):LRESULT; stdcall;
const
NoProcess:boolean=true;
begin
result:=0;
case hMessage of
WM_INITDIALOG: begin
TranslateDialogDefault(Dialog);
MakeEditField(Dialog,IDC_EDIT_PRGPATH);
MakeEditField(Dialog,IDC_EDIT_PRGARGS);
end;
WM_ACT_SETVALUE: begin
NoProcess:=true;
ClearFields(Dialog);
with tProgramAction(lParam) do
begin
SetDlgItemTextW(Dialog,IDC_EDIT_PRGPATH ,prgname);
SetDlgItemTextW(Dialog,IDC_EDIT_PRGARGS ,args);
SetEditFlags(Dialog,IDC_EDIT_PRGPATH,EF_SCRIPT,ord((flags and ACF_PRG_PRG)<>0));
SetEditFlags(Dialog,IDC_EDIT_PRGARGS,EF_SCRIPT,ord((flags and ACF_PRG_ARG)<>0));
SetDlgItemInt(Dialog,IDC_EDIT_PROCTIME,time,false);
case show of
SW_HIDE : CheckDlgButton(Dialog,IDC_FLAG_HIDDEN,BST_CHECKED);
SW_SHOWMINIMIZED: CheckDlgButton(Dialog,IDC_FLAG_MINIMIZE,BST_CHECKED);
SW_SHOWMAXIMIZED: CheckDlgButton(Dialog,IDC_FLAG_MAXIMIZE,BST_CHECKED);
else
{SW_SHOWNORMAL :} CheckDlgButton(Dialog,IDC_FLAG_NORMAL,BST_CHECKED);
end;
if (flags and ACF_CURPATH)<>0 then
CheckDlgButton(Dialog,IDC_FLAG_CURPATH,BST_CHECKED);
if (flags and ACF_PRTHREAD)<>0 then
CheckDlgButton(Dialog,IDC_FLAG_PARALLEL,BST_CHECKED)
else
CheckDlgButton(Dialog,IDC_FLAG_CONTINUE,BST_CHECKED);
end;
NoProcess:=false;
end;
WM_ACT_RESET: begin
NoProcess:=true;
ClearFields(Dialog);
SetDlgItemTextW(Dialog,IDC_EDIT_PRGPATH,nil);
SetDlgItemTextW(Dialog,IDC_EDIT_PRGARGS,nil);
SetEditFlags(Dialog,IDC_EDIT_PRGPATH,EF_ALL,0);
SetEditFlags(Dialog,IDC_EDIT_PRGARGS,EF_ALL,0);
CheckDlgButton(Dialog,IDC_FLAG_PARALLEL,BST_CHECKED);
CheckDlgButton(Dialog,IDC_FLAG_NORMAL ,BST_CHECKED);
SetDlgItemInt(Dialog,IDC_EDIT_PROCTIME,0,false);
NoProcess:=false;
end;
WM_ACT_SAVE: begin
with tProgramAction(lParam) do
begin
{mFreeMem(prgname); }prgname:=GetDlgText(Dialog,IDC_EDIT_PRGPATH);
{mFreeMem(args ); }args :=GetDlgText(Dialog,IDC_EDIT_PRGARGS);
{
p:=GetDlgText(IDC_EDIT_PRGPATH);
if p<>nil then
begin
CallService(MS_UTILS_PATHTORELATIVE,dword(p),dword(@buf));
StrDupW(prgname,@buf);
mFreeMem(p);
end;
}
if IsDlgButtonChecked(Dialog,IDC_FLAG_PARALLEL)=BST_CHECKED then
flags:=flags or ACF_PRTHREAD;
if IsDlgButtonChecked(Dialog,IDC_FLAG_CURPATH)=BST_CHECKED then
flags:=flags or ACF_CURPATH;
time:=GetDlgItemInt(Dialog,IDC_EDIT_PROCTIME,pbool(nil)^,false);
if IsDlgButtonChecked(Dialog,IDC_FLAG_MINIMIZE)=BST_CHECKED then
show:=SW_SHOWMINIMIZED
else if IsDlgButtonChecked(Dialog,IDC_FLAG_MAXIMIZE)=BST_CHECKED then
show:=SW_SHOWMAXIMIZED
else if IsDlgButtonChecked(Dialog,IDC_FLAG_HIDDEN)=BST_CHECKED then
show:=SW_HIDE
else //if IsDlgButtonChecked(Dialog,IDC_FLAG_NORMAL)=BST_CHECKED then
show:=SW_SHOWNORMAL;
if (GetEditFlags(Dialog,IDC_EDIT_PRGPATH) and EF_SCRIPT)<>0 then flags:=flags or ACF_PRG_PRG;
if (GetEditFlags(Dialog,IDC_EDIT_PRGARGS) and EF_SCRIPT)<>0 then flags:=flags or ACF_PRG_ARG;
end;
end;
WM_COMMAND: begin
case wParam shr 16 of
EN_CHANGE: if not NoProcess then
SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0);
BN_CLICKED: begin
case loword(wParam) of
IDC_PROGRAM: begin
if not FillFileName(Dialog,IDC_EDIT_PRGPATH) then
exit;
end;
end;
SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0);
end;
end;
end;
WM_HELP: begin
MessageBoxW(0,
TranslateW('Text replacing'#13#10+
'by last result'#13#10#13#10+
'Text replacing'#13#10+
'by parameter'),
TranslateW('Text'),0);
result:=1;
end;
end;
end;
//----- Export/interface functions -----
var
vc:tActModule;
function CreateAction:tBaseAction;
begin
result:=tProgramAction.Create(vc.Hash);
end;
function CreateDialog(parent:HWND):HWND;
begin
result:=CreateDialogW(hInstance,'IDD_ACTPROGRAM',parent,@DlgProc);
end;
procedure Init;
begin
vc.Next :=ModuleLink;
vc.Name :='Program';
vc.Dialog :=@CreateDialog;
vc.Create :=@CreateAction;
vc.Icon :='IDI_PROGRAM';
vc.Hash :=0;
ModuleLink :=@vc;
end;
begin
Init;
end.