From 74e738f374f759723daf8920677158712d0ca5c1 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 16 Jul 2013 20:08:30 +0000 Subject: - Actman 3 added (not adopted) git-svn-id: http://svn.miranda-ng.org/main/trunk@5391 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Actman30/actman.dpr | 254 +++++++ plugins/Actman30/ask.rc | 20 + plugins/Actman30/dlgshare.pas | 73 ++ plugins/Actman30/dlgshare.rc | 13 + plugins/Actman30/global.pas | 29 + plugins/Actman30/hooks/hooks.pas | 69 ++ plugins/Actman30/hooks/hooks.rc | 28 + plugins/Actman30/hooks/i_hconst.inc | 20 + plugins/Actman30/hooks/i_hook.inc | 154 ++++ plugins/Actman30/hooks/i_opt_dlg.inc | 419 +++++++++++ plugins/Actman30/hooks/i_options.inc | 71 ++ plugins/Actman30/i_cnst_chain.inc | 6 + plugins/Actman30/i_cnst_contact.inc | 6 + plugins/Actman30/i_cnst_database.inc | 18 + plugins/Actman30/i_cnst_dlgshare.inc | 11 + plugins/Actman30/i_cnst_inout.inc | 17 + plugins/Actman30/i_cnst_jump.inc | 15 + plugins/Actman30/i_cnst_message.inc | 17 + plugins/Actman30/i_cnst_program.inc | 13 + plugins/Actman30/i_cnst_service.inc | 12 + plugins/Actman30/i_cnst_settings.inc | 11 + plugins/Actman30/i_cnst_storage.inc | 5 + plugins/Actman30/i_cnst_text.inc | 4 + plugins/Actman30/i_const.inc | 31 + plugins/Actman30/i_opt_dlg.inc | 52 ++ plugins/Actman30/i_opt_dlg2.inc | 1318 ++++++++++++++++++++++++++++++++++ plugins/Actman30/i_options.inc | 177 +++++ plugins/Actman30/i_services.inc | 317 ++++++++ plugins/Actman30/iac_.pas | 155 ++++ plugins/Actman30/iac_chain.pas | 372 ++++++++++ plugins/Actman30/iac_chain.rc | 18 + plugins/Actman30/iac_contact.pas | 252 +++++++ plugins/Actman30/iac_contact.rc | 18 + plugins/Actman30/iac_database.rc | 37 + plugins/Actman30/iac_dbrw.pas | 686 ++++++++++++++++++ plugins/Actman30/iac_global.pas | 428 +++++++++++ plugins/Actman30/iac_inout.pas | 667 +++++++++++++++++ plugins/Actman30/iac_inout.rc | 30 + plugins/Actman30/iac_jump.pas | 699 ++++++++++++++++++ plugins/Actman30/iac_jump.rc | 32 + plugins/Actman30/iac_messagebox.pas | 386 ++++++++++ plugins/Actman30/iac_messagebox.rc | 36 + plugins/Actman30/iac_program.pas | 491 +++++++++++++ plugins/Actman30/iac_program.rc | 31 + plugins/Actman30/iac_service.pas | 1023 ++++++++++++++++++++++++++ plugins/Actman30/iac_service.rc | 32 + plugins/Actman30/iac_settings.pas | 157 ++++ plugins/Actman30/iac_settings.rc | 26 + plugins/Actman30/iac_storage.pas | 292 ++++++++ plugins/Actman30/iac_storage.rc | 16 + plugins/Actman30/iac_text.pas | 495 +++++++++++++ plugins/Actman30/iac_text.rc | 14 + plugins/Actman30/ico/advance.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/apply.ico | Bin 0 -> 1406 bytes plugins/Actman30/ico/chain.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/contact.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/delete.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/down.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/export.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/format.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/import.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/insert.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/jump.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/message.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/new.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/program.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/reload.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/rw.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/service.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/settings.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/storage.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/test.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/text.ico | Bin 0 -> 2550 bytes plugins/Actman30/ico/up.ico | Bin 0 -> 2550 bytes plugins/Actman30/inoutini.pas | 153 ++++ plugins/Actman30/inoutxml.pas | 155 ++++ plugins/Actman30/lowlevelc.pas | 294 ++++++++ plugins/Actman30/m_actman.h | 96 +++ plugins/Actman30/m_actman.inc | 152 ++++ plugins/Actman30/make.bat | 18 + plugins/Actman30/options.rc | 70 ++ plugins/Actman30/question.pas | 58 ++ plugins/Actman30/readme.txt | 126 ++++ plugins/Actman30/services.ini | 523 ++++++++++++++ plugins/Actman30/tasks/i_opt_dlg.inc | 536 ++++++++++++++ plugins/Actman30/tasks/i_options.inc | 99 +++ plugins/Actman30/tasks/i_service.inc | 87 +++ plugins/Actman30/tasks/i_task.inc | 242 +++++++ plugins/Actman30/tasks/i_tconst.inc | 27 + plugins/Actman30/tasks/scheduler.pas | 76 ++ plugins/Actman30/tasks/tasks.rc | 47 ++ plugins/Actman30/ua/action.ico | Bin 0 -> 2550 bytes plugins/Actman30/ua/i_inoutjson.inc | 355 +++++++++ plugins/Actman30/ua/i_inoutxm.inc | 357 +++++++++ plugins/Actman30/ua/i_opt_dlg.inc | 572 +++++++++++++++ plugins/Actman30/ua/i_options.inc | 252 +++++++ plugins/Actman30/ua/i_ua.inc | 219 ++++++ plugins/Actman30/ua/i_uaplaces.inc | 832 +++++++++++++++++++++ plugins/Actman30/ua/i_uavars.inc | 121 ++++ plugins/Actman30/ua/i_uconst.inc | 34 + plugins/Actman30/ua/ua.pas | 108 +++ plugins/Actman30/ua/ua.rc | 51 ++ 102 files changed, 15233 insertions(+) create mode 100644 plugins/Actman30/actman.dpr create mode 100644 plugins/Actman30/ask.rc create mode 100644 plugins/Actman30/dlgshare.pas create mode 100644 plugins/Actman30/dlgshare.rc create mode 100644 plugins/Actman30/global.pas create mode 100644 plugins/Actman30/hooks/hooks.pas create mode 100644 plugins/Actman30/hooks/hooks.rc create mode 100644 plugins/Actman30/hooks/i_hconst.inc create mode 100644 plugins/Actman30/hooks/i_hook.inc create mode 100644 plugins/Actman30/hooks/i_opt_dlg.inc create mode 100644 plugins/Actman30/hooks/i_options.inc create mode 100644 plugins/Actman30/i_cnst_chain.inc create mode 100644 plugins/Actman30/i_cnst_contact.inc create mode 100644 plugins/Actman30/i_cnst_database.inc create mode 100644 plugins/Actman30/i_cnst_dlgshare.inc create mode 100644 plugins/Actman30/i_cnst_inout.inc create mode 100644 plugins/Actman30/i_cnst_jump.inc create mode 100644 plugins/Actman30/i_cnst_message.inc create mode 100644 plugins/Actman30/i_cnst_program.inc create mode 100644 plugins/Actman30/i_cnst_service.inc create mode 100644 plugins/Actman30/i_cnst_settings.inc create mode 100644 plugins/Actman30/i_cnst_storage.inc create mode 100644 plugins/Actman30/i_cnst_text.inc create mode 100644 plugins/Actman30/i_const.inc create mode 100644 plugins/Actman30/i_opt_dlg.inc create mode 100644 plugins/Actman30/i_opt_dlg2.inc create mode 100644 plugins/Actman30/i_options.inc create mode 100644 plugins/Actman30/i_services.inc create mode 100644 plugins/Actman30/iac_.pas create mode 100644 plugins/Actman30/iac_chain.pas create mode 100644 plugins/Actman30/iac_chain.rc create mode 100644 plugins/Actman30/iac_contact.pas create mode 100644 plugins/Actman30/iac_contact.rc create mode 100644 plugins/Actman30/iac_database.rc create mode 100644 plugins/Actman30/iac_dbrw.pas create mode 100644 plugins/Actman30/iac_global.pas create mode 100644 plugins/Actman30/iac_inout.pas create mode 100644 plugins/Actman30/iac_inout.rc create mode 100644 plugins/Actman30/iac_jump.pas create mode 100644 plugins/Actman30/iac_jump.rc create mode 100644 plugins/Actman30/iac_messagebox.pas create mode 100644 plugins/Actman30/iac_messagebox.rc create mode 100644 plugins/Actman30/iac_program.pas create mode 100644 plugins/Actman30/iac_program.rc create mode 100644 plugins/Actman30/iac_service.pas create mode 100644 plugins/Actman30/iac_service.rc create mode 100644 plugins/Actman30/iac_settings.pas create mode 100644 plugins/Actman30/iac_settings.rc create mode 100644 plugins/Actman30/iac_storage.pas create mode 100644 plugins/Actman30/iac_storage.rc create mode 100644 plugins/Actman30/iac_text.pas create mode 100644 plugins/Actman30/iac_text.rc create mode 100644 plugins/Actman30/ico/advance.ico create mode 100644 plugins/Actman30/ico/apply.ico create mode 100644 plugins/Actman30/ico/chain.ico create mode 100644 plugins/Actman30/ico/contact.ico create mode 100644 plugins/Actman30/ico/delete.ico create mode 100644 plugins/Actman30/ico/down.ico create mode 100644 plugins/Actman30/ico/export.ico create mode 100644 plugins/Actman30/ico/format.ico create mode 100644 plugins/Actman30/ico/import.ico create mode 100644 plugins/Actman30/ico/insert.ico create mode 100644 plugins/Actman30/ico/jump.ico create mode 100644 plugins/Actman30/ico/message.ico create mode 100644 plugins/Actman30/ico/new.ico create mode 100644 plugins/Actman30/ico/program.ico create mode 100644 plugins/Actman30/ico/reload.ico create mode 100644 plugins/Actman30/ico/rw.ico create mode 100644 plugins/Actman30/ico/service.ico create mode 100644 plugins/Actman30/ico/settings.ico create mode 100644 plugins/Actman30/ico/storage.ico create mode 100644 plugins/Actman30/ico/test.ico create mode 100644 plugins/Actman30/ico/text.ico create mode 100644 plugins/Actman30/ico/up.ico create mode 100644 plugins/Actman30/inoutini.pas create mode 100644 plugins/Actman30/inoutxml.pas create mode 100644 plugins/Actman30/lowlevelc.pas create mode 100644 plugins/Actman30/m_actman.h create mode 100644 plugins/Actman30/m_actman.inc create mode 100644 plugins/Actman30/make.bat create mode 100644 plugins/Actman30/options.rc create mode 100644 plugins/Actman30/question.pas create mode 100644 plugins/Actman30/readme.txt create mode 100644 plugins/Actman30/services.ini create mode 100644 plugins/Actman30/tasks/i_opt_dlg.inc create mode 100644 plugins/Actman30/tasks/i_options.inc create mode 100644 plugins/Actman30/tasks/i_service.inc create mode 100644 plugins/Actman30/tasks/i_task.inc create mode 100644 plugins/Actman30/tasks/i_tconst.inc create mode 100644 plugins/Actman30/tasks/scheduler.pas create mode 100644 plugins/Actman30/tasks/tasks.rc create mode 100644 plugins/Actman30/ua/action.ico create mode 100644 plugins/Actman30/ua/i_inoutjson.inc create mode 100644 plugins/Actman30/ua/i_inoutxm.inc create mode 100644 plugins/Actman30/ua/i_opt_dlg.inc create mode 100644 plugins/Actman30/ua/i_options.inc create mode 100644 plugins/Actman30/ua/i_ua.inc create mode 100644 plugins/Actman30/ua/i_uaplaces.inc create mode 100644 plugins/Actman30/ua/i_uavars.inc create mode 100644 plugins/Actman30/ua/i_uconst.inc create mode 100644 plugins/Actman30/ua/ua.pas create mode 100644 plugins/Actman30/ua/ua.rc (limited to 'plugins/Actman30') diff --git a/plugins/Actman30/actman.dpr b/plugins/Actman30/actman.dpr new file mode 100644 index 0000000000..2f22cda9e2 --- /dev/null +++ b/plugins/Actman30/actman.dpr @@ -0,0 +1,254 @@ +{$include compilers.inc} +{$IFDEF COMPILER_16_UP} + {$WEAKLINKRTTI ON} + {.$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} +{$ENDIF} +{$IMAGEBASE $13200000} +library actman; +{%File 'm_actman.inc'} +{%File 'i_const.inc'} +{%File 'i_opt_dlg2.inc'} +{%File 'i_opt_dlg.inc'} +{%File 'i_options.inc'} +{%File 'i_services.inc'} +{%File 'i_vars.inc'} +{%File 'i_inoutxm.inc'} +{%File 'tasks\i_opt_dlg.inc'} +{%File 'tasks\i_options.inc'} +{%File 'tasks\i_task.inc'} +{%File 'hooks\i_options.inc'} +{%File 'hooks\i_hook.inc'} +{%File 'hooks\i_opt_dlg.inc'} +{%File 'ua\i_opt_dlg.inc'} +{%File 'ua\i_inoutxm.inc'} +{%File 'ua\i_options.inc'} +{%File 'ua\i_ua.inc'} +{%File 'ua\i_uaplaces.inc'} +{%File 'ua\i_uconst.inc'} + +uses +// fastmm4, + m_api, + Windows, + messages, + commctrl, + common, + wrapper, + io, + dbsettings, + mirutils, + syswin, + base64, + question, + mApiCardM, + global, + lowlevelc, + dlgshare, + iac_global, + iac_settings, + iac_storage, + iac_dbrw, + iac_messagebox, + iac_text, + iac_jump, + iac_inout, + iac_service, + iac_program, + iac_chain, + iac_contact, + inoutxml, + sedit, + strans, + ua in 'ua\ua.pas', + hooks in 'hooks\hooks.pas', + scheduler in 'tasks\scheduler.pas'; + +{$r options.res} + +const + PluginName = 'Action Manager'; +var + hevaction,hHookChanged,hevinout:THANDLE; + +{$include m_actman.inc} + + +function MirandaPluginInfoEx(mirandaVersion:DWORD):PPLUGININFOEX; cdecl; +begin + result:=@PluginInfo; + PluginInfo.cbSize :=SizeOf(TPLUGININFOEX); + PluginInfo.shortName :='Action manager'; + PluginInfo.version :=$00030001; + PluginInfo.description:='Plugin for manage hotkeys to open contact window, insert text, '+ + 'run program and call services'; + PluginInfo.author :='Awkward'; + PluginInfo.authorEmail:='panda75@bk.ru; awk1975@ya.ru'; + PluginInfo.copyright :='(c) 2007-2013 Awkward'; + PluginInfo.homepage :='http://code.google.com/p/delphi-miranda-plugins/'; + PluginInfo.flags :=UNICODE_AWARE; + PluginInfo.uuid :=MIID_ACTMAN; +end; + +{$include i_const.inc} + +{$include i_options.inc} +{$include i_services.inc} +{$include i_opt_dlg.inc} +{.$include i_inoutxm.inc} + +function PreShutdown(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + ptr:pActionLink; +begin + result:=0; + + ptr:=ActionLink; + while ptr<>nil do + begin + if @ptr^.DeInit<>nil then + ptr^.DeInit; + ptr:=ptr^.Next; + end; + + MacroList.Clear; + MacroList.Free; + + DestroyHookableEvent(hHookChanged); + DestroyHookableEvent(hevinout); + DestroyHookableEvent(hevaction); + +end; + +procedure RegisterActTypes; +var + p:pActModule; + sid:TSKINICONDESC; + buf:array [0..63] of AnsiChar; + pc:pAnsiChar; +// ii:tIconItem; +begin + FillChar(sid,SizeOf(sid),0); + sid.cbSize:=SizeOf(sid); + sid.cx:=16; + sid.cy:=16; + sid.szSection.a:='Actions'; + sid.pszName :=@buf; + pc:=StrCopyE(buf,IcoLibPrefix); + p:=ModuleLink; +{ + ii.size :=0; + ii.hIcolib:=0; + ii.szName :=@buf; +} + while p<>nil do + begin + if p^.Hash=0 then + p^.Hash:=Hash(p^.Name,StrLen(p^.Name)); + //!! must add icon registration in icolib +{ + StrCopy(pc,p^.Name); + ii.szDescr :=p^.Name; + ii.DefIconID:=; + Icon_Register(hInstance,'Actions',@ii,1); +} + sid.hDefaultIcon :=LoadImageA(hInstance,p^.Icon,IMAGE_ICON,16,16,0); + sid.szDescription.a:=p^.Name; + StrCopy(pc,p^.Name); + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + p:=p^.Next; + end; +end; + +// This function implements autostart action execution after all others plugins loading +function DoAutostart(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + i:integer; + Macro:pMacroRecord; + section:array [0..127] of AnsiChar; + p,p1:pAnsiChar; +begin + Result:=0; + CallService(MS_ACT_RUNBYNAME,TWPARAM(AutoStartName),0); + + p1:=StrCopyE(section,opt_group); + for i:=0 to MacroList.Count-1 do + begin + Macro:=MacroList[i]; + if (Macro^.flags and ACF_FIRSTRUN)<>0 then + begin + CallService(MS_ACT_RUNBYID,TWPARAM(Macro^.id),0); + Macro^.flags:=Macro^.flags and not ACF_FIRSTRUN; + p:=StrEnd(IntToStr(p1,i)); + p^:='/'; inc(p); + StrCopy(p,opt_flags); DBWriteDWord(0,DBBranch,section,Macro^.flags); + end; + end; +end; + +function OnModulesLoaded(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + ptr:pActionLink; +begin + Result:=0; + + RegisterActTypes; + + LoadMacros; + RegisterIcons; + + HookEvent(ME_OPT_INITIALISE ,@OnOptInitialise); + HookEvent(ME_SYSTEM_SHUTDOWN{ME_SYSTEM_OKTOEXIT},@PreShutdown); + NotifyEventHooks(hHookChanged,twparam(ACTM_LOADED),0); + + //----- DBEDITOR support ----- +// CallService(MS_DBEDIT_REGISTERSINGLEMODULE,twparam(PluginShort),0); + + IsMultiThread:=true; + // Load additional modules + ptr:=ActionLink; + while ptr<>nil do + begin + if @ptr^.Init<>nil then + ptr^.Init; + ptr:=ptr^.Next; + end; + + // cheat + HookEvent(ME_SYSTEM_MODULESLOADED,@DoAutostart); +// DoAutostart(0,0); +end; + +function Load:int; cdecl; +begin + Result:=0; + Langpack_Register; + + hHookChanged:=CreateHookableEvent(ME_ACT_CHANGED); + hevinout :=CreateHookableEvent(ME_ACT_INOUT); + hevaction :=CreateHookableEvent(ME_ACT_ACTION); + + CreateServiceFunction(MS_ACT_FREELIST ,@ActFreeList); + CreateServiceFunction(MS_ACT_GETLIST ,@ActGetList); + CreateServiceFunction(MS_ACT_RUNBYID ,@ActRun); + CreateServiceFunction(MS_ACT_RUNBYNAME,@ActRunGroup); + CreateServiceFunction(MS_ACT_RUNPARAMS,@ActRunParam); +//!! CreateServiceFunction(MS_ACT_INOUT ,@ActInOut); + CreateServiceFunction(MS_ACT_SELECT ,@ActSelect); + + HookEvent(ME_SYSTEM_MODULESLOADED,@OnModulesLoaded); +end; + +function Unload: int; cdecl; +begin + Result:=0; +end; + +exports + Load, Unload, + MirandaPluginInfoEx; + +begin + DisableThreadLibraryCalls(hInstance); +end. diff --git a/plugins/Actman30/ask.rc b/plugins/Actman30/ask.rc new file mode 100644 index 0000000000..cb36bcf8ee --- /dev/null +++ b/plugins/Actman30/ask.rc @@ -0,0 +1,20 @@ +#include "i_const.inc" + +LANGUAGE 0,0 + +IDD_ASK DIALOGEX 0, 0, 276, 72, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Choose action" +FONT 8, "MS Shell Dlg", 0, 0 +{ + CTEXT "", IDC_ASK,4,4,268,42,SS_CENTERIMAGE + + CONTROL "", -1, "STATIC", SS_ETCHEDHORZ, 2, 50, 272, 2 + + DEFPUSHBUTTON "&Yes" , IDOK , 4, 54, 40, 16 + PUSHBUTTON "&No" , IDCANCEL , 52, 54, 40, 16 + PUSHBUTTON "A&ppend" , IDC_APPEND, 100, 54, 52, 16 + PUSHBUTTON "Yes to &All", IDC_YESALL, 160, 54, 52, 16 + PUSHBUTTON "N&o to All" , IDC_NOALL , 220, 54, 52, 16 +} diff --git a/plugins/Actman30/dlgshare.pas b/plugins/Actman30/dlgshare.pas new file mode 100644 index 0000000000..cd6dbb9023 --- /dev/null +++ b/plugins/Actman30/dlgshare.pas @@ -0,0 +1,73 @@ +unit dlgshare; + +interface + +uses windows,lowlevelc; + +var + MacroListWindow, + ActionListWindow:HWND; +var + EditMacroList:tMacroList; + +const + ACI_APPLY = 0; + ACI_NEW = 1; + ACI_DELETE = 2; + ACI_UP = 3; + ACI_DOWN = 4; + ACI_TEST = 5; + ACI_IMPORT = 6; + ACI_EXPORT = 7; + ACI_REFRESH = 8; + +procedure RegisterIcons; +function OptSetButtonIcon(btn:HWND;num:integer):HICON; +procedure OptFillContactList(wnd:HWND); + +implementation + +uses messages, m_api, dbsettings, contact, common, global; + +{$include i_cnst_dlgshare.inc} +{$resource dlgshare.res} + +const + IconAmount = 9; +const + Icons:array [0..IconAmount-1] of tIconItem = ( + (szDescr: 'Apply' ; szName: 'Apply' ; defIconID: IDI_APPLY ; size: 0; hIcolib: 0;), + (szDescr: 'New' ; szName: 'New' ; defIconID: IDI_NEW ; size: 0; hIcolib: 0;), + (szDescr: 'Delete' ; szName: 'Delete'; defIconID: IDI_DELETE; size: 0; hIcolib: 0;), + (szDescr: 'Up' ; szName: 'Up' ; defIconID: IDI_UP ; size: 0; hIcolib: 0;), + (szDescr: 'Down' ; szName: 'Down' ; defIconID: IDI_DOWN ; size: 0; hIcolib: 0;), + (szDescr: 'Test' ; szName: 'Test' ; defIconID: IDI_TEST ; size: 0; hIcolib: 0;), + (szDescr: 'Import' ; szName: 'Import'; defIconID: IDI_IMPORT; size: 0; hIcolib: 0;), + (szDescr: 'Export' ; szName: 'Export'; defIconID: IDI_EXPORT; size: 0; hIcolib: 0;), + (szDescr: 'Reload/Refresh'; szName: 'Reload'; defIconID: IDI_RELOAD; size: 0; hIcolib: 0;) + ); + + +procedure RegisterIcons; +begin + Icon_Register(hInstance,'Actions',@Icons,IconAmount,'ACI'); +end; + +function OptSetButtonIcon(btn:HWND;num:integer):HICON; +begin + result:=CallService(MS_SKIN2_GETICONBYHANDLE,0,LPARAM(Icons[num].hIcolib)); + SendMessage(btn,BM_SETIMAGE,IMAGE_ICON,result); +end; + +procedure OptFillContactList(wnd:HWND); +var + fCLformat:pWideChar; + fCLfilter:byte; +begin + fCLfilter:=DBReadByte (0,DBBranch,'CLfilter',BST_UNCHECKED); + fCLformat:=DBReadUnicode(0,DBBranch,'CLformat'); + FillContactList(wnd, fCLfilter<>BST_UNCHECKED, fCLformat); + mFreeMem(fCLformat); +end; + +end. diff --git a/plugins/Actman30/dlgshare.rc b/plugins/Actman30/dlgshare.rc new file mode 100644 index 0000000000..dfeb197281 --- /dev/null +++ b/plugins/Actman30/dlgshare.rc @@ -0,0 +1,13 @@ +#include "i_cnst_dlgshare.inc" + +LANGUAGE 0,0 + +IDI_NEW ICON "ico\new.ico" +IDI_UP ICON "ico\up.ico" +IDI_DOWN ICON "ico\down.ico" +IDI_DELETE ICON "ico\delete.ico" +IDI_RELOAD ICON "ico\reload.ico" +IDI_TEST ICON "ico\test.ico" +IDI_EXPORT ICON "ico\export.ico" +IDI_IMPORT ICON "ico\import.ico" +IDI_APPLY ICON "ico\apply.ico" diff --git a/plugins/Actman30/global.pas b/plugins/Actman30/global.pas new file mode 100644 index 0000000000..276f71dea7 --- /dev/null +++ b/plugins/Actman30/global.pas @@ -0,0 +1,29 @@ +unit global; + +interface + +const + DBBranch = 'ActMan'; +const + ACF_SELECTED = $08000000; + ACF_EXPORT = ACF_SELECTED; + ACF_IMPORT = ACF_SELECTED; + ACF_OVERLOAD = $01000000; + +type + tAddOption = function(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +type + pActionLink=^tActionLink; + tActionLink=record + Next :pActionLink; + Init :procedure; + DeInit :procedure; + AddOption:tAddOption; + end; + +const + ActionLink:pActionLink=nil; + +implementation + +end. \ No newline at end of file diff --git a/plugins/Actman30/hooks/hooks.pas b/plugins/Actman30/hooks/hooks.pas new file mode 100644 index 0000000000..02ab937cab --- /dev/null +++ b/plugins/Actman30/hooks/hooks.pas @@ -0,0 +1,69 @@ +unit hooks; + +interface + +implementation + +uses + windows, commctrl, messages, + mirutils, common, dbsettings, m_api, wrapper, + global, mApiCardM; + +{$R hooks.res} + +{$include m_actman.inc} + +{$include i_hook.inc} +{$include i_hconst.inc} +{$include i_options.inc} +{$include i_opt_dlg.inc} + +// ------------ base interface functions ------------- + +procedure Init; +begin + + MessageWindow:=CreateWindowExW(0,'STATIC',nil,0,1,1,1,1,HWND_MESSAGE,0,hInstance,nil); + if MessageWindow<>0 then + SetWindowLongPtrW(MessageWindow,GWL_WNDPROC,LONG_PTR(@HookWndProc)); + + if LoadHooks=0 then + begin + MaxHooks:=8; + GetMem (HookList ,MaxHooks*SizeOf(tHookRec)); + FillChar(HookList^,MaxHooks*SizeOf(tHookRec),0); + end + else + SetAllHooks; +end; + +procedure DeInit; +begin + ClearHooks; + if MessageWindow<>0 then + DestroyWindow(MessageWindow); +end; + +function AddOptionPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +begin + result:=0; + tmpl:=PAnsiChar(IDD_HOOKS); + proc:=@DlgProcOpt; + name:='Hooks'; +end; + +var + amLink:tActionLink; + +procedure InitLink; +begin + amLink.Next :=ActionLink; + amLink.Init :=@Init; + amLink.DeInit :=@DeInit; + amLink.AddOption:=@AddOptionPage; + ActionLink :=@amLink; +end; + +initialization + InitLink; +end. diff --git a/plugins/Actman30/hooks/hooks.rc b/plugins/Actman30/hooks/hooks.rc new file mode 100644 index 0000000000..ff351cc94d --- /dev/null +++ b/plugins/Actman30/hooks/hooks.rc @@ -0,0 +1,28 @@ +#include "i_hconst.inc" + +LANGUAGE 0,0 + +IDD_HOOKS DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + CONTROL "", IDC_HOOKLIST, "SysListView32", + WS_BORDER | WS_TABSTOP | + LVS_SHOWSELALWAYS| LVS_REPORT | LVS_EDITLABELS,// | LVS_SINGLESEL + 0, 2, 280, 160, WS_EX_CONTROLPARENT + + CONTROL "Help" ,IDC_EVENT_HELP ,"MButtonClass",WS_TABSTOP,284, 2,16,16,$18000000 + CONTROL "Delete",IDC_HOOK_DELETE,"MButtonClass",WS_TABSTOP,284, 96,16,16,$18000000 + + CONTROL "New" ,IDC_HOOK_NEW ,"MButtonClass",WS_TABSTOP,284,126,16,16,$18000000 + CONTROL "Apply" ,IDC_HOOK_APPLY ,"MButtonClass",WS_TABSTOP,284,146,16,16,$18000000 + + CONTROL "Help" ,IDC_EVENT_CHELP,"MButtonClass",WS_TABSTOP,2 ,162,16,16,$18000000 + CTEXT "Event" ,-1 ,18, 165, 121, 11, SS_CENTERIMAGE + COMBOBOX IDC_EVENTLIST , 0, 178, 157, 128, CBS_DROPDOWN | CBS_SORT | WS_VSCROLL + CTEXT "Action",-1 , 0, 195, 157, 11, SS_CENTERIMAGE + COMBOBOX IDC_ACTIONLIST, 0, 208, 157, 128, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL + + LTEXT "",IDC_DESCR, 160, 165, 138, 57 +} diff --git a/plugins/Actman30/hooks/i_hconst.inc b/plugins/Actman30/hooks/i_hconst.inc new file mode 100644 index 0000000000..d011278b7e --- /dev/null +++ b/plugins/Actman30/hooks/i_hconst.inc @@ -0,0 +1,20 @@ +{resource constants} +const + // dialogs + IDD_HOOKS = 1029; + + // icons + IDI_NEW = 1025; + IDI_DELETE = 1028; + + // Hook editor + IDC_HOOKLIST = 1025; + IDC_ACTIONLIST = 1026; + IDC_EVENTLIST = 1027; + IDC_EVENT_HELP = 1028; + IDC_HOOK_NEW = 1029; + IDC_HOOK_DELETE = 1030; + IDC_HOOK_APPLY = 1031; + IDC_EVENT_CHELP = 1032; + + IDC_DESCR = 1040; diff --git a/plugins/Actman30/hooks/i_hook.inc b/plugins/Actman30/hooks/i_hook.inc new file mode 100644 index 0000000000..8b7b487d98 --- /dev/null +++ b/plugins/Actman30/hooks/i_hook.inc @@ -0,0 +1,154 @@ +{} + +const + HWND_MESSAGE = HWND(-3); +const + ACF_ASSIGNED = $80000000; // hook assigned + ACF_DISABLED = $10000000; // hook disabled +const + WM_RESETHOOKS = WM_USER+1312; + WM_FIRSTHOOK = WM_USER+1313; + WM_LASTHOOK = WM_FIRSTHOOK+1000; + +type + pHookRec = ^tHookRec; + tHookRec = record + flags :dword; + name :PAnsiChar; // name for hook + handle :THANDLE; // handle of hook + descr :PWideChar; // name for list + action :dword; // assigned action + message:uint; // window message for hook + end; + pHookList = ^tHookList; + tHookList = array [0..1023] of tHookRec; + +var + HookList:pHookList = nil; + MaxHooks:integer = 0; + MessageWindow:HWND = 0; + +function GetNextMessage:uint; +var + i:uint; + j:integer; +begin + result:=0; + for i:=WM_FIRSTHOOK to WM_LASTHOOK do + begin + for j:=0 to MaxHooks-1 do + begin + with HookList^[j] do + begin + if ((flags and ACF_ASSIGNED)<>0) and (i=message) then + begin + inc(result); + break; + end; + end; + end; + if result=0 then + begin + result:=i; + break; + end + else + result:=0; + end; +end; + +procedure SetAllHooks; +var + i:integer; + msg:cardinal; +begin + msg:=WM_FIRSTHOOK; + for i:=0 to MaxHooks-1 do + begin + with HookList[i] do + begin + message:=msg; + if (flags and ACF_ASSIGNED)<>0 then + begin + if (flags and ACF_DISABLED)<>0 then + begin + if handle<>0 then + begin + UnhookEvent(handle); + handle:=0; + end; + end + else + begin + if handle<>0 then + UnhookEvent(handle); + handle:=HookEventMessage(name,MessageWindow,message); + end; + end; + end; + inc(msg); + end; +end; + +function GetHookByMessage(msg:uint):pHookRec; +var + i:integer; +begin + result:=nil; + for i:=0 to MaxHooks-1 do + begin + with HookList[i] do + begin + if ((flags and ACF_ASSIGNED)<>0) and (msg=message) then + begin + result:=@HookList[i]; + break; + end; + end; + end; +end; + +function HookWndProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + p:pHookRec; + ap:tAct_Param; +begin + result:=0; + case hMessage of + WM_FIRSTHOOK..WM_LASTHOOK: begin + p:=GetHookByMessage(hMessage); + if p<>nil then + begin + ap.flags :=ACTP_WAIT; + ap.Id :=p^.action; + ap.wParam:=wParam; + ap.lParam:=lParam; + result:=CallService(MS_ACT_RUNPARAMS,0,TLPARAM(@ap)); + end; + end; + else + result:=DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; + +procedure ClearHooks; +var + i:integer; +begin + for i:=0 to MaxHooks-1 do + begin + with HookList[i] do + begin + if (flags and ACF_ASSIGNED)<>0 then + begin + mFreeMem(descr); + mFreeMem(name); + if handle<>0 then + UnhookEvent(handle); + end; + end; + end; + FreeMem(HookList); + MaxHooks:=0; +end; + diff --git a/plugins/Actman30/hooks/i_opt_dlg.inc b/plugins/Actman30/hooks/i_opt_dlg.inc new file mode 100644 index 0000000000..012fc5b361 --- /dev/null +++ b/plugins/Actman30/hooks/i_opt_dlg.inc @@ -0,0 +1,419 @@ +{} +const + settings:HWND = 0; +var + OldTableProc:pointer; + onactchanged:THANDLE; + ApiCard:tmApiCard; + +const + ACI_NEW :PAnsiChar = 'ACI_New'; + ACI_APPLY :PAnsiChar = 'ACI_Apply'; + ACI_DELETE :PAnsiChar = 'ACI_Delete'; + +procedure CheckHookList(wnd:HWND); +var + i:integer; + li:LV_ITEMW; + arr:array [0..127] of WideChar; +begin + ClearHooks; + + li.mask :=LVIF_TEXT or LVIF_PARAM; + li.pszText :=@arr; + li.cchTextMax:=SizeOf(arr) div SizeOf(WideChar); + + MaxHooks:=SendMessage(wnd,LVM_GETITEMCOUNT,0,0); + + GetMem (HookList ,MaxHooks*SizeOf(tHookRec)); + FillChar(HookList^,MaxHooks*SizeOf(tHookRec),0); + for i:=0 to MaxHooks-1 do + begin + with HookList[i] do + begin + flags:=ACF_ASSIGNED; + li.iItem :=i; + li.iSubItem:=0; + SendMessageW(wnd,LVM_GETITEMW,0,LPARAM(@li)); + StrDupW(descr,arr); + action:=li.lParam; + li.iSubItem:=1; + SendMessageA(wnd,LVM_GETITEMA,0,LPARAM(@li)); + StrDup(name,pAnsiChar(@arr)); + + if ListView_GetCheckState(wnd,i)=0 then // disabled + flags:=flags or ACF_DISABLED; + end; + end; +end; + +procedure FillHookList(wnd:HWND); +var + i:integer; + li:LV_ITEMW; +begin + SendMessage(wnd,LVM_DELETEALLITEMS,0,0); + for i:=0 to MaxHooks-1 do + begin + with HookList[i] do + begin + if (flags and ACF_ASSIGNED)<>0 then + begin + li.mask :=LVIF_TEXT+LVIF_PARAM; + li.iSubItem:=0; + li.iItem :=i; + li.lParam :=action; + li.pszText :=descr; + li.iItem :=SendMessageW(wnd,LVM_INSERTITEMW,0,LPARAM(@li)); + li.mask :=LVIF_TEXT; + li.iSubItem:=1; + li.pszText :=pWideChar(name); + SendMessageA(wnd,LVM_SETITEMA,0,LPARAM(@li)); + ListView_SetCheckState(wnd,li.iItem,(flags and ACF_DISABLED)=0); + end; + end; + end; + ListView_SetItemState(wnd,0, + LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); +end; + +procedure FillActionList(wnd:HWND); +var + ptr,ptr1:pChain; + i,cnt:integer; +begin + cnt:=CallService(MS_ACT_GETLIST,0,LPARAM(@ptr)); + SendMessage(wnd,CB_RESETCONTENT,0,0); + if cnt>0 then + begin + ptr1:=ptr; + inc(pbyte(ptr),4); + for i:=0 to cnt-1 do + begin + CB_AddStrDataW(wnd,ptr^.descr,ptr^.id); + inc(ptr); + end; + + CallService(MS_ACT_FREELIST,0,LPARAM(ptr1)); + SendMessage(wnd,CB_SETCURSEL,0,0); + end; +end; + +function ActListChange(wParam:WPARAM;lParam:LPARAM):integer; cdecl; +begin + result:=0; + if settings<>0 then + FillActionList(GetDlgItem(settings,IDC_ACTIONLIST)); +end; + +procedure ShowHookData(Dialog:HWND; item:integer=-1); +var + li:LV_ITEM; + arr:array [0..127] of WideChar; + wnd:HWND; +begin + wnd:=GetDlgItem(Dialog,IDC_HOOKLIST); + if item<0 then + li.iItem:=SendMessage(wnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED) + else + li.iItem:=item; + + li.mask :=LVIF_TEXT+LVIF_PARAM; + li.iSubItem :=1; + li.pszText :=@arr; + li.cchTextMax:=SizeOf(arr) div SizeOf(WideChar); + arr[0]:=#0; + SendMessageW(wnd,LVM_GETITEMW,0,LPARAM(@li)); + if arr[0]<>#0 then + SetDlgItemTextW(Dialog,IDC_EVENTLIST,arr); + CB_SelectData(GetDlgItem(Dialog,IDC_ACTIONLIST),li.lParam); +end; + +procedure SaveHookData(Dialog:HWND; item:integer=-1); +var + wnd:HWND; + li:LV_ITEMW; + p:pAnsiChar; + buf:array [0..127] of WideChar; +begin + wnd:=GetDlgItem(Dialog,IDC_HOOKLIST); + if item<0 then + li.iItem:=SendMessage(wnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED) + else + li.iItem:=item; + li.mask :=LVIF_PARAM; + li.lParam :=CB_GetData(GetDlgItem(Dialog,IDC_ACTIONLIST)); + li.iSubItem :=0; + SendMessageW(wnd,LVM_SETITEMW,0,LPARAM(@li)); + li.mask :=LVIF_TEXT; + li.iSubItem :=1; + p:=ApiCard.NameFromList(GetDlgItem(Dialog,IDC_EVENTLIST)); + li.pszText :=FastAnsitoWideBuf(p,buf); + //GetDlgText(Dialog,IDC_EVENTLIST); + SendMessageW(wnd,LVM_SETITEMW,0,LPARAM(@li)); + mFreeMem(li.pszText); +end; + +function NewHook(Dialog:HWND;item:integer=-1):integer; +var + wnd:HWND; + li:LV_ITEMW; +begin + wnd:=GetDlgItem(Dialog,IDC_HOOKLIST); + li.mask :=LVIF_TEXT; + if item<0 then + li.iItem :=SendMessage(wnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED)+1 + else + li.iItem :=item; + li.iSubItem:=0; + li.pszText :=TranslateW('hook sample'); + result:=SendMessageW(wnd,LVM_INSERTITEMW,0,LPARAM(@li)); +end; + +function DeleteHook(Dialog:HWND):integer; +var + wnd:HWND; + i:integer; +begin + result:=0; + wnd:=GetDlgItem(Dialog,IDC_HOOKLIST); + for i:=ListView_GetItemCount(wnd)-1 downto 0 do + begin + if ListView_GetItemState(wnd,i,LVIS_SELECTED)<>0 then + SendMessage(wnd,LVM_DELETEITEM,i,0); + end; + Listview_SetItemState(wnd,0,LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); +end; + +function NewHKTableProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + i:integer; +begin + result:=0; + case hMessage of + WM_KEYDOWN: begin + if (lParam and (1 shl 30))=0 then + begin + case wParam of + VK_F2: begin + i:=SendMessage(Dialog,LVM_GETNEXTITEM,-1,LVNI_FOCUSED); + if i>=0 then + PostMessageW(Dialog,LVM_EDITLABELW,i,0); + exit; + end; + VK_INSERT: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_HOOK_NEW,0); + exit; + end; + VK_DELETE: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_HOOK_DELETE,0); + exit; + end; + end; + end; + end; + end; + result:=CallWindowProc(OldTableProc,Dialog,hMessage,wParam,lParam); +end; + +procedure SetIcons(Dialog:HWND); +var + ti:TTOOLINFOW; + hwndTooltip:HWND; +begin + hwndTooltip:=CreateWindowW(TOOLTIPS_CLASS,nil,TTS_ALWAYSTIP, + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + Dialog,0,hInstance,nil); + + FillChar(ti,SizeOf(ti),0); + ti.cbSize :=sizeof(TOOLINFO); + ti.uFlags :=TTF_IDISHWND or TTF_SUBCLASS; + ti.hwnd :=dialog; + ti.hinst :=hInstance; + + ti.lpszText:=TranslateW('Help'); + ti.uId :=GetDlgItem(Dialog,IDC_EVENT_HELP); + SendMessage(ti.uId,BM_SETIMAGE,IMAGE_ICON, + CallService(MS_SKIN_LOADICON,SKINICON_OTHER_HELP,0)); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,LPARAM(@ti)); + ti.uId :=GetDlgItem(Dialog,IDC_EVENT_CHELP); + SendMessage(ti.uId,BM_SETIMAGE,IMAGE_ICON, + CallService(MS_SKIN_LOADICON,SKINICON_OTHER_HELP,0)); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,LPARAM(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_HOOK_NEW); + ti.lpszText:=TranslateW('New'); + SetButtonIcon(ti.uId,ACI_NEW); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,LPARAM(@ti)); + ti.uId :=GetDlgItem(Dialog,IDC_HOOK_APPLY); + ti.lpszText:=TranslateW('Apply'); + SetButtonIcon(ti.uId,ACI_APPLY); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,LPARAM(@ti)); + ti.uId :=GetDlgItem(Dialog,IDC_HOOK_DELETE); + ti.lpszText:=TranslateW('Delete'); + SetButtonIcon(ti.uId,ACI_DELETE); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,LPARAM(@ti)); +end; + +function DlgProcOpt(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + wnd:HWND; + lv:LV_COLUMNW; + i:integer; + tmp:pAnsiChar; + buf:array [0..255] of AnsiChar; +begin + result:=0; + case hMessage of + WM_CLOSE: begin + ApiCard.Free; + + UnhookEvent(onactchanged); + settings:=0; + end; + + WM_INITDIALOG: begin + ApiCard:=CreateEventCard(Dialog); + + wnd:=GetDlgItem(Dialog,IDC_HOOKLIST); + SendMessage(wnd,LVM_SETUNICODEFORMAT,1,0); + FillChar(lv,SizeOf(lv),0); + lv.mask :=LVCF_TEXT or LVCF_WIDTH; + lv.pszText:=TranslateW('Description'); + lv.cx :=110; + SendMessageW(wnd,LVM_INSERTCOLUMNW ,0,TLPARAM(@lv)); + lv.pszText:=TranslateW('Name'); + lv.cx :=110; + SendMessageW(wnd,LVM_INSERTCOLUMNW ,1,TLPARAM(@lv)); + SendMessageW(wnd,LVM_SETCOLUMNWIDTH,1,LVSCW_AUTOSIZE_USEHEADER); +// SendMessage (wnd,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_CHECKBOXES,LVS_EX_CHECKBOXES); + SendMessage (wnd,LVM_SETEXTENDEDLISTVIEWSTYLE,0, + LVS_EX_FULLROWSELECT or LVS_EX_CHECKBOXES or LVS_EX_GRIDLINES); + SendMessage(wnd,LVM_SETUNICODEFORMAT,1,0); + OldTableProc:=pointer(SetWindowLongPtrW(wnd,GWL_WNDPROC,LONG_PTR(@NewHKTableProc))); + TranslateDialogDefault(Dialog); + + SetIcons(Dialog); + + ApiCard.FillList(GetDlgItem(Dialog,IDC_EVENTLIST), + DBReadByte(0,DBBranch,'SrvListMode')); + + FillActionList(GetDlgItem(Dialog,IDC_ACTIONLIST)); + FillHookList(wnd); + ShowHookData(Dialog); + + onactchanged:=HookEvent(ME_ACT_CHANGED,@ActListChange); + settings:=Dialog; + end; + + WM_HELP: begin + tmp:=ApiCard.NameFromList(GetDlgItem(Dialog,IDC_EVENTLIST)); + ApiCard.Event:=tmp; + mFreeMem(tmp); + ApiCard.Show; + end; + + WM_RESETHOOKS:begin + FillHookList(GetDlgItem(Dialog,IDC_HOOKLIST)); + end; + + WM_COMMAND: begin + case wParam shr 16 of + EN_CHANGE, + CBN_EDITCHANGE, + CBN_SELCHANGE: begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + + case wParam shr 16 of + CBN_EDITCHANGE: begin + case loword(wParam) of + IDC_EVENTLIST: begin + tmp :=GetDlgText(Dialog,IDC_EVENTLIST,true); + ApiCard.Event:=tmp; + mFreeMem(tmp); + tmp:=ApiCard.Description; + SetDlgItemTextA(Dialog,IDC_DESCR,Translate(tmp)); + mFreeMem(tmp); + end; + end; + end; + + CBN_SELENDOK: begin + case loword(wParam) of + IDC_EVENTLIST: begin + i:=SendMessage(LOWORD(lParam),CB_GETCURSEL,0,0); + SendMessageA(LOWORD(lParam),CB_GETLBTEXT,i,TLPARAM(@buf)); + ApiCard.Event:=@buf; + tmp:=ApiCard.Description; + SetDlgItemTextA(Dialog,IDC_DESCR,Translate(tmp)); + mFreeMem(tmp); + end; + end; + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + + BN_CLICKED: begin + case loword(wParam) of + IDC_EVENT_CHELP: SendMessage(Dialog,WM_HELP,0,0); + IDC_EVENT_HELP : ; + IDC_HOOK_NEW : NewHook(Dialog); + IDC_HOOK_DELETE: DeleteHook(Dialog); + IDC_HOOK_APPLY : SaveHookData(Dialog); + end; + end; + end; + end; + + WM_NOTIFY: begin + case integer(PNMHdr(lParam)^.code) of + PSN_APPLY: begin + SaveHookData(Dialog); + CheckHookList(GetDlgItem(Dialog,IDC_HOOKLIST)); + SetAllHooks; + SaveHooks; + end; + + NM_DBLCLK: begin + if PNMListView(lParam)^.iItem>=0 then + PostMessageW(PNMHdr(lParam)^.hWndFrom,LVM_EDITLABELW, + PNMListView(lParam)^.iItem,0); + end; + + LVN_ENDLABELEDITW: begin + with PLVDISPINFOW(lParam)^ do + begin + if item.pszText<>nil then + begin + item.mask:=LVIF_TEXT; + SendMessageW(hdr.hWndFrom,LVM_SETITEMW,0,TLPARAM(@item)); + end; + end; + result:=1; + end; + + LVN_ITEMCHANGED: begin + if PNMLISTVIEW(lParam)^.uChanged=LVIF_STATE then + begin + i:=(PNMLISTVIEW(lParam)^.uOldState and LVNI_FOCUSED)- + (PNMLISTVIEW(lParam)^.uNewState and LVNI_FOCUSED); + + if i>0 then // old focus + SaveHookData(Dialog,PNMLISTVIEW(lParam)^.iItem) + else if i<0 then // new focus + begin + ShowHookData(Dialog,PNMLISTVIEW(lParam)^.iItem); + end + else if (settings<>0) and + ((PNMLISTVIEW(lParam)^.uOldState or PNMLISTVIEW(lParam)^.uNewState)=$3000) then + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + end; + end; + end; +end; diff --git a/plugins/Actman30/hooks/i_options.inc b/plugins/Actman30/hooks/i_options.inc new file mode 100644 index 0000000000..4404cfbde6 --- /dev/null +++ b/plugins/Actman30/hooks/i_options.inc @@ -0,0 +1,71 @@ +{} +const + opt_hook :PAnsiChar = 'Hook'; + opt_hooks :PAnsiChar = 'Hooks'; + opt_count :PAnsiChar = 'numhooks'; + opt_flags :PAnsiChar = 'flags'; + opt_descr :PAnsiChar = 'descr'; + opt_name :PAnsiChar = 'name'; + opt_action:PAnsiChar = 'action'; + +procedure SaveHooks; +var + section:array [0..63] of AnsiChar; + p,p1:PAnsiChar; + i,amount:integer; +begin + DBDeleteGroup(0,DBBranch,opt_hooks); + amount:=0; + p1:=StrCopyE(section,opt_hooks); + p1^:='/'; inc(p1); + p1:=StrCopyE(p1,opt_hook); + for i:=0 to MaxHooks-1 do + begin + if (HookList[i].flags and ACF_ASSIGNED)=0 then + continue; + + p:=StrEnd(IntToStr(p1,amount)); + p^:='/'; inc(p); + + with HookList[i] do + begin + StrCopy(p,opt_flags ); DBWriteDWord (0,DBBranch,section,flags); + StrCopy(p,opt_descr ); DBWriteUnicode(0,DBBranch,section,descr); + StrCopy(p,opt_name ); DBWriteString (0,DBBranch,section,name); + StrCopy(p,opt_action); DBWriteDWord (0,DBBranch,section,action); + end; + inc(amount); + end; + DBWriteByte(0,DBBranch,opt_count,amount); +end; + +function LoadHooks:integer; +var + section:array [0..63] of AnsiChar; + p,p1:PAnsiChar; + i:integer; +begin + MaxHooks:=DBReadByte(0,DBBranch,opt_count); + result:=MaxHooks; + if MaxHooks>0 then + begin + GetMem (HookList ,MaxHooks*SizeOf(tHookRec)); + FillChar(HookList^,MaxHooks*SizeOf(tHookRec),0); + p1:=StrCopyE(section,opt_hooks); + p1^:='/'; inc(p1); + p1:=StrCopyE(p1,opt_hook); + for i:=0 to MaxHooks-1 do + begin + p:=StrEnd(IntToStr(p1,i)); + p^:='/'; inc(p); + + with HookList[i] do + begin + StrCopy(p,opt_flags ); flags :=DBReadDWord (0,DBBranch,section); + StrCopy(p,opt_descr ); descr :=DBReadUnicode(0,DBBranch,section); + StrCopy(p,opt_name ); name :=DBReadString (0,DBBranch,section); + StrCopy(p,opt_action); action:=DBReadDWord (0,DBBranch,section); + end; + end; + end; +end; diff --git a/plugins/Actman30/i_cnst_chain.inc b/plugins/Actman30/i_cnst_chain.inc new file mode 100644 index 0000000000..477d8ce137 --- /dev/null +++ b/plugins/Actman30/i_cnst_chain.inc @@ -0,0 +1,6 @@ +{resource constants} +const + IDC_MACRO_LIST = 2501; + IDC_MACRO_NOWAIT = 2502; + IDC_MACRO_KEEPOLD = 2503; + IDC_MACRO_SAMETHREAD = 2504; diff --git a/plugins/Actman30/i_cnst_contact.inc b/plugins/Actman30/i_cnst_contact.inc new file mode 100644 index 0000000000..5b2cf3991d --- /dev/null +++ b/plugins/Actman30/i_cnst_contact.inc @@ -0,0 +1,6 @@ +{resource constants} +const + IDC_CONTACTLIST = 2141; + IDC_CNT_KEEP = 2142; + IDC_CNT_GET = 2143; + IDC_CNT_REFRESH = 2147; diff --git a/plugins/Actman30/i_cnst_database.inc b/plugins/Actman30/i_cnst_database.inc new file mode 100644 index 0000000000..01b6e382c5 --- /dev/null +++ b/plugins/Actman30/i_cnst_database.inc @@ -0,0 +1,18 @@ +{resource constants} +const + IDC_RW_READ = 2601; + IDC_RW_WRITE = 2602; + IDC_RW_DELETE = 2603; + IDC_RW_MODULE = 2606; + IDC_RW_SETTING = 2608; + IDC_RW_VALUE = 2610; + IDC_RW_DATATYPE = 2611; + IDC_RW_CURRENT = 2614; + IDC_RW_PARAM = 2615; + IDC_RW_MANUAL = 2616; + IDC_RW_RESULT = 2619; + IDC_RW_LAST = 2620; + IDC_RW_SAVE = 2621; + + IDC_CONTACTLIST = 2141; + IDC_CNT_REFRESH = 2142; diff --git a/plugins/Actman30/i_cnst_dlgshare.inc b/plugins/Actman30/i_cnst_dlgshare.inc new file mode 100644 index 0000000000..396499e68a --- /dev/null +++ b/plugins/Actman30/i_cnst_dlgshare.inc @@ -0,0 +1,11 @@ +{all dialogs icons} +const + IDI_NEW = 1025; + IDI_UP = 1026; + IDI_DOWN = 1027; + IDI_DELETE = 1028; + IDI_RELOAD = 1029; + IDI_TEST = 1037; + IDI_EXPORT = 1038; + IDI_IMPORT = 1039; + IDI_APPLY = 1044; diff --git a/plugins/Actman30/i_cnst_inout.inc b/plugins/Actman30/i_cnst_inout.inc new file mode 100644 index 0000000000..ff1cf50d7c --- /dev/null +++ b/plugins/Actman30/i_cnst_inout.inc @@ -0,0 +1,17 @@ +{clipboard/file} +const + IDC_FLAG_CLIP = 2454; + IDC_FLAG_MESSAGE = 2455; + IDC_CLIP_COPYTO = 2456; + IDC_CLIP_PASTE = 2457; + IDC_FILE_ENC = 2459; +// IDC_CLIP_ANSI = 2459; +// IDC_CLIP_WIDE = 2460; + IDC_FLAG_FILE = 2461; + IDC_FILE_PATH = 2462; + IDC_FILE_FILEBTN = 2463; + IDC_FILE_READ = 2464; + IDC_FILE_WRITE = 2465; + IDC_FILE_APPEND = 2466; + + IDC_TEXT_SEND = 2453; diff --git a/plugins/Actman30/i_cnst_jump.inc b/plugins/Actman30/i_cnst_jump.inc new file mode 100644 index 0000000000..9782c9a9d3 --- /dev/null +++ b/plugins/Actman30/i_cnst_jump.inc @@ -0,0 +1,15 @@ +{resource constants} +const + IDC_FLAG_MATH = 2506; + IDC_FLAG_TEXT = 2507; + IDC_FLAG_NOP = 2509; + IDC_FLAG_NOT = 2510; + + IDC_JMP_MATH = 2511; + IDC_JMP_TEXT = 2512; + IDC_JMP_VALUE = 2513; + IDC_FLAG_CASE = 2514; + IDC_FLAG_BACK = 2515; + IDC_JMP_ACTLIST = 2522; + IDC_FLAG_BREAK = 2523; + IDC_FLAG_JUMP = 2524; diff --git a/plugins/Actman30/i_cnst_message.inc b/plugins/Actman30/i_cnst_message.inc new file mode 100644 index 0000000000..02db4c3d9b --- /dev/null +++ b/plugins/Actman30/i_cnst_message.inc @@ -0,0 +1,17 @@ +{resource constants} +const + IDC_MSG_TITLE = 2703; + IDC_MSG_TEXT = 2704; + IDC_MSGB_ARI = 2706; + IDC_MSGB_OK = 2707; + IDC_MSGB_OC = 2708; + IDC_MSGB_RC = 2709; + IDC_MSGB_YN = 2710; + IDC_MSGB_YNC = 2711; + IDC_MSGI_NONE = 2713; + IDC_MSGI_WARN = 2714; + IDC_MSGI_INFO = 2715; + IDC_MSGI_QUEST = 2716; + IDC_MSGI_ERROR = 2717; + IDC_MSG_RTL = 2718; + IDC_MSG_RIGHT = 2719; diff --git a/plugins/Actman30/i_cnst_program.inc b/plugins/Actman30/i_cnst_program.inc new file mode 100644 index 0000000000..93d2ed5d0b --- /dev/null +++ b/plugins/Actman30/i_cnst_program.inc @@ -0,0 +1,13 @@ +{resource constants} +const + IDC_FLAG_MINIMIZE = 2350; + IDC_EDIT_PRGPATH = 2352; + IDC_PROGRAM = 2353; + IDC_EDIT_PRGARGS = 2355; + IDC_EDIT_PROCTIME = 2356; + IDC_FLAG_NORMAL = 2360; + IDC_FLAG_HIDDEN = 2361; + IDC_FLAG_MAXIMIZE = 2362; + IDC_FLAG_CURPATH = 2363; + IDC_FLAG_PARALLEL = 2364; + IDC_FLAG_CONTINUE = 2365; diff --git a/plugins/Actman30/i_cnst_service.inc b/plugins/Actman30/i_cnst_service.inc new file mode 100644 index 0000000000..2e5f0cca83 --- /dev/null +++ b/plugins/Actman30/i_cnst_service.inc @@ -0,0 +1,12 @@ +const + IDC_FLAG_WPAR = 2154; + IDC_FLAG_LPAR = 2155; + IDC_EDIT_WPAR = 2156; + IDC_EDIT_LPAR = 2157; + IDC_EDIT_SERVICE = 2159; + IDC_WSTRUCT = 2160; + IDC_LSTRUCT = 2161; + + IDC_SRV_RESULT = 2255; + IDC_RES_FREEMEM = 2256; + IDC_RES_UNICODE = 2257; diff --git a/plugins/Actman30/i_cnst_settings.inc b/plugins/Actman30/i_cnst_settings.inc new file mode 100644 index 0000000000..6728f953a9 --- /dev/null +++ b/plugins/Actman30/i_cnst_settings.inc @@ -0,0 +1,11 @@ +{resource constants} +const + IDC_EDIT_FORMAT = 2144; + IDC_CNT_FILTER = 2145; + IDC_CNT_APPLY = 2146; + + IDC_SERVICELIST = 2150; + IDC_SRV_APPLY = 2151; + + IDC_FR_FLAG = 2155; + IDC_HC_WPAR = 2156; diff --git a/plugins/Actman30/i_cnst_storage.inc b/plugins/Actman30/i_cnst_storage.inc new file mode 100644 index 0000000000..adaa7690c6 --- /dev/null +++ b/plugins/Actman30/i_cnst_storage.inc @@ -0,0 +1,5 @@ +{resource constants} +const + IDC_STORAGELIST = 2141; + IDC_FLAG_TO = 2142; + IDC_FLAG_FROM = 2143; diff --git a/plugins/Actman30/i_cnst_text.inc b/plugins/Actman30/i_cnst_text.inc new file mode 100644 index 0000000000..b25f155ef2 --- /dev/null +++ b/plugins/Actman30/i_cnst_text.inc @@ -0,0 +1,4 @@ +{text data} +const + IDC_TXT_TEXT = 2190; + IDC_TXT_POST = 2191; diff --git a/plugins/Actman30/i_const.inc b/plugins/Actman30/i_const.inc new file mode 100644 index 0000000000..baf5b5edf3 --- /dev/null +++ b/plugins/Actman30/i_const.inc @@ -0,0 +1,31 @@ +{resource constants} +const + // dialogs + IDD_ACTION = 1025; + IDD_ASK = 1028; + + IDC_ACTION_TYPE = 2005; + IDC_STAT_ACTION = 2006; + + IDC_ACTION_LIST = 2007; + IDC_ACTION_NEW = 2008; + IDC_ACTION_DELETE = 2009; + IDC_ACTION_UP = 2010; + IDC_ACTION_DOWN = 2011; + + IDC_MACRO_LIST = 2012; + IDC_GROUP_NEW = 2015; + IDC_GROUP_RELOAD = 2016; + IDC_GROUP_DELETE = 2017; + IDC_GROUP_TEST = 2018; + IDC_GROUP_UP = 2019; + IDC_GROUP_DOWN = 2020; + IDC_GROUP_EXPORT = 2021; + IDC_GROUP_IMPORT = 2022; + IDC_ACTION_HELP = 2023; + +// Question + IDC_ASK = 1025; + IDC_YESALL = 1026; + IDC_NOALL = 1027; + IDC_APPEND = 1028; diff --git a/plugins/Actman30/i_opt_dlg.inc b/plugins/Actman30/i_opt_dlg.inc new file mode 100644 index 0000000000..62a0a6c66f --- /dev/null +++ b/plugins/Actman30/i_opt_dlg.inc @@ -0,0 +1,52 @@ +{} +var + xmlfilename:array [0..511] of WideChar; +const + etMacro = 1; // Groups changed + etACT = 2; // Actions changed + +{$include i_opt_dlg2.inc} + +function OnOptInitialise(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + odp:TOPTIONSDIALOGPAGE; + ptr:pActionLink; + tmpl:pAnsiChar; + name:pansiChar; + proc:pointer; + i:integer; +begin + result:=0; + NoDescription:=TranslateW('No Description'); + + StrCopyW(xmlfilename,'c:\export.xml'); + + DoInitCommonControls(ICC_USEREX_CLASSES); + + FillChar(odp,SizeOf(odp),0); + odp.cbSize :=SizeOf(odp); + odp.flags :=ODPF_BOLDGROUPS; + odp.Position :=900003000; + odp.hInstance :=hInstance; + odp.szGroup.a :='Services'; + odp.szTitle.a :='Actions'; + odp.szTab.a :='Actions'; + odp.pfnDlgProc :=@DlgProcOpt2; + odp.pszTemplate:=PAnsiChar(IDD_ACTION); + Options_AddPage(wParam,@odp); + + ptr:=ActionLink; + while ptr<>nil do + begin + if @ptr^.AddOption<>nil then + begin + i:=ptr^.AddOption(tmpl,proc,name); + odp.pszTemplate:=tmpl; + odp.pfnDlgProc :=proc; + odp.szTab.a :=name; + Options_AddPage(wParam,@odp); + if i>0 then continue; + end; + ptr:=ptr^.Next; + end; +end; diff --git a/plugins/Actman30/i_opt_dlg2.inc b/plugins/Actman30/i_opt_dlg2.inc new file mode 100644 index 0000000000..8313b4d4a3 --- /dev/null +++ b/plugins/Actman30/i_opt_dlg2.inc @@ -0,0 +1,1318 @@ +{} + +const + inoutfilter:pWideChar = 'XML files'#0'*.xml'#0'All files'#0'*.*'#0#0; +const + MaxDescrLen = 128; +const + hlpVariables = 30; + hlpAdvVariables = 31; + +var + DontReact:bool; + OldGroupTableProc, + OldActTableProc:pointer; + EventMask:dword; + +procedure ChangeListNotify(list:integer); +var + p:pActModule; +begin + p:=ModuleLink; + while p<>nil do + begin + SendMessage(p^.DlgHandle,WM_ACT_LISTCHANGE,list,0); + p:=p^.Next; + end; +end; + +procedure ResetDialogs; +var + p:pActModule; +begin + p:=ModuleLink; + while p<>nil do + begin + SendMessage(p^.DlgHandle,WM_ACT_RESET,0,0); + p:=p^.Next; + end; +end; + +procedure ClearDialogData; +var + p:pActModule; +begin + p:=ModuleLink; + while p<>nil do + begin + if p^.DlgHandle<>0 then ShowWindow(p^.DlgHandle,SW_HIDE); + p:=p^.Next; + end; +end; + +function CheckChanges:dword; +var + i,j:integer; + found:boolean; +begin + result:=0; + // 1 - search new items (EditMacroList elements which don't exists in MacroList) + found:=true; + for i:=0 to EditMacroList.Count-1 do + begin + if (EditMacroList[i]^.flags and ACF_ASSIGNED)<>0 then + begin + found:=false; + for j:=0 to MacroList.Count-1 do + begin + if (MacroList[j]^.flags and ACF_ASSIGNED)<>0 then + begin + if EditMacroList[i]^.id=MacroList[j]^.id then + begin + found:=true; + break; + end; + end; + end; + if not found then break; + end; + end; + if not found then + result:=result or ACTM_NEW; + // 2 - search deleted items (MacroList elements which don't exists in EditMacroList) + found:=true; + for i:=0 to MacroList.Count-1 do + begin + if (MacroList[i]^.flags and ACF_ASSIGNED)<>0 then + begin + found:=false; + for j:=0 to EditMacroList.Count-1 do + begin + if (EditMacroList[j]^.flags and ACF_ASSIGNED)<>0 then + begin + if MacroList[i]^.id=EditMacroList[j]^.id then + begin + found:=true; + break; + end; + end; + end; + if not found then break; + end; + end; + if not found then + result:=result or ACTM_DELETE; + // 3 - resort? (maybe ANY EditMacroList position changes) +end; + +procedure SetChanged(wnd:HWND;atype:integer); +begin + SendMessage(GetParent(wnd),PSM_CHANGED,0,0); +// if ((atype and etMacro)<>0) and (NewGroupList =GroupList ) then NewGroupList :=CloneGroupList; +// if ((atype and etACT )<>0) and (NewActionList=ActionList) then NewActionList:=CloneActionList; +end; + +procedure SetStart; +begin + EditMacroList:=MacroList.Clone(); +end; + +// Cancel button pressed OR Edit window closed (After apply action) +// No main list changed (except flags clearance - not necessary) +// Edit macro list freeing with actions marked as introduced +procedure SetCancel; +var + i,j:integer; +begin + // Delete changed data + EditMacroList.Clear(ACF_INTRODUCED); + EditMacroList.Free; + + // Clear editing flags + for i:=0 to MacroList.Count-1 do + begin + with MacroList[i]^ do + if (flags and ACF_ASSIGNED)<>0 then + begin + for j:=0 to ActionCount-1 do + begin + ActionList^[j].flags:=ActionList^[j].flags and not ACF_REPLACED; + end; + end; + end; +end; + +// SAVE: fill edit macro list by dialog options, +// Free main macro list with actions marked as replaced +// copy content to main macro list (state as at option editing start) +// clear "introduced" and "replaced" flags +procedure SetSave(Dialog:HWND); +var + i,j:integer; + TmpMacroList:tMacroList; + TmpMacroCount:integer; + wnd:HWND; + li:LV_ITEMW; +begin + wnd:=MacroListWindow; + TmpMacroCount:=SendMessageW(wnd,LVM_GETITEMCOUNT,0,0); + + // need to clear flags and resort + if TmpMacroCount>0 then + begin + // Clear actions editing flags + for i:=0 to EditMacroList.Count-1 do + begin + with EditMacroList[i]^ do + if (flags and ACF_ASSIGNED)<>0 then + begin + for j:=0 to ActionCount-1 do + begin + ActionList^[j].flags:=ActionList^[j].flags and not ACF_INTRODUCED; + end; + end; + end; + + TmpMacroList:=tMacroList.Create(TmpMacroCount); + + // resort/copy macros + li.mask :=LVIF_PARAM; + li.iSubItem:=0; + for i:=0 to TmpMacroCount-1 do + begin + li.iItem:=i; + SendMessageW(wnd,LVM_GETITEMW,0,lparam(@li)); // GetLParam(wnd,i); + move(EditMacroList[loword(li.lParam)]^,TmpMacroList[i]^,SizeOf(tMacroRecord)); + if (li.lParam and ACF_FIRSTRUN)<>0 then + TmpMacroList[i]^.flags:=TmpMacroList[i]^.flags or ACF_FIRSTRUN + else + TmpMacroList[i]^.flags:=TmpMacroList[i]^.flags and not ACF_FIRSTRUN; + li.lParam:=(li.lParam and (not $FFFF)) or i; + SendMessageW(wnd,LVM_SETITEMW,0,lparam(@li)); + end; + + EditMacroList.Free; + EditMacroList:=TmpMacroList; + end; + + MacroList.Clear(ACF_REPLACED); + MacroList.Free; + MacroList:=EditMacroList.Clone; +end; + +// Fill action type combobox +function FillActTypeList(list:hwnd):HWND; +var + cbei:TCOMBOBOXEXITEMW; + il:HIMAGELIST; + i:integer; + buf:array [0..127] of WideChar; + p:pActModule; + rc:TRECT; + dlg:HWND; +begin + il:=ImageList_Create(16,16,ILC_COLOR32 or ILC_MASK,0,1); + SendMessage(list,CB_RESETCONTENT,0,0); + + FillChar(cbei,SizeOf(cbei),0); + cbei.mask:=CBEIF_IMAGE or CBEIF_SELECTEDIMAGE or CBEIF_TEXT or CBEIF_LPARAM; + p:=ModuleLink; + i:=0; + // initial action dialogs position + SetRect(rc,134,22,0,0); + dlg:=GetParent(list); + MapDialogRect(dlg,rc); + while p<>nil do + begin + StrCopy(StrCopyE(@buf,IcoLibPrefix),p^.Name); + ImageList_AddIcon(il,CallService(MS_SKIN2_GETICON,0,lparam(@buf))); + + cbei.pszText :=TranslateW(FastAnsiToWideBuf(p^.Name,buf)); + cbei.iItem :=i; + cbei.lParam :=p^.Hash; + cbei.iImage :=i; + cbei.iSelectedImage:=i; + if SendMessageW(list,CBEM_INSERTITEMW,0,lparam(@cbei))=-1 then + break; + p^.DlgHandle:=p^.Dialog(dlg); + SetWindowPos(p^.DlgHandle,0,rc.left,rc.top,0,0,SWP_NOZORDER or SWP_NOSIZE or SWP_HIDEWINDOW); + p:=p^.Next; + inc(i); + end; + ImageList_Destroy(SendMessage(list,CBEM_SETIMAGELIST,0,il)); + + SendMessage(list,CB_SETCURSEL,0,0); + result:=GetLink(CB_GetData(list,0))^.DlgHandle; +end; + +//----- Action list stuff ----- + +procedure SHActButtons(Dialog:HWND;mode:integer); +begin + ShowWindow(GetDlgItem(Dialog,IDC_STAT_ACTION),mode); + ShowWindow(GetDlgItem(Dialog,IDC_ACTION_TYPE),mode); + if mode=SW_HIDE then + ClearDialogData; +end; + +procedure CheckActListDirectionButtons(Dialog:HWND); +var + wnd:HWND; + dir:integer; + okup,okdown:boolean; +begin + wnd:=ActionListWindow; + + dir:=LV_CheckDirection(wnd); + okup :=odd(loword(dir)); + okdown:=(loword(dir) and 2)<>0; + + EnableWindow(GetDlgItem(Dialog,IDC_ACTION_UP ),okup); + EnableWindow(GetDlgItem(Dialog,IDC_ACTION_DOWN),okdown); + SendMessage(wnd,LVM_ENSUREVISIBLE,hiword(dir)-1,0); +end; + +procedure CheckActListButtons(Dialog:HWND); +var + mode:integer; + wnd:HWND; + b:boolean; +begin + wnd:=ActionListWindow; + b:=SendMessage(wnd,LVM_GETITEMCOUNT,0,0)>0; + if b then +{ + ListView_SetItemState(wnd,next, + LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); +} + mode:=SW_SHOW + else + mode:=SW_HIDE; + + SHActButtons(Dialog,mode); + + EnableWindow(wnd,b); + EnableWindow(GetDlgItem(Dialog,IDC_ACTION_HELP ),b); + EnableWindow(GetDlgItem(Dialog,IDC_GROUP_TEST ),b); + EnableWindow(GetDlgItem(Dialog,IDC_ACTION_DELETE),b); + EnableWindow(GetDlgItem(Dialog,IDC_ACTION_TYPE ),b); + + CheckActListDirectionButtons(Dialog); +end; + +// Fill dialog fields by choosen action +procedure FillAction(Dialog:HWND;act:tBaseAction); +var + p:pActModule; + i:lresult; + wnd:HWND; +begin + if act<>nil then + begin + p:=GetLink(act.UID); + if p<>nil then + SendMessage(p^.DlgHandle,WM_ACT_SETVALUE,0,tlparam(act)); + end + // for newly added and activated action + else + p:=ModuleLink; + + if p<>nil then + begin + wnd:=GetDlgItem(Dialog,IDC_ACTION_TYPE); + i:=CB_SelectData(wnd,tlparam(p^.Hash)); + ShowWindow(p^.DlgHandle,SW_SHOW); + // Saving "normal" action type + if p^.Hash>10 then + begin + SetWindowLongPtrW(wnd,GWLP_USERDATA,i); + end; + end; +end; + +// Fill Chain list +procedure FillActionList(Dialog:HWND;Macro:pMacroRecord); +var + idx:integer; + wnd:HWND; + li:LV_ITEMW; +begin + wnd:=ActionListWindow; + SendMessage(wnd,LVM_DELETEALLITEMS,0,0); + + if (Macro<>nil) and (Macro^.ActionCount>0) then + begin + li.mask :=LVIF_TEXT or LVIF_PARAM; + li.iSubitem:=0; + idx:=0; + while idx=0 then + begin + li.iSubItem:=0; + // getting SubAction number + li.mask:=LVIF_PARAM; + SendMessage(wnd,LVM_GETITEM,0,tlparam(@li)); + + // changing to default name + if str=nil then + begin + str:=StrCopyEW(@buf,TranslateW('Action')); + str^:=' '; inc(str); + IntToStr(str,SendMessage(wnd,LVM_GETITEMCOUNT,0,0)); + str:=@buf; + end; + + li.mask :=LVIF_TEXT; + li.pszText:=str; + SendMessageW(wnd,LVM_SETITEMW,0,tlparam(@li)); + end; +end; + +procedure SaveAction(Dialog:HWND;listnum:integer;actptr:tBaseAction); +var + wnd:HWND; +// li:LV_ITEMW; +// arr: array [0..255] of WideChar; + p:pActModule; +begin + wnd:=GetDlgItem(Dialog,IDC_ACTION_TYPE); + p:=GetLink(CB_GetData(wnd)); + if p^.Hash<10 then + begin + p:=GetLink(CB_GetData(wnd,GetWindowLongPtrW(wnd,GWLP_USERDATA))); + end; + + wnd:=ActionListWindow; + + if listnum<0 then + begin + listnum:=SendMessageW(wnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED); + if listnum<0 then + exit; + actptr:=tBaseAction(LV_GetLParam(wnd,listnum)); + end; + + // changed existing action + if actptr<>nil then + begin + if (actptr.flags and ACF_INTRODUCED)<>0 then // new but changed + actptr.Free + else // old + actptr.flags:=actptr.flags or ACF_REPLACED; + end; + + // Action saving + actptr:=p.Create; + SendMessage(p.DlgHandle,WM_ACT_SAVE,0,tlparam(actptr)); + actptr.flags:=actptr.flags or ACF_INTRODUCED; +{ maybe do it at full chain saving? + + li.iItem :=listnum; + li.mask :=LVIF_TEXT; + li.iSubItem :=0; + li.pszText :=@arr; + li.cchTextMax:=SizeOf(arr) div SizeOf(WideChar); + SendDlgItemMessageW(Dialog,IDC_ACTION_LIST,LVM_GETITEMW,0,tlparam(@li)); + StrDupW(actptr.ActionDescr,arr); + + if ListView_GetCheckState(wnd,listnum)=0 then + actptr.flags:=actptr.flags or ACF_DISABLED; +} + LV_SetLParam(wnd,tlparam(actptr),listnum); +end; + +procedure BuildActionChain(Dialog:HWND;group:integer=-1); +var + item:integer; + wnd:HWND; + idx:integer; + li:LV_ITEMW; + arr: array [0..255] of WideChar; +begin + idx:=loword(LV_GetLParam(MacroListWindow,group)); + if idx>=0 then // we have macro to save + begin + SaveAction(Dialog,-1,nil); + + with EditMacroList[idx]^ do + begin + if ActionCount>0 then + begin + ActionCount:=0; + FreeMem(ActionList); + ActionList:=nil; + end; + end; + + wnd:=ActionListWindow; + with EditMacroList[idx]^ do + begin + ActionCount:=SendMessageW(wnd,LVM_GETITEMCOUNT,0,0); + if ActionCount>0 then // have some actions - need to build list + begin + // fix count for empty actions + item:=0; + idx:=0; + while item0 then + Inc(idx); + Inc(item); + end; + // if REAL amount to save>0 (macro not empty) + if idx>0 then + begin + GetMem(ActionList,SizeOf(tBaseAction)*idx); + + li.mask :=LVIF_TEXT; + li.iSubItem :=0; + li.pszText :=@arr; + li.cchTextMax:=SizeOf(arr) div SizeOf(WideChar); + + idx:=0; + for item:=0 to ActionCount-1 do + begin + ActionList^[idx]:=tBaseAction(LV_GetLParam(wnd,item)); + if ActionList^[idx]<>nil then + begin + // set name and enabled/disabled flag + li.iItem:=item; + SendDlgItemMessageW(Dialog,IDC_ACTION_LIST,LVM_GETITEMW,0,tlparam(@li)); + mFreeMem(ActionList^[idx].ActionDescr); + StrDupW(ActionList^[idx].ActionDescr,arr); + + if ListView_GetCheckState(wnd,item)=0 then + ActionList^[idx].flags:=ActionList^[item].flags or ACF_DISABLED + else + ActionList^[idx].flags:=ActionList^[item].flags and not ACF_DISABLED; + inc(idx); + end; + end; + end; + ActionCount:=idx; // fix for empty actions + end; + end; + end; +end; + +// action (chain) table procedure (key hook) +function NewActTableProc(Dialog:HWnd;hMessage:uint;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + i:integer; +begin + result:=0; + case hMessage of + WM_KEYDOWN: begin + if (lParam and (1 shl 30))=0 then + begin + case wParam of + VK_F2: begin + i:=SendMessage(Dialog,LVM_GETNEXTITEM,-1,LVNI_FOCUSED); + if i>=0 then + PostMessageW(Dialog,LVM_EDITLABELW,i,0); + exit; + end; + VK_UP: begin + if (GetKeyState(VK_CONTROL) and $8000)<>0 then + begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_ACTION_UP,0); + exit; + end; + end; + VK_DOWN: begin + if (GetKeyState(VK_CONTROL) and $8000)<>0 then + begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_ACTION_DOWN,0); + exit; + end; + end; + VK_INSERT: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_ACTION_NEW,0); + exit; + end; + VK_DELETE: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_ACTION_DELETE,0); + exit; + end; + end; + end; + end; + end; + result:=CallWindowProc(OldActTableProc,Dialog,hMessage,wParam,lParam); +end; + +//----- Macro list stuff ----- + +// action group table procedure (key hook) +function NewGroupTableProc(Dialog:HWnd;hMessage:uint;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + i:integer; +begin + result:=0; + case hMessage of + WM_KEYDOWN: begin + if (lParam and (1 shl 30))=0 then + begin + case wParam of + VK_F2: begin + i:=SendMessage(Dialog,LVM_GETNEXTITEM,-1,LVNI_FOCUSED); + if i>=0 then + PostMessageW(Dialog,LVM_EDITLABELW,i,0); + exit; + end; + VK_INSERT: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_GROUP_NEW,0); + exit; + end; + VK_DELETE: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_GROUP_DELETE,0); + exit; + end; + VK_UP: begin + if (GetKeyState(VK_CONTROL) and $8000)<>0 then + begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_GROUP_UP,0); + exit; + end; + end; + VK_DOWN: begin + if (GetKeyState(VK_CONTROL) and $8000)<>0 then + begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_GROUP_DOWN,0); + exit; + end; + end; + end; + end; + end; + end; + result:=CallWindowProc(OldGroupTableProc,Dialog,hMessage,wParam,lParam); +end; + +function AddMacro(Dialog:HWND;MacroNum:cardinal):integer; +var + li:LV_ITEMW; + list:HWND; +begin + with EditMacroList[MacroNum]^ do + begin + list:=MacroListWindow; + li.mask :=LVIF_PARAM+LVIF_TEXT; + li.iItem :=SendMessage(list,LVM_GETNEXTITEM,-1,LVNI_FOCUSED)+1; + li.iSubItem :=0; + li.lParam :=MacroNum; + li.pszText :=@descr; + li.iItem :=SendMessageW(list,LVM_INSERTITEMW,0,lparam(@li)); + if li.iItem>0 then + dec(li.iItem); + ListView_SetItemState(list,li.iItem, + LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); + result:=li.iItem; + end; +end; + +function MoveMacro(list:HWND;num:integer;incr:integer):integer; +var + i,j:integer; +begin + if num<0 then + begin + result:=-1; + j:=SendMessage(list,LVM_GETITEMCOUNT,0,0)-1; + if incr<0 then // up, from beginning + begin + for i:=0 to j do + begin + if SendMessage(list,LVM_GETITEMSTATE,i,LVIS_SELECTED)<>0 then + begin + if i=0 then break; // first selected is first already, nothing to move + LV_MoveItem(list,incr,i); + if result<0 then result:=i+incr; + end; + end; + end + else // down, from the end + begin + for i:=j downto 0 do + begin + if SendMessage(list,LVM_GETITEMSTATE,i,LVIS_SELECTED)<>0 then + begin + if i=j then break; // last selected is last already, nothing to move + LV_MoveItem(list,incr,i); + if result<0 then result:=i+incr; + end; + end; + end; + end + else + begin + LV_MoveItem(list,incr,num); + result:=num; + end; +end; + +// enable/disable navigation chain buttons +procedure CheckMacroListDirectionButtons(Dialog:HWND); +var + wnd:HWND; + dir:integer; + okup,okdown:boolean; +begin + wnd:=MacroListWindow; + dir:=LV_CheckDirection(wnd); + okup :=odd(loword(dir)); + okdown:=(loword(dir) and 2)<>0; + + EnableWindow(GetDlgItem(Dialog,IDC_GROUP_UP ),okup); + EnableWindow(GetDlgItem(Dialog,IDC_GROUP_DOWN),okdown); + SendMessage(wnd,LVM_ENSUREVISIBLE,hiword(dir)-1,0); +end; + +procedure CheckMacroList(Dialog:HWND); +var + wnd:HWND; + b:boolean; +begin + wnd:=MacroListWindow; + + b:=SendMessage(wnd,LVM_GETITEMCOUNT,0,0)>0; + if not b then + CheckActListButtons(Dialog); + + EnableWindow(wnd,b); + EnableWindow(GetDlgItem(Dialog,IDC_ACTION_NEW ),b); + EnableWindow(GetDlgItem(Dialog,IDC_GROUP_DELETE),b); + EnableWindow(GetDlgItem(Dialog,IDC_GROUP_EXPORT),b); + + CheckMacroListDirectionButtons(Dialog); +end; + +// Fill action group list and disable chain controls +function FillMacroList(Dialog:hwnd):integer; +var + CurMacro:pMacroRecord; + i:integer; + list:HWND; + lvi:TLVITEMW; +begin + SendDlgItemMessage(Dialog,IDC_ACTION_LIST,LVM_DELETEALLITEMS,0,0); + CheckActListButtons(Dialog); + + list:=MacroListWindow; + + SendMessage(list,LVM_DELETEALLITEMS,0,0); + result:=-1; + if EditMacroList.Count>0 then + begin + CurMacro:=EditMacroList[0]; + lvi.mask:=LVIF_TEXT+LVIF_PARAM; + lvi.iSubItem:=0; + for i:=0 to EditMacroList.Count-1 do + begin + if (CurMacro^.flags and ACF_ASSIGNED)<>0 then + begin + lvi.iItem :=i; + + lvi.lParam:=i; + if (CurMacro^.flags and ACF_FIRSTRUN)<>0 then + lvi.lParam:=lvi.lParam or ACF_FIRSTRUN; + + lvi.pszText:=@(CurMacro^.descr); + SendMessageW(list,LVM_INSERTITEMW,0,tlparam(@lvi)); + inc(result); + end; + inc(CurMacro); + end; + end; + + CheckMacroList(Dialog); +//?? SendMessage(list,CB_SETCURSEL,0,0); + SendMessage(list,LVM_SETCOLUMNWIDTH,0,LVSCW_AUTOSIZE_USEHEADER); + + ListView_SetItemState(list,0, + LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); +end; + +//----- Other stuff ----- + +procedure SetButtonIcons2(Dialog:HWND); +var + ti:TTOOLINFOW; + hwndTooltip:HWND; +begin + hwndTooltip:=CreateWindowW(TOOLTIPS_CLASS,nil,TTS_ALWAYSTIP, + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + Dialog,0,hInstance,nil); + + FillChar(ti,SizeOf(ti),0); + ti.cbSize :=sizeof(TOOLINFO); + ti.uFlags :=TTF_IDISHWND or TTF_SUBCLASS; + ti.hwnd :=Dialog; + ti.hinst :=hInstance; + + ti.uId :=GetDlgItem(Dialog,IDC_ACTION_HELP); + ti.lpszText:=TranslateW('Help'); + SendMessage(ti.uId,BM_SETIMAGE,IMAGE_ICON, + CallService(MS_SKIN_LOADICON,SKINICON_OTHER_HELP,0)); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_ACTION_NEW); + ti.lpszText:=TranslateW('New'); + OptSetButtonIcon(ti.uId,ACI_NEW); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); +{ + hNew:=GetDlgItem(Dialog,IDC_NEW); + SendMessage (hNew,BUTTONADDTOOLTIP,TWPARAM(TranslateW('New')),BATF_UNICODE); + OptSetButtonIcon(hNew,ACI_NEW); +} + + ti.uId :=GetDlgItem(Dialog,IDC_GROUP_NEW); + OptSetButtonIcon(ti.uId,ACI_NEW); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_ACTION_UP); + ti.lpszText:=TranslateW('Up'); + OptSetButtonIcon(ti.uId,ACI_UP); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_GROUP_UP); + OptSetButtonIcon(ti.uId,ACI_UP); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_ACTION_DOWN); + ti.lpszText:=TranslateW('Down'); + OptSetButtonIcon(ti.uId,ACI_DOWN); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_GROUP_DOWN); + OptSetButtonIcon(ti.uId,ACI_DOWN); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_ACTION_DELETE); + ti.lpszText:=TranslateW('Delete'); + OptSetButtonIcon(ti.uId,ACI_DELETE); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_GROUP_DELETE); + OptSetButtonIcon(ti.uId,ACI_DELETE); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); +{ + ti.uId :=GetDlgItem(Dialog,IDC_GROUP_RELOAD); + ti.lpszText:=TranslateW('Reload'); + OptSetButtonIcon(ti.uId,ACI_RELOAD); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); +} + ti.uId :=GetDlgItem(Dialog,IDC_GROUP_TEST); + ti.lpszText:=TranslateW('Test'); + OptSetButtonIcon(ti.uId,ACI_TEST); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_GROUP_IMPORT); + ti.lpszText:=TranslateW('Import'); + OptSetButtonIcon(ti.uId,ACI_IMPORT); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_GROUP_EXPORT); + ti.lpszText:=TranslateW('Export'); + OptSetButtonIcon(ti.uId,ACI_EXPORT); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); +end; + +function DlgProcOpt2(Dialog:HWnd;hMessage:uint;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + wnd:HWND; + p:pActModule; + i,j,num:int_ptr; + lvflag:integer; + li:LV_ITEMW; + lv:LV_COLUMNW; +begin + result:=0; + case hMessage of + WM_DESTROY: begin + SetCancel; + end; + + WM_INITDIALOG: begin + SetStart; + DontReact :=true; + // variant - put after all dialogs adds (to translate them too) + TranslateDialogDefault(Dialog); + // For some actions + MacroListWindow :=GetDlgItem(Dialog,IDC_MACRO_LIST); + ActionListWindow:=GetDlgItem(Dialog,IDC_ACTION_LIST); + + SetButtonIcons2(Dialog); + wnd:=ActionListWindow; + SendMessage(wnd,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_CHECKBOXES,LVS_EX_CHECKBOXES); + SendMessage(wnd,LVM_SETUNICODEFORMAT,1,0); + FillChar(lv,SizeOf(lv),0); + lv.mask:=LVCF_WIDTH; + lv.cx :=110; + SendMessageW(wnd,LVM_INSERTCOLUMNW ,0,tlparam(@lv)); + SendMessageW(wnd,LVM_SETCOLUMNWIDTH,0,LVSCW_AUTOSIZE_USEHEADER); + + // action type combobox + FillActTypeList(GetDlgItem(Dialog,IDC_ACTION_TYPE)); + + // XML import/export service + if ServiceExists(MS_SYSTEM_GET_XI)=0 then + begin + EnableWindow(GetDlgItem(Dialog,IDC_GROUP_EXPORT),false); + EnableWindow(GetDlgItem(Dialog,IDC_GROUP_IMPORT),false); + end; + + OldActTableProc :=pointer(SetWindowLongPtrW(wnd,GWL_WNDPROC,long_ptr(@NewActTableProc))); + OldGroupTableProc:=pointer(SetWindowLongPtrW(MacroListWindow, + GWL_WNDPROC,long_ptr(@NewGroupTableProc))); + + ClearDialogData; + ResetDialogs; + + // fill group list + wnd:=MacroListWindow; + SendMessage(wnd,LVM_SETUNICODEFORMAT,1,0); + lv.mask:=LVCF_WIDTH; + lv.cx :=110; + SendMessageW(wnd,LVM_INSERTCOLUMNW,0,tlparam(@lv)); + FillMacroList(Dialog); + ChangeListNotify(1); + + // fill current group + FillActionList(Dialog,EditMacroList[0]); + ChangeListNotify(2); + EventMask:=0; + DontReact:=false; + end; + + WM_COMMAND: begin + if DontReact then exit; + case wParam shr 16 of +{ + EN_CHANGE: begin +// check for group renaming + if loword(wParam)<>IDC_EDIT_FORMAT then + begin + SetChanged(Dialog,etACT); + end; + end; +} + CBN_SELCHANGE: begin + case loword(wParam) of + IDC_ACTION_TYPE: begin + ClearDialogData; + p:=GetLink(CB_GetData(lParam)); + ShowWindow(p^.DlgHandle,SW_SHOW); + + // Saving prevoius "normal" action type + if p^.Hash>10 then + begin + SetWindowLongPtrW(lParam,GWLP_USERDATA, + SendMessage(lParam,CB_GETCURSEL,0,0)); + SetChanged(Dialog,etACT); + end; + end; + end; + end; + + BN_CLICKED: begin + case loword(wParam) of + IDC_GROUP_RELOAD, // don't affect to saved (DB) datas + IDC_ACTION_HELP, + IDC_GROUP_EXPORT, + IDC_GROUP_TEST: ; + + IDC_GROUP_UP, + IDC_GROUP_DOWN, + IDC_GROUP_NEW : SetChanged(Dialog,etMacro); + + IDC_GROUP_DELETE, // action deleting with subactions + IDC_GROUP_IMPORT, + IDC_ACTION_NEW, + IDC_ACTION_DELETE, + IDC_ACTION_UP, + IDC_ACTION_DOWN: begin + SetChanged(Dialog,etMacro+etACT); + end; + else + SetChanged(Dialog,etACT); + end; + + case loword(wParam) of +{ + IDC_GROUP_EXPORT: begin + if ShowDlgW(xmlfilename,xmlfilename,TranslateW(inoutfilter),false) then + begin + wnd:=MacroListWindow; + for i:=0 to ListView_GetItemCount(wnd)-1 do + begin + if ListView_GetItemState(wnd,i,LVIS_SELECTED)<>0 then + begin + with EditMacroList[LV_GetLParam(wnd,i)] do + if (flags and ACF_ASSIGNED)<>0 then // must be always true + flags:=flags or ACF_EXPORT; + end + else + with EditMacroList[i] do + if (flags and (ACF_EXPORT or ACF_ASSIGNED))= + (ACF_EXPORT or ACF_ASSIGNED) then + flags:=flags and not ACF_EXPORT; + end; + i:=ACIO_EXPORT or ACIO_SELECTED; + if GetFSize(xmlfilename)>0 then + if MessageBoxW(Dialog,TranslateW('Append data to file'), + PluginName,MB_YESNO+MB_ICONWARNING)=IDYES then + i:=i or ACIO_APPEND; +//!!!!!!!!!!!!!!! +// we MUST Export EditMacroList, NOT MacroList +// OR +// Use "Apply" code before + CallService(MS_ACT_INOUT,i,TLPARAM(@xmlfilename)); + for i:=0 to MaxGroups-1 do + with EditMacroList[i] do + if (flags and (ACF_EXPORT or ACF_ASSIGNED))= + (ACF_EXPORT or ACF_ASSIGNED) then + flags:=flags and not ACF_EXPORT; + end; + end; +} + IDC_GROUP_IMPORT: begin + if ShowDlgW(xmlfilename,xmlfilename,TranslateW(inoutfilter)) then + begin + // "save" selected macro (in edit list only) + BuildActionChain(Dialog); + + if Import(EditMacroList,xmlfilename,0)<>0 then +// if CallService(MS_ACT_INOUT,0,TLPARAM(@xmlfilename))<>0 then + begin + // copy from WM_INITDIALOG + FillMacroList(Dialog); + ChangeListNotify(1); + + // fill current group + FillActionList(Dialog,EditMacroList[0]); + ChangeListNotify(2); + + CheckMacroListDirectionButtons(Dialog); + end; + end; + end; + + IDC_GROUP_TEST: begin + li.mask :=LVIF_PARAM; + li.iSubItem:=0; + // Get selected macro + li.iItem :=SendMessage(MacroListWindow,LVM_GETNEXTITEM,-1,LVNI_FOCUSED); + // "save" selected macro (in edit list only) + BuildActionChain(Dialog,li.iItem); + // Get lParam = EditMacroList element + SendMessageW(MacroListWindow,LVM_GETITEMW,0,tlparam(@li)); + + ActionStarter(EditMacroList[loword(li.lParam)],nil,ACTP_SAMETHREAD or ACTP_WAIT); + end; + + IDC_GROUP_NEW: begin + if AddMacro(Dialog,EditMacroList.NewMacro())>=0 then + begin + CheckMacroList(Dialog); + ChangeListNotify(1); + end; + end; + IDC_GROUP_DELETE: begin + DontReact:=true; + wnd:=MacroListWindow; + for i:=ListView_GetItemCount(wnd)-1 downto 0 do + begin + if ListView_GetItemState(wnd,i,LVIS_SELECTED)<>0 then + begin + num:=Loword(LV_GetLParam(wnd,i)); + // mark old to delete on apply (must be first) + with EditMacroList[num]^ do + for j:=0 to ActionCount-1 do + ActionList[j].flags:=ActionList[j].flags or ACF_REPLACED; + // delete new actions + FreeMacro(EditMacroList[num],ACF_INTRODUCED); + + SendMessage(wnd,LVM_DELETEITEM,i,0); + end; + end; + Listview_SetItemState(wnd,-1,0,LVIS_FOCUSED or LVIS_SELECTED); + DontReact:=false; + SendDlgItemMessage(Dialog,IDC_ACTION_LIST,LVM_DELETEALLITEMS,0,0); + Listview_SetItemState(wnd,0,LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); + CheckMacroList(Dialog); + ChangeListNotify(1); + end; + + IDC_ACTION_HELP: begin + SendMessage( + GetLink(CB_GetData(GetDlgItem(Dialog,IDC_ACTION_TYPE)))^.DlgHandle, + WM_HELP,0,0); + end; + + IDC_ACTION_NEW: begin + wnd:=ActionListWindow; + li.mask :=LVIF_PARAM; + i :=SendMessage(wnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED); + li.iItem :=i+1; + li.iSubItem:=0; + li.lParam :=0;{NewAction(NewActionList,NewMaxActions);} + SendMessageW(wnd,LVM_INSERTITEMW,0,tlparam(@li)); + ListView_SetCheckState(wnd,li.iItem,true); + if li.iItem=0 then + begin + ListView_SetItemState(wnd,0,LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); + SHActButtons(Dialog,SW_SHOW); + SendDlgItemMessage(Dialog,IDC_ACTION_TYPE,CB_SETCURSEL,0,0); + end; + ChangeActionName(Dialog,li.iItem); + + CheckActListButtons(Dialog); + ChangeListNotify(2); + end; + IDC_ACTION_DELETE: begin + DontReact:=true; + wnd:=ActionListWindow; + for i:=ListView_GetItemCount(wnd)-1 downto 0 do + begin + if ListView_GetItemState(wnd,i,LVIS_SELECTED)<>0 then + begin + j:=LV_GetLParam(wnd,i); + if j<>0 then + begin + if (tBaseAction(j).flags and ACF_INTRODUCED)<>0 then + tBaseAction(j).Free + else + tBaseAction(j).flags:=tBaseAction(j).flags or ACF_REPLACED; + end; + SendMessage(wnd,LVM_DELETEITEM,i,0); + end; + end; + Listview_SetItemState(wnd,-1,0,LVIS_FOCUSED or LVIS_SELECTED); + DontReact:=false; + Listview_SetItemState(wnd,0,LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); + CheckActListButtons(Dialog); + ChangeListNotify(2); + end; + + IDC_GROUP_UP: begin + MoveMacro(MacroListWindow,-1,-1); + CheckMacroListDirectionButtons(Dialog); + EventMask:=EventMask or ACTM_SORT; + ChangeListNotify(1); + end; + IDC_GROUP_DOWN: begin + MoveMacro(MacroListWindow,-1,1); + CheckMacroListDirectionButtons(Dialog); + EventMask:=EventMask or ACTM_SORT; + ChangeListNotify(1); + end; + + IDC_ACTION_UP: begin + MoveMacro(ActionListWindow,-1,-1); + CheckActListDirectionButtons(Dialog); + ChangeListNotify(2); + end; + IDC_ACTION_DOWN: begin + MoveMacro(ActionListWindow,-1,1); + CheckActListDirectionButtons(Dialog); + ChangeListNotify(2); + end; + + end; + end; + end; + end; + + WM_HELP: begin + SendMessage( + GetLink(CB_GetData(GetDlgItem(Dialog,IDC_ACTION_TYPE)))^.DlgHandle, + WM_HELP,0,lParam); + result:=1; + end; + + WM_NOTIFY: begin + case integer(PNMHdr(lParam)^.code) of + PSN_APPLY: begin + BuildActionChain(Dialog); + + EventMask:=EventMask or CheckChanges(); + SetSave(Dialog); + SaveMacros; + + if EventMask<>0 then //?? + begin + NotifyEventHooks(hHookChanged,EventMask,0); + EventMask:=0; + end; + + end; + + NM_DBLCLK: begin + if PNMListView(lParam)^.iItem>=0 then + PostMessageW(PNMHdr(lParam)^.hWndFrom,LVM_EDITLABELW, + PNMListView(lParam)^.iItem,0); + end; + + LVN_ITEMCHANGED: begin + if DontReact then exit; // bug when group moved avoid + + if wParam=IDC_MACRO_LIST then + begin + if PNMLISTVIEW(lParam)^.uChanged=LVIF_STATE then + begin + lvflag:=(PNMLISTVIEW(lParam)^.uOldState and LVNI_FOCUSED)- + (PNMLISTVIEW(lParam)^.uNewState and LVNI_FOCUSED); + + if lvflag>0 then // old focus + BuildActionChain(Dialog,PNMLISTVIEW(lParam)^.iItem) + else if lvflag<0 then // new focus + begin + DontReact:=true; + + ClearDialogData; + ResetDialogs; + FillActionList(Dialog,EditMacroList[Loword(PNMLISTVIEW(lParam)^.lParam)]); + CheckMacroListDirectionButtons(Dialog); + ChangeListNotify(2); + + DontReact:=false; + end + else + begin +{?? + lvflag:=(PNMLISTVIEW(lParam)^.uOldState and LVNI_SELECTED)- + (PNMLISTVIEW(lParam)^.uNewState and LVNI_SELECTED); + + if lvflag<>0 then + CheckMacroListDirectionButtons(Dialog); +} + end; + end; + end + + else if wParam=IDC_ACTION_LIST then + begin + lvflag:=(PNMLISTVIEW(lParam)^.uOldState and LVNI_FOCUSED)- + (PNMLISTVIEW(lParam)^.uNewState and LVNI_FOCUSED); + if lvflag>0 then // old focus + begin + SaveAction(Dialog, + PNMLISTVIEW(lParam)^.iItem, + tBaseAction(PNMLISTVIEW(lParam)^.lParam)); + end + else if lvflag<0 then // new focus + begin + DontReact:=true; + + ClearDialogData; + ResetDialogs; + FillAction(Dialog,tBaseAction(PNMLISTVIEW(lParam)^.lParam)); + CheckActListDirectionButtons(Dialog); + + DontReact:=false; + end + else + begin // checkboxes +{?? + lvflag:=(PNMLISTVIEW(lParam)^.uOldState and LVNI_SELECTED)- + (PNMLISTVIEW(lParam)^.uNewState and LVNI_SELECTED); + + if lvflag<>0 then + CheckMacroListDirectionButtons(Dialog); +} + if (PNMLISTVIEW(lParam)^.uOldState or PNMLISTVIEW(lParam)^.uNewState)=$3000 then + begin + SetChanged(Dialog,etACT); + end; + end; + end; + end; + + LVN_ENDLABELEDITW: begin + if DontReact then exit; + + if wParam=IDC_MACRO_LIST then + begin + with PLVDISPINFOW(lParam)^ do + begin + if item.pszText<>nil then + begin + EventMask:=EventMask or ACTM_RENAME; + SetChanged(Dialog,etMacro); + item.mask:=LVIF_TEXT; + if pWideChar(item.pszText)^=#0 then + pWideChar(item.pszText):=NoDescription; + SendMessageW(hdr.hWndFrom,LVM_SETITEMW,0,tlparam(@item)); + + with EditMacroList[loword(item.lParam)]^ do + begin + StrCopyW(descr,item.pszText,MacroNameLen-1); + end; + ChangeListNotify(1); + + result:=1; + end; + end; + end + else if wParam=IDC_ACTION_LIST then + begin + with PLVDISPINFOW(lParam)^ do + begin + if item.pszText<>nil then + begin + SetChanged(Dialog,etACT); + ChangeActionName(Dialog,item.iItem,pWideChar(item.pszText)); + ChangeListNotify(2); + result:=1; + end; + end; + end; + end; + + end; + end; + else +// {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +// {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); +end; diff --git a/plugins/Actman30/i_options.inc b/plugins/Actman30/i_options.inc new file mode 100644 index 0000000000..3a3d8dc65a --- /dev/null +++ b/plugins/Actman30/i_options.inc @@ -0,0 +1,177 @@ +{Save/load options} + +const + opt_group = 'Group'; + opt_actions = 'Action'; + opt_numacts = 'numactions'; + opt_nummacro = 'numgroups'; + + opt_descr = 'descr'; + opt_id = 'id'; + opt_uid = 'uid'; + opt_flags = 'flags'; + +//----- Save settings ----- + +procedure SaveActions(Macro:pMacroRecord;section:pAnsiChar); +var + p,p1:PAnsiChar; + i:integer; +begin + p:=StrEnd(section); + StrCopy(p,opt_numacts); DBWriteWord(0,DBBranch,section,Macro^.ActionCount); + + // in: section = "Group#/" + p1:=StrCopyE(p,opt_actions); // "Group#/Action" + DBDeleteGroup(0,DBBranch,section); + + for i:=0 to Macro^.ActionCount-1 do + begin + p:=StrEnd(IntToStr(p1,i)); + p^:='/'; inc(p); // "Group#/Action#/" + +//?? StrCopy(p,opt_uid); DBWriteDWord(0,DBBranch,section,Macro^.ActionList[i].uid); + p^:=#0; + Macro^.ActionList[i].Save(section,0); + end; + +end; + +procedure SaveMacros; +var + Macro:pMacroRecord; + NumMacro:integer; + i:integer; + section:array [0..127] of AnsiChar; + p,p1:PAnsiChar; +begin +// even if crap in settings, skip on read +// DBDeleteGroup(0,DBBranch,opt_group); + Macro:=MacroList[0]; + i:=MacroList.Count; + NumMacro:=0; + + p1:=StrCopyE(section,opt_group); + while i>0 do + begin + with Macro^ do + begin + if (flags and (ACF_ASSIGNED or ACF_VOLATILE))=ACF_ASSIGNED then + begin + p:=StrEnd(IntToStr(p1,NumMacro)); + p^:='/'; inc(p); + + StrCopy(p,opt_id ); DBWriteDWord(0,DBBranch,section,id); + StrCopy(p,opt_flags); DBWriteDWord(0,DBBranch,section,flags); + StrCopy(p,opt_descr); DBWriteUnicode (0,DBBranch,section,descr); + + p^:=#0; + + SaveActions(Macro,section); + + inc(NumMacro); + end; + end; + inc(Macro); + dec(i); + end; + DBWriteWord(0,DBBranch,opt_nummacro,NumMacro); +end; + +//----- Load settings ----- + +function LoadActions(Macro:pMacroRecord;section:pAnsiChar):integer; +var + p,p1:PAnsiChar; + i,num:integer; + actm:pActModule; + action:tBaseAction; + uid:dword; + tmp:pActionList; +begin + result:=0; + p:=StrEnd(section); + StrCopy(p,opt_numacts); Macro^.ActionCount:=DBReadWord(0,DBBranch,section); + if Macro^.ActionCount>0 then + begin + GetMem(Macro^.ActionList,SizeOf(tBaseAction)*Macro^.ActionCount); + p1:=StrCopyE(p,opt_actions); // "Group#/Action" + + num:=0; + for i:=0 to Macro^.ActionCount-1 do + begin + p:=StrEnd(IntToStr(p1,i)); + p^:='/'; inc(p); // "Group#/Action#/" + + // get uid + StrCopy(p,opt_uid); uid:=DBReadDWord(0,DBBranch,section,0); + if uid<>0 then + begin + p^:=#0; + // call proper constructor + actm:=GetLink(uid); + if actm=nil then + continue; + + action:=actm.Create; + // call proper loader + action.Load(section,0); + + Macro^.ActionList^[num]:=action; + inc(num); + end; + end; + if Macro^.ActionCount<>num then + begin + GetMem(tmp,SizeOf(tBaseAction)*num); + move(Macro^.ActionList^,tmp^,SizeOf(tBaseAction)*num); + Macro^.ActionCount:=num; + FreeMem(Macro^.ActionList); + Macro^.ActionList:=tmp; + end; + end; +end; + +procedure LoadMacros; +var + Macro:pMacroRecord; + i:cardinal; + p,p1:PAnsiChar; + section:array [0..127] of AnsiChar; + NumMacros:cardinal; + tmp:pWideChar; +begin + // Allocate macro list + NumMacros :=DBReadWord(0,DBBranch,opt_nummacro,0); + MacroList:=tMacroList.Create(NumMacros); + + // read macro list settings + if NumMacros>0 then //?? really, not so necessary + begin + Macro:=MacroList[0]; + i:=0; + p1:=StrCopyE(section,opt_group); + while i0 then //?? not needed in normal cases + begin + StrCopy(p,opt_id ); id :=DBReadDWord (0,DBBranch,section); + StrCopy(p,opt_descr); tmp:=DBReadUnicode(0,DBBranch,section,NoDescription); + StrCopyW(descr,tmp,MacroNameLen-1); + mFreeMem(tmp); + p^:=#0; + LoadActions(Macro,section); + end; + end; + inc(Macro); + inc(i); + end; + end; +end; diff --git a/plugins/Actman30/i_services.inc b/plugins/Actman30/i_services.inc new file mode 100644 index 0000000000..2954fa4b15 --- /dev/null +++ b/plugins/Actman30/i_services.inc @@ -0,0 +1,317 @@ +{Basic ActMan services} + +function ActSelect(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +begin + if odd(wParam) then + result:=int_ptr(MacroList.GetMacro(lParam)) + else + result:=int_ptr(MacroList.GetMacro(pWideChar(lParam))); + + if result<>0 then + with pMacroRecord(result)^ do + begin + if (wParam and 4)<>0 then + result:=ord((flags and ACF_SELECTED)<>0) + else + begin + if (wParam and 2)<>0 then + flags:=flags and not ACF_SELECTED + else + flags:=flags or ACF_SELECTED; + end; + end; +end; + +function ActFreeList(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +begin + result:=0; + mFreeMem(PAnsiChar(lParam)); +end; + +function ActGetList(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + pc:^tChain; + p:pMacroRecord; + i,cnt:integer; +begin + p:=MacroList[0]; + cnt:=0; + for i:=0 to MacroList.Count-1 do + begin + if (p^.flags and (ACF_ASSIGNED or ACF_VOLATILE))=ACF_ASSIGNED then inc(cnt); + inc(p); + end; + result:=cnt; + if lParam=0 then exit; + if cnt>0 then + begin + mGetMem(pc,cnt*SizeOf(tChain)+4); + puint_ptr(lParam)^:=uint_ptr(pc); + pdword(pc)^:=SizeOf(tChain); + inc(PByte(pc),4); + + p:=MacroList[0]; + for i:=0 to MacroList.Count-1 do + begin + if (p^.flags and (ACF_ASSIGNED or ACF_VOLATILE))=ACF_ASSIGNED then + begin + pc^.descr:=p^.descr; + pc^.id :=p^.id; + pc^.flags:=p^.flags; + inc(pc); + end; + inc(p); + end; + end + else + puint_ptr(lParam)^:=0; +end; + +//====================== Execute code ======================= + +{$IFDEF DEBUG} +procedure ActmanMacroDebug(txt:pWideChar); +begin + OutputDebugStringW(txt); +end; +{$ENDIF} + +procedure DoAction(Macro:pMacroRecord;var WorkData:tWorkData); +var + res:LRESULT; + i,cnt:integer; +{$IFDEF DEBUG} + buf:array [0..1023] of WideChar; + buf1,buf2:array [0..31] of WideChar; + p:pWideChar; +{$ENDIF} +begin + cnt:=Macro^.ActionCount; + if cnt<>0 then + begin +//!! act:=CloneActions(action); + i:=0; + WorkData.ActionList :=Macro^.ActionList; + WorkData.ActionCount:=Macro^.ActionCount; + while i0 then // res = next action number+1 + begin + i:=res-1; + continue; + end; + end; + inc(i); + end; +//!! FreeActionsContinued(act_org); + end; +end; + +type + pActStartData = ^tActStartData; + tActStartData = record + macro :pMacroRecord; + event :THANDLE; + WorkData:tWorkData; + flags :dword; + end; + +procedure ThDoAction(arg:pActStartData); cdecl; +var + i:integer; +begin + if (arg^.flags and ACTP_NOTIFY)<>0 then + begin + NotifyEventHooks(hevaction,arg^.macro.id,0); // started + arg^.macro.flags:=arg^.macro.flags or ACF_USEDNOW; + end; + + DoAction(arg^.macro,arg^.WorkData); + + if (arg^.flags and ACTP_NOTIFY)<>0 then + begin + arg^.macro.flags:=arg^.macro.flags and not ACF_USEDNOW; + NotifyEventHooks(hevaction,arg^.macro.id,1); // finished + end; + + if arg^.event<>0 then // service, waiting + SetEvent(arg^.event) + else if (arg^.flags and ACTP_SAMETHREAD)=0 then // no waiting + begin + ClearResult(arg^.WorkData); // free last result memory if needs + // Free Storage + for i:=0 to 9 do + ClearResult(arg^.WorkData,i); + mFreeMem(arg); // free ActStartData (no time to free after) + end; +end; + +function ActionStarter(macro:pMacroRecord;wd:pWorkData;flags:dword):LPARAM; +var + tmp:pActStartData; + i:integer; +begin + mGetMem (tmp ,SizeOf(tActStartData)); + FillChar(tmp^,SizeOf(tActStartData),0); + + if wd<>nil then + begin + tmp^.WorkData.ResultType:=wd^.ResultType; + case wd^.ResultType of + rtInt : tmp^.WorkData.LastResult:=wd^.LastResult; + rtWide: StrDupW(pWideChar(tmp^.WorkData.LastResult),pWideChar(wd^.LastResult)); + rtAnsi: begin + AnsiToWide(pAnsiChar(wd^.LastResult),pWideChar(tmp^.WorkData.LastResult)); + tmp^.WorkData.ResultType:=rtWide; + end; + rtUTF8: begin + UTF8ToWide(pAnsiChar(wd^.LastResult),pWideChar(tmp^.WorkData.LastResult)); + tmp^.WorkData.ResultType:=rtWide; + end; + end; + tmp^.WorkData.Parameter:=wd^.Parameter; + end + else + tmp^.WorkData.ResultType:=rtInt; + + tmp^.macro :=macro; + tmp^.flags :=flags; + + if (flags and ACTP_SAMETHREAD)<>0 then // with waiting, macro or service + begin + tmp^.event:=0; + ThDoAction(tmp); + // keep text result (for macro from macro) + if (flags and ACTP_KEEPRESULT)<>0 then + begin + wd^.ResultType:=tmp^.WorkData.ResultType; + if wd^.ResultType=rtInt then + wd^.LastResult:=tmp^.WorkData.LastResult + else + StrDupW(pWideChar(wd^.LastResult),pWideChar(tmp^.WorkData.LastResult)); + result:=0; + end + else if tmp^.WorkData.ResultType=rtInt then + result:=tmp^.WorkData.LastResult + // result no needs or macro from service + else + result:=StrToInt(pWideChar(tmp^.WorkData.LastResult)); + end + + else if (flags and ACTP_WAIT)<>0 then // with waiting, service + begin + tmp^.event:=CreateEvent(nil,FALSE,FALSE,nil); + {CloseHandle}(mir_forkthread(@ThDoAction,tmp)); + //!!!!!!!!! movetmp structure (event handle) to array, not stack? + WaitForSingleObjectEx(tmp^.event,INFINITE,true); + CloseHandle(tmp^.event); + if tmp^.WorkData.ResultType=rtWide then + result:=StrToInt(pWideChar(tmp^.WorkData.LastResult)) + else + result:=tmp^.WorkData.LastResult; + end + + else // no waiting, service or macro + begin + tmp^.event:=0; + {CloseHandle}(mir_forkthread(@ThDoAction,tmp)); + result:=0; + exit; + end; + + ClearResult(tmp^.WorkData); // free last result memory if needs + // Free Storage + for i:=0 to 9 do + ClearResult(tmp^.WorkData,i); + mFreeMem(tmp); // free ActStartData (no time to free after) +end; + +//----- execute services ----- + +function ActRun(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + p:pMacroRecord; + w:tWorkData; +begin + result:=-1; + p:=MacroList.GetMacro(wParam); + if p<>nil then + begin + FillChar(w,SizeOf(w),0); + w.ResultType:=rtInt; + w.Parameter:=lParam; + result:=ActionStarter(p,@w,ACTP_SAMETHREAD); + end; +end; + +function ActRunGroup(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + p:pMacroRecord; + w:tWorkData; +begin + result:=-1; + p:=MacroList.GetMacro(pWideChar(wParam)); + if p<>nil then + begin + FillChar(w,SizeOf(w),0); + w.ResultType:=rtInt; + w.Parameter:=lParam; + result:=ActionStarter(p,@w,ACTP_SAMETHREAD); + end; +end; + +function ActRunParam(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + p:pMacroRecord; + w:tWorkData; +begin + result:=-1; + if (pAct_Param(lParam)^.flags and ACTP_BYNAME)=0 then + p:=MacroList.GetMacro(pAct_Param(lParam)^.Id) + else + p:=MacroList.GetMacro(pWideChar(pAct_Param(lParam)^.Id)); + + if p<>nil then + begin + FillChar(w,SizeOf(w),0); + w.Parameter :=pAct_Param(lParam)^.wParam; + w.LastResult:=pAct_Param(lParam)^.lParam; + w.ResultType:=pAct_Param(lParam)^.lPType; + result:=ActionStarter(p,@w,pAct_Param(lParam)^.flags); + if (pAct_Param(lParam)^.flags and (ACTP_KEEPRESULT or ACTP_SAMETHREAD))= + (ACTP_KEEPRESULT or ACTP_SAMETHREAD) then + begin + pAct_Param(lParam)^.lParam:=w.LastResult; + pAct_Param(lParam)^.lPType:=w.ResultType; + end; + end; +end; diff --git a/plugins/Actman30/iac_.pas b/plugins/Actman30/iac_.pas new file mode 100644 index 0000000000..f99e4f7366 --- /dev/null +++ b/plugins/Actman30/iac_.pas @@ -0,0 +1,155 @@ +unit iac_; + +interface + +implementation + +uses windows, iac_global, mirutils; + + +type + = class(tBaseAction) + + 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 ----- + +//----- Object realization ----- + +constructor .Create(uid:dword); +begin + inherited Create(uid); +end; + +destructor .Destroy; +begin + + inherited Destroy; +end; + +function .Clone:tBaseAction; +begin + result:=.Create(0); + Duplicate(result); + +end; + +function .DoAction(var WorkData:tWorkData):LRESULT; +begin + result:=0; +end; + +procedure .Load(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; +begin + inherited Load(node,fmt); + case fmt of + 0: begin + pc:=StrCopyE(section,pAnsiChar(node)); + end; +{ + 1: begin + end; +} + end; +end; + +procedure .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)); + end; +{ + 1: begin + end; +} + end; +end; + +//----- Dialog realization ----- + +procedure ClearFields(Dialog:HWND); +begin +end; + +function DlgProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +begin + result:=0; + + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + end; + + WM_ACT_SETVALUE: begin + ClearFields(Dialog); + with (lParam) do + begin + end; + end; + + WM_ACT_RESET: begin + ClearFields(Dialog); + end; + + WM_ACT_SAVE: begin + with (lParam) do + begin + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of + end; + end; + + WM_HELP: begin + result:=1; + end; + + end; +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=.Create(vc.Hash); +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,,parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :=; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :=; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_chain.pas b/plugins/Actman30/iac_chain.pas new file mode 100644 index 0000000000..a4736ab1ca --- /dev/null +++ b/plugins/Actman30/iac_chain.pas @@ -0,0 +1,372 @@ +unit iac_chain; + +interface + +implementation + +uses + windows, messages, commctrl, + global, iac_global, mirutils, m_api, + dlgshare,lowlevelc,common,dbsettings, wrapper; + +{$include m_actman.inc} +{$include i_cnst_chain.inc} +{$resource iac_chain.res} + +const + ACF_BYNAME = $00000001; // Address action link by name, not Id + ACF_NOWAIT = $00000002; // Don't wait execution result, continue + ACF_KEEPOLD = $00000004; // Don't change LastResult value + ACF_SAMETHREAD = $00000008; // Execute in same thread with waiting +const + ioNoWait = 'nowait'; + ioKeepOld = 'keepold'; + ioSameThread = 'samethread'; +const + opt_chain = 'chain'; + opt_actname = 'actname'; +const + NoChainText:PWideChar = 'not defined'; + +type + tChainAction = class(tBaseAction) + private + id :dword; + actname:pWideChar; + 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 ----- + +//----- Object realization ----- + +constructor tChainAction.Create(uid:dword); +begin + inherited Create(uid); + + id :=0; + actname:=nil; +end; + +destructor tChainAction.Destroy; +begin + if (flags and ACF_BYNAME)<>0 then + mFreeMem(actname); + + inherited Destroy; +end; +{ +function tChainAction.Clone:tBaseAction; +begin + result:=tChainAction.Create(0); + Duplicate(result); + + tChainAction(result).id:=id; + StrDupW(tChainAction(result).actname,actname); +end; +} +function tChainAction.DoAction(var WorkData:tWorkData):LRESULT; +var + params:tAct_Param; + res:int_ptr; +begin + result:=0; + + if (flags and ACF_BYNAME)<>0 then + begin + params.flags:=ACTP_BYNAME; + params.Id :=uint_ptr(actname); + end + else + begin + params.flags:=0; + params.Id :=id; + end; + if (flags and ACF_SAMETHREAD)<>0 then + params.flags:=params.flags or ACTP_SAMETHREAD + else if (flags and ACF_NOWAIT)=0 then + params.flags:=params.flags or ACTP_WAIT; + + if (flags and ACF_KEEPOLD)=0 then + params.flags:=params.flags or ACTP_KEEPRESULT; + + params.wParam:=WorkData.Parameter; + params.lParam:=WorkData.LastResult; + res:=CallService(MS_ACT_RUNPARAMS,0,tlparam(@params)); + + if (flags and ACF_KEEPOLD)=0 then + begin + ClearResult(WorkData); + if (flags and ACF_SAMETHREAD)=0 then + begin + WorkData.LastResult:=res; + WorkData.ResultType:=rtInt; + end + else + begin + WorkData.LastResult:=params.lParam; + WorkData.ResultType:=params.lPType; + end; + end; +end; + +procedure tChainAction.Load(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; +begin + inherited Load(node,fmt); + case fmt of + 0: begin + pc:=StrCopyE(section,pAnsiChar(node)); + if (flags and ACF_BYNAME)=0 then + begin + StrCopy(pc,opt_chain); id:=DBReadDWord(0,DBBranch,section); + end + else + begin + StrCopy(pc,opt_actname); actname:=DBReadUnicode(0,DBBranch,section); + end; + end; + + 1: begin + with xmlparser do + begin + StrDupW(actname,getText(HXML(node))); + flags:=flags or ACF_BYNAME; + + if StrToInt(getAttrValue(HXML(node),ioNoWait))=1 then + flags:=flags or ACF_NOWAIT; + + if StrToInt(getAttrValue(HXML(node),ioKeepOld))=1 then + flags:=flags or ACF_KEEPOLD; + + if StrToInt(getAttrValue(HXML(node),ioSameThread))=1 then + flags:=flags or ACF_SAMETHREAD; + end; + end; +{ + 2: begin + + UF8ToWide(GetParamSectionStr(node,'name',nil),actname); + flags:=flags or ACF_BYNAME; + + if GetParamSectionInt(node,ioNoWait)=1 then + flags:=flags or ACF_NOWAIT; + + if GetParamSectionInt(node,ioKeepOld)=1 then + flags:=flags or ACF_KEEPOLD; + + if GetParamSectionInt(node,ioSameThread)=1 then + flags:=flags or ACF_SAMETHREAD; + end; +} + end; +end; + +procedure tChainAction.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)); + if (flags and ACF_BYNAME)=0 then + begin + StrCopy(pc,opt_chain); DBWriteDWord(0,DBBranch,section,id); + end + else + begin + StrCopy(pc,opt_actname); DBWriteUnicode(0,DBBranch,section,actname); + end; + end; +{ + 1: begin + end; +} +{ + 2: begin + end; +} +{ + 3: begin + Out(node,['CallAction',actname, + IFF(flags or ACF_SAMETHREAD,'samethread',''), + IFF(flags or ACF_NOWAIT ,'nowait',''), + IFF(flags or ACF_KEEPOLD ,'keepold','') + ]); + end; +} + end; +end; + +//----- Dialog realization ----- + +procedure FillChainList(Dialog:hwnd); +var + wnd,list:HWND; + i:integer; + + li:LV_ITEMW; + Macro:pMacroRecord; +begin + wnd:=GetDlgItem(Dialog,IDC_MACRO_LIST); + + SendMessage(wnd,CB_RESETCONTENT,0,0); + SendMessage(wnd,CB_SETITEMDATA, + SendMessageW(wnd,CB_ADDSTRING,0,lparam(TranslateW(NoChainText))),0); + + list:=MacroListWindow; + li.mask :=LVIF_PARAM; + li.iSubItem :=0; + for i:=0 to SendMessage(list,LVM_GETITEMCOUNT,0,0)-1 do + begin + li.iItem:=i; + SendMessageW(list,LVM_GETITEMW,0,tlparam(@li)); + Macro:=EditMacroList[loword(li.lParam)]; + SendMessage(wnd,CB_SETITEMDATA, + SendMessageW(wnd,CB_ADDSTRING,0,lparam(@(Macro.descr))),Macro.id); + end; + +end; + +procedure ClearFields(Dialog:HWND); +begin + CheckDlgButton(Dialog,IDC_MACRO_NOWAIT ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MACRO_SAMETHREAD,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MACRO_KEEPOLD ,BST_UNCHECKED); +end; + +function DlgProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + tmp:dword; + wnd:HWND; + bb:boolean; +begin + result:=0; + + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + + FillChainList(Dialog); + end; + + WM_ACT_SETVALUE: begin + ClearFields(Dialog); + with tChainAction(lParam) do + begin + if (flags and ACF_BYNAME)<>0 then + SendDlgItemMessageW(Dialog,IDC_MACRO_LIST,CB_SELECTSTRING,twparam(-1),tlparam(actname)) + else + CB_SelectData(Dialog,IDC_MACRO_LIST,id); + if (flags and ACF_KEEPOLD)<>0 then + CheckDlgButton(Dialog,IDC_MACRO_KEEPOLD,BST_CHECKED); + + if (flags and ACF_SAMETHREAD)<>0 then + begin + bb:=false; + CheckDlgButton(Dialog,IDC_MACRO_SAMETHREAD,BST_CHECKED); + end + else + begin + bb:=true; + if (flags and ACF_NOWAIT)<>0 then + CheckDlgButton(Dialog,IDC_MACRO_NOWAIT,BST_CHECKED); + end; + EnableWindow(GetDlgItem(Dialog,IDC_MACRO_NOWAIT),bb); + end; + end; + + WM_ACT_RESET: begin + ClearFields(Dialog); + CheckDlgButton(Dialog,IDC_MACRO_SAMETHREAD,BST_CHECKED); + SendDlgItemMessage(Dialog,IDC_MACRO_LIST,CB_SETCURSEL,0,0); + end; + + WM_ACT_SAVE: begin + with tChainAction(lParam) do + begin + id:=CB_GetData(GetDlgItem(Dialog,IDC_MACRO_LIST)); + + if IsDlgButtonChecked(Dialog,IDC_MACRO_SAMETHREAD)<>BST_UNCHECKED then + flags:=flags or ACF_SAMETHREAD + else if IsDlgButtonChecked(Dialog,IDC_MACRO_NOWAIT)<>BST_UNCHECKED then + flags:=flags or ACF_NOWAIT; + + if IsDlgButtonChecked(Dialog,IDC_MACRO_KEEPOLD)<>BST_UNCHECKED then + flags:=flags or ACF_KEEPOLD; + end; + end; + + WM_ACT_LISTCHANGE: begin + if wParam=1 then + begin + wnd:=GetDlgItem(Dialog,IDC_MACRO_LIST); + tmp:=CB_GetData(wnd); + FillChainList(Dialog); + CB_SelectData(wnd,tmp); + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of + CBN_SELCHANGE: SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + BN_CLICKED: begin + if loword(wParam)=IDC_MACRO_SAMETHREAD then + begin + EnableWindow(GetDlgItem(Dialog,IDC_MACRO_NOWAIT), + IsDlgButtonChecked(Dialog,IDC_MACRO_SAMETHREAD)=BST_UNCHECKED); + end; + + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + end; + end; + + WM_HELP: begin + result:=1; + end; + end; +// result:=DefWindowProc(Dialog,hMessage,wParam,lParam); +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=tChainAction.Create(vc.Hash); +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,'IDD_ACTCHAIN',parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :='Chain'; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :='IDI_CHAIN'; + vc.Hash :=0; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_chain.rc b/plugins/Actman30/iac_chain.rc new file mode 100644 index 0000000000..35cc17f53f --- /dev/null +++ b/plugins/Actman30/iac_chain.rc @@ -0,0 +1,18 @@ +#include "i_cnst_chain.inc" + +LANGUAGE 0,0 + +IDD_ACTCHAIN DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + RTEXT "Other Action groups",-1, 0, 2, 160, 10 + COMBOBOX IDC_MACRO_LIST, 1, 13, 166, 128, + CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL + AUTOCHECKBOX "Keep old result" , IDC_MACRO_KEEPOLD , 1, 31, 166, 11 + AUTOCHECKBOX "Same thread" , IDC_MACRO_SAMETHREAD, 1, 44, 166, 11 + AUTOCHECKBOX "Don't wait end of execution", IDC_MACRO_NOWAIT , 1, 57, 166, 11 +} + +IDI_CHAIN ICON "ico\chain.ico" diff --git a/plugins/Actman30/iac_contact.pas b/plugins/Actman30/iac_contact.pas new file mode 100644 index 0000000000..eb9a5790cd --- /dev/null +++ b/plugins/Actman30/iac_contact.pas @@ -0,0 +1,252 @@ +unit iac_contact; + +interface + +implementation + +uses + windows, messages, commctrl, + m_api, global, iac_global, common, + contact, dlgshare, syswin, + wrapper, mirutils, dbsettings; + +{$include i_cnst_contact.inc} +{$resource iac_contact.res} + +const + ACF_KEEPONLY = $00000001; // keep contact handle in Last, don't show window + ACF_GETACTIVE = $00000002; // try to get contact from active window + +const + ioKeepOnly = 'keeponly'; + ioWindow = 'window'; + +type + tContactAction = class(tBaseAction) + private + contact:THANDLE; + public + constructor Create(uid:dword); +// 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 ----- + +constructor tContactAction.Create(uid:dword); +begin + inherited Create(uid); + + contact:=0; +end; +{ +function tContactAction.Clone:tBaseAction; +begin + result:=tContactAction.Create(0); + Duplicate(result); + + tContactAction(result).contact:=contact; +end; +} + +//----- Object realization ----- + +function tContactAction.DoAction(var WorkData:tWorkData):LRESULT; +var + wnd:HWND; +begin + ClearResult(WorkData); + + if (flags and ACF_GETACTIVE)<>0 then + begin + wnd:=WaitFocusedWndChild(GetForegroundWindow){GetFocus}; + if wnd<>0 then + contact:=WndToContact(wnd) + else + contact:=0; + end + else if (flags and ACF_KEEPONLY)=0 then + ShowContactDialog(contact); + + WorkData.LastResult:=contact; + WorkData.ResultType:=rtInt; + + result:=0; +end; + +procedure tContactAction.Load(node:pointer;fmt:integer); +begin + inherited Load(node,fmt); + case fmt of + 0: if (flags and ACF_GETACTIVE)=0 then + contact:=LoadContact(DBBranch,node); + + 1: begin + with xmlparser do + begin + contact:=ImportContact(HXML(node)); + if StrToInt(getAttrValue(HXML(node),ioKeepOnly))=1 then + flags:=flags or ACF_KEEPONLY; + if StrToInt(getAttrValue(HXML(node),ioWindow))=1 then + flags:=flags or ACF_GETACTIVE; + end; + end; +{ + 2: begin + contact:=ImportContactINI(node); + + if GetParamSectionInt(node,ioKeepOnly)=1 then + flags:=flags or ACF_KEEPONLY; + if GetParamSectionInt(node,ioWindow)=1 then + flags:=flags or ACF_GETACTIVE; + end; +} + end; +end; + +procedure tContactAction.Save(node:pointer;fmt:integer); +begin + inherited Save(node,fmt); + case fmt of + 0: if (flags and ACF_GETACTIVE)=0 then + SaveContact(contact,DBBranch,node); +{ + 1: begin + sub:=AddChild(actnode,ioContactWindow,nil); + ExportContact(sub,contact); +// AddAttrInt(sub,ioNumber,0); // contact + if (flags and ACF_KEEPONLY)<>0 then AddAttrInt(sub,ioKeepOnly,1); + end; +} + end; +end; + +//----- Dialog realization ----- + +procedure ClearFields(Dialog:HWND); +begin + CheckDlgButton(Dialog,IDC_CNT_KEEP,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_CNT_GET ,BST_UNCHECKED); +end; + +function DlgProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + wnd:HWND; + bb:boolean; +begin + result:=0; + + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + + wnd:=GetDlgItem(Dialog,IDC_CNT_REFRESH); + OptSetButtonIcon(wnd,ACI_REFRESH); + SendMessage(wnd,BUTTONADDTOOLTIP,TWPARAM(TranslateW('Refresh')),BATF_UNICODE); + OptFillContactList(GetDlgItem(Dialog,IDC_CONTACTLIST)); + end; + + WM_ACT_SETVALUE: begin + ClearFields(Dialog); + + with tContactAction(lParam) do + begin + if (flags and ACF_GETACTIVE)<>0 then + begin + bb:=false; + CheckDlgButton(Dialog,IDC_CNT_GET,BST_CHECKED); + end + else + begin + bb:=true; + if (flags and ACF_KEEPONLY)<>0 then + CheckDlgButton(Dialog,IDC_CNT_KEEP,BST_CHECKED); + + SendDlgItemMessage(Dialog,IDC_CONTACTLIST,CB_SETCURSEL, + FindContact(GetDlgItem(Dialog,IDC_CONTACTLIST),contact),0); + end; + EnableWindow(GetDlgItem(Dialog,IDC_CNT_REFRESH),bb); + EnableWindow(GetDlgItem(Dialog,IDC_CONTACTLIST),bb); + EnableWindow(GetDlgItem(Dialog,IDC_CNT_KEEP ),bb); + end; + end; + + WM_ACT_RESET: begin + ClearFields(Dialog); + EnableWindow(GetDlgItem(Dialog,IDC_CNT_REFRESH),true); + EnableWindow(GetDlgItem(Dialog,IDC_CONTACTLIST),true); + EnableWindow(GetDlgItem(Dialog,IDC_CNT_KEEP ),true); + end; + + WM_ACT_SAVE: begin + with tContactAction(lParam) do + begin + contact:=SendDlgItemMessage(Dialog,IDC_CONTACTLIST,CB_GETITEMDATA, + SendDlgItemMessage(Dialog,IDC_CONTACTLIST,CB_GETCURSEL,0,0),0); + if IsDlgButtonChecked(Dialog,IDC_CNT_KEEP)=BST_CHECKED then + flags:=flags or ACF_KEEPONLY; + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of + CBN_SELCHANGE: SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + BN_CLICKED: begin + case loword(wParam) of + IDC_CNT_GET: begin + bb:=IsDlgButtonChecked(Dialog,IDC_CNT_GET)=BST_UNCHECKED; + EnableWindow(GetDlgItem(Dialog,IDC_CNT_REFRESH),bb); + EnableWindow(GetDlgItem(Dialog,IDC_CONTACTLIST),bb); + EnableWindow(GetDlgItem(Dialog,IDC_CNT_KEEP ),bb); + end; + + IDC_CNT_REFRESH: begin + OptFillContactList(GetDlgItem(Dialog,IDC_CONTACTLIST)); + exit; + end; + end; + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + + end; + end; + + WM_HELP: begin + result:=1; + end; + end; +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=tContactAction.Create(vc.Hash); +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,'IDD_ACTCONTACT',parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :='Contact'; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :='IDI_CONTACT'; + vc.Hash :=0; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_contact.rc b/plugins/Actman30/iac_contact.rc new file mode 100644 index 0000000000..b3923502b3 --- /dev/null +++ b/plugins/Actman30/iac_contact.rc @@ -0,0 +1,18 @@ +#include "i_cnst_contact.inc" + +LANGUAGE 0,0 + +IDD_ACTCONTACT DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + RTEXT "Choose Contact", -1 , 0, 2, 160, 10 + CONTROL "Refresh",IDC_CNT_REFRESH,"MButtonClass",WS_TABSTOP,1,12,16,16,$18000000 + COMBOBOX IDC_CONTACTLIST, 19, 14, 148, 128, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL + AUTOCHECKBOX "Keep handle only", IDC_CNT_KEEP , 1, 31, 160, 11 + + AUTOCHECKBOX "Get from active window", IDC_CNT_GET, 1, 45, 160, 11 +} + +IDI_CONTACT ICON "ico\contact.ico" diff --git a/plugins/Actman30/iac_database.rc b/plugins/Actman30/iac_database.rc new file mode 100644 index 0000000000..5c5fe1f791 --- /dev/null +++ b/plugins/Actman30/iac_database.rc @@ -0,0 +1,37 @@ +#include "i_cnst_database.inc" + +LANGUAGE 0,0 + +IDD_ACTDATABASE DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + AUTORADIOBUTTON "Own settings", IDC_RW_CURRENT, 1, 0, 81, 11, BS_RIGHT | BS_LEFTTEXT | WS_GROUP + AUTORADIOBUTTON "Manual" , IDC_RW_MANUAL , 1, 12, 81, 11, BS_RIGHT | BS_LEFTTEXT + AUTORADIOBUTTON "Parameter" , IDC_RW_PARAM , 86, 0, 81, 11 + AUTORADIOBUTTON "Last result" , IDC_RW_RESULT , 86, 12, 81, 11 + + CONTROL "Refresh",IDC_CNT_REFRESH,"MButtonClass",WS_TABSTOP,1,23,16,16,$18000000 + COMBOBOX IDC_CONTACTLIST, 18, 25, 148, 128, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL + + RTEXT "Module" , -1, 1, 43, 160, 8, SS_CENTERIMAGE + EDITTEXT IDC_RW_MODULE , 1, 52, 166, 12, ES_AUTOHSCROLL + RTEXT "Setting" , -1, 1, 67, 160, 8, SS_CENTERIMAGE + EDITTEXT IDC_RW_SETTING, 1, 76, 166, 12, ES_AUTOHSCROLL + + GROUPBOX "Operation" , -1, 1, 92, 166, 23, WS_GROUP + AUTORADIOBUTTON "Read" , IDC_RW_READ , 4, 101, 52, 11 + AUTORADIOBUTTON "Write" , IDC_RW_WRITE , 57, 101, 52, 11 + AUTORADIOBUTTON "Delete" , IDC_RW_DELETE , 110, 101, 52, 11 + + GROUPBOX "Value" , -1, 1, 116, 166, 64, WS_GROUP + + COMBOBOX IDC_RW_DATATYPE, 86, 125, 79, 96, CBS_DROPDOWNLIST | WS_VSCROLL + + AUTOCHECKBOX "Last result" , IDC_RW_LAST , 6, 142, 156, 11, BS_RIGHT | BS_LEFTTEXT + EDITTEXT IDC_RW_VALUE, 4, 154, 160, 11, ES_AUTOHSCROLL + AUTOCHECKBOX "Save value" , IDC_RW_SAVE , 6, 166, 156, 11, BS_RIGHT | BS_LEFTTEXT +} + +IDI_DATABASE ICON "ico\rw.ico" diff --git a/plugins/Actman30/iac_dbrw.pas b/plugins/Actman30/iac_dbrw.pas new file mode 100644 index 0000000000..0c9e0ad502 --- /dev/null +++ b/plugins/Actman30/iac_dbrw.pas @@ -0,0 +1,686 @@ +unit iac_dbrw; + +interface + +implementation + +uses + windows, messages, commctrl, + global, iac_global, + m_api,dbsettings, + common,mirutils,wrapper, + editwrapper,contact,dlgshare; + +{$include i_cnst_database.inc} +{$resource iac_database.res} + +const + opt_module = 'module'; + opt_setting = 'setting'; + opt_value = 'value'; +const + ioOper = 'oper'; + ioDelete = 'delete'; + ioWrite = 'write'; + ioCurrent = 'current'; + ioParam = 'param'; + ioResult = 'result'; + ioModule = 'module'; + ioSetting = 'setting'; + ioContact = 'contact'; + ioFileVariable = 'modvariables'; + ioArgVariable = 'argvariables'; + ioVariables = 'variables'; + ioType = 'type'; + ioByte = 'byte'; + ioWord = 'word'; + ioDword = 'dword'; + ioAnsi = 'ansi'; + ioLast = 'last'; + ioSaveValue = 'savevalue'; + +const + ACF_DBWRITE = $00000001; // write to (not read from) DB + ACF_DBDELETE = $00000002; // delete setting + ACF_DBBYTE = $00000004; // read/write byte (def. dword) + ACF_DBWORD = $00000008; // read/write word (def. dword) + ACF_DBUTEXT = $00000010; // read/write Unicode string + ACF_DBANSI = $00000020; // read/write ANSI string + ACF_PARAM = $00000040; // hContact from parameter + ACF_CURRENT = $00000080; // hContact is 0 (user settings) + ACF_RESULT = $00000100; // hContact is last result value + ACF_LAST = $00000200; // use last result for DB writing + ACF_SAVE = $00000400; // save writing value to Last Result + // dummy + ACF_DBDWORD = 0; + ACF_DBREAD = 0; + ACF_MANUAL = 0; + + ACF_NOCONTACT = ACF_PARAM or ACF_CURRENT or ACF_RESULT; + ACF_VALUETYPE = ACF_DBBYTE or ACF_DBWORD or ACF_DBUTEXT or ACF_DBANSI; + ACF_TEXT = ACF_DBUTEXT or ACF_DBANSI; + ACF_OPERATION = ACF_DBWRITE or ACF_DBDELETE; + + ACF_RW_MODULE = $00001000; // script for module name + ACF_RW_SETTING = $00002000; // script for setting name + ACF_RW_VALUE = $00004000; // script for data value + +type + tDataBaseAction = class(tBaseAction) + private + dbcontact:THANDLE; + dbmodule :PWideChar; + dbsetting:PWideChar; + dbvalue :PWideChar; // keep all in unicode (str to int translation fast) + 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 ----- + +//----- Object realization ----- + +constructor tDataBaseACtion.Create(uid:dword); +begin + inherited Create(uid); + + dbcontact:=0; + dbmodule :=nil; + dbsetting:=nil; + dbvalue :=nil; +end; + +destructor tDataBaseAction.Destroy; +begin + mFreeMem(dbmodule); + mFreeMem(dbsetting); + mFreeMem(dbvalue); + + inherited Destroy; +end; +{ +function tDataBaseAction.Clone:tBaseAction; +var + tmp:tDataBaseAction; +begin + result:=tDataBaseAction.Create(0); + Duplicate(result); + + tmp.dbcontact:=dbcontact; + StrDupW(tmp.dbmodule ,dbmodule); + StrDupW(tmp.dbsetting,dbsetting); + + if ((flags and ACF_DBDELETE)=0) and + ((flags and ACF_LAST)=0) then + StrDupW(tmp.dbvalue,dbvalue); + + result:=tmp; +end; +} +function tDataBaseAction.DoAction(var WorkData:tWorkData):LRESULT; +var + sbuf:array [0..31] of WideChar; + bufw:array [0..255] of WideChar; + ambuf,asbuf:array [0..127] of AnsiChar; + ls,tmp:pWideChar; + tmpa,tmpa1:pAnsiChar; + hContact:THANDLE; + proto:pAnsiChar; + avalue:uint_ptr; +begin + result:=0; + // contact + case (flags and ACF_NOCONTACT) of + ACF_CURRENT: hContact:=0; + ACF_PARAM : hContact:=WorkData.Parameter; + ACF_RESULT : hContact:=WorkData.LastResult; + else + hContact:=dbcontact; + end; + + //--- + // last result for scripts + if WorkData.ResultType=rtWide then + ls:=pWideChar(WorkData.LastResult) + else + begin + ls:=@sbuf; + IntToStr(sbuf,WorkData.LastResult); + end; + + proto:=GetContactProtoAcc(hContact); + // now need to process module + if (flags and ACF_RW_MODULE)<>0 then + begin + tmp:=ParseVarString(dbmodule,hContact,ls); + StrCopyW(bufw,tmp); + mFreeMem(tmp); + end + else + StrCopyW(bufw,dbmodule); + StrReplaceW(@bufw,'',ls); + FastWideToAnsiBuf(bufw,ambuf,SizeOf(ambuf)-1); + StrReplace(ambuf,protostr,proto); + + // now process settings + if (flags and ACF_RW_SETTING)<>0 then + begin + tmp:=ParseVarString(dbsetting,hContact,ls); + StrCopyW(bufw,tmp); + mFreeMem(tmp); + end + else + StrCopyW(bufw,dbsetting); + StrReplaceW(@bufw,'',ls); + FastWideToAnsiBuf(bufw,asbuf,SizeOf(asbuf)-1); + StrReplace(asbuf,protostr,proto); + + // Delete data + if (flags and ACF_DBDELETE)<>0 then + begin + if (asbuf[0]='*') or (asbuf[StrLen(asbuf)-1]='*') then + DBDeleteGroup(hContact,ambuf,asbuf) + else + DBDeleteSetting(hContact,ambuf,asbuf); + end + else + begin + if (flags and ACF_LAST)<>0 then + begin + avalue:=WorkData.LastResult; + if WorkData.ResultType=rtInt then // have number + begin + if (flags and ACF_DBUTEXT)=ACF_DBUTEXT then // need wide text + avalue:=uint_ptr(IntToStr(sbuf,avalue)) + else if (flags and ACF_DBANSI)=ACF_DBANSI then // need ansi text + avalue:=uint_ptr(IntToStr(pAnsiChar(@sbuf),avalue)); + end + // got wide text + else if (flags and ACF_TEXT)=0 then // need number + avalue:=NumToInt(pWideChar(avalue)); +{ + val=LR(wide) (wide,ansi) + val=pointer to static buffer (wide, ansi) + val=number(number) +} + end + else + begin + if (flags and ACF_RW_VALUE)<>0 then + begin + avalue:=uint_ptr(ParseVarString(dbvalue,hContact,ls)); + end + else + avalue:=uint_ptr(dbvalue); + + if (flags and ACF_TEXT)=0 then // need a number + begin + tmp:=pWideChar(avalue); + avalue:=NumToInt(pWideChar(avalue)); + if (flags and ACF_RW_VALUE)<>0 then + mFreeMem(tmp); + end; +{ + val=uint_ptr if need number(number) + val=script result wide(need to free) (wide,ansi) + val=original dbvalue wide (wide,ansi) +} + end; + // Write value + if (flags and ACF_DBWRITE)<>0 then + begin + case (flags and ACF_VALUETYPE) of + ACF_DBBYTE: DBWriteByte(hContact,ambuf,asbuf,avalue); + ACF_DBWORD: DBWriteWord(hContact,ambuf,asbuf,avalue); + ACF_DBANSI: begin + WideToAnsi(pWideChar(avalue),tmpa,MirandaCP); + DBWriteString(hContact,ambuf,asbuf,tmpa); + mFreeMem(tmpa); + end; + ACF_DBUTEXT: begin + DBWriteUnicode(hContact,ambuf,asbuf,pWideChar(avalue)); + end; + else + DBWriteDWord(hContact,ambuf,asbuf,avalue); + end; + + if (flags and ACF_SAVE)<>0 then + begin + ClearResult(WorkData); + case (flags and ACF_VALUETYPE) of + ACF_DBANSI, + ACF_DBUTEXT: begin + StrDupW(pWideChar(WorkData.LastResult),pWideChar(avalue)); + WorkData.ResultType:=rtWide; + end; + else + WorkData.LastResult:=avalue; + WorkData.ResultType:=rtInt; + end; + end; + end + // Read value + else + begin + ClearResult(WorkData); + WorkData.ResultType:=rtInt; + case (flags and ACF_VALUETYPE) of + ACF_DBBYTE: WorkData.LastResult:=DBReadByte(hContact,ambuf,asbuf,avalue); + ACF_DBWORD: WorkData.LastResult:=DBReadWord(hContact,ambuf,asbuf,avalue); + ACF_DBANSI: begin + WideToAnsi(pWideChar(avalue),tmpa1,MirandaCP); + tmpa:=DBReadString(hContact,ambuf,asbuf,tmpa1); + AnsiToWide(tmpa,PWideChar(WorkData.LastResult),MirandaCP); + WorkData.ResultType:=rtWide; + mFreeMem(tmpa1); + mFreeMem(tmpa); + end; + ACF_DBUTEXT: begin + WorkData.LastResult:=uint_ptr(DBReadUnicode(hContact,ambuf,asbuf,pWideChar(avalue))); + WorkData.ResultType:=rtWide; + end + else + WorkData.LastResult:=DBReadDWord(hContact,ambuf,asbuf,avalue); + end; + end; + + if (flags and ACF_RW_VALUE)<>0 then + begin + if (flags and ACF_TEXT)<>0 then + begin + mFreeMem(avalue); + end; + end; + end; +end; + +procedure tDataBaseAction.Load(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; + tmp:pWideChar; +begin + inherited Load(node,fmt); + case fmt of + 0: begin + if (flags and ACF_NOCONTACT)=0 then + dbcontact:=LoadContact(DBBranch,node); + pc:=StrCopyE(section,pAnsiChar(node)); + StrCopy(pc,opt_module ); dbmodule :=DBReadUnicode(0,DBBranch,section); + StrCopy(pc,opt_setting); dbsetting:=DBReadUnicode(0,DBBranch,section); + if ((flags and ACF_DBDELETE)=0) and + ((flags and ACF_LAST)=0) then + begin + StrCopy(pc,opt_value); dbvalue:=DBReadUnicode(0,DBBranch,section); + end; + end; + + 1: begin + with xmlparser do + begin + tmp:=getAttrValue(HXML(node),ioOper); + if lstrcmpiw(tmp,ioDelete)=0 then flags:=flags or ACF_DBDELETE + else if lstrcmpiw(tmp,ioWrite )=0 then flags:=flags or ACF_DBWRITE; + // else if lstrcmpiw(tmp,ioRead)=0 then ; + tmp:=getAttrValue(HXML(node),ioContact); + if lstrcmpiw(tmp,ioCurrent)=0 then flags:=flags or ACF_CURRENT + else if lstrcmpiw(tmp,ioResult )=0 then flags:=flags or ACF_RESULT + else if lstrcmpiw(tmp,ioParam )=0 then flags:=flags or ACF_PARAM + else if lstrcmpiw(tmp,ioContact)=0 then + begin + dbcontact:=ImportContact(HXML(node)); + end; + + StrDupW(dbmodule ,getAttrValue(HXML(node),ioModule)); + StrDupW(dbsetting,getAttrValue(HXML(node),ioSetting)); + + if StrToInt(getAttrValue(HXML(node),ioFileVariable))=1 then flags:=flags or ACF_RW_MODULE; + if StrToInt(getAttrValue(HXML(node),ioArgVariable ))=1 then flags:=flags or ACF_RW_SETTING; + if StrToInt(getAttrValue(HXML(node),ioVariables ))=1 then flags:=flags or ACF_RW_VALUE; + + tmp:=getAttrValue(HXML(node),ioType); + if lstrcmpiw(tmp,ioByte )=0 then flags:=flags or ACF_DBBYTE + else if lstrcmpiw(tmp,ioWord )=0 then flags:=flags or ACF_DBWORD + else if lstrcmpiw(tmp,ioDword)=0 then + else if lstrcmpiw(tmp,ioAnsi )=0 then flags:=flags or ACF_DBANSI + else flags:=flags or ACF_DBUTEXT; + + if StrToInt(getAttrValue(HXML(node),ioSaveValue))=1 then + flags:=flags or ACF_SAVE; + + if StrToInt(getAttrValue(HXML(node),ioLast))=1 then + flags:=flags or ACF_LAST + else + StrDupW(dbvalue,getText(HXML(node))); + end; + end; +{ + 2: begin + pc:=GetParamSectionStr(node,ioOper); + if lstrcmpi(pc,ioDelete)=0 then flags:=flags or ACF_DBDELETE + else if lstrcmpi(pc,ioWrite )=0 then flags:=flags or ACF_DBWRITE; +// else if lstrcmpiw(tmp,ioRead)=0 then ; + pc:=GetParamSectionStr(node,ioContact); + if lstrcmpi(pc,ioCurrent)=0 then flags:=flags or ACF_CURRENT + else if lstrcmpi(pc,ioResult )=0 then flags:=flags or ACF_RESULT + else if lstrcmpi(pc,ioParam )=0 then flags:=flags or ACF_PARAM + else if lstrcmpi(pc,ioContact)=0 then + begin + dbcontact:=ImportContactINI(node); + end; + + UF8ToWide(GetParamSectionStr(node,ioModule ),dbmodule); + UF8ToWide(GetParamSectionStr(node,ioSetting),dbsetting); + + if GetParamSectionInt(node,ioFileVariable)=1 then flags:=flags or ACF_RW_MODULE; + if GetParamSectionInt(node,ioArgVariable )=1 then flags:=flags or ACF_RW_SETTING; + if GetParamSectionInt(node,ioVariables )=1 then flags:=flags or ACF_RW_VALUE; + + pc:=GetParamSectionStr(node,ioType); + if lstrcmpi(pc,ioByte )=0 then flags:=flags or ACF_DBBYTE + else if lstrcmpi(pc,ioWord )=0 then flags:=flags or ACF_DBWORD + else if lstrcmpi(pc,ioDword)=0 then + else if lstrcmpi(pc,ioAnsi )=0 then flags:=flags or ACF_DBANSI + else flags:=flags or ACF_DBUTEXT; + + if GetParamSectionInt(node,ioLast))=1 then + flags:=flags or ACF_LAST + else + UF8ToWide(GetParamSectionStr(node,'value'),dbvalue); //!! + end; +} + end; +end; + +procedure tDataBaseAction.Save(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; +begin + inherited Save(node,fmt); + case fmt of + 0: begin + if (flags and ACF_NOCONTACT)=0 then + SaveContact(dbcontact,DBBranch,node); + pc:=StrCopyE(section,pAnsiChar(node)); + StrCopy(pc,opt_module ); DBWriteUnicode(0,DBBranch,section,dbmodule); + StrCopy(pc,opt_setting); DBWriteUnicode(0,DBBranch,section,dbsetting); + if ((flags and ACF_DBDELETE)=0) and + ((flags and ACF_LAST)=0) then + begin + StrCopy(pc,opt_value); DBWriteUnicode(0,DBBranch,section,dbvalue); + end; + end; +{ + 1: begin + end; +} + end; +end; + +//----- Dialog realization ----- + +procedure MakeDataTypeList(wnd:HWND); +begin + SendMessage(wnd,CB_RESETCONTENT,0,0); + InsertString(wnd,0,'Byte'); + InsertString(wnd,1,'Word'); + InsertString(wnd,2,'DWord'); + InsertString(wnd,3,'Ansi'); + InsertString(wnd,4,'Unicode'); + SendMessage(wnd,CB_SETCURSEL,0,0); +end; + +procedure ClearFields(Dialog:HWND); +begin + CheckDlgButton(Dialog,IDC_RW_LAST,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_RW_SAVE,BST_UNCHECKED); + + CheckDlgButton(Dialog,IDC_RW_CURRENT,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_RW_MANUAL ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_RW_PARAM ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_RW_RESULT ,BST_UNCHECKED); + + CheckDlgButton(Dialog,IDC_RW_READ ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_RW_WRITE ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_RW_DELETE,BST_UNCHECKED); +end; + +function DlgProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +const + NoProcess:boolean=true; +var + wnd:HWND; + i:integer; + bb:boolean; +begin + result:=0; + + case hMessage of + + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + + MakeDataTypeList(GetDlgItem(Dialog,IDC_RW_DATATYPE)); + + wnd:=GetDlgItem(Dialog,IDC_CNT_REFRESH); + OptSetButtonIcon(wnd,ACI_REFRESH); + SendMessage(wnd,BUTTONADDTOOLTIP,TWPARAM(TranslateW('Refresh')),BATF_UNICODE); + OptFillContactList(GetDlgItem(Dialog,IDC_CONTACTLIST)); + + MakeEditField(Dialog,IDC_RW_MODULE); + MakeEditField(Dialog,IDC_RW_SETTING); + MakeEditField(Dialog,IDC_RW_VALUE); + end; + + WM_ACT_SETVALUE: begin + NoProcess:=true; + ClearFields(Dialog); + + with tDataBaseAction(lParam) do + begin + // operation + if (flags and ACF_DBDELETE)<>0 then i:=IDC_RW_DELETE + else if (flags and ACF_DBWRITE )= 0 then i:=IDC_RW_READ + else i:=IDC_RW_WRITE; + CheckDlgButton(Dialog,i,BST_CHECKED); + + // contact + bb:=false; + case (flags and ACF_NOCONTACT) of + ACF_CURRENT: i:=IDC_RW_CURRENT; + ACF_PARAM : i:=IDC_RW_PARAM; + ACF_RESULT : i:=IDC_RW_RESULT; + else + i:=IDC_RW_MANUAL; + bb:=true; + SendDlgItemMessage(Dialog,IDC_CONTACTLIST,CB_SETCURSEL, + FindContact(GetDlgItem(Dialog,IDC_CONTACTLIST),dbcontact),0); + end; + CheckDlgButton(Dialog,i,BST_CHECKED); + EnableWindow(GetDlgItem(Dialog,IDC_CONTACTLIST),bb); + + SetDlgItemTextW(Dialog,IDC_RW_MODULE ,dbmodule); + SetDlgItemTextW(Dialog,IDC_RW_SETTING,dbsetting); + SetEditFlags(Dialog,IDC_RW_MODULE ,EF_SCRIPT,ord((flags and ACF_RW_MODULE )<>0)); + SetEditFlags(Dialog,IDC_RW_SETTING,EF_SCRIPT,ord((flags and ACF_RW_SETTING)<>0)); + + // values + bb:=true; + if (flags and ACF_LAST)<>0 then + begin + CheckDlgButton(Dialog,IDC_RW_LAST,BST_CHECKED); + bb:=false; + end; + if (flags and ACF_DBDELETE)<>0 then + bb:=false; + EnableWindow(GetDlgItem(Dialog,IDC_RW_VALUE),bb); + + if (flags and ACF_SAVE)<>0 then + CheckDlgButton(Dialog,IDC_RW_SAVE,BST_CHECKED); + EnableWindow(GetDlgItem(Dialog,IDC_RW_SAVE),(flags and ACF_DBWRITE)<>0); + + case (flags and ACF_VALUETYPE) of + ACF_DBBYTE : i:=0; + ACF_DBWORD : i:=1; + ACF_DBANSI : i:=3; + ACF_DBUTEXT: i:=4; + else + i:=2; + end; + CB_SelectData(GetDlgItem(Dialog,IDC_RW_DATATYPE),i); + + SetDlgItemTextW(Dialog,IDC_RW_VALUE,dbvalue); + SetEditFlags(Dialog,IDC_RW_VALUE,EF_SCRIPT,ord((flags and ACF_RW_VALUE)<>0)); + end; + NoProcess:=false; + end; + + WM_ACT_RESET: begin + NoProcess:=true; + ClearFields(Dialog); + + SetDlgItemTextW(Dialog,IDC_RW_MODULE ,nil); + SetDlgItemTextW(Dialog,IDC_RW_SETTING,nil); + SetDlgItemTextW(Dialog,IDC_RW_VALUE ,nil); + SetEditFlags(Dialog,IDC_RW_MODULE ,EF_ALL,0); + SetEditFlags(Dialog,IDC_RW_SETTING,EF_ALL,0); + SetEditFlags(Dialog,IDC_RW_VALUE ,EF_ALL,0); + + CB_SelectData(GetDlgItem(Dialog,IDC_RW_DATATYPE),0); + CheckDlgButton(Dialog,IDC_RW_READ ,BST_CHECKED); + CheckDlgButton(Dialog,IDC_RW_MANUAL,BST_CHECKED); + + EnableWindow(GetDlgItem(Dialog,IDC_CONTACTLIST),true); + EnableWindow(GetDlgItem(Dialog,IDC_RW_VALUE),true); + NoProcess:=false; + end; + + WM_ACT_SAVE: begin + with tDataBaseAction(lParam) do + begin + // contact + if IsDlgButtonChecked(Dialog,IDC_RW_CURRENT)=BST_CHECKED then flags:=flags or ACF_CURRENT + else if IsDlgButtonChecked(Dialog,IDC_RW_RESULT )=BST_CHECKED then flags:=flags or ACF_RESULT + else if IsDlgButtonChecked(Dialog,IDC_RW_PARAM )=BST_CHECKED then flags:=flags or ACF_PARAM + else + dbcontact:=SendDlgItemMessage(Dialog,IDC_CONTACTLIST,CB_GETITEMDATA, + SendDlgItemMessage(Dialog,IDC_CONTACTLIST,CB_GETCURSEL,0,0),0); + + {mFreeMem(dbmodule ); }dbmodule :=GetDlgText(Dialog,IDC_RW_MODULE); + {mFreeMem(dbsetting); }dbsetting:=GetDlgText(Dialog,IDC_RW_SETTING); + if (GetEditFlags(Dialog,IDC_RW_MODULE ) and EF_SCRIPT)<>0 then flags:=flags or ACF_RW_MODULE; + if (GetEditFlags(Dialog,IDC_RW_SETTING) and EF_SCRIPT)<>0 then flags:=flags or ACF_RW_SETTING; + + // operation + if IsDlgButtonChecked(Dialog,IDC_RW_WRITE )=BST_CHECKED then flags:=flags or ACF_DBWRITE + else if IsDlgButtonChecked(Dialog,IDC_RW_DELETE)=BST_CHECKED then flags:=flags or ACF_DBDELETE; + + // value + if IsDlgButtonChecked(Dialog,IDC_RW_LAST)<>BST_UNCHECKED then + flags:=flags or ACF_LAST + else if (flags and ACF_DBDELETE)=0 then + begin + {mFreeMem(dbvalue); }dbvalue:=GetDlgText(Dialog,IDC_RW_VALUE); + if (GetEditFlags(Dialog,IDC_RW_VALUE) and EF_SCRIPT)<>0 then flags:=flags or ACF_RW_VALUE; + end; + + if IsDlgButtonChecked(Dialog,IDC_RW_SAVE)<>BST_UNCHECKED then + flags:=flags or ACF_SAVE; + + i:=CB_GetData(GetDlgItem(Dialog,IDC_RW_DATATYPE)); + case i of + 0: flags:=flags or ACF_DBBYTE; + 1: flags:=flags or ACF_DBWORD; + 2: flags:=flags or 0; + 3: flags:=flags or ACF_DBANSI; + 4: flags:=flags or ACF_DBUTEXT; + end; + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of + CBN_SELCHANGE, + EN_CHANGE: if not NoProcess then + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + + BN_CLICKED: begin + case loword(wParam) of + IDC_RW_READ, + IDC_RW_WRITE, + IDC_RW_DELETE: begin + bb:=IsDlgButtonChecked(Dialog,IDC_RW_DELETE)=BST_UNCHECKED; + EnableWindow(GetDlgItem(Dialog,IDC_RW_DATATYPE),bb); + EnableWindow(GetDlgItem(Dialog,IDC_RW_LAST),bb); + if bb then + bb:=IsDlgButtonChecked(Dialog,IDC_RW_LAST)=BST_UNCHECKED; + EnableEditField(GetDlgItem(Dialog,IDC_RW_VALUE),bb); + + bb:=loword(wParam)=IDC_RW_WRITE; + EnableWindow(GetDlgItem(Dialog,IDC_RW_SAVE),bb); + end; + IDC_RW_CURRENT, + IDC_RW_PARAM, + IDC_RW_RESULT: EnableWindow(GetDlgItem(Dialog,IDC_CONTACTLIST),false); + IDC_RW_MANUAL: EnableWindow(GetDlgItem(Dialog,IDC_CONTACTLIST),true); + + IDC_RW_LAST: begin + EnableEditField(GetDlgItem(Dialog,IDC_RW_VALUE), + IsDlgButtonChecked(Dialog,IDC_RW_LAST)=BST_UNCHECKED); + end; + + IDC_CNT_REFRESH: begin + OptFillContactList(GetDlgItem(Dialog,IDC_CONTACTLIST)); + exit; + end; + end; + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + + end; + end; + + WM_HELP: begin + result:=1; + end; + + end; +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=tDataBaseAction.Create(vc.Hash); +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,'IDD_ACTDATABASE',parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :='Database'; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :='IDI_DATABASE'; + vc.Hash :=0; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_global.pas b/plugins/Actman30/iac_global.pas new file mode 100644 index 0000000000..64a8604b2c --- /dev/null +++ b/plugins/Actman30/iac_global.pas @@ -0,0 +1,428 @@ +unit iac_global; + +interface + +uses + windows, messages, + m_api; + +var + xmlparser:XML_API_W; + +const + IcoLibPrefix = 'action_type_'; +const + NoDescription:PWideChar='No Description'; +const + protostr = ''; +const + WM_ACT_SETVALUE = WM_USER + 13; + WM_ACT_RESET = WM_USER + 14; + WM_ACT_SAVE = WM_USER + 15; + WM_ACT_LISTCHANGE = WM_USER + 16; // group, action + +const + ACF_DISABLED = $10000000; // action disabled + ACF_REPLACED = $20000000; // action replaced by new in options + ACF_INTRODUCED = $40000000; // action is newly created (not saved) in options + +type + tLRType = record + value:uint_ptr; + rtype:byte; // rt* const + end; +type + pWorkData = ^tWorkData; + tWorkData = record + Parameter :LPARAM; + ActionList :pointer; + LastResult :uint_ptr; + ActionCount:integer; + ResultType :integer; // rt* const + Storage :array [0..9] of tLRType; + end; + +type + pBaseAction = ^tBaseAction; + tBaseAction = class + ActionDescr:pWideChar; // description (user name) + UID :dword; // hash of action type name + flags :dword; + + procedure Duplicate(var dst:tBaseAction); + + constructor Create(uid:dword); + destructor Destroy; override; +// function Clone:tBaseAction; virtual; + function DoAction(var WorkData:tWorkData):LRESULT; virtual; // process action + procedure Load(node:pointer;fmt:integer); virtual; // load/import action + procedure Save(node:pointer;fmt:integer); virtual; // save/export action + end; + +type + tCreateActionFunc = function:tBaseAction; + tCreateDialogFunc = function(parent:HWND):HWND; +// tCheckImportFunc = function(node:pointer;fmt:integer):boolean; + +type + pActModule = ^tActModule; + tActModule = record + Next :pActModule; + Name :pAnsiChar; // action type name + Dialog :tCreateDialogFunc; // action dialog creating + Create :tCreateActionFunc; // action object creation +// CheckImp :tCheckImportFunc; // check for action type + Icon :pAnsiChar; // icon resource name + // runtime data + DlgHandle:HWND; + Hash :dword; // will be calculated at registration cycle + end; + +const + ModuleLink:pActModule=nil; + +function ClearResult(var WorkData:tWorkData;num:integer=-1):uint_ptr; +function GetResultNumber(var WorkData:tWorkData;num:integer=-1):uint_ptr; + +procedure InsertString(wnd:HWND;num:dword;str:PAnsiChar); + +function GetLink(hash:dword):pActModule; +function GetLinkByName(name:pAnsiChar):pActModule; + +function ImportContact (node:HXML ):THANDLE; +function ImportContactINI(node:pointer):THANDLE; + +implementation + +uses Common, global, dbsettings, base64, mirutils; + +//----- tBaseAction code ----- +const + ioDisabled = 'disabled'; + ioName = 'name'; +const + opt_uid = 'uid'; + opt_descr = 'descr'; + opt_flags = 'flags'; + +constructor tBaseAction.Create(uid:dword); +begin + inherited Create; + + if uid<>0 then + begin + StrDupW(ActionDescr,NoDescription); + Self.UID:=uid; + flags:=0; + end; +end; + +destructor tBaseAction.Destroy; +begin + mFreeMem(ActionDescr); + + inherited Destroy; +end; + +procedure tBaseAction.Duplicate(var dst:tBaseAction); +begin + StrDupW(dst.ActionDescr,ActionDescr); + dst.UID :=UID; + dst.flags:=flags; +end; +{ +function tBaseAction.Clone:tBaseAction; +begin + //dummy + result:=nil; +end; +} +function tBaseAction.DoAction(var WorkData:tWorkData):LRESULT; +begin + result:=0; + // nothing +end; + +procedure tBaseAction.Load(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; +begin + case fmt of + 0: begin + pc:=StrCopyE(section,pAnsiChar(node)); + mFreeMem(ActionDescr); // created by constructor + StrCopy(pc,opt_descr); ActionDescr:=DBReadUnicode(0,DBBranch,section,NoDescription); + StrCopy(pc,opt_flags); flags :=DBReadDword (0,DBBranch,section); + // UID reading in main program, set by constructor + end; + + 1: begin + with xmlparser do + begin + if StrToInt(getAttrValue(HXML(node),ioDisabled))=1 then + flags:=flags or ACF_DISABLED; + + StrDupW(ActionDescr,getAttrValue(HXML(node),ioName)); + end; + end; +{ + 2: begin + if GetParamSectionInt(node,ioDisabled))=1 then + flags:=flags or ACF_DISABLED; + + UF8ToWide(GetParamSectionStr(node,ioName),ActionDescr); + end; +} + end; +end; + +procedure tBaseAction.Save(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; +begin + case fmt of + 0: begin + pc:=StrCopyE(section,pAnsiChar(node)); + StrCopy(pc,opt_uid ); DBWriteDWord (0,DBBranch,section,uid); + StrCopy(pc,opt_flags); DBWriteDWord (0,DBBranch,section,flags); + StrCopy(pc,opt_descr); DBWriteUnicode(0,DBBranch,section,ActionDescr); + end; +{ + 1: begin + end; +} + end; +end; + +//----- LastResult processing ----- + +function ClearResult(var WorkData:tWorkData;num:integer=-1):uint_ptr; +var + rt:pbyte; + lr:^uint_ptr; +begin + result:=0; + + if num<0 then + begin + rt:=@WorkData.ResultType; + lr:=@WorkData.LastResult; + end + else if num<10 then + begin + rt:=@WorkData.Storage[num].rtype; + lr:=@WorkData.Storage[num].value; + end + else + exit; + + if rt^=rtInt then + result:=lr^ + else if rt^<>rtUnkn then + begin + mFreeMem(pWideChar(lr^)); + result:=0; + end; +end; + +function GetResultNumber(var WorkData:tWorkData;num:integer=-1):uint_ptr; +var + rt:pbyte; + lr:^uint_ptr; +begin + result:=0; + + if num<0 then + begin + rt:=@WorkData.ResultType; + lr:=@WorkData.LastResult; + end + else if num<10 then + begin + rt:=@WorkData.Storage[num].rtype; + lr:=@WorkData.Storage[num].value; + end + else + exit; + + if rt^=rtInt then + result:=lr^ + else if rt^<>rtUnkn then + begin + result:=NumToInt(pWideChar(lr^)); +{ + if (pWideChar(WorkData.LastResult)[0]='$') and + (AnsiChar(pWideChar(WorkData.LastResult)[1]) in sHexNum) then + result:=HexToInt(pWideChar(WorkData.LastResult)+1) + else + if (pWideChar(WorkData.LastResult)[0]='0') and + (pWideChar(WorkData.LastResult)[1]='x') and + (AnsiChar(pWideChar(WorkData.LastResult)[2]) in sHexNum) then + result:=HexToInt(pWideChar(WorkData.LastResult)+2) + else + result:=StrToInt(pWideChar(WorkData.LastResult)); +} + end; +end; + +procedure InsertString(wnd:HWND;num:dword;str:PAnsiChar); +var + buf:array [0..127] of WideChar; +begin + SendMessageW(wnd,CB_SETITEMDATA, + SendMessageW(wnd,CB_ADDSTRING,0, + lparam(TranslateW(FastAnsiToWideBuf(str,buf)))), + num); +{ + SendMessageW(wnd,CB_INSERTSTRING,num, + dword(TranslateW(FastAnsiToWideBuf(str,buf)))); +} +end; + +function GetLink(hash:dword):pActModule; +begin + result:=ModuleLink; + while (result<>nil) and (result.Hash<>hash) do + result:=result^.Next; +end; + +function GetLinkByName(name:pAnsiChar):pActModule; +begin + result:=ModuleLink; + while (result<>nil) and (StrCmp(result.Name,name)<>0) do + result:=result^.Next; +end; + +const + ioCProto = 'cproto'; + ioIsChat = 'ischat'; + ioCUID = 'cuid'; + ioCUIDType = 'cuidtype'; + +function ImportContact(node:HXML):THANDLE; +var + proto:pAnsiChar; + tmpbuf:array [0..63] of AnsiChar; + dbv:TDBVARIANT; + tmp:pWideChar; + is_chat:boolean; +begin + with xmlparser do + begin + proto:=FastWideToAnsiBuf(getAttrValue(node,ioCProto),tmpbuf); + if (proto=nil) or (proto^=#0) then + begin + result:=0; + exit; + end; + is_chat:=StrToInt(getAttrValue(node,ioIsChat))<>0; + + tmp:=getAttrValue(node,ioCUID); + if is_chat then + begin + dbv.szVal.W:=tmp; + end + else + begin + FillChar(dbv,SizeOf(TDBVARIANT),0); + dbv._type:=StrToInt(getAttrValue(node,ioCUIDType)); + case dbv._type of + DBVT_BYTE : dbv.bVal:=StrToInt(tmp); + DBVT_WORD : dbv.wVal:=StrToInt(tmp); + DBVT_DWORD : dbv.dVal:=StrToInt(tmp); + DBVT_ASCIIZ: FastWideToAnsi(tmp,dbv.szVal.A); + DBVT_UTF8 : WideToUTF8(tmp,dbv.szVal.A); + DBVT_WCHAR : dbv.szVal.W:=tmp; + DBVT_BLOB : begin + Base64Decode(FastWideToAnsi(tmp,pAnsiChar(dbv.pbVal)),dbv.pbVal); + end; + end; + end; + end; + result:=FindContactHandle(proto,dbv,is_chat); + if not is_chat then + case dbv._type of + DBVT_ASCIIZ, + DBVT_UTF8 : mFreeMem(dbv.szVal.A); + DBVT_BLOB : mFreeMem(dbv.pbVal); + end; +end; + +function ImportContactINI(node:pointer):THANDLE; +{ +var + proto:pAnsiChar; + dbv:TDBVARIANT; + tmp:pAnsiChar; + is_chat:boolean; +} +begin + result:=0; +{ + proto:=GetParamSectionStr(node,ioCProto); // LATIN chars must be + if (proto=nil) or (proto^=#0) then + begin + result:=0; + exit; + end; + is_chat:=GetParamSectionInt(node,ioIsChat)<>0; + + tmp:=GetParamSectionStr(node,ioCUID); + if is_chat then + begin + dbv.szVal.W:=UTF8ToWide(tmp); + end + else + begin + FillChar(dbv,SizeOf(TDBVARIANT),0); + dbv._type:=GetParamSectionInt(node,ioCUIDType); + case dbv._type of + DBVT_BYTE : dbv.bVal:=StrToInt(tmp); + DBVT_WORD : dbv.wVal:=StrToInt(tmp); + DBVT_DWORD : dbv.dVal:=StrToInt(tmp); + DBVT_ASCIIZ: dbv.szVal.A:=tmp; // must be LATIN + DBVT_UTF8 : dbv.szVal.A:=tmp; + DBVT_WCHAR : UTF8ToWide(tmp); + DBVT_BLOB : begin // must be LATIN (base64) + Base64Decode(tmp,dbv.pbVal); + end; + end; + end; + + result:=FindContactHandle(proto,dbv,is_chat); + + if is_chat or (dbv._type=DBVT_WCHAR) then + mFreeMem(dbv.szVal.W) + else if dbv._type=DBVT_BLOB then + mFreeMem(dbv.pbVal); +} +end; +{ +function CreateImportClass(node:pointer;fmt:integer):tBaseAction; +var + module:pActModule; + uid:dword; + section:array [0..127] of AnsiChar; +begin + result:=nil; + module:=ModuleLink; + case fmt of + 0: begin + StrCopy(StrCopyE(section,pAnsiChar(node)),opt_uid); + uid:=DBReadDWord(0,DBBranch,section,0); + + while module<>nil do + begin + module:=module^.Next; + end; + end; + 1: begin + end; + 2: begin + end; + end; +end; +} +end. diff --git a/plugins/Actman30/iac_inout.pas b/plugins/Actman30/iac_inout.pas new file mode 100644 index 0000000000..999d3fccaf --- /dev/null +++ b/plugins/Actman30/iac_inout.pas @@ -0,0 +1,667 @@ +unit iac_inout; + +interface + +implementation + +uses + windows, messages, commctrl, + iac_global, global, + mirutils, common, dbsettings, + wrapper, editwrapper, io, syswin, + m_api; + +{$include i_cnst_inout.inc} +{$resource iac_inout.res} + +const + opt_file = 'file'; +const + ioObject = 'object'; + ioClipboard = 'clipboard'; + ioOper = 'oper'; + ioCopy = 'copy'; + ioFile = 'file'; + ioFileVariable = 'modvariables'; + ioWrite = 'write'; + ioAppend = 'append'; + ioEnc = 'enc'; +const + ACF_CLIPBRD = $00000002; // Clipboard operations, not window + ACF_ANSI = $00000004; // File: ANSI or Unicode (UTF8/UTF16) text + ACF_COPYTO = $00000008; // Clipboard operations: 'copy to' or 'paste from' + + ACF_FILE = $00000010; // File operations + ACF_FWRITE = $00000020; // read/write file + ACF_FAPPEND = $00000040; // append file + ACF_UTF8 = $00000080; // File: UTF8 or UTF16 + ACF_SIGN = $00000100; // File: with signature or not + ACF_FILE_PATH = $00000200; + + ACF_TEXTSEND = $00000400; + // dummy + ACF_MESSAGE = 0; + +type + tInOutAction = class(tBaseAction) + private + tfile:pWideChar; + 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 ----- + +//----- Object realization ----- + +constructor tInOutAction.Create(uid:dword); +begin + inherited Create(uid); + + tfile:=nil; +end; + +destructor tInOutAction.Destroy; +begin + mFreeMem(tfile); + + inherited Destroy; +end; +{ +function tInOutAction.Clone:tBaseAction; +begin + result:=.Create(0); + Duplicate(result); + +end; +} +function tInOutAction.DoAction(var WorkData:tWorkData):LRESULT; +var + tmp:PWideChar; + blob,p:PAnsiChar; + w:PWideChar; + hContact:THANDLE; + wnd:HWND; + fexist:bool; + dbei:TDBEVENTINFO; + i:cardinal; + cp:integer; + fh:THANDLE; + lstr:pWideChar; + llen:integer; + buf:array [0..31] of WideChar; + b,b1:array [0..MAX_PATH] of AnsiChar; + + last:pWideChar; +begin + result:=0; + + if WorkData.ResultType=rtInt then + last:=pWideChar(IntToStr(buf,WorkData.LastResult)) + else + last:=pWideChar(WorkData.LastResult); + + // Clipboard + if (flags and ACF_CLIPBRD)<>0 then + begin + if (flags and ACF_COPYTO)<>0 then + CopyToClipboard(last,false) + else + begin + ClearResult(WorkData); + WorkData.LastResult:=uint_ptr(PasteFromClipboard(false)); + WorkData.ResultType:=rtWide; + end; + exit; + end; + + // File + if (flags and ACF_FILE)<>0 then + begin + if (flags and ACF_FILE_PATH)<>0 then + begin + if CallService(MS_DB_CONTACT_IS,WorkData.Parameter,0)<>0 then + hContact:=WorkData.Parameter + else + hContact:=0; + tmp:=ParseVarString(tfile,hContact,last) + end + else + tmp:=tfile; + + // File write + if (flags and (ACF_FAPPEND or ACF_FWRITE))<>0 then + begin + if (flags and ACF_ANSI)=ACF_ANSI then cp:=1 // Ansi + else if (flags and (ACF_UTF8 or ACF_SIGN))=ACF_UTF8 then cp:=2 // UTF8 + else if (flags and (ACF_UTF8 or ACF_SIGN))=ACF_SIGN then cp:=4 // Wide+Sign + else if (flags and (ACF_UTF8 or ACF_SIGN))=(ACF_UTF8 or ACF_SIGN) then cp:=3 // UTF8+Sign + else cp:=0; // Wide + + case cp of + 1: begin + llen:=StrLen(WideToAnsi(last,pAnsiChar(lstr),MirandaCP)); + end; + 2,3: begin + llen:=StrLen(WideToUTF8(last,pAnsiChar(lstr))); + end; + else + lstr:=last; + llen:=StrLenW(lstr)*SizeOf(WideChar); + end; + + fexist:=FileExists(tmp); + // Append file + if fexist and ((flags and ACF_FAPPEND)<>0) then + begin + fh:=Append(tmp); + if fh<>THANDLE(INVALID_HANDLE_VALUE) then + begin + BlockWrite(fh,lstr^,llen); + end; + if (cp<>0) and (cp<>4) then + mFreeMem(lstr); + end + // Write file + else if ((flags and ACF_FWRITE)<>0) or + (not fexist and ((flags and ACF_FAPPEND)<>0)) then + begin + fh:=ReWrite(tmp); + if fh<>THANDLE(INVALID_HANDLE_VALUE) then + begin + if cp=3 then + begin + i:=SIGN_UTF8; + BlockWrite(fh,i,3); // UTF8 sign + end + else if cp=4 then + begin + i:=SIGN_UNICODE; + BlockWrite(fh,i,2); // UTF16 sign + end; + + BlockWrite(fh,lstr^,llen); + if (cp<>0) and (cp<>4) then + mFreeMem(lstr); + end; + end + else + fh:=THANDLE(INVALID_HANDLE_VALUE); + end + // File read + else + begin + // remove file - download + if StrPosW(tmp,'://')<>nil then // remote + begin + GetTempPathA(MAX_PATH,b); + GetTempFileNameA(b,'wat',GetCurrentTime,b1); + GetFile(FastWideToAnsiBuf(tmp,b),b1); + if tmp<>tfile then + mFreeMem(tmp); + FastAnsiToWide(b1,tmp); + end + else + b1[0]:=#0; + fh:=Reset(tmp); + // process file + if fh<>THANDLE(INVALID_HANDLE_VALUE) then + begin + i:=GetFSize(tmp); + mGetMem (w ,i+SizeOf(WideChar)); + FillChar(w^,i+SizeOf(WideChar),0); + BlockRead(fh,w^,i); + if (flags and ACF_ANSI)<>0 then + begin + AnsiToWide(pAnsiChar(w),lstr,MirandaCP); + mFreeMem(w); + w:=lstr; + end + else if (flags and ACF_UTF8)<>0 then + begin + UTF8ToWide(pAnsiChar(w),lstr); + mFreeMem(w); + w:=lstr; + end + else + ChangeUnicode(w); + + ClearResult(WorkData); + WorkData.LastResult:=uint_ptr(w); + WorkData.ResultType:=rtWide; + end; + if b1[0]<>#0 then + DeleteFileA(b1); + end; + + if fh<>THANDLE(INVALID_HANDLE_VALUE) then + CloseHandle(fh); + if tmp<>tfile then + mFreeMem(tmp); + exit; + end; + + // Message + wnd:=WaitFocusedWndChild(GetForegroundWindow){GetFocus}; + + // with Autosend + if (flags and ACF_TEXTSEND)<>0 then + begin + if wnd<>0 then + hContact:=WndToContact(wnd) + else + hContact:=0; + + if hContact=0 then + begin + if CallService(MS_DB_CONTACT_IS,WorkData.Parameter,0)<>0 then + hContact:=WorkData.Parameter; + end; + + if hContact=0 then exit; + + p:=GetContactProtoAcc(hContact); + cp:=DBReadDWord(hContact,'Tab_SRMsg','ANSIcodepage',MirandaCP); + if DBReadByte(hContact,p,'ChatRoom',0)<>1 then + begin + i:=WideToCombo(last,blob,cp); +// if CallContactService(hContact,PSS_MESSAGEW,0,TLPARAM(blob))= +// ACKRESULT_FAILED then + CallContactService(hContact,PSS_MESSAGE,PREF_UNICODE,tlparam(blob)); + dbei.cbSize :=sizeof(dbei); + dbei.cbBlob :=i; + dbei.pBlob :=pByte(blob); + dbei.eventType:=EVENTTYPE_MESSAGE; + dbei.timestamp:=GetCurrentTime; + dbei.szModule :=p; + dbei.flags :=DBEF_SENT; + db_event_add(hContact, @dbei); + mFreeMem(blob); + end + else + SendToChat(hContact,last); + end + else + begin + GetWindowThreadProcessId(GetForegroundWindow,@i); + if (i=GetCurrentProcessId) and (wnd<>0) then + SendMessageW(wnd,EM_REPLACESEL,1,tlparam(last)) + else + SendString(0,last); + end; + +end; + +procedure tInOutAction.Load(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; + tmp:pWideChar; +begin + inherited Load(node,fmt); + case fmt of + 0: begin + pc:=StrCopyE(section,pAnsiChar(node)); + if (flags and ACF_FILE)<>0 then + begin + StrCopy(pc,opt_file); tfile:=DBReadUnicode(0,DBBranch,section,nil); + end; + end; + + 1: begin + with xmlparser do + begin + tmp:=getAttrValue(HXML(node),ioObject); + if lstrcmpiw(tmp,ioClipboard)=0 then + begin + flags:=flags or ACF_CLIPBRD; + tmp:=getAttrValue(HXML(node),ioOper); + if lstrcmpiw(tmp,ioCopy)=0 then flags:=flags or ACF_COPYTO; + // else if lstrcmpiw(tmp,'paste')=0 then ; + end + else + begin + if lstrcmpiw(tmp,ioFile)=0 then + begin + + if StrToInt(getAttrValue(HXML(node),ioFileVariable))=1 then + flags:=flags or ACF_FILE_PATH; + + flags:=flags or ACF_FILE; + StrDupW(tfile,getAttrValue(HXML(node),ioFile)); + tmp:=getAttrValue(HXML(node),ioOper); + if lstrcmpiw(tmp,ioWrite )=0 then flags:=flags or ACF_FWRITE + else if lstrcmpiw(tmp,ioAppend)=0 then flags:=flags or ACF_FAPPEND; + case StrToInt(getAttrValue(HXML(node),ioEnc)) of + 0: flags:=flags or ACF_ANSI; + 1: flags:=flags or ACF_UTF8; + 2: flags:=flags or ACF_UTF8 or ACF_SIGN; + 3: flags:=flags or 0; + 4: flags:=flags or ACF_SIGN; + end; + end; + end; + end; + end; +{ + 2: begin + pc:=GetParamSectionStr(node,ioObject); + if lstrcmpi(tmp,ioClipboard)=0 then + begin + flags:=flags or ACF_CLIPBRD; + pc:=GetParamSectionStr(node,ioOper); + if lstrcmpi(pc,ioCopy)=0 then flags:=flags or ACF_COPYTO; +// else if lstrcmpi(pc,'paste')=0 then ; + end + else + begin + if lstrcmpi(pc,ioFile)=0 then + begin + flags:=flags or ACF_FILE; + + if GetParamSectionInt(node,ioFileVariable))=1 then + flags:=flags or ACF_FILE_PATH; + + UTF8ToWide(GetParamSectionStr(node,ioFile),tfile); + + pc:=GetParamSectionStr(node,ioOper); + if lstrcmpi(pc,ioWrite )=0 then flags:=flags or ACF_FWRITE + else if lstrcmpi(pc,ioAppend)=0 then flags:=flags or ACF_FAPPEND; + + case GetParamSectionInt(node,ioEnc)) of + 0: flags:=flags or ACF_ANSI; + 1: flags:=flags or ACF_UTF8; + 2: flags:=flags or ACF_UTF8 or ACF_SIGN; + 3: flags:=flags or 0; + 4: flags:=flags or ACF_SIGN; + end; + end; + end; + end; +} + end; +end; + +procedure tInOutAction.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)); + if (flags and ACF_FILE)<>0 then + begin + StrCopy(pc,opt_file); DBWriteUnicode(0,DBBranch,section,tfile); + end; + end; +{ + 1: begin + end; +} + end; +end; + +//----- Dialog realization ----- + +procedure FillFileName(Dialog:HWND;idc:integer); +var + pw,ppw:pWideChar; +begin + mGetMem(pw,1024*SizeOf(WideChar)); + ppw:=GetDlgText(Dialog,idc); + if ShowDlgW(pw,ppw) then + begin + SetDlgItemTextW(Dialog,idc,pw); + SetEditFlags(Dialog,idc,EF_SCRIPT,0); + end; + mFreeMem(ppw); + mFreeMem(pw); +end; + +procedure MakeTextTypeList(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 SetSet(Dialog:HWND;num:integer); +var + lclip,lfile,lmess:boolean; +begin + case num of + 0: begin lclip:=true ; lfile:=false; lmess:=false; end; + 1: begin lclip:=false; lfile:=true ; lmess:=false; end; +// 2: begin lclip:=false; lfile:=false; lmess:=true; end; + else + lclip:=false; lfile:=false; lmess:=true; + end; + EnableWindow(GetDlgItem(Dialog,IDC_CLIP_COPYTO),lclip); + EnableWindow(GetDlgItem(Dialog,IDC_CLIP_PASTE ),lclip); + + EnableWindow(GetDlgItem(Dialog,IDC_FILE_READ ),lfile); + EnableWindow(GetDlgItem(Dialog,IDC_FILE_WRITE ),lfile); + EnableWindow(GetDlgItem(Dialog,IDC_FILE_APPEND ),lfile); + EnableWindow(GetDlgItem(Dialog,IDC_FILE_ENC ),lfile); + EnableWindow(GetDlgItem(Dialog,IDC_FILE_FILEBTN),lfile); + EnableEditField(Dialog,IDC_FILE_PATH,lfile); + + EnableWindow(GetDlgItem(Dialog,IDC_TEXT_SEND),lmess); +end; + +procedure ClearFields(Dialog:HWND); +begin + SetDlgItemTextW(Dialog,IDC_FILE_PATH,nil); + SetEditFlags(Dialog,IDC_FILE_PATH,EF_ALL,0); + + CheckDlgButton(Dialog,IDC_FLAG_CLIP ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FLAG_FILE ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FLAG_MESSAGE,BST_UNCHECKED); + + CheckDlgButton(Dialog,IDC_CLIP_COPYTO,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_CLIP_PASTE ,BST_UNCHECKED); + + CheckDlgButton(Dialog,IDC_FILE_READ ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FILE_WRITE ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FILE_APPEND,BST_UNCHECKED); + + CheckDlgButton(Dialog,IDC_TEXT_SEND,BST_UNCHECKED); +end; + +function DlgProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +const + NoProcess:boolean=true; +var + i:integer; +begin + result:=0; + + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + + MakeTextTypeList(GetDlgItem(Dialog,IDC_FILE_ENC)); + + MakeEditField(Dialog,IDC_FILE_PATH); + end; + + WM_ACT_SETVALUE: begin + NoProcess:=true; + ClearFields(Dialog); + + with tInOutAction(lParam) do + begin + if (flags and ACF_CLIPBRD)<>0 then + begin + CheckDlgButton(Dialog,IDC_FLAG_CLIP,BST_CHECKED); + if (flags and ACF_COPYTO)<>0 then + CheckDlgButton(Dialog,IDC_CLIP_COPYTO,BST_CHECKED) + else + CheckDlgButton(Dialog,IDC_CLIP_PASTE,BST_CHECKED); + SetSet(Dialog,0); + end + + else if (flags and ACF_FILE)<>0 then + begin + CheckDlgButton(Dialog,IDC_FLAG_FILE,BST_CHECKED); + + if (flags and ACF_ANSI)<>0 then + i:=0 + else if (flags and ACF_UTF8)<>0 then + begin + if (flags and ACF_SIGN)<>0 then + i:=2 + else + i:=1 + end + else if (flags and ACF_SIGN)<>0 then + i:=4 + else + i:=3; + CB_SelectData(GetDlgItem(Dialog,IDC_FILE_ENC),i); + + if (flags and ACF_FAPPEND)<>0 then CheckDlgButton(Dialog,IDC_FILE_APPEND,BST_CHECKED) + else if (flags and ACF_FWRITE )<>0 then CheckDlgButton(Dialog,IDC_FILE_WRITE ,BST_CHECKED) + else CheckDlgButton(Dialog,IDC_FILE_READ ,BST_CHECKED); + SetDlgItemTextW(Dialog,IDC_FILE_PATH,tfile); + SetEditFlags(Dialog,IDC_FILE_PATH,EF_SCRIPT,ord((flags and ACF_FILE_PATH)<>0)); + + SetSet(Dialog,1); + end + else + begin + CheckDlgButton(Dialog,IDC_FLAG_MESSAGE,BST_CHECKED); + + if (flags and ACF_TEXTSEND)<>0 then CheckDlgButton(Dialog,IDC_TEXT_SEND,BST_CHECKED); + + SetSet(Dialog,2); + end; + end; + NoProcess:=false; + end; + + WM_ACT_RESET: begin + NoProcess:=true; + ClearFields(Dialog); + + CheckDlgButton(Dialog,IDC_FLAG_CLIP,BST_CHECKED); + CheckDlgButton(Dialog,IDC_CLIP_COPYTO,BST_CHECKED); + CheckDlgButton(Dialog,IDC_FILE_READ,BST_CHECKED); + SetSet(Dialog,0); // clipboard + NoProcess:=false; + end; + + WM_ACT_SAVE: begin + with tInOutAction(lParam) do + begin +// flags:=0; + // Clipboard + if IsDlgButtonChecked(Dialog,IDC_FLAG_CLIP)<>BST_UNCHECKED then + begin + flags:=flags or ACF_CLIPBRD; + if IsDlgButtonChecked(Dialog,IDC_CLIP_COPYTO)<>BST_UNCHECKED then + flags:=flags or ACF_COPYTO; + end + // text file + else if IsDlgButtonChecked(Dialog,IDC_FLAG_FILE)<>BST_UNCHECKED then + begin + flags:=flags or ACF_FILE; + case CB_GetData(GetDlgItem(Dialog,IDC_FILE_ENC)) of + 0: flags:=flags or ACF_ANSI; + 1: flags:=flags or ACF_UTF8; + 2: flags:=flags or ACF_UTF8 or ACF_SIGN; + 3: flags:=flags or 0; + 4: flags:=flags or ACF_SIGN; + end; + + tfile:=GetDlgText(Dialog,IDC_FILE_PATH); + if (GetEditFlags(Dialog,IDC_FILE_PATH) and EF_SCRIPT)<>0 then flags:=flags or ACF_FILE_PATH; + + if IsDlgButtonChecked(Dialog,IDC_FILE_APPEND)<>BST_UNCHECKED then + flags:=flags or ACF_FAPPEND + else if IsDlgButtonChecked(Dialog,IDC_FILE_WRITE)<>BST_UNCHECKED then + flags:=flags or ACF_FWRITE; + end + // Message + else + begin + if IsDlgButtonChecked(Dialog,IDC_TEXT_SEND)<>BST_UNCHECKED then + flags:=flags or ACF_TEXTSEND; + end; + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of + CBN_SELCHANGE, + EN_CHANGE: if not NoProcess then + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + + BN_CLICKED: begin + case loword(wParam) of + IDC_FLAG_CLIP: begin + SetSet(Dialog,0); + end; + IDC_FLAG_FILE: begin + SetSet(Dialog,1); + end; + IDC_FLAG_MESSAGE: begin + SetSet(Dialog,2); + end; + IDC_FILE_FILEBTN: begin + FillFileName(Dialog,IDC_FILE_PATH); + end; + end; + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + end; + end; + + WM_HELP: begin + result:=1; + end; + + end; +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=tInOutAction.Create(vc.Hash); +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,'IDD_INOUT',parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :='In/Out'; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :='IDI_INOUT'; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_inout.rc b/plugins/Actman30/iac_inout.rc new file mode 100644 index 0000000000..ca61e5f492 --- /dev/null +++ b/plugins/Actman30/iac_inout.rc @@ -0,0 +1,30 @@ +#include "i_cnst_inout.inc" + +LANGUAGE 0,0 + +IDD_INOUT DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + AUTORADIOBUTTON "Clipboard" , IDC_FLAG_CLIP , 1, 2, 166, 11, WS_GROUP + AUTORADIOBUTTON "File" , IDC_FLAG_FILE , 1, 52, 166, 11 + AUTORADIOBUTTON "Message window", IDC_FLAG_MESSAGE, 1, 118, 166, 11 + + GROUPBOX "" , -1 , 1, 11, 166, 33 + AUTORADIOBUTTON "Copy to" , IDC_CLIP_COPYTO, 6, 18, 158, 11, WS_GROUP + AUTORADIOBUTTON "Paste from", IDC_CLIP_PASTE , 6, 29, 158, 11 + + GROUPBOX "" , -1 , 1, 61, 166, 52 + AUTORADIOBUTTON "Read" , IDC_FILE_READ , 4, 69, 52, 11, WS_GROUP + AUTORADIOBUTTON "Write" , IDC_FILE_WRITE , 57, 69, 52, 11 + AUTORADIOBUTTON "Append" , IDC_FILE_APPEND , 110, 69, 52, 11 + EDITTEXT IDC_FILE_PATH , 4, 82, 140, 12, ES_AUTOHSCROLL + PUSHBUTTON "..." , IDC_FILE_FILEBTN, 147, 82, 16, 12 + COMBOBOX IDC_FILE_ENC , 4, 97, 160, 76, CBS_DROPDOWNLIST | WS_VSCROLL + + GROUPBOX "" , -1 , 1, 127, 166, 22 + AUTOCHECKBOX "Autosend" , IDC_TEXT_SEND, 6, 135, 158, 11 +} + +IDI_INOUT ICON "ico\insert.ico" diff --git a/plugins/Actman30/iac_jump.pas b/plugins/Actman30/iac_jump.pas new file mode 100644 index 0000000000..9a54d7181b --- /dev/null +++ b/plugins/Actman30/iac_jump.pas @@ -0,0 +1,699 @@ +unit iac_jump; + +interface + +implementation + +uses + windows, messages, commctrl, + m_api, dbsettings, + global,iac_global, editwrapper, dlgshare, + common, mirutils, wrapper; + +{$include i_cnst_jump.inc} +{$resource iac_jump.res} + +const // condition code + aeGT = 1; + aeLT = 2; + aeEQ = 3; + aeXR = 4; + aeND = 5; + + aeEMP = 1; + aeEQU = 2; + aeCON = 3; + aeSTR = 4; + aeEND = 5; +const + opt_value = 'value'; + opt_condition = 'condition'; + opt_label = 'label'; +const + ioIf = 'IF'; + ioCond = 'cond'; + ioNop = 'nop'; + ioNot = 'not'; + ioValue = 'value'; + ioOper = 'oper'; + ioAction = 'action'; + ioLabel = 'label'; + ioBreak = 'break'; + ioJump = 'jump'; + ioPost = 'POST'; + ioCase = 'case'; + ioBack = 'back'; +const + ACF_NOP = $00000001; + ACF_MATH = $00000002; + ACF_NOT = $00000004; + ACF_CASE = $00000008; + ACF_BREAK = $00000010; + ACF_BACK = $00000020; + ACF_VALUE = $00000100; + +type + tJumpAction = class(tBaseAction) + private + value :pWideChar; + actlabel :pWideChar; + condition:integer; + 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 ----- + +//----- Object realization ----- + +constructor tJumpAction.Create(uid:dword); +begin + inherited Create(uid); + + condition:=0; + value :=nil; + actlabel :=nil; +end; + +destructor tJumpAction.Destroy; +begin + mFreeMem(value); + mFreeMem(actlabel); + + inherited Destroy; +end; +{ +function tJumpAction.Clone:tBaseAction; +begin + result:=tJumpAction.Create(0); + Duplicate(result); + + result.condition:=condition; + StrDupW(result.value,value); + StrDupW(result.actlabel,actlabel); +end; +} +function tJumpAction.DoAction(var WorkData:tWorkData):LRESULT; +var + tmpint:int64; + vnum:int_ptr; + vstr,vlast:pWideChar; + buf:array [0..31] of WideChar; + res:boolean; + vlr,vval:pWideChar; + tmp:pWideChar; + delta:integer; + lptr:pBaseAction; +begin + result:=0; + + // Condition + if (flags and ACF_NOP)=0 then + begin + // preparing value + if WorkData.ResultType=rtInt then + vlast:=IntToStr(buf,WorkData.LastResult) + else + vlast:=pWideChar(WorkData.LastResult); + + if (flags and ACF_VALUE)<>0 then + begin + vstr:=ParseVarString(value,WorkData.Parameter,vlast); + end + else + vstr:=value; + + res:=false; + // now comparing + if (flags and ACF_MATH)<>0 then + begin + vnum:=int_ptr(GetResultNumber(WorkData)); + tmpint:=NumToInt(vstr); + case condition of + aeGT: res:=vnum>tmpint; + aeLT: res:=vnum0; + aeND: res:=(vnum and tmpint)<>0; + end; + + end + else + begin + if (condition=aeEMP) and ((vlast=nil) or (vlast[0]=#0)) then + res:=true + else + begin + if (flags and ACF_CASE)=0 then + begin + StrDupW(vlr,vlast); + StrDupW(vval,vstr); + CharUpperW(vlr); + CharUpperW(vval); + end + else + begin + vlr :=vlast; + vval:=vstr; + end; + + if (flags and ACF_BACK)<>0 then + begin + tmp:=vlr; + vlr:=vval; + vval:=tmp; + end; + + case condition of + aeEQU: res:=StrCmpW(vlr,vval)=0; + aeCON: res:=StrPosW(vlr,vval)<>nil; + aeSTR: res:=StrPosW(vlr,vval)=vlr; + aeEND: begin + delta:=StrLenW(vval)-StrLenW(vlr); + if delta>=0 then + res:=StrCmpW(vlr,vval+delta)=0; + end; + end; + + if (vlr<>vlast) and (vlr<>vstr) then + begin + mFreeMem(vlr); + mFreeMem(vval); + end; + end; + end; + + if (flags and ACF_NOT)<>0 then + res:=not res; + + if (flags and ACF_VALUE)<>0 then + mFreeMem(vstr); + end + else + res:=true; + + // Operation + if res then + if (flags and ACF_BREAK)<>0 then + result:=-1 + else + begin + lptr:=pBaseAction(WorkData.ActionList); + for delta:=0 to WorkData.ActionCount-1 do + begin + if StrCmpW(actlabel,lptr^.ActionDescr)=0 then + begin + result:=delta+1; + break; + end; + inc(lptr); + end; + end; +end; + +procedure tJumpAction.Load(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; + tmp:pWideChar; + sub:HXML; +begin + inherited Load(node,fmt); + case fmt of + 0: begin + pc:=StrCopyE(section,pAnsiChar(node)); + if (flags and ACF_NOP)=0 then + begin + StrCopy(pc,opt_value ); value :=DBReadUnicode(0,DBBranch,section,nil); + StrCopy(pc,opt_condition); condition:=DBReadByte (0,DBBranch,section,0); + end; + if (flags and ACF_BREAK)=0 then + begin + StrCopy(pc,opt_label); actlabel:=DBReadUnicode(0,DBBranch,section,nil); + end; + end; + + 1: begin + with xmlparser do + begin + sub:=getNthChild(HXML(node),ioIf,0); + if sub<>0 then + begin + tmp:=getAttrValue(sub,ioOper); + if lstrcmpiw(tmp,'math')=0 then flags:=flags or ACF_MATH + else if lstrcmpiw(tmp,ioNop )=0 then flags:=flags or ACF_NOP; + + tmp:=getAttrValue(sub,ioCond); + if lstrcmpiw(tmp,ioNop)=0 then flags:=flags or ACF_NOP // compatibility + else if (flags and ACF_NOP)=0 then + begin + if flags and ACF_MATH<>0 then + begin + if lstrcmpiw(tmp,'gt' )=0 then condition:=aeGT + else if lstrcmpiw(tmp,'lt' )=0 then condition:=aeLT + else if lstrcmpiw(tmp,'eq' )=0 then condition:=aeEQ + else if lstrcmpiw(tmp,'xor')=0 then condition:=aeXR + else if lstrcmpiw(tmp,'and')=0 then condition:=aeND; + end + else + begin + if lstrcmpiw(tmp,'empty')=0 then condition:=aeEMP + else if lstrcmpiw(tmp,'eq' )=0 then condition:=aeEQU + else if lstrcmpiw(tmp,'cont' )=0 then condition:=aeCON + else if lstrcmpiw(tmp,'start')=0 then condition:=aeSTR + else if lstrcmpiw(tmp,'ends' )=0 then condition:=aeEND; + + if StrToInt(getAttrValue(sub,ioCase))=1 then + flags:=flags or ACF_CASE; + if StrToInt(getAttrValue(sub,ioBack))=1 then + flags:=flags or ACF_BACK; + end; + if StrToInt(getAttrValue(sub,ioNot))=1 then + flags:=flags or ACF_NOT; + + if ((flags and ACF_MATH)<>0) or (condition<>aeEMP) then + StrDupW(value,getAttrValue(sub,ioValue)); + end; + end; + + sub:=getNthChild(HXML(node),ioPost,0); + if sub<>0 then + begin + tmp:=getAttrValue(sub,ioOper); + if lstrcmpiw(tmp,ioBreak)=0 then flags:=flags or ACF_BREAK + else if lstrcmpiw(tmp,ioJump )=0 then StrDupW(actlabel,getAttrValue(sub,ioValue)); + end; + end; + end; +{ + 2: begin + pc:=GetParamSectionStr(node,ioOper); + if lstrcmpi(pc,'math')=0 then flags:=flags or ACF_MATH + else if lstrcmpi(pc,ioNop )=0 then flags:=flags or ACF_NOP; + + pc:=GetParamSectionStr(node,ioCond); + if lstrcmpi(pc,ioNop)=0 then flags:=flags or ACF_NOP // compatibility + else if (flags and ACF_NOP)=0 then + begin + if flags and ACF_MATH<>0 then + begin + if lstrcmpi(pc,'gt' )=0 then condition:=aeGT + else if lstrcmpi(pc,'lt' )=0 then condition:=aeLT + else if lstrcmpi(pc,'eq' )=0 then condition:=aeEQ + else if lstrcmpi(pc,'xor')=0 then condition:=aeXR + else if lstrcmpi(pc,'and')=0 then condition:=aeND; + end + else + begin + if lstrcmpi(pc,'empty')=0 then condition:=aeEMP + else if lstrcmpi(pc,'eq' )=0 then condition:=aeEQU + else if lstrcmpi(pc,'cont' )=0 then condition:=aeCON + else if lstrcmpi(pc,'start')=0 then condition:=aeSTR + else if lstrcmpi(pc,'ends' )=0 then condition:=aeEND; + + if GetParamSectionInt(node,ioCase)=1 then + flags:=flags or ACF_CASE; + if GetParamSectionInt(node,ioBack)=1 then + flags:=flags or ACF_BACK; + end; + if GetParamSectionInt(node,ioNot)=1 then + flags:=flags or ACF_NOT; + + if ((flags and ACF_MATH)<>0) or (condition<>aeEMP) then + UTF8ToWide(GetParamSectionStr(node,ioValue),value); + end; + + pc:=GetParamSectionStr(node,ioAction); + if lstrcmpi(pc,ioBreak)=0 then flags:=flags or ACF_BREAK + else if lstrcmpi(pc,ioJump )=0 then UTF8ToWide(GetParamSectionStr(node,ioLabel),actlabel); + end; +} + end; +end; + +procedure tJumpAction.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)); + if (flags and ACF_NOP)=0 then + begin + StrCopy(pc,opt_value ); DBWriteUnicode(0,DBBranch,section,value); + StrCopy(pc,opt_condition); DBWriteByte (0,DBBranch,section,condition); + end; + if (flags and ACF_BREAK)=0 then + begin + StrCopy(pc,opt_label); DBWriteUnicode(0,DBBranch,section,actlabel); + end; + end; +{ + 1: begin + end; +} + end; +end; + +//----- Dialog realization ----- + +procedure FillMathList(Dialog:HWND); +var + wnd:HWND; +begin + wnd:=GetDlgItem(Dialog,IDC_JMP_MATH); + + SendMessage(wnd,CB_RESETCONTENT,0,0); + + InsertString(wnd,cardinal(aeGT),'> greater'); + InsertString(wnd,cardinal(aeLT),'> lesser'); + InsertString(wnd,cardinal(aeEQ),'= equ'); + InsertString(wnd,cardinal(aeXR),'^ xor'); + InsertString(wnd,cardinal(aeND),'& and'); + + SendMessage(wnd,CB_SETCURSEL,0,0); +end; + +procedure FillTextList(Dialog:HWND); +var + wnd:HWND; +begin + wnd:=GetDlgItem(Dialog,IDC_JMP_TEXT); + + SendMessage(wnd,CB_RESETCONTENT,0,0); + + InsertString(wnd,cardinal(aeEMP),'empty'); + InsertString(wnd,cardinal(aeEQU),'= equ'); + InsertString(wnd,cardinal(aeCON),'contains'); + InsertString(wnd,cardinal(aeSTR),'starts with'); + InsertString(wnd,cardinal(aeEND),'ends with'); + + SendMessage(wnd,CB_SETCURSEL,0,0); +end; + +procedure FillActionList(Dialog:HWND); +var + list,wnd:HWND; + i,act:integer; + arr:array [0..127] of WideChar; + li:LV_ITEMW; +begin + wnd:=GetDlgItem(Dialog,IDC_JMP_ACTLIST); + + SendMessage(wnd,CB_RESETCONTENT,0,0); + + list:=ActionListWindow; + act:=SendMessageW(list,LVM_GETITEMCOUNT,0,0); + i:=0; + li.mask :=LVIF_TEXT; + li.iSubItem :=0; + li.pszText :=@arr; + li.cchTextMax:=SizeOf(arr) div SizeOf(WideChar); + while iBST_UNCHECKED then + begin + bmath:=false; + btext:=false; + end + else if IsDlgButtonChecked(Dialog,IDC_FLAG_MATH)<>BST_UNCHECKED then + begin + bmath:=true; + btext:=false; + end + else + begin + bmath:=false; + btext:=true; + end; + EnableWindow(GetDlgItem(Dialog,IDC_JMP_MATH ),bmath); + EnableWindow(GetDlgItem(Dialog,IDC_JMP_TEXT ),btext); + EnableWindow(GetDlgItem(Dialog,IDC_FLAG_CASE),btext); + EnableWindow(GetDlgItem(Dialog,IDC_FLAG_BACK),btext); + EnableWindow(GetDlgItem(Dialog,IDC_FLAG_NOT ),bmath or btext); + EnableEditField(GetDlgItem(Dialog,IDC_JMP_VALUE),bmath or btext); + if btext then + begin + btext:=CB_GetData(GetDlgItem(Dialog,IDC_JMP_TEXT))<>aeEMP; + EnableWindow (GetDlgItem(Dialog,IDC_FLAG_CASE),btext); + EnableWindow (GetDlgItem(Dialog,IDC_FLAG_BACK),btext); + EnableEditField(GetDlgItem(Dialog,IDC_JMP_VALUE),btext); + end; +end; + +procedure ClearFields(Dialog:HWND); +begin + EnableWindow(GetDlgItem(Dialog,IDC_JMP_MATH ),true); + EnableWindow(GetDlgItem(Dialog,IDC_JMP_TEXT ),true); + EnableWindow(GetDlgItem(Dialog,IDC_FLAG_NOT ),true); + EnableWindow(GetDlgItem(Dialog,IDC_FLAG_CASE),true); + EnableEditField(GetDlgItem(Dialog,IDC_JMP_VALUE),true); + SetDlgItemTextW(Dialog,IDC_JMP_VALUE,nil); + SetEditFlags(Dialog,IDC_JMP_VALUE,EF_ALL,0); + + CheckDlgButton(Dialog,IDC_FLAG_NOP ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FLAG_MATH ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FLAG_TEXT ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FLAG_NOT ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FLAG_CASE ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FLAG_BACK ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FLAG_BREAK,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FLAG_JUMP ,BST_UNCHECKED); +end; + +function DlgProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +const + NoProcess:boolean=true; +var + bb:boolean; + wnd:HWND; + tmp:dword; +begin + result:=0; + + case hMessage of + WM_INITDIALOG: begin + FillMathList(Dialog); + FillTextList(Dialog); + + TranslateDialogDefault(Dialog); + + MakeEditField(Dialog,IDC_JMP_VALUE); + end; + + WM_ACT_SETVALUE: begin + NoProcess:=true; + ClearFields(Dialog); + with tJumpAction(lParam) do + begin + FillActionList(Dialog); +// SendDlgItemMessage(Dialog,IDC_JMP_ACTLIST,CB_SETCURSEL,0,0); + // Condition + if (flags and ACF_NOP)<>0 then + begin + CheckDlgButton(Dialog,IDC_FLAG_NOP,BST_CHECKED); + end + else + begin + if (flags and ACF_NOT)<>0 then + CheckDlgButton(Dialog,IDC_FLAG_NOT,BST_CHECKED); + SetDlgItemTextW(Dialog,IDC_JMP_VALUE,value); + SetEditFlags(Dialog,IDC_JMP_VALUE,EF_SCRIPT,ord((flags and ACF_VALUE)<>0)); + + // Math + if (flags and ACF_MATH)<>0 then + begin + CheckDlgButton(Dialog,IDC_FLAG_MATH,BST_CHECKED); + CB_SelectData(Dialog,IDC_JMP_MATH,condition); + end + // Text + else + begin + if (flags and ACF_CASE)<>0 then + CheckDlgButton(Dialog,IDC_FLAG_CASE,BST_CHECKED); + if (flags and ACF_BACK)<>0 then + CheckDlgButton(Dialog,IDC_FLAG_BACK,BST_CHECKED); + CheckDlgButton(Dialog,IDC_FLAG_TEXT,BST_CHECKED); + CB_SelectData(Dialog,IDC_JMP_TEXT,condition); + end; + end; + SetFields(Dialog); + + //Operation + if (flags and ACF_BREAK)<>0 then + begin + CheckDlgButton(Dialog,IDC_FLAG_BREAK,BST_CHECKED); + EnableWindow(GetDlgItem(Dialog,IDC_JMP_ACTLIST),false); + end + else + begin + CheckDlgButton(Dialog,IDC_FLAG_JUMP,BST_CHECKED); + EnableWindow(GetDlgItem(Dialog,IDC_JMP_ACTLIST),true); + SendDlgItemMessageW(Dialog,IDC_JMP_ACTLIST,CB_SELECTSTRING, + twparam(-1),tlparam(actlabel)); + end; + + end; + NoProcess:=false; + end; + + WM_ACT_RESET: begin + NoProcess:=true; + ClearFields(Dialog); + + CheckDlgButton(Dialog,IDC_FLAG_BREAK,BST_CHECKED); + CheckDlgButton(Dialog,IDC_FLAG_NOP ,BST_CHECKED); + SetFields(Dialog); + CB_SelectData(GetDlgItem(Dialog,IDC_JMP_MATH),aeEQ); + CB_SelectData(GetDlgItem(Dialog,IDC_JMP_TEXT),aeEQU); + EnableWindow(GetDlgItem(Dialog,IDC_JMP_ACTLIST),false); + NoProcess:=false; + end; + + WM_ACT_SAVE: begin + with tJumpAction(lParam) do + begin + // Condition + if IsDlgButtonChecked(Dialog,IDC_FLAG_NOP)<>BST_UNCHECKED then + flags:=flags or ACF_NOP + else + begin + if IsDlgButtonChecked(Dialog,IDC_FLAG_NOT)<>BST_UNCHECKED then + flags:=flags or ACF_NOT; + + value:=GetDlgText(Dialog,IDC_JMP_VALUE); + if (GetEditFlags(Dialog,IDC_JMP_VALUE) and EF_SCRIPT)<>0 then + flags:=flags or ACF_VALUE; + + // math + if IsDlgButtonChecked(Dialog,IDC_FLAG_MATH)<>BST_UNCHECKED then + begin + flags:=flags or ACF_MATH; + condition:=CB_GetData(GetDlgItem(Dialog,IDC_JMP_MATH)); + end + // text + else + begin + condition:=CB_GetData(GetDlgItem(Dialog,IDC_JMP_TEXT)); + if condition<>aeEMP then + begin + if IsDlgButtonChecked(Dialog,IDC_FLAG_CASE)<>BST_UNCHECKED then + flags:=flags or ACF_CASE; + + if IsDlgButtonChecked(Dialog,IDC_FLAG_BACK)<>BST_UNCHECKED then + flags:=flags or ACF_BACK; + end; + end; + end; + + // Operation + if IsDlgButtonChecked(Dialog,IDC_FLAG_BREAK)<>BST_UNCHECKED then + flags:=flags or ACF_BREAK + else + begin + actlabel:=GetDlgText(Dialog,IDC_JMP_ACTLIST); + end; + + end; + end; + + WM_ACT_LISTCHANGE: begin + if wParam=2 then + begin + wnd:=GetDlgItem(Dialog,IDC_JMP_ACTLIST); + tmp:=CB_GetData(wnd); + FillActionList(Dialog); + CB_SelectData(wnd,tmp); + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of + EN_CHANGE: if not NoProcess then + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + + CBN_SELCHANGE: begin + case loword(wParam) of + IDC_JMP_TEXT: begin + bb:=CB_GetData(lParam)<>aeEMP; + EnableWindow (GetDlgItem(Dialog,IDC_FLAG_CASE),bb); + EnableWindow (GetDlgItem(Dialog,IDC_FLAG_BACK),bb); + EnableEditField(GetDlgItem(Dialog,IDC_JMP_VALUE),bb); + end; + end; + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + + BN_CLICKED: begin + case loword(wParam) of + IDC_FLAG_NOP, + IDC_FLAG_MATH, + IDC_FLAG_TEXT: SetFields(Dialog); + IDC_FLAG_BREAK: begin + EnableWindow(GetDlgItem(Dialog,IDC_JMP_ACTLIST),false); + end; + IDC_FLAG_JUMP: begin + EnableWindow(GetDlgItem(Dialog,IDC_JMP_ACTLIST),true); + end; + end; + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + end; + end; + + WM_HELP: begin + result:=1; + end; + + end; +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=tJumpAction.Create(vc.Hash); +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,'IDD_ACTJUMP',parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :='Jump'; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :='IDI_JUMP'; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_jump.rc b/plugins/Actman30/iac_jump.rc new file mode 100644 index 0000000000..4731042c38 --- /dev/null +++ b/plugins/Actman30/iac_jump.rc @@ -0,0 +1,32 @@ +#include "i_cnst_jump.inc" + +LANGUAGE 0,0 + +IDD_ACTJUMP DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + GROUPBOX "Condition", -1 , 1, 2, 166, 144 + + AUTORADIOBUTTON "NOP" , IDC_FLAG_NOP , 4, 11, 160, 11, WS_GROUP + AUTORADIOBUTTON "Math" , IDC_FLAG_MATH, 4, 24, 160, 11 + AUTORADIOBUTTON "Text" , IDC_FLAG_TEXT, 4, 53, 160, 11 + + COMBOBOX IDC_JMP_MATH , 12, 37, 152, 96, CBS_DROPDOWNLIST | WS_VSCROLL | CBS_AUTOHSCROLL + + AUTOCHECKBOX "Case sensitive", IDC_FLAG_CASE, 4, 66, 160, 11 + AUTOCHECKBOX "Opposite order", IDC_FLAG_BACK, 4, 78, 160, 11 + COMBOBOX IDC_JMP_TEXT , 12, 92, 152, 96, CBS_DROPDOWNLIST | WS_VSCROLL | CBS_AUTOHSCROLL + + AUTOCHECKBOX "NOT" , IDC_FLAG_NOT , 4, 118, 32, 11 + RTEXT "Value" , -1 , 86, 118, 78, 11, SS_CENTERIMAGE + EDITTEXT IDC_JMP_VALUE, 4, 132, 160, 11, ES_AUTOHSCROLL + + GROUPBOX "Operation", -1 , 1, 152, 166, 39, WS_GROUP + AUTORADIOBUTTON "BREAK" , IDC_FLAG_BREAK , 4, 161, 62, 12 + AUTORADIOBUTTON "JUMP" , IDC_FLAG_JUMP , 4, 174, 62, 12 + COMBOBOX IDC_JMP_ACTLIST, 66, 174, 99, 96, CBS_DROPDOWNLIST | WS_VSCROLL | CBS_AUTOHSCROLL +} + +IDI_JUMP ICON "ico\jump.ico" diff --git a/plugins/Actman30/iac_messagebox.pas b/plugins/Actman30/iac_messagebox.pas new file mode 100644 index 0000000000..f782e54e94 --- /dev/null +++ b/plugins/Actman30/iac_messagebox.pas @@ -0,0 +1,386 @@ +unit iac_messagebox; + +interface + +implementation + +uses + editwrapper, + windows, messages, commctrl, + m_api, global, iac_global, + wrapper, mirutils, common, dbsettings; + +{$include i_cnst_message.inc} +{$resource iac_messagebox.res} + +const + ACF_MSG_TTL = $00000001; + ACF_MSG_TXT = $00000002; + +const + opt_msgtitle = 'msgtitle'; + opt_msgtext = 'msgtext'; + opt_boxopts = 'boxopts'; +const + ioTitle = 'title'; + ioText = 'text'; + ioType = 'type'; + ioArgVariable = 'argvariables'; + ioVariables = 'variables'; +type + tMessageAction = class(tBaseAction) + private + msgtitle:pWideChar; + msgtext :pWideChar; + boxopts :uint; + 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; + +//----- Object realization ----- + +constructor tMessageAction.Create(uid:dword); +begin + inherited Create(uid); + + msgtext :=nil; + msgtitle:=nil; + boxopts :=0; +end; + +destructor tMessageAction.Destroy; +begin + mFreeMem(msgtitle); + mFreeMem(msgtext); + + inherited Destroy; +end; +{ +function tMessageAction.Clone:tBaseAction; +begin + result:=tMessageAction.Create(0); + Duplicate(result); + + StrDupW(tMessageAction(result).msgtext ,msgtext); + StrDupW(tMessageAction(result).msgtitle,msgtitle); + tMessageAction(result).boxopts:=boxopts; +end; +} +function tMessageAction.DoAction(var WorkData:tWorkData):LRESULT; +var + i:integer; + buf:array [0..31] of WideChar; + tmpc:pWideChar; // LastResult value + tmpc1,tmpc2:pWideChar; // title/text after LastResult insertion + tmpcv1,tmpcv2:pWideChar; // title/text after Variables processing +begin + result:=0; + + if WorkData.ResultType=rtWide then + tmpc:=pWidechar(WorkData.LastResult) + else + begin + IntToStr(buf,WorkData.LastResult); + tmpc:=@buf; + end; + // LastResult + if StrPosW(msgtitle,'')<>nil then + begin + mGetMem(tmpc1,8192); + StrCopyW(tmpc1,msgtitle); + StrReplaceW(tmpc1,'',tmpc); + end + else + tmpc1:=msgtitle; + if StrPosW(msgtext,'')<>nil then + begin + mGetMem(tmpc2,8192); + StrCopyW(tmpc2,msgtext); + StrReplaceW(tmpc2,'',tmpc); + end + else + tmpc2:=msgtext; + // Variables + if (flags and ACF_MSG_TTL)<>0 then + tmpcv1:=ParseVarString(tmpc1,WorkData.Parameter,tmpc) + else + tmpcv1:=tmpc1; + if (flags and ACF_MSG_TXT)<>0 then + tmpcv2:=ParseVarString(tmpc2,WorkData.Parameter,tmpc) + else + tmpcv2:=tmpc2; + + i:=MessageBoxW(0,tmpcv2,tmpcv1,boxopts); + + // Keep old result just if has single OK button + if (boxopts and $0F)<>MB_OK then + begin + ClearResult(WorkData); + + WorkData.ResultType:=rtInt; + WorkData.LastResult:=i; + end; + + if tmpcv1<>tmpc1 then mFreeMem(tmpcv1); + if tmpcv2<>tmpc2 then mFreeMem(tmpcv2); + if tmpc1 <>msgtitle then mFreeMem(tmpc1); + if tmpc2 <>msgtext then mFreeMem(tmpc2); +end; + +procedure tMessageAction.Load(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc: pAnsiChar; +begin + inherited Load(node,fmt); + case fmt of + 0: begin + pc:=StrCopyE(section,pAnsiChar(node)); + StrCopy(pc,opt_msgtitle); msgtitle:=DBReadUnicode(0,DBBranch,section); + StrCopy(pc,opt_msgtext ); msgtext :=DBReadUnicode(0,DBBranch,section); + StrCopy(pc,opt_boxopts ); boxopts :=DBReadDword (0,DBBranch,section); + end; + + 1: begin + with xmlparser do + begin + StrDupW(msgtitle,getAttrValue(HXML(node),ioTitle)); + StrDupW(msgtext,getText(HXML(node))); + boxopts:=StrToInt(getAttrValue(HXML(node),ioType)); + + if StrToInt(getAttrValue(HXML(node),ioArgVariable))=1 then flags:=flags or ACF_MSG_TXT; + if StrToInt(getAttrValue(HXML(node),ioVariables ))=1 then flags:=flags or ACF_MSG_TTL; + end; + end; +{ + 2: begin + UTF8ToWide(GetParamSectionInt(node,ioTitle),msgtitle); + UTF8ToWide(GetParamSectionInt(node,ioText ),msgtext); + boxopts:=GetParamSectionInt(node,ioType); + + if GetParamSectionInt(node,ioArgVariable)=1 then flags:=flags or ACF_MSG_TXT; + if GetParamSectionInt(node,ioVariables )=1 then flags:=flags or ACF_MSG_TTL; + end; +} + end; +end; + +procedure tMessageAction.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_msgtitle); DBWriteUnicode(0,DBBranch,section,msgtitle); + StrCopy(pc,opt_msgtext ); DBWriteUnicode(0,DBBranch,section,msgtext); + StrCopy(pc,opt_boxopts ); DBWriteDWord (0,DBBranch,section,boxopts); + end; +{ + 1: begin + end; +} + end; +end; + +//----- Dialog realization ----- + +procedure SetMBRadioIcon(Dialog:HWND;h:THANDLE;id:dword;icon:uint_ptr); +begin + SendDlgItemMessage(Dialog,id,BM_SETIMAGE,IMAGE_ICON, + LoadImage(h,MAKEINTRESOURCE(icon),IMAGE_ICON,16,16,0{LR_SHARED})); +// SendDlgItemMessage(Dialog,id,BM_SETIMAGE,IMAGE_ICON,LoadIcon(0,icon)); +end; + +procedure SetMBRadioIcons(Dialog:HWND); +var + h:THANDLE; +begin + h:=LoadLibrary('user32.dll'); +// SetMBRadioIcon(IDC_MSGI_NONE,IDI_); //? + SetMBRadioIcon(Dialog,h,IDC_MSGI_ERROR,103{IDI_HAND}); + SetMBRadioIcon(Dialog,h,IDC_MSGI_QUEST,102{IDI_QUESTION}); + SetMBRadioIcon(Dialog,h,IDC_MSGI_WARN ,101{IDI_EXCLAMATION}); + SetMBRadioIcon(Dialog,h,IDC_MSGI_INFO ,104{IDI_ASTERISK}); + FreeLibrary(h); +end; + +procedure ClearFields(Dialog:HWND); +begin + CheckDlgButton(Dialog,IDC_MSG_RTL ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MSG_RIGHT,BST_UNCHECKED); + + CheckDlgButton(Dialog,IDC_MSGB_OK ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MSGB_OC ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MSGB_ARI,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MSGB_YNC,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MSGB_YN ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MSGB_RC ,BST_UNCHECKED); + + CheckDlgButton(Dialog,IDC_MSGI_NONE ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MSGI_ERROR,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MSGI_QUEST,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MSGI_WARN ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MSGI_INFO ,BST_UNCHECKED); +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_MSG_TITLE); + MakeEditField(Dialog,IDC_MSG_TEXT); + + SetMBRadioIcons(Dialog); + end; + + WM_ACT_SETVALUE: begin + NoProcess:=true; + ClearFields(Dialog); + with tMessageAction(lParam) do + begin + SetDlgItemTextW(Dialog,IDC_MSG_TITLE,msgtitle); + SetDlgItemTextW(Dialog,IDC_MSG_TEXT ,msgtext); + + SetEditFlags(Dialog,IDC_MSG_TITLE,EF_SCRIPT,ord((flags and ACF_MSG_TTL)<>0)); + SetEditFlags(Dialog,IDC_MSG_TEXT ,EF_SCRIPT,ord((flags and ACF_MSG_TXT)<>0)); + + if (boxopts and MB_RTLREADING)<>0 then CheckDlgButton(Dialog,IDC_MSG_RTL ,BST_CHECKED); + if (boxopts and MB_RIGHT )<>0 then CheckDlgButton(Dialog,IDC_MSG_RIGHT,BST_CHECKED); + + case boxopts and $0F of + MB_OKCANCEL : CheckDlgButton(Dialog,IDC_MSGB_OC ,BST_CHECKED); + MB_ABORTRETRYIGNORE : CheckDlgButton(Dialog,IDC_MSGB_ARI,BST_CHECKED); + MB_YESNOCANCEL : CheckDlgButton(Dialog,IDC_MSGB_YNC,BST_CHECKED); + MB_YESNO : CheckDlgButton(Dialog,IDC_MSGB_YN ,BST_CHECKED); + MB_RETRYCANCEL : CheckDlgButton(Dialog,IDC_MSGB_RC ,BST_CHECKED); +// MB_CANCELTRYCONTINUE: + else + CheckDlgButton(Dialog,IDC_MSGB_OK,BST_CHECKED); + end; + case boxopts and $F0 of + MB_ICONERROR : CheckDlgButton(Dialog,IDC_MSGI_ERROR,BST_CHECKED); + MB_ICONQUESTION : CheckDlgButton(Dialog,IDC_MSGI_QUEST,BST_CHECKED); + MB_ICONWARNING : CheckDlgButton(Dialog,IDC_MSGI_WARN ,BST_CHECKED); + MB_ICONINFORMATION: CheckDlgButton(Dialog,IDC_MSGI_INFO ,BST_CHECKED); + else + CheckDlgButton(Dialog,IDC_MSGI_NONE,BST_CHECKED); + end; + end; + NoProcess:=false; + end; + + WM_ACT_RESET: begin + NoProcess:=true; + ClearFields(Dialog); + + SetDlgItemTextW(Dialog,IDC_MSG_TITLE,nil); + SetDlgItemTextW(Dialog,IDC_MSG_TEXT ,nil); + SetEditFlags(Dialog,IDC_MSG_TITLE,EF_ALL,0); + SetEditFlags(Dialog,IDC_MSG_TEXT ,EF_ALL,0); + + CheckDlgButton(Dialog,IDC_MSGB_OK ,BST_CHECKED); + CheckDlgButton(Dialog,IDC_MSGI_NONE,BST_CHECKED); + NoProcess:=false; + end; + + WM_ACT_SAVE: begin + with tMessageAction(lParam) do + begin + {mFreeMem(msgtitle); }msgtitle:=GetDlgText(Dialog,IDC_MSG_TITLE); + {mFreeMem(msgtext ); }msgtext :=GetDlgText(Dialog,IDC_MSG_TEXT); + + if (GetEditFlags(Dialog,IDC_MSG_TITLE) and EF_SCRIPT)<>0 then flags:=flags or ACF_MSG_TTL; + if (GetEditFlags(Dialog,IDC_MSG_TEXT ) and EF_SCRIPT)<>0 then flags:=flags or ACF_MSG_TXT; + + if IsDlgButtonChecked(Dialog,IDC_MSG_RTL )=BST_CHECKED then boxopts:=boxopts or MB_RTLREADING; + if IsDlgButtonChecked(Dialog,IDC_MSG_RIGHT)=BST_CHECKED then boxopts:=boxopts or MB_RIGHT; + + if IsDlgButtonChecked(Dialog,IDC_MSGB_OC )=BST_CHECKED then boxopts:=boxopts or MB_OKCANCEL + else if IsDlgButtonChecked(Dialog,IDC_MSGB_ARI)=BST_CHECKED then boxopts:=boxopts or MB_ABORTRETRYIGNORE + else if IsDlgButtonChecked(Dialog,IDC_MSGB_YNC)=BST_CHECKED then boxopts:=boxopts or MB_YESNOCANCEL + else if IsDlgButtonChecked(Dialog,IDC_MSGB_YN )=BST_CHECKED then boxopts:=boxopts or MB_YESNO + else if IsDlgButtonChecked(Dialog,IDC_MSGB_RC )=BST_CHECKED then boxopts:=boxopts or MB_RETRYCANCEL + else{if IsDlgButtonChecked(Dialog,IDC_MSGB_OK )=BST_CHECKED then}boxopts:=boxopts or MB_OK; + + if IsDlgButtonChecked(Dialog,IDC_MSGI_ERROR)=BST_CHECKED then boxopts:=boxopts or MB_ICONHAND + else if IsDlgButtonChecked(Dialog,IDC_MSGI_QUEST)=BST_CHECKED then boxopts:=boxopts or MB_ICONQUESTION + else if IsDlgButtonChecked(Dialog,IDC_MSGI_WARN )=BST_CHECKED then boxopts:=boxopts or MB_ICONWARNING + else if IsDlgButtonChecked(Dialog,IDC_MSGI_INFO )=BST_CHECKED then boxopts:=boxopts or MB_ICONINFORMATION + ;//else if IsDlgButtonChecked(Dialog,IDC_MSGI_NONE)=BST_CHECKED then ; + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of + EN_CHANGE, + BN_CLICKED: if not NoProcess then + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + end; + + WM_HELP: begin + MessageBoxW(0, + TranslateW( + 'Text replacing'#13#10+ + 'by last result'#13#10#13#10+ + 'Returns:'#13#10+ + '--------'#13#10+ + 'OK'#9'= 1'#13#10+ + 'CANCEL'#9'= 2'#13#10+ + 'ABORT'#9'= 3'#13#10+ + 'RETRY'#9'= 4'#13#10+ + 'IGNORE'#9'= 5'#13#10+ + 'YES'#9'= 6'#13#10+ + 'NO'#9'= 7'#13#10+ + 'CLOSE'#9'= 8'), + TranslateW('MessageBox'),0); + result:=1; + end; + end; +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=tMessageAction.Create(vc.Hash); +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,'IDD_ACTMESSAGEBOX',parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :='MessageBox'; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :='IDI_MESSAGE'; + vc.Hash :=0; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_messagebox.rc b/plugins/Actman30/iac_messagebox.rc new file mode 100644 index 0000000000..0bb2c7eedb --- /dev/null +++ b/plugins/Actman30/iac_messagebox.rc @@ -0,0 +1,36 @@ +#include "i_cnst_message.inc" + +LANGUAGE 0,0 + +IDD_ACTMESSAGEBOX DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + RTEXT "Message title",-1, 2, 0, 164, 11, SS_CENTERIMAGE + EDITTEXT IDC_MSG_TITLE, 1, 12, 165, 12, ES_AUTOHSCROLL +// ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN + RTEXT "Message text" ,-1, 2, 26, 164, 11, SS_CENTERIMAGE + EDITTEXT IDC_MSG_TEXT , 1, 38, 165, 12, ES_AUTOHSCROLL +// ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN + + AUTOCHECKBOX "RTL" , IDC_MSG_RTL , 1, 54, 160, 11 + AUTOCHECKBOX "Right justifed text", IDC_MSG_RIGHT, 1, 67, 160, 11 + + GROUPBOX "Icons" , -1 , 0, 89, 167, 30, WS_GROUP + AUTORADIOBUTTON "Error" , IDC_MSGI_ERROR, 5, 98, 24, 20, BS_ICON + AUTORADIOBUTTON "Question", IDC_MSGI_QUEST, 31, 98, 24, 20, BS_ICON + AUTORADIOBUTTON "Warning" , IDC_MSGI_WARN , 57, 98, 24, 20, BS_ICON + AUTORADIOBUTTON "Info" , IDC_MSGI_INFO , 83, 98, 24, 20, BS_ICON + AUTORADIOBUTTON "None" , IDC_MSGI_NONE , 109, 98, 53, 20//, BS_ICON + + GROUPBOX "Buttons" , -1, 0, 122, 167, 71, WS_GROUP + AUTORADIOBUTTON "OK" , IDC_MSGB_OK , 5, 131, 156, 10 + AUTORADIOBUTTON "OK, Cancel" , IDC_MSGB_OC , 5, 141, 156, 10 + AUTORADIOBUTTON "Abort, Retry, Ignore", IDC_MSGB_ARI, 5, 151, 156, 10 + AUTORADIOBUTTON "Yes, No, Cancel" , IDC_MSGB_YNC, 5, 161, 156, 10 + AUTORADIOBUTTON "Yes, No" , IDC_MSGB_YN , 5, 171, 156, 10 + AUTORADIOBUTTON "Retry, Cancel" , IDC_MSGB_RC , 5, 181, 156, 10 +} + +IDI_MESSAGE ICON "ico\message.ico" diff --git a/plugins/Actman30/iac_program.pas b/plugins/Actman30/iac_program.pas new file mode 100644 index 0000000000..56e494b3d2 --- /dev/null +++ b/plugins/Actman30/iac_program.pas @@ -0,0 +1,491 @@ +unit iac_program; + +interface + +implementation + +uses + editwrapper, + windows, messages, commctrl, + global, iac_global, m_api, wrapper, syswin, + mirutils, 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 + 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 CallService(MS_DB_CONTACT_IS,WorkData.Parameter,0)<>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; +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; + + 1: begin + with xmlparser do + begin + StrDupW(prgname,getText(HXML(node))); + StrDupW(args,getAttrValue(HXML(node),ioArgs)); + if StrToInt(getAttrValue(HXML(node),ioCurrent))=1 then + flags:=flags or ACF_CURPATH; + + if StrToInt(getAttrValue(HXML(node),ioParallel))=1 then + flags:=flags or ACF_PRTHREAD + else + time:=StrToInt(getAttrValue(HXML(node),ioWait)); + + if StrToInt(getAttrValue(HXML(node),ioFileVariable))=1 then + flags:=flags or ACF_PRG_PRG; + + if StrToInt(getAttrValue(HXML(node),ioArgVariable))=1 then + flags:=flags or ACF_PRG_ARG; + + tmp:=getAttrValue(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; + 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; +} + 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; + +procedure FillFileName(Dialog:HWND;idc:integer); +var + pw,ppw:pWideChar; +begin + mGetMem(pw,1024*SizeOf(WideChar)); + ppw:=GetDlgText(Dialog,idc); + if ShowDlgW(pw,ppw) 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 + FillFileName(Dialog,IDC_EDIT_PRGPATH); + 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. diff --git a/plugins/Actman30/iac_program.rc b/plugins/Actman30/iac_program.rc new file mode 100644 index 0000000000..0460c5c9ac --- /dev/null +++ b/plugins/Actman30/iac_program.rc @@ -0,0 +1,31 @@ +#include "i_cnst_program.inc" + +LANGUAGE 0,0 + +IDD_ACTPROGRAM DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + GROUPBOX "Process options" , -1, 1, 4, 166, 46, WS_GROUP + AUTORADIOBUTTON "Parallel" , IDC_FLAG_PARALLEL, 4, 13, 161, 11 + AUTORADIOBUTTON "Continued" , IDC_FLAG_CONTINUE, 4, 24, 161, 11 + EDITTEXT IDC_EDIT_PROCTIME, 4, 36, 31, 11, ES_RIGHT | ES_NUMBER + LTEXT "Process time, ms", -1, 37, 36, 128, 11, SS_CENTERIMAGE + + AUTOCHECKBOX "Current path" , IDC_FLAG_CURPATH, 4, 52, 161, 11 + + GROUPBOX "Window option" , -1, 1, 63, 166, 55, WS_GROUP + AUTORADIOBUTTON "Start normal" , IDC_FLAG_NORMAL , 4, 72, 162, 11 + AUTORADIOBUTTON "Start hidden" , IDC_FLAG_HIDDEN , 4, 83, 162, 11 + AUTORADIOBUTTON "Start minimized", IDC_FLAG_MINIMIZE, 4, 94, 162, 11 + AUTORADIOBUTTON "Start maximized", IDC_FLAG_MAXIMIZE, 4, 105, 162, 11 + + RTEXT "Program path", -1, 1, 135, 160, 8 + EDITTEXT IDC_EDIT_PRGPATH, 1, 144, 148, 12, ES_AUTOHSCROLL + PUSHBUTTON "..." , IDC_PROGRAM , 151, 144, 16, 12 + RTEXT "Program args", -1, 1, 159, 160, 8 + EDITTEXT IDC_EDIT_PRGARGS, 1, 168, 166, 12, ES_AUTOHSCROLL +} + +IDI_PROGRAM ICON "ico\program.ico" diff --git a/plugins/Actman30/iac_service.pas b/plugins/Actman30/iac_service.pas new file mode 100644 index 0000000000..67a565c477 --- /dev/null +++ b/plugins/Actman30/iac_service.pas @@ -0,0 +1,1023 @@ +unit iac_service; + +interface + +implementation + +uses + windows, messages, commctrl, + global, iac_global, + m_api, + sedit,strans,mApiCardM, + mirutils,dbsettings, editwrapper, + syswin,wrapper,common; + +{$include i_cnst_service.inc} +{$resource iac_service.res} + +const + ACF_PARNUM = $00000001; // Param is number + ACF_UNICODE = $00000002; // Param is Unicode string + ACF_CURRENT = $00000004; // Param is ignored, used current user handle + // from current message window + ACF_RESULT = $00000008; // Param is previous action result + ACF_PARAM = $00000010; // Param is Call parameter + ACF_STRUCT = $00000020; + ACF_PARTYPE = ACF_PARNUM or ACF_UNICODE or + ACF_CURRENT or ACF_RESULT or + ACF_PARAM or ACF_STRUCT; + + ACF_RSTRING = $00010000; // Service result is string + ACF_RUNICODE = $00020000; // Service result is Widestring + ACF_RSTRUCT = $00040000; // Service result in structure + ACF_RFREEMEM = $00080000; // Need to free memory + + ACF_SCRIPT_PARAM = $00001000; + ACF_SCRIPT_SERVICE = $00002000; + // dummy + ACF_STRING = 0; + +const + opt_service = 'service'; + opt_flags2 = 'flags2'; + opt_wparam = 'wparam'; + opt_lparam = 'lparam'; +const + ioService = 'service'; + ioType = 'type'; + ioResult = 'result'; + ioCurrent = 'current'; + ioParam = 'param'; + ioStruct = 'struct'; + ioValue = 'value'; + ioNumber = 'number'; + ioUnicode = 'unicode'; + ioVariables = 'variables'; + ioWParam = 'WPARAM'; + ioLParam = 'LPARAM'; + ioOutput = 'OUTPUT'; + ioFree = 'free'; + ioAnsi = 'ansi'; + ioInt = 'int'; + +type + tServiceAction = class(tBaseAction) + private + service:PAnsiChar; + wparam :pWideChar; + lparam :pWideChar; + flags2 :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 ----- + +//----- Object realization ----- + +constructor tServiceAction.Create(uid:dword); +begin + inherited Create(uid); +end; + +procedure ClearParam(flags:dword; var param); +begin + if (flags and (ACF_CURRENT or ACF_RESULT or ACF_PARAM))=0 then + mFreeMem(pointer(param)); +end; + +destructor tServiceAction.Destroy; +begin + mFreeMem(service); + ClearParam(flags ,wparam); + ClearParam(flags2,lparam); + + inherited Destroy; +end; +{ +function tServiceAction.Clone:tBaseAction; +begin + result:=tServiceAction.Create(0); + Duplicate(result); + + tServiceAction(result).flags2 :=flags2; + StrDup(tServiceAction(result).service,service); + + if (flags and (ACF_PARNUM or ACF_RESULT or ACF_PARAM))=0 then + StrDup(pAnsiChar(tServiceAction(result).wparam),pAnsiChar(wparam)) + else if ((flags and ACF_PARNUM)<>0) and ((flags and ACF_SCRIPT_PARAM)<>0) then + StrDup(pAnsiChar(tServiceAction(result).wparam),pAnsiChar(wparam)) + else + tServiceAction(result).wparam:=wparam; + + if (flags2 and (ACF_PARNUM or ACF_RESULT or ACF_PARAM))=0 then + StrDup(pAnsiChar(tServiceAction(result).lparam),pAnsiChar(lparam)) + else if ((flags2 and ACF_PARNUM)<>0) and ((flags and ACF_SCRIPT_PARAM)<>0) then + StrDup(pAnsiChar(tServiceAction(result).lparam),pAnsiChar(lparam)) + else + tServiceAction(result).lparam:=lparam; +end; +} +procedure PreProcess(flags:dword;var l_param:LPARAM;const WorkData:tWorkData); +var + tmp1:pWideChar; +begin + with WorkData do + begin + if (flags and ACF_STRUCT)<>0 then + begin + l_param:=uint_ptr(MakeStructure(pAnsiChar(l_param),Parameter,LastResult,ResultType)) + end + else if (flags and ACF_PARAM)<>0 then + begin + l_param:=Parameter; + end + else if (flags and ACF_RESULT)<>0 then + begin + l_param:=LastResult; + end + else if (flags and ACF_CURRENT)<>0 then + begin + l_param:=WndToContact(WaitFocusedWndChild(GetForegroundwindow){GetFocus}); + end + else + begin + if (flags and ACF_SCRIPT_PARAM)<>0 then + l_param:=uint_ptr(ParseVarString(pWideChar(l_param),Parameter)); + + tmp1:=pWideChar(l_param); + if (flags and ACF_PARNUM)=0 then + begin + if (flags and ACF_UNICODE)=0 then + WideToAnsi(tmp1,pAnsiChar(l_param),MirandaCP) + else + StrDupW(pWideChar(l_param),tmp1); + end + else + l_param:=NumToInt(tmp1); + + if (flags and ACF_SCRIPT_PARAM)<>0 then + mFreeMem(tmp1); + end; + end; +end; + +procedure PostProcess(flags:dword;var l_param:LPARAM; var WorkData:tWorkData); +var + code:integer; + len:integer; + pc:pAnsiChar; +begin + if (flags and ACF_STRUCT)<>0 then + begin + with WorkData do + begin + LastResult:=GetStructureResult(l_param,@code,@len); + case code of +{ + SST_LAST: begin + result:=LastResult; + end; +} + SST_PARAM: begin //?? + LastResult:=Parameter; + ResultType:=rtInt; + end; + SST_BYTE,SST_WORD,SST_DWORD, + SST_QWORD,SST_NATIVE: begin + ResultType:=rtInt; + end; + SST_BARR: begin + StrDup(pAnsiChar(pc),pAnsiChar(LastResult),len); + AnsiToWide(pAnsiChar(pc),PWideChar(LastResult),MirandaCP); + mFreeMem(pAnsiChar(pc)); + ResultType:=rtWide; + end; + SST_WARR: begin + StrDupW(pWideChar(LastResult),pWideChar(LastResult),len); + ResultType:=rtWide; + end; + SST_BPTR: begin + AnsiToWide(pAnsiChar(LastResult),pWideChar(LastResult),MirandaCP); + ResultType:=rtWide; + end; + SST_WPTR: begin + StrDupW(pWideChar(LastResult),pWideChar(LastResult)); + ResultType:=rtWide; + end; + end; + FreeStructure(l_param); + l_param:=0; + end + end; +end; + +function tServiceAction.DoAction(var WorkData:tWorkData):LRESULT; +var + buf:array [0..255] of AnsiChar; + lservice:pAnsiChar; + lwparam,llparam:TLPARAM; + res:int_ptr; +begin + result:=0; + + lservice:=service; + lwparam :=TLPARAM(wparam); + llparam :=TLPARAM(lparam); + // Service name processing + if (flags and ACF_SCRIPT_SERVICE)<>0 then + lservice:=ParseVarString(lservice,WorkData.Parameter); + + StrCopy(buf,lservice); + if StrPos(lservice,protostr)<>nil then + if CallService(MS_DB_CONTACT_IS,WorkData.Parameter,0)=0 then + begin + if (flags and ACF_SCRIPT_SERVICE)<>0 then + mFreeMem(lservice); + exit; + end + else + StrReplace(buf,protostr,GetContactProtoAcc(WorkData.Parameter)); + + if ServiceExists(buf)<>0 then + begin + + PreProcess(flags ,lwparam,WorkData); + PreProcess(flags2,llparam,WorkData); + + res:=CallServiceSync(buf,lwparam,llparam); + ClearResult(WorkData); + + // result type processing + if (flags and ACF_RSTRING)<>0 then + begin +//!! delete old or not? + if (flags and ACF_RUNICODE)=0 then + AnsiToWide(pAnsiChar(res),pWideChar(WorkData.LastResult),MirandaCP) + else + StrDupW(pWideChar(WorkData.LastResult),pWideChar(res)); + WorkData.ResultType:=rtWide; + + if (flags and ACF_RFREEMEM)<>0 then + mFreeMem(pAnsiChar(res)); //?? Miranda MM?? + end + else if (flags and ACF_RSTRUCT)=0 then + WorkData.ResultType:=rtInt + else if (flags and ACF_RSTRUCT)<>0 then + begin + PostProcess(flags ,lwparam,WorkData); + PostProcess(flags2,llparam,WorkData); + end; + + // free string (ansi+unicode) parameters + if ((flags and ACF_PARTYPE)=ACF_STRING) or + ((flags and ACF_PARTYPE)=ACF_UNICODE) then + mFreeMem(pointer(lwparam)); + if ((flags2 and ACF_PARTYPE)=ACF_STRING) or + ((flags2 and ACF_PARTYPE)=ACF_UNICODE) then + mFreeMem(pointer(llparam)); + end; + if (flags and ACF_SCRIPT_SERVICE)<>0 then + mFreeMem(lservice); +end; + +procedure LoadParam(section:PAnsiChar;flags:dword; var param:pointer); +begin + if (flags and (ACF_CURRENT or ACF_RESULT or ACF_PARAM))=0 then + begin + if (flags and ACF_STRUCT)<>0 then + param:=DBReadUTF8(0,DBBranch,section,nil) + else + param:=DBReadUnicode(0,DBBranch,section,nil); + end; +end; + +function ReadParam(act:HXML; var param:pWideChar;isvar:boolean):dword; +var + tmp:pWideChar; +begin + result:=0; + if act=0 then + exit; + with xmlparser do + begin + tmp:=getAttrValue(act,ioType); + if lstrcmpiw(tmp,ioCurrent)=0 then result:=result or ACF_CURRENT + else if lstrcmpiw(tmp,ioResult )=0 then result:=result or ACF_RESULT + else if lstrcmpiw(tmp,ioParam )=0 then result:=result or ACF_PARAM + else if lstrcmpiw(tmp,ioStruct )=0 then + begin + result:=result or ACF_STRUCT; +//!!!! param:=ReadStruct(act); + end + else + begin + StrDupW(pWideChar(param),getAttrValue(act,ioValue)); + + if lstrcmpiw(tmp,ioNumber )=0 then result:=result or ACF_PARNUM + else if lstrcmpiw(tmp,ioUnicode)=0 then result:=result or ACF_UNICODE; +// else if lstrcmpiw(tmp,ioAnsi)=0 then; + end; + end; +end; +{ +function ReadParamINI(node:pointer;prefix:pAnsiChar;var param:pWideChar;isvar:boolean):dword; +var + pc,pc1:pAnsiChar; + buf:array [0..63] of AnsiChar; +begin + result:=0; + pc1:=StrCopyE(buf,prefix); + pc:=GetParamSectionStr(node,StrCopy(pc1,ioType)); + if lstrcmpi(pc,ioCurrent)=0 then result:=result or ACF_CURRENT + else if lstrcmpi(pc,ioResult )=0 then result:=result or ACF_RESULT + else if lstrcmpi(pc,ioParam )=0 then result:=result or ACF_PARAM + else if lstrcmpi(pc,ioStruct )=0 then + begin + result:=result or ACF_STRUCT; +//!!!! param:=ReadStruct(act); + end + else + begin + UTF8ToWide(GetParamSectionInt(node,StrCopy(pc1,ioValue)),param); + + if lstrcmpi(pc,ioNumber )=0 then result:=result or ACF_PARNUM + else if lstrcmpi(pc,ioUnicode)=0 then result:=result or ACF_UNICODE; +// else if lstrcmpi(pc,ioAnsi)=0 then; + end; +end; +} +procedure tServiceAction.Load(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; + sub:HXML; + tmp:pWideChar; +begin + inherited Load(node,fmt); + + case fmt of + 0: begin + pc:=StrCopyE(section,pAnsiChar(node)); + + StrCopy(pc,opt_service); service:=DBReadString(0,DBBranch,section,nil); + StrCopy(pc,opt_flags2 ); flags2 :=DBReadDword (0,DBBranch,section); + + StrCopy(pc,opt_wparam); LoadParam(section,flags ,pointer(wparam)); + StrCopy(pc,opt_lparam); LoadParam(section,flags2,pointer(lparam)); + end; + + 1: begin + with xmlparser do + begin + FastWideToAnsi(getAttrValue(HXML(node),ioService),service); +//!!!! StrDupW(service,getAttrValue(HXML(node),ioService)); + if StrToInt(getAttrValue(HXML(node),ioVariables))=1 then + flags:=flags or ACF_SCRIPT_SERVICE; + + sub:=getNthChild(HXML(node),ioWParam,0); + if StrToInt(getAttrValue(sub,ioVariables))=1 then + flags:=flags or ACF_SCRIPT_PARAM; + flags:=flags or ReadParam(sub,wparam,(flags and ACF_SCRIPT_PARAM)<>0); + + sub:=getNthChild(HXML(node),ioLParam,0); + if StrToInt(getAttrValue(sub,ioVariables))=1 then + flags2:=flags2 or ACF_SCRIPT_PARAM; + flags2:=flags2 or ReadParam(sub,lparam,(flags2 and ACF_SCRIPT_PARAM)<>0); + + sub:=getNthChild(HXML(node),ioOutput,0); + if StrToInt(getAttrValue(sub,ioFree))=1 then flags:=flags or ACF_RFREEMEM; + + tmp:=getAttrValue(sub,ioType); + if lstrcmpiw(tmp,ioUnicode)=0 then flags:=flags or ACF_RUNICODE + else if lstrcmpiw(tmp,ioAnsi )=0 then flags:=flags or ACF_RSTRING + else if lstrcmpiw(tmp,ioStruct )=0 then flags:=flags or ACF_RSTRUCT + else if lstrcmpiw(tmp,ioInt )=0 then ; + end; + end; +{ + 2: begin + StrDup(service,GetParamSectionStr(node,ioService)); +//!!!! UTF8ToWide(GetParamSectionStr(node,ioService),service); + if GetParamSectionInt(node,ioVariables)=1 then + flags:=flags or ACF_SCRIPT_SERVICE; + + if GetParamSectionInt(node,ioWParam+'.'+ioVariables))=1 then + flags:=flags or ACF_SCRIPT_PARAM; + flags:=flags or ReadParamINI(node,ioWParam+'.',wparam,(flags and ACF_SCRIPT_PARAM)<>0); + + if GetParamSectionInt(node,ioLParam+'.'+ioVariables))=1 then + flags2:=flags2 or ACF_SCRIPT_PARAM; + flags2:=flags2 or ReadParamINI(node,ioLParam+'.',lparam,(flags2 and ACF_SCRIPT_PARAM)<>0); + + if GetParamSectionInt(node,ioFree)=1 then flags:=flags or ACF_RFREEMEM; + + pc:=GetParamSectionStr(node,ioType); + if lstrcmpi(pñ,ioUnicode)=0 then flags:=flags or ACF_RUNICODE + else if lstrcmpi(pñ,ioAnsi )=0 then flags:=flags or ACF_RSTRING + else if lstrcmpi(pñ,ioStruct )=0 then flags:=flags or ACF_RSTRUCT +// else if lstrcmpi(pñ,ioInt )=0 then ; + end; +} + end; +end; + +procedure SaveParam(section:PAnsiChar;flags:dword; param:pointer); +begin + if (flags and (ACF_CURRENT or ACF_RESULT or ACF_PARAM))=0 then + begin + if pointer(param)<>nil then + begin + if (flags and ACF_STRUCT)<>0 then + DBWriteUTF8(0,DBBranch,section,param) + else + DBWriteUnicode(0,DBBranch,section,param); + end; + end; +end; + +procedure tServiceAction.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_service); DBWriteString(0,DBBranch,section,service); + StrCopy(pc,opt_flags2 ); DBWriteDWord (0,DBBranch,section,flags2); + + StrCopy(pc,opt_wparam); SaveParam(section,flags ,pointer(wparam)); + StrCopy(pc,opt_lparam); SaveParam(section,flags2,pointer(lparam)); + end; +{ + 1: begin + end; +} + end; +end; + +//----- Dialog realization ----- + +const + ptNumber = 0; + ptString = 1; + ptUnicode = 2; + ptCurrent = 3; + ptResult = 4; + ptParam = 5; + ptStruct = 6; +const + sresInt = 0; + sresString = 1; + sresStruct = 2; + +procedure MakeResultTypeList(wnd:HWND); +begin + SendMessage(wnd,CB_RESETCONTENT,0,0); + InsertString(wnd,sresInt ,'Integer'); + InsertString(wnd,sresString,'String'); + InsertString(wnd,sresStruct,'Structure'); + SendMessage(wnd,CB_SETCURSEL,0,0); +end; + +procedure MakeParamTypeList(wnd:HWND); +begin + SendMessage(wnd,CB_RESETCONTENT,0,0); + InsertString(wnd,ptNumber ,'number value'); + InsertString(wnd,ptString ,'ANSI string'); + InsertString(wnd,ptUnicode,'Unicode string'); + InsertString(wnd,ptCurrent,'current contact'); + InsertString(wnd,ptResult ,'last result'); + InsertString(wnd,ptParam ,'parameter'); + InsertString(wnd,ptStruct ,'structure'); + SendMessage(wnd,CB_SETCURSEL,0,0); +end; + +var + ApiCard:tmApiCard; + +function FixParam(Dialog:HWND;buf:PAnsiChar;flag:integer):integer; +begin + if StrCmp(buf,Translate('hContact' ))=0 then result:=ptCurrent + else if StrCmp(buf,Translate('parameter' ))=0 then result:=ptParam + else if StrCmp(buf,Translate('result' ))=0 then result:=ptResult + else if StrCmp(buf,Translate('structure' ))=0 then result:=ptStruct + else if StrCmp(buf,Translate('Unicode text'))=0 then result:=ptUnicode + else + begin + if (buf[0] in ['0'..'9']) or ((buf[0]='-') and (buf[1] in ['0'..'9'])) or + ((buf[0]='$') and (buf[1] in sHexNum)) or + ((buf[0]='0') and (buf[1]='x') and (buf[2] in sHexNum)) then + result:=ptNumber + else + result:=ptString; + end; + + CB_SelectData(Dialog,flag,result); +// SendDlgItemMessage(Dialog,flag,CB_SETCURSEL,result,0); + SendMessage(Dialog,WM_COMMAND,(CBN_SELCHANGE shl 16) or flag,GetDlgItem(Dialog,flag)); +end; + +procedure ReloadService(Dialog:HWND;setvalue:boolean); +var + pc:pAnsiChar; + buf,buf1:array [0..127] of AnsiChar; + wnd:hwnd; + i:integer; + struct:pAnsiChar; +// bufw:array [0..MaxDescrLen] of WideChar; +begin + wnd:=GetDlgItem(Dialog,IDC_EDIT_SERVICE); + SendMessageA(wnd,CB_GETLBTEXT,SendMessage(wnd,CB_GETCURSEL,0,0),tlparam(@buf)); + ApiCard.Service:=@buf; + + pc:=ApiCard.FillParams(GetDlgItem(Dialog,IDC_EDIT_WPAR),true); + if pc<>nil then + begin + if GetDlgItemTextA(Dialog,IDC_EDIT_WPAR,buf1,SizeOf(buf1))>0 then + case FixParam(Dialog,@buf1,IDC_FLAG_WPAR) of + ptStruct: begin + if setvalue then + begin + struct:=pAnsiChar(SetWindowLongPtrW(GetDlgItem(Dialog,IDC_WSTRUCT),GWLP_USERDATA, + long_ptr(StrDup(struct,StrScan(pc,'|')+1)))); + mFreeMem(struct); + end; + +{ struct:=pAnsiChar(GetWindowLongPtrW(GetDlgItem(Dialog,IDC_WSTRUCT),GWLP_USERDATA)); + mFreeMem(struct); + StrDup(struct,StrScan(pc,'|')+1); + SetWindowLongPtrW(GetDlgItem(Dialog,IDC_WSTRUCT),GWLP_USERDATA,long_ptr(struct)); +// AnsiToWide(StrScan(pc,'|')+1,wstruct,MirandaCP); +} + end; + end; + mFreeMem(pc); + end; + + pc:=ApiCard.FillParams(GetDlgItem(Dialog,IDC_EDIT_LPAR),false); + if pc<>nil then + begin + if GetDlgItemTextA(Dialog,IDC_EDIT_LPAR,buf1,SizeOf(buf1))>0 then + case FixParam(Dialog,@buf1,IDC_FLAG_LPAR) of + ptStruct: begin + if setvalue then + begin + struct:=pAnsiChar(SetWindowLongPtrW(GetDlgItem(Dialog,IDC_LSTRUCT),GWLP_USERDATA, + long_ptr(StrDup(struct,StrScan(pc,'|')+1)))); + mFreeMem(struct); + end; +{ + struct:=pAnsiChar(GetWindowLongPtrW(GetDlgItem(Dialog,IDC_LSTRUCT),GWLP_USERDATA)); + mFreeMem(struct); + StrDup(struct,StrScan(pc,'|')+1); + SetWindowLongPtrW(GetDlgItem(Dialog,IDC_LSTRUCT),GWLP_USERDATA,long_ptr(struct)); +// AnsiToWide(StrScan(pc,'|')+1,lstruct,MirandaCP); +} + end; + end; + mFreeMem(pc); + end; + + pc:=ApiCard.ResultType; + i:=sresInt; + if pc<>nil then + begin + if lstrcmpia(pc,'struct')=0 then i:=sresStruct + else if lstrcmpia(pc,'str')=0 then + begin + i:=sresString; + CheckDlgButton(Dialog,IDC_RES_UNICODE,BST_UNCHECKED); + end + else if lstrcmpia(pc,'wide')=0 then + begin + i:=sresString; + CheckDlgButton(Dialog,IDC_RES_UNICODE,BST_CHECKED); + end; + mFreeMem(pc); + end; + CB_SelectData(Dialog,IDC_SRV_RESULT,i); +// ApiCard.Show; +end; + +// true - need to show structure +function SetParam(Dialog:HWND; aflags:dword; id:integer; aparam:pWideChar):integer; +var + wnd:HWND; +begin + wnd:=GetDlgItem(Dialog,id); + if (aflags and ACF_PARAM)<>0 then + begin + EnableWindow(wnd,false); + result:=ptParam; + end + else if (aflags and ACF_RESULT)<>0 then + begin + EnableWindow(wnd,false); + result:=ptResult; + end + else if (aflags and ACF_CURRENT)<>0 then + begin + EnableWindow(wnd,false); + result:=ptCurrent; + end + else if (aflags and ACF_PARNUM)<>0 then + begin + result:=ptNumber; + SetDlgItemTextW(Dialog,id,aparam); + end + else if (aflags and ACF_STRUCT)<>0 then + begin + result:=ptStruct; + end + else if (aflags and ACF_UNICODE)<>0 then + begin + result:=ptUnicode; + SetDlgItemTextW(Dialog,id,aparam); + end + else + begin + result:=ptString; + SetDlgItemTextW(Dialog,id,aparam); + end; + SetEditFlags(wnd,EF_SCRIPT,ord((aflags and ACF_SCRIPT_PARAM)<>0)); +end; + +procedure ClearFields(Dialog:HWND); +var + wnd:HWND; +begin + ShowWindow(GetDlgItem(Dialog,IDC_WSTRUCT),SW_HIDE); + wnd:=GetDlgItem(Dialog,IDC_EDIT_WPAR); + ShowEditField (wnd,SW_SHOW); + EnableEditField(wnd,true); + SendMessage (wnd,CB_RESETCONTENT,0,0); +//?? SetDlgItemTextW(Dialog,IDC_EDIT_WPAR,nil); + CB_SelectData(GetDlgItem(Dialog,IDC_FLAG_WPAR),ptNumber); + SetEditFlags(wnd,EF_ALL,0); + + ShowWindow (GetDlgItem(Dialog,IDC_LSTRUCT),SW_HIDE); + wnd:=GetDlgItem(Dialog,IDC_EDIT_LPAR); + ShowEditField (wnd,SW_SHOW); + EnableEditField(wnd,true); + SendMessage (wnd,CB_RESETCONTENT,0,0); +//?? SetDlgItemTextW(Dialog,IDC_EDIT_LPAR,nil); + CB_SelectData(GetDlgItem(Dialog,IDC_FLAG_LPAR),ptNumber); + SetEditFlags(wnd,EF_ALL,0); + + ShowWindow(GetDlgItem(Dialog,IDC_RES_FREEMEM),SW_HIDE); + ShowWindow(GetDlgItem(Dialog,IDC_RES_UNICODE),SW_HIDE); + CheckDlgButton(Dialog,IDC_RES_FREEMEM,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_RES_UNICODE,BST_UNCHECKED); + + CB_SelectData(Dialog,IDC_SRV_RESULT,sresInt); +end; + +function DlgProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +const + NoProcess:boolean=true; +var + i:integer; + pc,pc1:pAnsiChar; + wnd,wnd1:HWND; + pcw:PWideChar; +begin + result:=0; + + case hMessage of + WM_DESTROY: begin + ApiCard.Free; + pc:=pAnsiChar(GetWindowLongPtrW(GetDlgItem(Dialog,IDC_WSTRUCT),GWLP_USERDATA)); + mFreeMem(pc); + pc:=pAnsiChar(GetWindowLongPtrW(GetDlgItem(Dialog,IDC_LSTRUCT),GWLP_USERDATA)); + mFreeMem(pc); + end; + + WM_INITDIALOG: begin + MakeResultTypeList(GetDlgItem(Dialog,IDC_SRV_RESULT)); + MakeParamTypeList(GetDlgItem(Dialog,IDC_FLAG_WPAR)); + MakeParamTypeList(GetDlgItem(Dialog,IDC_FLAG_LPAR)); + + TranslateDialogDefault(Dialog); + +//?? + MakeEditField(Dialog,IDC_EDIT_SERVICE); + MakeEditField(Dialog,IDC_EDIT_WPAR); + MakeEditField(Dialog,IDC_EDIT_LPAR); + + ApiCard:=CreateServiceCard(Dialog); + ApiCard.FillList(GetDlgItem(Dialog,IDC_EDIT_SERVICE), + DBReadByte(0,DBBranch,'SrvListMode')); + end; + + WM_ACT_SETVALUE: begin + NoProcess:=true; + ClearFields(Dialog); + + with tServiceAction(lParam) do + begin + if CB_SelectData(Dialog,IDC_EDIT_SERVICE,Hash(service,StrLen(service)))<>CB_ERR then +// if SendDlgItemMessageA(Dialog,IDC_EDIT_SERVICE,CB_SELECTSTRING,twparam(-1),tlparam(service))<>CB_ERR then + ReloadService(Dialog,false) + else + SetDlgItemTextA(Dialog,IDC_EDIT_SERVICE,service); +//!! + SetEditFlags(GetDlgItem(Dialog,IDC_EDIT_SERVICE),EF_SCRIPT, + ord((flags and ACF_SCRIPT_SERVICE)<>0)); + + // RESULT + if (flags and ACF_RSTRUCT)<>0 then + i:=sresStruct + else if (flags and ACF_RSTRING)<>0 then + begin + i:=sresString; + if (flags and ACF_RUNICODE)<>0 then CheckDlgButton(Dialog,IDC_RES_UNICODE,BST_CHECKED); + if (flags and ACF_RFREEMEM)<>0 then CheckDlgButton(Dialog,IDC_RES_FREEMEM,BST_CHECKED); + end + else + begin + i:=sresInt; + end; + CB_SelectData(Dialog,IDC_SRV_RESULT,i); + + // WPARAM + i:=SetParam(Dialog,flags,IDC_EDIT_WPAR,pWideChar(wparam)); + if i=ptStruct then + begin + ShowEditField(GetDlgItem(Dialog,IDC_EDIT_WPAR),SW_HIDE); + ShowWindow (GetDlgItem(Dialog,IDC_WSTRUCT ),SW_SHOW); + +{ + p:=pAnsiChar(GetWindowLongPtrW(GetDlgItem(Dialog,IDC_WSTRUCT),GWLP_USERDATA)); + mFreeMem(p); +} + SetWindowLongPtrW(GetDlgItem(Dialog,IDC_WSTRUCT),GWLP_USERDATA, + long_ptr(StrDup(pc,pAnsiChar(wparam)))); + end; + CB_SelectData(GetDlgItem(Dialog,IDC_FLAG_WPAR),i); + + // LPARAM + i:=SetParam(Dialog,flags2,IDC_EDIT_LPAR,pWideChar(lparam)); + if i=ptStruct then + begin + ShowEditField(GetDlgItem(Dialog,IDC_EDIT_LPAR),SW_HIDE); + ShowWindow (GetDlgItem(Dialog,IDC_LSTRUCT ),SW_SHOW); + +{ + p:=pAnsiChar(GetWindowLongPtrW(GetDlgItem(Dialog,IDC_LSTRUCT),GWLP_USERDATA)); + mFreeMem(p); +} + SetWindowLongPtrW(GetDlgItem(Dialog,IDC_LSTRUCT),GWLP_USERDATA, + long_ptr(StrDup(pc,pAnsiChar(lparam)))); + end; + CB_SelectData(GetDlgItem(Dialog,IDC_FLAG_LPAR),i); + + end; + NoProcess:=false; + end; + + WM_ACT_RESET: begin + NoProcess:=true; + ClearFields(Dialog); + SetDlgItemTextW(Dialog,IDC_EDIT_SERVICE,nil); + SetDlgItemTextW(Dialog,IDC_EDIT_WPAR,'0'); + SetDlgItemTextW(Dialog,IDC_EDIT_LPAR,'0'); +{ + ShowWindow(GetDlgItem(Dialog,IDC_WSTRUCT),SW_HIDE); + ShowWindow(GetDlgItem(Dialog,IDC_LSTRUCT),SW_HIDE); +} + NoProcess:=false; + end; + + WM_ACT_SAVE: begin + with tServiceAction(lParam) do + begin + //WPARAM + wnd:=GetDlgItem(Dialog,IDC_EDIT_WPAR); + case CB_GetData(GetDlgItem(Dialog,IDC_FLAG_WPAR)) of + ptParam: begin + flags:=flags or ACF_PARAM + end; + ptResult: begin + flags:=flags or ACF_RESULT + end; + ptCurrent: begin + flags:=flags or ACF_CURRENT + end; + ptNumber: begin + flags:=flags or ACF_PARNUM; + wparam:=GetDlgText(wnd); + end; + ptStruct: begin + flags:=flags or ACF_STRUCT; + StrDup(pAnsiChar(wparam), + pAnsiChar(GetWindowLongPtrW(GetDlgItem(Dialog,IDC_WSTRUCT),GWLP_USERDATA))); + end; + ptUnicode: begin + flags:=flags or ACF_UNICODE; + wparam:=GetDlgText(wnd); + end; + ptString: wparam:=GetDlgText(wnd); + end; + if (GetEditFlags(wnd) and EF_SCRIPT)<>0 then + flags:=flags or ACF_SCRIPT_PARAM; + + // LPARAM + wnd:=GetDlgItem(Dialog,IDC_EDIT_LPAR); + case CB_GetData(GetDlgItem(Dialog,IDC_FLAG_LPAR)) of + ptParam: begin + flags2:=flags2 or ACF_PARAM + end; + ptResult: begin + flags2:=flags2 or ACF_RESULT + end; + ptCurrent: begin + flags2:=flags2 or ACF_CURRENT + end; + ptNumber: begin + flags2:=flags2 or ACF_PARNUM; + lparam:=GetDlgText(wnd); + end; + ptStruct: begin + flags2:=flags2 or ACF_STRUCT; + StrDup(pAnsiChar(lparam), + pAnsiChar(GetWindowLongPtrW(GetDlgItem(Dialog,IDC_LSTRUCT),GWLP_USERDATA))); + end; + ptUnicode: begin + flags2:=flags2 or ACF_UNICODE; + lparam:=GetDlgText(wnd); + end; + ptString: lparam:=GetDlgText(wnd); + end; + if (GetEditFlags(wnd) and EF_SCRIPT)<>0 then + flags2:=flags2 or ACF_SCRIPT_PARAM; + + // RESULT + case CB_GetData(GetDlgItem(Dialog,IDC_SRV_RESULT)) of + sresString: begin + flags:=flags or ACF_RSTRING; + if IsDlgButtonChecked(Dialog,IDC_RES_UNICODE)=BST_CHECKED then + flags:=flags or ACF_RUNICODE; + if IsDlgButtonChecked(Dialog,IDC_RES_FREEMEM)=BST_CHECKED then + flags:=flags or ACF_RFREEMEM; + end; + sresStruct: flags:=flags or ACF_RSTRUCT; + end; + + service:=ApiCard.NameFromList(GetDlgItem(Dialog,IDC_EDIT_SERVICE)); +//!! + if (GetEditFlags(Dialog,IDC_EDIT_SERVICE) and EF_SCRIPT)<>0 then + flags:=flags or ACF_SCRIPT_SERVICE; + end; + end; + + WM_SHOWWINDOW: begin + // hide window by ShowWindow function + if (lParam=0) and (wParam=0) then + begin + pc:=pAnsiChar(SetWindowLongPtrW(GetDlgItem(Dialog,IDC_WSTRUCT),GWLP_USERDATA,0)); + mFreeMem(pc); + pc:=pAnsiChar(SetWindowLongPtrW(GetDlgItem(Dialog,IDC_LSTRUCT),GWLP_USERDATA,0)); + mFreeMem(pc); + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of +{ CBN_EDITUPDATE, +} + CBN_EDITCHANGE, + EN_CHANGE: if not NoProcess then + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + + CBN_SELCHANGE: begin + case loword(wParam) of + IDC_SRV_RESULT: begin + i:=CB_GetData(lParam); + case i of + sresInt,sresStruct: begin + ShowWindow(GetDlgItem(Dialog,IDC_RES_FREEMEM),SW_HIDE); + ShowWindow(GetDlgItem(Dialog,IDC_RES_UNICODE),SW_HIDE); + end; + sresString: begin + ShowWindow(GetDlgItem(Dialog,IDC_RES_FREEMEM),SW_SHOW); + ShowWindow(GetDlgItem(Dialog,IDC_RES_UNICODE),SW_SHOW); + end; + end; + end; + + IDC_FLAG_WPAR,IDC_FLAG_LPAR: begin + if loword(wParam)=IDC_FLAG_WPAR then + begin + wnd :=GetDlgItem(Dialog,IDC_EDIT_WPAR); + wnd1:=GetDlgItem(Dialog,IDC_WSTRUCT); + end + else + begin + wnd :=GetDlgItem(Dialog,IDC_EDIT_LPAR); + wnd1:=GetDlgItem(Dialog,IDC_LSTRUCT); + end; + i:=CB_GetData(GetDlgItem(Dialog,loword(wParam))); + + if i=ptStruct then + begin + ShowEditField(wnd,SW_HIDE); + ShowWindow(wnd1,SW_SHOW); + end + else + begin + ShowEditField(wnd,SW_SHOW); + ShowWindow(wnd1,SW_HIDE); + if i in [ptCurrent,ptResult,ptParam] then + EnableEditField(wnd,false) + else + begin + if i=ptNumber then + begin + pcw:='0'; + SendMessageW(wnd,WM_SETTEXT,0,TLParam(pcw)); + end; + EnableEditField(wnd,true); + end; + end; + end; + + IDC_EDIT_SERVICE: ReloadService(Dialog,true); + end; + if not NoProcess then + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + + BN_CLICKED: begin + case loword(wParam) of + IDC_WSTRUCT, IDC_LSTRUCT: begin + pc:=pAnsiChar(GetWindowLongPtrW(lParam,GWLP_USERDATA)); +//!!!! + pc1:=EditStructure(pAnsiChar(pc),Dialog); + if pc1<>nil then + begin + mFreeMem(pc); + SetWindowLongPtrW(lParam,GWLP_USERDATA,long_ptr(pc1)); + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + end; + else + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + end; + + end; + end; + + WM_HELP: begin + pc:=ApiCard.NameFromList(GetDlgItem(Dialog,IDC_EDIT_SERVICE)); + ApiCard.Service:=pc; + mFreeMem(pc); + ApiCard.Show; + + result:=1; + end; + + end; +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=tServiceAction.Create(vc.Hash); +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,'IDD_ACTSERVICE',parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :='Service'; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :='IDI_SERVICE'; + vc.Hash :=0; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_service.rc b/plugins/Actman30/iac_service.rc new file mode 100644 index 0000000000..10160c5361 --- /dev/null +++ b/plugins/Actman30/iac_service.rc @@ -0,0 +1,32 @@ +#include "i_cnst_service.inc" + +LANGUAGE 0,0 + +IDD_ACTSERVICE DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + GROUPBOX "Result" , -1, 1, 0, 166, 64, WS_GROUP + RTEXT "Result type" , -1 , 4, 10, 159, 11 + COMBOBOX IDC_SRV_RESULT , 4, 21, 159, 76, CBS_DROPDOWN | WS_VSCROLL | CBS_AUTOHSCROLL + AUTOCHECKBOX "Free memory" , IDC_RES_FREEMEM, 4, 38, 159, 11 + AUTOCHECKBOX "Unicode string", IDC_RES_UNICODE, 4, 50, 159, 11 + + RTEXT "Service name", -1, 1, 68, 160, 8 + COMBOBOX IDC_EDIT_SERVICE , 1, 78, 166, 96, CBS_DROPDOWN | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_SORT + + RTEXT "wParam type", -1, 1, 101, 63, 14, SS_CENTERIMAGE + COMBOBOX IDC_FLAG_WPAR, 66, 101, 102, 56, CBS_DROPDOWNLIST | WS_VSCROLL +// RTEXT "wParam" , -1, 1, 116, 160, 8 + COMBOBOX IDC_EDIT_WPAR, 1, 116, 166, 76, CBS_DROPDOWN | WS_VSCROLL | CBS_AUTOHSCROLL + PUSHBUTTON "Structure" , IDC_WSTRUCT , 1, 116, 166, 14 + + RTEXT "lParam type", -1, 1, 142, 63, 14, SS_CENTERIMAGE + COMBOBOX IDC_FLAG_LPAR, 66, 142, 102, 56, CBS_DROPDOWNLIST | WS_VSCROLL +// RTEXT "lParam" , -1, 1, 157, 160, 8 + COMBOBOX IDC_EDIT_LPAR, 1, 157, 166, 76, CBS_DROPDOWN | WS_VSCROLL | CBS_AUTOHSCROLL + PUSHBUTTON "Structure" , IDC_LSTRUCT , 1, 157, 166, 14 +} + +IDI_SERVICE ICON "ico\service.ico" diff --git a/plugins/Actman30/iac_settings.pas b/plugins/Actman30/iac_settings.pas new file mode 100644 index 0000000000..bb2c8efe5a --- /dev/null +++ b/plugins/Actman30/iac_settings.pas @@ -0,0 +1,157 @@ +unit iac_settings; + +interface + +implementation + +uses + windows, messages, commctrl, + global,iac_global, dlgshare, lowlevelc, + m_api, mirutils, dbsettings, common, wrapper; + +{$include i_cnst_settings.inc} +{$resource iac_settings.res} + + +//----- Support functions ----- + + +//----- Dialog realization ----- + +procedure FillServiceModeList(wnd:HWND); +begin + SendMessage(wnd,CB_RESETCONTENT,0,0); + InsertString(wnd,0 ,'value'); + InsertString(wnd,1 ,'name'); + InsertString(wnd,2 ,'value (name)'); + InsertString(wnd,3 ,'name ''value'''); + SendMessage(wnd,CB_SETCURSEL,0,0); +end; + +procedure ClearFields(Dialog:HWND); +begin + CheckDlgButton(Dialog,IDC_CNT_FILTER,BST_UNCHECKED); + SetDlgItemTextW(Dialog,IDC_EDIT_FORMAT,''); + + CheckDlgButton(Dialog,IDC_FR_FLAG,BST_UNCHECKED); +end; + +function DlgProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + fCLformat:pWideChar; + lp:TLPARAM; + stat:integer; +begin + result:=0; + + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + + OptSetButtonIcon(GetDlgItem(Dialog,IDC_CNT_APPLY),ACI_APPLY); + + OptSetButtonIcon(GetDlgItem(Dialog,IDC_SRV_APPLY),ACI_APPLY); + FillServiceModeList(GetDlgItem(Dialog,IDC_SERVICELIST)); + end; + + WM_ACT_SETVALUE: begin + ClearFields(Dialog); + end; + + WM_ACT_RESET: begin + ClearFields(Dialog); + // Contact list settings + CheckDlgButton (Dialog,IDC_CNT_FILTER,DBReadByte(0,DBBranch,'CLfilter',BST_UNCHECKED)); + fCLformat:=DBReadUnicode(0,DBBranch,'CLformat'); + SetDlgItemTextW(Dialog,IDC_EDIT_FORMAT,fCLformat); + mFreeMem(fCLformat); + + // Servicelist mode settings + CB_SelectData(Dialog,IDC_SERVICELIST,DBReadByte(0,DBBranch,'SrvListMode')); + end; + + WM_SHOWWINDOW: begin + // Show window by ShowWindow function + if (lParam=0) and (wParam=1) then + begin + lp:=LV_GetLParam(MacroListWindow); + if (lp and ACF_FIRSTRUN)<>0 then + stat:=BST_CHECKED + else + stat:=BST_UNCHECKED; + CheckDlgButton(Dialog,IDC_FR_FLAG,stat); + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of + BN_CLICKED: begin + case loword(wParam) of + IDC_SRV_APPLY: begin + DBWriteByte(0,DBBranch,'SrvListMode', + CB_GetData(GetDlgItem(Dialog,IDC_SERVICELIST))); + end; + + IDC_CNT_APPLY: begin + fCLformat:=GetDlgText(Dialog,IDC_EDIT_FORMAT); + DBWriteUnicode(0,DBBranch,'CLformat',fCLformat); + mFreeMem(fCLformat); + end; + + IDC_CNT_FILTER: begin + DBWriteByte(0,DBBranch,'CLfilter',IsDlgButtonChecked(Dialog,IDC_CNT_FILTER)); + end; + + IDC_FR_FLAG: begin + lp:=LV_GetLParam(MacroListWindow); + if IsDlgButtonChecked(Dialog,IDC_FR_FLAG)=BST_UNCHECKED then + lp:=lp and not ACF_FIRSTRUN + else + lp:=lp or ACF_FIRSTRUN; + LV_SetLParam(MacroListWindow,lp); + + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + end; + end; + end; + end; + + WM_HELP: begin + result:=1; + end; + + end; +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=nil; +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,'IDD_SETTINGS',parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :='Settings'; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :='IDI_SETTINGS'; + vc.Hash :=1; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_settings.rc b/plugins/Actman30/iac_settings.rc new file mode 100644 index 0000000000..957fba3088 --- /dev/null +++ b/plugins/Actman30/iac_settings.rc @@ -0,0 +1,26 @@ +#include "i_cnst_settings.inc" + +LANGUAGE 0,0 + +IDD_SETTINGS DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + GROUPBOX "Contact list", -1, 1, 2, 166, 77, WS_GROUP + AUTOCHECKBOX "Active accounts only",IDC_CNT_FILTER, 4, 11, 160, 11 + RTEXT "Contact list format",-1, 4, 24, 160, 11 + EDITTEXT IDC_EDIT_FORMAT, 22, 38, 142, 12, ES_AUTOHSCROLL + CONTROL "Apply",IDC_CNT_APPLY,"MButtonClass",WS_TABSTOP,4,36,16,16,$18000000 + CTEXT "You can use %name%, %uid%, %account% and %group% substitutes",-1, 4, 53, 160, 24 + + RTEXT "Service list format",-1, 0, 82, 166, 11 + COMBOBOX IDC_SERVICELIST , 19, 94, 148, 96, CBS_DROPDOWNLIST | WS_VSCROLL + CONTROL "Apply",IDC_SRV_APPLY,"MButtonClass",WS_TABSTOP,1,93,16,16,$18000000 + + GROUPBOX "Current Macro", -1, 1, 116, 166, 28, WS_GROUP + AUTOCHECKBOX "Select for FirstRun",IDC_FR_FLAG, 4, 125, 160, 12 +// AUTOCHECKBOX "hContact in wParam" ,IDC_HC_WPAR, 4, 138, 160, 12 +} + +IDI_SETTINGS ICON "ico\settings.ico" diff --git a/plugins/Actman30/iac_storage.pas b/plugins/Actman30/iac_storage.pas new file mode 100644 index 0000000000..aaa7351452 --- /dev/null +++ b/plugins/Actman30/iac_storage.pas @@ -0,0 +1,292 @@ +unit iac_storage; + +interface + +implementation + +uses + windows, messages, + common, wrapper, + mirutils,m_api,dbsettings, + global,iac_global; + +{$include i_cnst_storage.inc} +{$resource iac_storage.res} + +const + opt_number = 'number'; +const + ioNumber = 'number'; + ioOper = 'oper'; + ioCopy = 'copy'; +const + ACF_COPYFROM = $00000001; +type + tStorageAction = class(tBaseAction) + Number:integer; + + 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 ----- + +//----- Object realization ----- + +constructor tStorageAction.Create(uid:dword); +begin + inherited Create(uid); + + Number:=0; +end; + +destructor tStorageAction.Destroy; +begin + + inherited Destroy; +end; +{ +function tStorageAction.Clone:tBaseAction; +begin + result:=.Create(0); + Duplicate(result); + +end; +} +function tStorageAction.DoAction(var WorkData:tWorkData):LRESULT; +var + num:integer; + st,dt:pByte; + sv,dv:^uint_ptr; +begin + result:=0; + + if Number in [0..9] then + begin + // copy to slot + if (flags and ACF_COPYFROM)=0 then + begin + num:=Number; + st:=@WorkData.ResultType; + dt:=@WorkData.Storage[Number].rtype; + sv:=@WorkData.LastResult; + dv:=@WorkData.Storage[Number].value; + end + // copy from slot + else + begin + num:=-1; + dt:=@WorkData.ResultType; + st:=@WorkData.Storage[Number].rtype; + dv:=@WorkData.LastResult; + sv:=@WorkData.Storage[Number].value; + end; + + ClearResult(WorkData,num); + dt^:=st^; + + if WorkData.ResultType=rtInt then // Number + dv^:=sv^ + + else if WorkData.ResultType=rtWide then // Unicode + StrDupW(pWideChar(dv^),pWideChar(sv^)) + + else if WorkData.ResultType<>rtUnkn then // Ansi and UTF8 + StrDup(pAnsiChar(dv^),pAnsiChar(sv^)); + end; + +{ + // copy to slot + if (flags and ACF_COPYFROM)=0 then + begin + if Number in [0..9] then + begin + ClearResult(WorkData,Number); + WorkData.Storage[Number].rtype:=WorkData.ResultType; + + if WorkData.ResultType=rtInt then // Number + WorkData.Storage[Number].value:=WorkData.LastResult + + else if WorkData.ResultType=rtWide then // Unicode + StrDupW(pWideChar(WorkData.Storage[Number].value),pWideChar(WorkData.LastResult)) + + else if WorkData.ResultType<>rtUnkn then // Ansi and UTF8 + StrDup(pAnsiChar(WorkData.Storage[Number].value),pAnsiChar(WorkData.LastResult)); + + end; + end + // copy from slot + else + begin + if Number in [0..9] then + begin + ClearResult(WorkData); + WorkData.ResultType:=WorkData.Storage[Number].rtype; + + if WorkData.ResultType=rtInt then // Number + WorkData.LastResult:=WorkData.Storage[Number].value + + else if WorkData.ResultType=rtWide then // Unicode + StrDupW(pWideChar(WorkData.LastResult),pWideChar(WorkData.Storage[Number].value)) + + else if WorkData.ResultType<>rtUnkn then // Ansi and UTF8 + StrDup(pAnsiChar(WorkData.LastResult),pAnsiChar(WorkData.Storage[Number].value)); + + end; + end; +} +end; + +procedure tStorageAction.Load(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; +begin + inherited Load(node,fmt); + case fmt of + 0: begin + pc:=StrCopyE(section,pAnsiChar(node)); + StrCopy(pc,opt_number); Number:=DBReadByte(0,DBBranch,section,0); + end; + + 1: begin + with xmlparser do + begin + if lstrcmpiw(getAttrValue(HXML(node),ioOper),ioCopy)=1 then + flags:=flags or ACF_COPYFROM; + Number:=StrToInt(getAttrValue(HXML(node),ioNumber)); + end; + end; + end; +end; + +procedure tStorageAction.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_number); DBWriteByte(0,DBBranch,section,Number); + end; +{ + 1: begin + end; +} + end; +end; + +//----- Dialog realization ----- + +procedure FillStorageCombo(wnd:HWND); +var + i:integer; + buf:array [0..31] of AnsiChar; + p:pAnsiChar; +begin + SendMessage(wnd,CB_RESETCONTENT,0,0); + + p:=StrCopyE(buf,'Slot #')-1; + for i:=0 to 9 do + begin + p^:=AnsiChar(ORD('0')+i); + InsertString(wnd,i,buf); + end; + + SendMessage(wnd,CB_SETCURSEL,0,0); +end; + +procedure ClearFields(Dialog:HWND); +begin + CheckDlgButton(Dialog,IDC_FLAG_TO ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_FLAG_FROM,BST_UNCHECKED); +end; + +function DlgProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +begin + result:=0; + + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + + FillStorageCombo(GetDlgItem(Dialog,IDC_STORAGELIST)); + end; + + WM_ACT_SETVALUE: begin + ClearFields(Dialog); + with tStorageAction(lParam) do + begin + if (flags and ACF_COPYFROM)=0 then + CheckDlgButton(Dialog,IDC_FLAG_TO ,BST_CHECKED) + else + CheckDlgButton(Dialog,IDC_FLAG_FROM,BST_CHECKED); + + CB_SelectData(GetDlgItem(Dialog,IDC_STORAGELIST),Number); + end; + end; + + WM_ACT_RESET: begin + ClearFields(Dialog); + CheckDlgButton(Dialog,IDC_FLAG_TO,BST_CHECKED); + CB_SelectData(GetDlgItem(Dialog,IDC_STORAGELIST),0); + end; + + WM_ACT_SAVE: begin + with tStorageAction(lParam) do + begin + if IsDlgButtonChecked(Dialog,IDC_FLAG_FROM)<>BST_UNCHECKED then + flags:=flags or ACF_COPYFROM; + + Number:=CB_GetData(GetDlgItem(Dialog,IDC_STORAGELIST)); + end; + end; +{ + WM_COMMAND: begin + case wParam shr 16 of + end; + end; +} + WM_HELP: begin + result:=1; + end; + + end; +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=tStorageAction.Create(vc.Hash); +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,'IDD_ACTSTORAGE',parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :='Storage'; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :='IDI_STORAGE'; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_storage.rc b/plugins/Actman30/iac_storage.rc new file mode 100644 index 0000000000..6e4391e15c --- /dev/null +++ b/plugins/Actman30/iac_storage.rc @@ -0,0 +1,16 @@ +#include "i_cnst_storage.inc" + +LANGUAGE 0,0 + +IDD_ACTSTORAGE DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + AUTORADIOBUTTON "LastResult to " , IDC_FLAG_TO , 1, 2, 166, 11, WS_GROUP + AUTORADIOBUTTON "LastResult from", IDC_FLAG_FROM , 1, 15, 166, 11 + + COMBOBOX IDC_STORAGELIST, 19, 30, 148, 128, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL +} + +IDI_STORAGE ICON "ico\storage.ico" diff --git a/plugins/Actman30/iac_text.pas b/plugins/Actman30/iac_text.pas new file mode 100644 index 0000000000..e6a05d8fc0 --- /dev/null +++ b/plugins/Actman30/iac_text.pas @@ -0,0 +1,495 @@ +unit iac_text; + +interface + +implementation + +uses + windows, messages, commctrl, + global, iac_global, m_api, editwrapper, + dbsettings, common, io, + mirutils, syswin, wrapper; + +{$include i_cnst_text.inc} +{$resource iac_text.res} + +const + BufferSize = 32768; // chars + +const + opt_text = 'text'; +const + ioVariables = 'variables'; + ioText = 'text'; + ioPost = 'post'; +const + ACF_TEXTSCRIPT = $00000001; + ACF_POSTPROCESS = $00000002; + +type + tTextAction = class(tBaseAction) + private + text: pWideChar; + 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 ----- + +//----- Object realization ----- + +constructor tTextAction.Create(uid:dword); +begin + inherited Create(uid); + + text:=nil; +end; + +destructor tTextAction.Destroy; +begin + mFreeMem(text); + + inherited Destroy; +end; +{ +function tTextAction.Clone:tBaseAction; +begin + result:=.Create(0); + Duplicate(result); + +end; +} +type + trec = record + text:PAnsiChar; + one, two:integer; + end; + +function GetFileString(fname:PAnsiChar;linenum:integer):pWideChar; +var + pc,FileBuf,CurLine:PAnsiChar; + f:THANDLE; + NumLines, j:integer; +begin + f:=Reset(fname); + if f<>INVALID_HANDLE_VALUE then + begin + j:=FileSize(f); + mGetMem(FileBuf,j+1); + BlockRead(f,FileBuf^,j); + while (FileBuf+j)^<' ' do dec(j); + (FileBuf+j+1)^:=#0; + CloseHandle(f); + pc:=FileBuf; + CurLine:=pc; + NumLines:=1; + while pc^<>#0 do // count number of lines + begin + if pc^=#13 then + begin + if linenum=NumLines then + break; + inc(pc); + if pc^=#10 then + inc(pc); + inc(NumLines); + CurLine:=pc; + end + else + inc(pc); + end; + if (linenum>NumLines) or (linenum=0) then //ls - lastline + else if linenum<0 then + begin + randomize; + j:=random(NumLines)+1; + pc:=FileBuf; + NumLines:=1; + CurLine:=pc; + repeat + if (pc^=#13) or (pc^=#0) then + begin + if j=NumLines then + break; + if pc^<>#0 then + begin + inc(pc); + if pc^=#10 then + inc(pc); + end; + inc(NumLines); + CurLine:=pc; + end + else + inc(pc); + until false; + end; + pc^:=#0; + StrReplace(CurLine,'\n',#13#10); + StrReplace(CurLine,'\t',#09); + AnsiToWide(CurLine,result,CP_ACP); + mFreeMem(FileBuf); + end + else + result:=nil; +end; + +function Split(buf:PWideChar;macro:PWideChar;var r:trec):integer; +type + tconv = packed record + case boolean of + false: (res:int); + true: (lo,hi:word); + end; +var + i:integer; + p,pp,lp:pWideChar; + ls:array [0..511] of WideChar; +begin + result:=0; + i:=StrIndexW(buf,macro); + if i>0 then + begin + dec(i); + p:=buf+i+StrLenW(macro); + pp:=p; + while (p^<>#0) and (p^<>')') do + inc(p); + ls[0]:=#0; + if p^<>#0 then // correct syntax + begin + lp:=ls; + while (pp<>p) and (pp^<>',') do // filename + begin + lp^:=pp^; + inc(lp); + inc(pp); + end; + lp^:=#0; + WideToAnsi(ls,r.text,MirandaCP); + r.one:=-1; + r.two:=-1; + if pp^=',' then + begin + inc(pp); + r.one:=StrToInt(pp); + while (pp<>p) and (pp^<>',') do inc(pp); + if pp^=',' then + begin + inc(pp); + r.two:=StrToInt(pp); + end; + end; + tconv(result).lo:=p-buf-i+1; // length + tconv(result).hi:=i; // position + end; + end; +end; + +procedure PasteFileString(dst:pWideChar); +var + i:integer; + lp:pWideChar; + buf:array [0..511] of AnsiChar; + r:trec; +begin + repeat + i:=Split(dst,'^f(',r); + if i>0 then + begin + StrDeleteW(dst,i shr 16,loword(i)); + ConvertFileName(r.text,buf); +// CallService(MS_UTILS_PATHTOABSOLUTE,WPARAM(r.text),LPARAM(@buf)); + lp:=GetFileString(@buf,r.one); + if lp<>nil then + begin + StrInsertW(lp,dst,i shr 16); + mFreeMem(lp); + end; + end + else + break; + until false; +end; + +procedure PasteClipboard(dst:pWideChar); +var + p:pWideChar; + fh:tHandle; +begin + if StrPosW(dst,'^v')<>nil then + begin + if OpenClipboard(0) then + begin + fh:=GetClipboardData(cf_UnicodeText); + p:=GlobalLock(fh); + StrReplaceW(dst,'^v',p); + GlobalUnlock(fh); + CloseClipboard; + end + end +end; + +procedure PasteSelectedText(dst:pWideChar); +var + sel:integer; + buf:pWideChar; + wnd:HWND; +begin + if StrPosW(dst,'^s')<>nil then + begin + wnd:=WaitFocusedWndChild(GetForegroundWindow){GetFocus}; + if wnd<>0 then + begin + sel:=SendMessageW(wnd,EM_GETSEL,0,0); + if loword(sel)=(sel shr 16) then + StrReplaceW(dst,'^s',nil) + else + begin + buf:=GetDlgText(wnd,false); + buf[sel shr 16]:=#0; + StrReplaceW(dst,'^s',buf+loword(sel)); + mFreeMem(buf); + end; + end + else + StrReplaceW(dst,'^s',nil); + end; +end; + +function tTextAction.DoAction(var WorkData:tWorkData):LRESULT; +var + buf:array [0..31] of WideChar; + w,tmp,last:pWideChar; +begin + result:=0; + + tmp:=text; + if (flags and ACF_POSTPROCESS)=0 then + if (flags and ACF_TEXTSCRIPT)<>0 then + begin + if WorkData.ResultType=rtInt then + last:=pWideChar(IntToStr(buf,WorkData.LastResult)) + else + last:=pWideChar(WorkData.LastResult); + + tmp:=ParseVarString(text,WorkData.Parameter,last); + end; + + mGetMem (w ,BufferSize*SizeOf(WideChar)); + FillChar(w^,BufferSize*SizeOf(WideChar),0); + StrCopyW(w,tmp); + if (flags and ACF_POSTPROCESS)=0 then + if (flags and ACF_TEXTSCRIPT)<>0 then + mFreeMem(tmp); + + PasteClipboard(w); // ^v + PasteFileString(w); // ^f + + PasteSelectedText(w); // ^s + // ^a - get ALL text? + + if WorkData.ResultType=rtInt then + begin + StrReplaceW(w,'^l',IntToStr(buf,WorkData.LastResult)); // ^l + StrReplaceW(w,'^h',IntToHex(buf,WorkData.LastResult)); // ^h + end + else + begin + StrReplaceW(w,'^l',pWideChar(WorkData.LastResult)); + StrReplaceW(w,'^h',IntToHex(buf,NumToInt(pWideChar(WorkData.LastResult)))); + end; + + StrReplaceW(w,'^t',#9); // ^t + StrReplaceW(w,'^e',nil); // ^e + + if (flags and ACF_POSTPROCESS)<>0 then + if (flags and ACF_TEXTSCRIPT)<>0 then + begin + if WorkData.ResultType=rtInt then + last:=pWideChar(IntToStr(buf,WorkData.LastResult)) + else + last:=pWideChar(WorkData.LastResult); + + tmp:=ParseVarString(w,WorkData.Parameter,last); + mFreeMem(w); + w:=tmp; + end; + + ClearResult(WorkData); + WorkData.LastResult:=uint_ptr(w); + WorkData.ResultType:=rtWide; +end; + +procedure tTextAction.Load(node:pointer;fmt:integer); +var + section: array [0..127] of AnsiChar; + pc:pAnsiChar; +begin + inherited Load(node,fmt); + case fmt of + 0: begin + pc:=StrCopyE(section,pAnsiChar(node)); + + StrCopy(pc,opt_text); text:=DBReadUnicode(0,DBBranch,section,nil); + end; + + 1: begin + with xmlparser do + begin + StrDupW(text,getText(HXML(node))); + if StrToInt(getAttrValue(HXML(node),ioVariables))=1 then + flags:=flags or ACF_TEXTSCRIPT; + if StrToInt(getAttrValue(HXML(node),ioPost))=1 then + flags:=flags or ACF_POSTPROCESS; + end; + end; +{ + 2: begin + UTF8ToWide(GetParamSectionInt(node,ioText),text); + if GetParamSectionInt(node,ioVariables)=1 then + flags:=flags or ACF_TEXTSCRIPT; + end; +} + end; +end; + +procedure tTextAction.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_text); DBWriteUnicode(0,DBBranch,section,text); + end; +{ + 1: begin + end; +} + end; +end; + +//----- Dialog realization ----- + +procedure ClearFields(Dialog:HWND); +begin + SetDlgItemTextW(Dialog,IDC_TXT_TEXT,nil); + SetEditFlags (Dialog,IDC_TXT_TEXT,EF_ALL,0); + CheckDlgButton (Dialog,IDC_TXT_POST,BST_UNCHECKED); +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_TXT_TEXT); + end; + + WM_ACT_SETVALUE: begin + NoProcess:=true; + ClearFields(Dialog); + + with tTextAction(lParam) do + begin + SetDlgItemTextW(Dialog,IDC_TXT_TEXT,text); + SetEditFlags(Dialog,IDC_TXT_TEXT,EF_SCRIPT,ord((flags and ACF_TEXTSCRIPT)<>0)); + if (flags and ACF_POSTPROCESS)<>0 then + CheckDlgButton(Dialog,IDC_TXT_POST,BST_CHECKED); + end; + NoProcess:=false; + end; + + WM_ACT_RESET: begin + NoProcess:=true; + ClearFields(Dialog); + NoProcess:=false; + end; + + WM_ACT_SAVE: begin + with tTextAction(lParam) do + begin + flags:=0; + + {mFreeMem(text); }text:=GetDlgText(Dialog,IDC_TXT_TEXT); + if (GetEditFlags(Dialog,IDC_TXT_TEXT) and EF_SCRIPT)<>0 then + flags:=flags or ACF_TEXTSCRIPT; + + if IsDlgButtonChecked(Dialog,IDC_TXT_POST)=BST_CHECKED then + flags:=flags or ACF_POSTPROCESS; + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of + BN_CLICKED: + if loword(wParam)=IDC_TXT_POST then + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + + EN_CHANGE: if not NoProcess then + SendMessage(GetParent(GetParent(Dialog)),PSM_CHANGED,0,0); + end; + end; + + WM_HELP: begin + MessageBoxW(0, + TranslateW('^s - selected (and replaced) part'#13#10+ + '^e - replaced by empty string'#13#10+ + '^v - paste text from Clipboard'#13#10+ + '^t - replaced by tabulation'#13#10+ + '^l - replaced by last result as unicode'#13#10+ + '^h - replaced by last result as hex'#13#10+ + '^f(name[,str])'#13#10+ + ' paste line from text file.'#13#10+ + ' brackets contents must be w/o spaces'), + TranslateW('Text'),0); + result:=1; + end; + + end; +end; + +//----- Export/interface functions ----- + +var + vc:tActModule; + +function CreateAction:tBaseAction; +begin + result:=tTextAction.Create(vc.Hash); +end; + +function CreateDialog(parent:HWND):HWND; +begin + result:=CreateDialogW(hInstance,'IDD_ACTTEXT',parent,@DlgProc); +end; + +procedure Init; +begin + vc.Next :=ModuleLink; + + vc.Name :='Text'; + vc.Dialog :=@CreateDialog; + vc.Create :=@CreateAction; + vc.Icon :='IDI_TEXT'; + + ModuleLink :=@vc; +end; + +begin + Init; +end. diff --git a/plugins/Actman30/iac_text.rc b/plugins/Actman30/iac_text.rc new file mode 100644 index 0000000000..06399716c4 --- /dev/null +++ b/plugins/Actman30/iac_text.rc @@ -0,0 +1,14 @@ +#include "i_cnst_text.inc" + +LANGUAGE 0,0 + +IDD_ACTTEXT DIALOGEX 0, 0, 168, 200, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + EDITTEXT IDC_TXT_TEXT, 1, 4, 166, 12, ES_AUTOHSCROLL + AUTOCHECKBOX "Script process after",IDC_TXT_POST, 4, 18, 160, 11 +} + +IDI_TEXT ICON "ico\text.ico" diff --git a/plugins/Actman30/ico/advance.ico b/plugins/Actman30/ico/advance.ico new file mode 100644 index 0000000000..fa6c604542 Binary files /dev/null and b/plugins/Actman30/ico/advance.ico differ diff --git a/plugins/Actman30/ico/apply.ico b/plugins/Actman30/ico/apply.ico new file mode 100644 index 0000000000..80c3802c09 Binary files /dev/null and b/plugins/Actman30/ico/apply.ico differ diff --git a/plugins/Actman30/ico/chain.ico b/plugins/Actman30/ico/chain.ico new file mode 100644 index 0000000000..3a98b8ac30 Binary files /dev/null and b/plugins/Actman30/ico/chain.ico differ diff --git a/plugins/Actman30/ico/contact.ico b/plugins/Actman30/ico/contact.ico new file mode 100644 index 0000000000..8174fa221a Binary files /dev/null and b/plugins/Actman30/ico/contact.ico differ diff --git a/plugins/Actman30/ico/delete.ico b/plugins/Actman30/ico/delete.ico new file mode 100644 index 0000000000..eea851da19 Binary files /dev/null and b/plugins/Actman30/ico/delete.ico differ diff --git a/plugins/Actman30/ico/down.ico b/plugins/Actman30/ico/down.ico new file mode 100644 index 0000000000..d4fdb83bbf Binary files /dev/null and b/plugins/Actman30/ico/down.ico differ diff --git a/plugins/Actman30/ico/export.ico b/plugins/Actman30/ico/export.ico new file mode 100644 index 0000000000..ddddb59074 Binary files /dev/null and b/plugins/Actman30/ico/export.ico differ diff --git a/plugins/Actman30/ico/format.ico b/plugins/Actman30/ico/format.ico new file mode 100644 index 0000000000..ddddb59074 Binary files /dev/null and b/plugins/Actman30/ico/format.ico differ diff --git a/plugins/Actman30/ico/import.ico b/plugins/Actman30/ico/import.ico new file mode 100644 index 0000000000..481da4dbaf Binary files /dev/null and b/plugins/Actman30/ico/import.ico differ diff --git a/plugins/Actman30/ico/insert.ico b/plugins/Actman30/ico/insert.ico new file mode 100644 index 0000000000..481da4dbaf Binary files /dev/null and b/plugins/Actman30/ico/insert.ico differ diff --git a/plugins/Actman30/ico/jump.ico b/plugins/Actman30/ico/jump.ico new file mode 100644 index 0000000000..3a98b8ac30 Binary files /dev/null and b/plugins/Actman30/ico/jump.ico differ diff --git a/plugins/Actman30/ico/message.ico b/plugins/Actman30/ico/message.ico new file mode 100644 index 0000000000..fa6c604542 Binary files /dev/null and b/plugins/Actman30/ico/message.ico differ diff --git a/plugins/Actman30/ico/new.ico b/plugins/Actman30/ico/new.ico new file mode 100644 index 0000000000..73937210e0 Binary files /dev/null and b/plugins/Actman30/ico/new.ico differ diff --git a/plugins/Actman30/ico/program.ico b/plugins/Actman30/ico/program.ico new file mode 100644 index 0000000000..30c7df1875 Binary files /dev/null and b/plugins/Actman30/ico/program.ico differ diff --git a/plugins/Actman30/ico/reload.ico b/plugins/Actman30/ico/reload.ico new file mode 100644 index 0000000000..dc070c5083 Binary files /dev/null and b/plugins/Actman30/ico/reload.ico differ diff --git a/plugins/Actman30/ico/rw.ico b/plugins/Actman30/ico/rw.ico new file mode 100644 index 0000000000..d5927ebb08 Binary files /dev/null and b/plugins/Actman30/ico/rw.ico differ diff --git a/plugins/Actman30/ico/service.ico b/plugins/Actman30/ico/service.ico new file mode 100644 index 0000000000..ddddb59074 Binary files /dev/null and b/plugins/Actman30/ico/service.ico differ diff --git a/plugins/Actman30/ico/settings.ico b/plugins/Actman30/ico/settings.ico new file mode 100644 index 0000000000..ddddb59074 Binary files /dev/null and b/plugins/Actman30/ico/settings.ico differ diff --git a/plugins/Actman30/ico/storage.ico b/plugins/Actman30/ico/storage.ico new file mode 100644 index 0000000000..dc070c5083 Binary files /dev/null and b/plugins/Actman30/ico/storage.ico differ diff --git a/plugins/Actman30/ico/test.ico b/plugins/Actman30/ico/test.ico new file mode 100644 index 0000000000..345530ba76 Binary files /dev/null and b/plugins/Actman30/ico/test.ico differ diff --git a/plugins/Actman30/ico/text.ico b/plugins/Actman30/ico/text.ico new file mode 100644 index 0000000000..fa6c604542 Binary files /dev/null and b/plugins/Actman30/ico/text.ico differ diff --git a/plugins/Actman30/ico/up.ico b/plugins/Actman30/ico/up.ico new file mode 100644 index 0000000000..56fde31eda Binary files /dev/null and b/plugins/Actman30/ico/up.ico differ diff --git a/plugins/Actman30/inoutini.pas b/plugins/Actman30/inoutini.pas new file mode 100644 index 0000000000..38dab2be45 --- /dev/null +++ b/plugins/Actman30/inoutini.pas @@ -0,0 +1,153 @@ +unit inoutini; + +interface + +uses windows, lowlevelc; + +{ +type + pINIioStruct = ^tINIioStruct; + tINIioStruct = record + storage, + section, + namespace:pAnsiChar; + end; +} +function Import(list:tMacroList;fname:PWideChar;aflags:dword):integer; + +implementation + +uses + io, common, m_api, question, + iac_global, global, memini; + +const + ioAction = 'Action'; + ioClass = 'class'; + ioName = 'name'; + ioVolatile = 'volatile'; +const + imp_yes = 1; + imp_yesall = 2; + imp_no = 3; + imp_noall = 4; + imp_append = 5; + +function ImportAction(section:pointer):tBaseAction; +var + pa:pActModule; +begin + if section<>nil then + begin + pa:=GetLinkByName(GetParamSectionStr(section,ioClass,nil)); + if pa<>nil then + begin + result:=pa.Create; + result.Load(section,2); + end + else + result:=tBaseAction(1); + end + else + result:=nil; +end; + +function Import(list:tMacroList;fname:PWideChar;aflags:dword):integer; +var + i:integer; + impact:integer; + buf:array [0..511] of WideChar; + oldid:dword; + arr:array [0..63] of tBaseAction; + act:tBaseAction; + p:pMacroRecord; + storage:pointer; + pc,pc1,ppc,ppc1:pAnsiChar; + pcw:pWideChar; +begin + result:=0; + + for i:=0 to list.Count-1 do + with list[i]^ do + if (flags and (ACF_IMPORT or ACF_ASSIGNED))= + (ACF_IMPORT or ACF_ASSIGNED) then + flags:=flags and not (ACF_IMPORT or ACF_OVERLOAD); + + if (fname=nil) or (fname^=#0) then + exit; + storage:=OpenStorage(fname); + if storage=nil then + exit; + + impact:=imp_yes; + + pc:=GetSectionList(storage,''); // list with "empty" namespaces + ppc:=pc; + while pc^<>#0 do + begin + UTF8ToWide(pc,pcw); + + p:=list.GetMacro(pcw); + oldid:=$FFFFFFFF; + if p<>nil then + begin + if (impact<>imp_yesall) and (impact<>imp_noall) then + begin + StrCopyW(buf,TranslateW('Action "$" exists, do you want to rewrite it?')); + impact:=ShowQuestion(StrReplaceW(buf,'$',pcw)); + end; + if (impact=imp_yesall) or (impact=imp_yes) then + begin + oldid:=p^.id; + FreeMacro(p); + end; + end; + // if new or overwriting then read macro details/actions + if (p=nil) or (impact=imp_yesall) or (impact=imp_yes) or (impact=imp_append) then + begin + with List[list.NewMacro()]^ do + begin + if (p<>nil) and (oldid<>$FFFFFFFF) then // set old id to keep UseAction setting + begin + flags:=flags or ACF_IMPORT or ACF_OVERLOAD; + id:=oldid; + end + else + flags:=flags or ACF_IMPORT; + + if GetParamInt(storage,pc,ioVolatile)=1 then flags:=flags or ACF_VOLATILE; + StrCopyW(descr,pcw,MacroNameLen-1); + + // reading actions + ActionCount:=0; // amount of loaded + pc1:=GetSectionList(storage,pc); + ppc1:=pc1; + while pc1^<>#0 do + begin + act:=ImportAction(SearchSection(storage,pc1,pc)); + if act=nil then + break; + if uint_ptr(act)<>1 then + begin + arr[ActionCount]:=act; + inc(ActionCount); + end; + end; + FreeSectionList(ppc1); + // moving actions to their place + if Actioncount>0 then + begin + GetMem(ActionList,SizeOf(tBaseAction)*ActionCount); + move(arr,ActionList^,SizeOf(tBaseAction)*ActionCount); + end; + inc(result); + end; + end; + + end; + FreeSectionList(ppc); + + CloseStorage(storage); +end; + +end. diff --git a/plugins/Actman30/inoutxml.pas b/plugins/Actman30/inoutxml.pas new file mode 100644 index 0000000000..3a7aea25d4 --- /dev/null +++ b/plugins/Actman30/inoutxml.pas @@ -0,0 +1,155 @@ +unit inoutxml; + +interface + +uses windows, lowlevelc; + +function Import(list:tMacroList;fname:PWideChar;aflags:dword):integer; + +implementation + +uses + io, common, m_api, question, + iac_global, global; + +const + ioAction = 'Action'; + ioClass = 'class'; + ioName = 'name'; + ioVolatile = 'volatile'; +const + imp_yes = 1; + imp_yesall = 2; + imp_no = 3; + imp_noall = 4; + imp_append = 5; + +function ImportAction(actnode:HXML):tBaseAction; +var + pa:pActModule; + buf:array [0..127] of AnsiChar; +begin + result:=nil; + if actnode=0 then exit; + with xmlparser do + begin + pa:=GetLinkByName(FastWideToAnsiBuf(getAttrValue(actnode,ioClass),buf)); + if pa<>nil then + begin + result:=pa.Create; + result.Load(pointer(actnode),1); + end + else + result:=tBaseAction(1); + end; +end; + +function Import(list:tMacroList;fname:PWideChar;aflags:dword):integer; +var + f:THANDLE; + i,nodenum,actcnt:integer; + tmp,res:pWideChar; + root,actnode:HXML; + impact:integer; + buf:array [0..511] of WideChar; + oldid:dword; + arr:array [0..63] of tBaseAction; + act:tBaseAction; + p:pMacroRecord; +begin + result:=0; + + for i:=0 to list.Count-1 do + with list[i]^ do + if (flags and (ACF_IMPORT or ACF_ASSIGNED))= + (ACF_IMPORT or ACF_ASSIGNED) then + flags:=flags and not (ACF_IMPORT or ACF_OVERLOAD); + + if (fname=nil) or (fname^=#0) then + exit; + i:=GetFSize(fname); + if i=0 then + exit; + mGetMem (res ,i+SizeOf(WideChar)); + FillChar(res^,i+SizeOf(WideChar),0); + f:=Reset(fname); + BlockRead(f,res^,i); + CloseHandle(f); + +//MessageBoxW(0,res,'SRC',0); + xmlparser.cbSize:=SizeOf(XML_API_W); + CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser)); + with xmlparser do + begin + root:=parseString(ChangeUnicode(res),@i,nil); + nodenum:=0; + impact:=imp_yes; + repeat + actnode:=getNthChild(root,ioAction,nodenum); + if actnode=0 then break; +//?? if StrCmpW(getName(actnode),ioAction)<>0 then break; + tmp:=getAttrValue(actnode,ioName); + if tmp<>nil then //!! + begin + p:=list.GetMacro(tmp); + oldid:=$FFFFFFFF; + if p<>nil then + begin + if (impact<>imp_yesall) and (impact<>imp_noall) then + begin + StrCopyW(buf,TranslateW('Action "$" exists, do you want to rewrite it?')); + impact:=ShowQuestion(StrReplaceW(buf,'$',tmp)); + end; + if (impact=imp_yesall) or (impact=imp_yes) then + begin + oldid:=p^.id; + FreeMacro(p); + end; + end; + // if new or overwriting then read macro details/actions + if (p=nil) or (impact=imp_yesall) or (impact=imp_yes) or (impact=imp_append) then + begin + with List[list.NewMacro()]^ do + begin + if (p<>nil) and (oldid<>$FFFFFFFF) then // set old id to keep UseAction setting + begin + flags:=flags or ACF_IMPORT or ACF_OVERLOAD; + id:=oldid; + end + else + flags:=flags or ACF_IMPORT; + if StrToInt(getAttrValue(actnode,ioVolatile))=1 then flags:=flags or ACF_VOLATILE; + StrCopyW(descr,tmp,MacroNameLen-1); + + // reading actions + actcnt:=0; // count in file + ActionCount:=0; // amount of loaded + repeat + act:=ImportAction(getChild(actnode,actcnt)); + if act=nil then + break; + if uint_ptr(act)<>1 then + begin + arr[ActionCount]:=act; + inc(ActionCount); + end; + inc(actcnt); + until false; + // moving actions to their place + if Actioncount>0 then + begin + GetMem(ActionList,SizeOf(tBaseAction)*ActionCount); + move(arr,ActionList^,SizeOf(tBaseAction)*ActionCount); + end; + inc(result); + end; + end; + end; + inc(nodenum); + until false; + destroyNode(root); + end; + mFreeMem(res); +end; + +end. diff --git a/plugins/Actman30/lowlevelc.pas b/plugins/Actman30/lowlevelc.pas new file mode 100644 index 0000000000..5c4d6b7965 --- /dev/null +++ b/plugins/Actman30/lowlevelc.pas @@ -0,0 +1,294 @@ +unit lowlevelc; + +interface + +uses + windows, + iac_global; + +const + ACF_ASSIGNED = $80000000; // action assigned + ACF_FIRSTRUN = $40000000; // FirstRun flag + ACF_USEDNOW = $20000000; // action in use (reserved) + ACF_VOLATILE = $10000000; // don't save in DB + + ACF_TOSAVE = ACF_ASSIGNED or ACF_FIRSTRUN; +type + pActionList = ^tActionList; + tActionList = array [0..1023] of tBaseAction; + +const + MacroNameLen = 64; +type + pMacroRecord = ^tMacroRecord; + tMacroRecord = record + id :dword; + flags :dword; // ACF_* flags + descr :array [0..MacroNameLen-1] of WideChar; + ActionList :pActionList; + ActionCount:integer; + end; + +type // array dimension - just for indexing + pMacroList = ^taMacroList; + taMacroList = array [0..1023] of tMacroRecord; + +type + tMacroList = class + private + fMacroList:pMacroList; + fMacroCount:cardinal; + + procedure ReallocMacroList; + function GetMacroElement(i:integer):pMacroRecord; + public + + constructor Create(isize:cardinal); + destructor Destroy; override; + + procedure Clear(filter:dword=0); + function Clone:tMacroList; + function NewMacro:cardinal; + + function GetMacro(id:uint_ptr ):pMacroRecord; overload; + function GetMacro(name:pWideChar):pMacroRecord; overload; + function GetMacroNameById(id:dword):PWideChar; + + property List[i:integer]:pMacroRecord read GetMacroElement; default; + property Count: cardinal read fMacroCount; + end; + +procedure FreeMacro(Macro:pMacroRecord;mask:dword=0); + +var + MacroList:tMacroList; + + +implementation + +uses Common; + +const + MacroListPage = 8; + + +function tMacroList.GetMacroElement(i:integer):pMacroRecord; +begin + result:=@fMacroList[i]; +end; + +function tMacroList.GetMacro(id:uint_ptr):pMacroRecord; +var + i:integer; +begin + for i:=0 to fMacroCount-1 do + begin + if ((fMacroList^[i].flags and ACF_ASSIGNED)<>0) and + (id=fMacroList^[i].id) then + begin + result:=@(fMacroList^[i]); + exit; + end; + end; + result:=nil; +end; + +function tMacroList.GetMacro(name:pWideChar):pMacroRecord; +var + i:integer; +begin + for i:=0 to fMacroCount-1 do + begin + if ((fMacroList^[i].flags and ACF_ASSIGNED)<>0) and + (StrCmpW(name,fMacroList^[i].descr)=0) then + begin + result:=@(fMacroList^[i]); + exit; + end; + end; + result:=nil; +end; + +function tMacroList.GetMacroNameById(id:dword):PWideChar; +var + p:pMacroRecord; +begin + p:=GetMacro(id); + if p<>nil then + result:=@(p^.descr) + else + result:=nil; +end; + +procedure FreeActionList(var src:pActionList; count:integer; mask:dword); +var + i:integer; +begin + for i:=0 to count-1 do + begin + if (mask=0) or ((src^[i].flags and mask)<>0) then + src^[i].Free; + end; + FreeMem(src); + src:=nil; +end; + +procedure FreeMacro(Macro:pMacroRecord;mask:dword=0); +begin + with Macro^ do + begin + if (flags and ACF_ASSIGNED)<>0 then + begin + flags:=0; // make Unassigned + FreeActionList(ActionList,ActionCount,mask); + ActionCount:=0; + end; + end; +end; + +procedure tMacroList.Clear(filter:dword=0); +var + i:integer; +begin + for i:=0 to fMacroCount-1 do + begin + FreeMacro(@(fMacroList[i]),filter); + end; + fMacroCount:=0; + FreeMem(fMacroList); + fMacroList:=nil; +end; + +destructor tMacroList.Destroy; +begin + fMacroCount:=0; + FreeMem(fMacroList); + fMacroList:=nil; + + inherited Destroy; +end; + +function CloneActionList(src:pActionList;count:integer):pActionList; +begin + if src=nil then + begin + result:=nil; + exit; + end; + GetMem(result ,count*SizeOf(tBaseAction)); + move(src^,result^,count*SizeOf(tBaseAction)) +end; + +procedure CloneMacro(var dst:pMacroRecord; src:pMacroRecord); +begin + if (src^.flags and ACF_ASSIGNED)<>0 then + begin + move(src^,dst^,SizeOf(tMacroRecord)); + dst^.ActionList:=CloneActionList(src^.ActionList,src^.ActionCount); + end; +end; + +function tMacroList.Clone:tMacroList; +var + src,dst:pMacroRecord; + i:integer; + cnt:integer; +begin + result:=nil; + + if fMacroList<>nil then + begin + cnt:=0; + for i:=0 to fMacroCount-1 do + if (fMacroList^[i].flags and ACF_ASSIGNED)<>0 then + inc(cnt); + if cnt>0 then + begin + result:=tMacroList.Create(cnt); + + src:=pMacroRecord(self.fMacroList); + dst:=pMacroRecord(result.fMacroList); + + while cnt>0 do + begin + if (src^.flags and ACF_ASSIGNED)<>0 then + begin + CloneMacro(dst,src); + inc(dst); + dec(cnt); + end; + inc(src); + end; + end; + end; + if result=nil then + result:=tMacroList.Create(0); +end; + +procedure tMacroList.ReallocMacroList; +var + i:cardinal; + tmp:pMacroList; +begin + i:=(fMacroCount+MacroListPage)*SizeOf(tMacroRecord); + GetMem(tmp,i); + FillChar(tmp^,i,0); + if fMacroCount>0 then + begin + move(fMacroList^,tmp^,fMacroCount*SizeOf(tMacroRecord)); + FreeMem(fMacroList); + end; + fMacroList:=tmp; + inc(fMacroCount,MacroListPage); +end; + +constructor tMacroList.Create(isize:cardinal); +begin + inherited Create; + + if isizenul + +if /i '%1' == 'fpc' ( + ..\FPC\bin\fpc.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else if /i '%1' == 'fpc64' ( + ..\FPC\bin64\ppcrossx64.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else if /i '%1' == 'xe2' ( + ..\XE2\BIN\dcc32.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else if /i '%1' == 'xe64' ( + ..\XE2\BIN\dcc64.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else ( + ..\delphi\dcc32 %myopts% %dprname% %1 %2 %3 %4 %5 %6 %7 %8 %9 +) +del /Q /S *.res >nul diff --git a/plugins/Actman30/options.rc b/plugins/Actman30/options.rc new file mode 100644 index 0000000000..c37268666e --- /dev/null +++ b/plugins/Actman30/options.rc @@ -0,0 +1,70 @@ +#include "i_const.inc" + +LANGUAGE 0,0 + +IDD_ACTION DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + CONTROL "New" ,IDC_GROUP_NEW ,"MButtonClass",WS_TABSTOP,114, 1,16,16,$18000000 | WS_GROUP + CONTROL "Up" ,IDC_GROUP_UP ,"MButtonClass",WS_TABSTOP,114, 18,16,16,$18000000 + CONTROL "Down" ,IDC_GROUP_DOWN ,"MButtonClass",WS_TABSTOP,114, 34,16,16,$18000000 + CONTROL "Delete",IDC_GROUP_DELETE,"MButtonClass",WS_TABSTOP,114, 68,16,16,$18000000 + CONTROL "Test" ,IDC_GROUP_TEST ,"MButtonClass",WS_TABSTOP,114, 85,16,16,$18000000 + CONTROL "Export",IDC_GROUP_EXPORT,"MButtonClass",WS_TABSTOP,114,102,16,16,$18000000 + CONTROL "Import",IDC_GROUP_IMPORT,"MButtonClass",WS_TABSTOP,114,119,16,16,$18000000 + + CONTROL "", IDC_MACRO_LIST, "SysListView32", + WS_BORDER | WS_TABSTOP | + LVS_NOCOLUMNHEADER | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_EDITLABELS,// | LVS_SINGLESEL, + 0, 2, 110, 132, WS_EX_CONTROLPARENT + + CONTROL "", IDC_ACTION_LIST, "SysListView32", + WS_BORDER | WS_TABSTOP | + LVS_NOCOLUMNHEADER | LVS_SHOWSELALWAYS| LVS_REPORT | LVS_EDITLABELS,// | LVS_SINGLESEL + 0, 138, 110, 86, WS_EX_CONTROLPARENT + + CONTROL "Help" ,IDC_ACTION_HELP ,"MButtonClass",WS_TABSTOP,114,138,16,16,$18000000 | WS_GROUP + CONTROL "New" ,IDC_ACTION_NEW ,"MButtonClass",WS_TABSTOP,114,156,16,16,$18000000 + CONTROL "Up" ,IDC_ACTION_UP ,"MButtonClass",WS_TABSTOP,114,174,16,16,$18000000 + CONTROL "Down" ,IDC_ACTION_DOWN ,"MButtonClass",WS_TABSTOP,114,190,16,16,$18000000 + CONTROL "Delete",IDC_ACTION_DELETE,"MButtonClass",WS_TABSTOP,114,208,16,16,$18000000 + +// PUSHBUTTON "Reset", IDC_RESET, 264, 2, 40, 12 + GROUPBOX "" , -1, 132, 0, 172, 226 + + RTEXT "Action",IDC_STAT_ACTION, 135, 6, 63, 12, SS_CENTERIMAGE + CONTROL "", IDC_ACTION_TYPE, "ComboBoxEx32", + WS_TABSTOP | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWNLIST, 200, 6, 101, 96 +} +/* +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,3,0,1 + PRODUCTVERSION 0,9,0,0 + FILEFLAGSMASK $3F + FILEOS 4 + FILETYPE 2 + FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName","" + VALUE "Comments", "Plugin for managing different Miranda actions "0 + VALUE "FileDescription", "Action manager for Miranda NG"0 + VALUE "FileVersion", "0, 3, 0, 1 "0 + VALUE "InternalName", "ActManager"0 + VALUE "OriginalFilename", "actman.dll"0 + VALUE "ProductName", "Action Manager Dynamic Link Library (DLL)"0 + VALUE "ProductVersion", "0, 9, 0, 0 "0 + VALUE "SpecialBuild", "18.11.2012 "0 + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation",0,1200 + END +END +*/ \ No newline at end of file diff --git a/plugins/Actman30/question.pas b/plugins/Actman30/question.pas new file mode 100644 index 0000000000..9e5f0d1b59 --- /dev/null +++ b/plugins/Actman30/question.pas @@ -0,0 +1,58 @@ +unit question; + +interface +uses windows,messages; + +function ShowQuestion(ask:pWideChar):integer; + +implementation + +uses m_api; + +{$include i_const.inc} +{$resource ask.res} + +const + imp_yes = 1; + imp_yesall = 2; + imp_no = 3; + imp_noall = 4; + imp_append = 5; + +function QuestionDlg(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):LRESULT; stdcall; +var + i:integer; +begin + result:=0; + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + SetDlgItemTextW(Dialog, IDC_ASK,pWideChar(lParam)); + result:=1; + end; + WM_COMMAND: begin + case loword(wParam) of + IDOK : i:=imp_yes; + IDCANCEL : i:=imp_no; + IDC_YESALL: i:=imp_yesall; + IDC_NOALL : i:=imp_noall; + IDC_APPEND: i:=imp_append; + else + i:=0; + end; + if i<>0 then + begin + EndDialog(Dialog,i); + result:=1; + end; + end; + end; +end; + +function ShowQuestion(ask:pWideChar):integer; +begin + result:=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_ASK),0, + @QuestionDlg,TLPARAM(ask)); +end; + +end. diff --git a/plugins/Actman30/readme.txt b/plugins/Actman30/readme.txt new file mode 100644 index 0000000000..0d1c6108b4 --- /dev/null +++ b/plugins/Actman30/readme.txt @@ -0,0 +1,126 @@ +Note +---- +'Actions' is action groups wich can be executed through services +'Subactions' is single simple action like 'Call service', ' rum program' etc. + +Description +----------- +This service plugin can be used for defining, management and executing some +actions. +Action can be executed later through miranda service. + +Settings +-------- +Main window consist of two parts. Left part is for action list and subaction list +for selected action. Navigation buttons for action list and subaction list positioned near +these lists. +'New' - to add new list item +'Delete' - to delete selected item +'Reload' - to reload settings from DB +'Test' - executes currently selected action +'Up','Down' - for place selected subaction upper or lower current position +With DblClick on ag list item you can rename this item + +When action list is not empty, in right side you can see combobox for subaction type selecting. +At this moment only next types supported: + Open contact window + Call service + Execute program + Insert text + Advanced + Link to action + Profile + MessageBox + +-- Open contact window +Just select needed contact from combobox. + +-- Call service +This is one of hard to understand action type. +wParam and lParam comboboxes in upper part are for parameter type. + 'number' - just integer number (decimal or hex started from $ sign) + 'ANSI string' - single-byte character string + 'Unicode string' - double-byte character string + 'Current contact' - mean what parameter is current user handle. + Current user is active window owner + 'Last result' - result from previous action or calling parameter + 'Parameter' - parameter from calling service + 'Structure' - parameter is structure which can be edited in options dialog + but will not saving changes in runtime. + +wParam and lParam in lower part are for values, passed to service. +If service.ini file presents in plugins directory, you can press F1 to see short help +notes for selected from combobox service name. +Most upper part, 'result action' is for action, what we must to do with result: +show in popup, in message window or paste into text. +Option to translate result are: integer decimal value (signed or not), hex value or +string value (Unicode or ANSI) +'' in service name will be replaced by protocol name for contact handle in paremeter + +-- Execute program +More hard for undestand are upper settings. +Process settings: 'parallel' means executing next subaction or return from executing action +immediately, 'continued' mean what next subaction will be only after finishing this program. +Process time option is for waiting time after that runned process will be shutdowned. +'Current path' mean what program will run with current directory as start directory. +Window options are for starting window view: minimized, normal, maximized etc. +Severl macros can be used in program name: + - parameter + - last result + +-- Insert text +You can work with Clipboard or file/mesage window here. +In field below action type combobox you can write some text which will be inserted +into text field of miranda and other program. +Or, that text can be writed to file or some text can be readed. +If you want help for text formatting, you can press F1. +You can use Variables plugin. If you want it, just mark checkbox. help button can +get help notes for available variables and functions. + +-- Advanced +Most ununderstable block. Upper group is conditions for operation executing. +'Value' is value for comparing last subaction result with it. +Next actions will be if condition is true: +'Math' - mathematic operations with last result and presented in 'value' field value. +After math calculations (or w/o it) can be used next operations: +'Operation' block consist of several operations: + 'BREAK' - break action executing (and return for 'parent' action executing - if exist) + 'JUMP' - jump to subaction with selected name + 'NOP' - not operation + +As 'Math' alternative, you can use Variables plugin scripts. +Script can be writed in text field below and checked by pressing 'Vars' button. +Variables %subject% and %extratext% can be used in the script. + +-- Call chain +Select action from combobox below. This action will be executed. After that next subaction +will be executed. + +-- Database +This subaction is for database reading/writing (see Operation block). +Value and value type is for type of data, reading or writing from/to database. +'Last result' mean that value is result of previous action. +Group of radioboxes is for contact type. + 'Own settings' - all settings only for our contact (our profle settings) + 'Parameter' - settings for contact with handle, passed from start parameter + 'Last result' - contact handle is result of last action + 'Manual' - contact handle selected from combobox +'' in module name will be replaced with contact protocol name + +-- MessageBox + Subaction uses for standard windows MessageBox showing. text will be replaced +by last result value. + +Using +----- +Executing action from option dialog is possible but not recommended. +First way is assign action to button for toolbar (maybe through modern clist skin engine) +Second way is assign action to hotkey (miranda core not so good for this now) +Third way is to insert action into menu by other plugin. +Pluginmaker Vasilich wrote his plugin (UserActions) which works with ActMan and gives +access to ability to assign actions to some controls (menu, toolbar, hotkey). + +Byte/Word/DWord - numeric integer data +byte/word pointers - pointers to some data (really, like ANSI/Unicode strings) +byte/word array - array of mixed data (really, like ANSI/Unicode strings) +last result/param - current working data = dword diff --git a/plugins/Actman30/services.ini b/plugins/Actman30/services.ini new file mode 100644 index 0000000000..1366cf950d --- /dev/null +++ b/plugins/Actman30/services.ini @@ -0,0 +1,523 @@ +;Small Service list +;if wparam or lparam consists of list, "|" is separator +;in list: if translation not needed, just add space before help +;numeric parameter format: numberhelp +;'hContact' will setup "Current contact" feature +;'structure' will setup "structure" feature +;'Unicode' as first word will setup "Unicode text" feature +; not sure what next are usable +;'parameter' will setup "Parameter" feature +;'result' will setup "last result" feature +;if "return" starts from int/hex/str/struct then separator, result type will set + + +;[Event:Event (name or constant] +;alias=constant name +;descr=text +;plugin=placement (including "core" and empty = "unknown" +;wparam= +;lparam= + +;full: full structure, with aliases +;short: smallest needed structure +;descr: structure description +;plugin: where defined + +[Service:CListFrames/HideALLFramesTB] +alias=MS_CLIST_FRAMES_HIDEALLFRAMESTB +wparam=0 +lparam=0 +return=int 0, if successful +descr=Hide All Titlebars + +[Service:CListFrames/ShowALLFrames] +alias=MS_CLIST_FRAMES_SHOWALLFRAMES +wparam=0 +lparam=0 +return=int 0, if successful +descr=Show All Frames + +[Service:CListFrames/ShowALLFramesTB] +alias=MS_CLIST_FRAMES_SHOWALLFRAMESTB +wparam=0 +lparam=0 +return=int 0, if successful +descr=Show All Titlebars + +[Service:CList/MenuBuildContact] +alias=MS_CLIST_MENUBUILDCONTACT +wparam=hContact +lparam=0 +return=int hMenu handle +descr=Built the context menu for a specific contact. Menu should be DestroyMenu()ed after done + +[Service:CList/SetHideOffline] +alias=MS_CLIST_SETHIDEOFFLINE +wparam=0 Show All Users|1 Show only Online Users|-1 Toggle status +lparam=0 +return=int 0, if successful +descr=Change 'hide offline contacts' option value + +[Service:CList/SetStatusMode] +alias=MS_CLIST_SETSTATUSMODE +wparam=40071 Offline|40072 Online|40073 Away|40074 DND|40075 NA|40076 Occupied|40077 Free for Chat|40078 Invisible|40079 On the Phone|40080 Out to Lunch +lparam=0 +return=int 0, if successful +descr=Set global status + +[Service:CList/ShowHide] +alias=MS_CLIST_SHOWHIDE +wparam=0 +lparam=0 +return=int 0, if successful +descr=Switch contactlist status + +[Service:CloseAction] +wparam=0 +lparam=0 +descr=Closes Miranda + +[Service:Console/Show/Hide] +wparam=0 +lparam=0 +plugin=Console (console.dll) +Show or hide netlog console window + +[Service:DB/Contact/GetCount] +alias=MS_DB_CONTACT_GETCOUNT +wparam=0 +lparam=0 +return=int Value +descr=Returns contact amount, excluding user account + +[Service:DB/Module/Delete] +alias=MS_DB_MODULE_DELETE +wparam=0 +lparam=Ansi Text +descr=Removes all settings for the specified module + +[Service:DBEditorpp/Import] +alias=MS_DBEDIT_IMPORT +wparam=hContact +lparam=Ansi Text +return=int 0 +descr=Import settings/contacts from file +plugin=Database Editor++ (dbeditorpp.dll) + +[Service:DBEditorpp/MenuCommand] +alias=MS_DBEDIT_MENUCOMMAND +wparam=0 +lparam=0 +return=int 0 +plugin=Database Editor++ (dbeditorpp.dll) +descr=Opens or activate database editor + +[Service:FindAdd/FindAddCommand] +alias=MS_FINDADDFINDADD +wparam=0 +lparam=0 +return=int 0 +descr=Opens or activate user search dialog + +[Service:FtMgr/Show] +wparam=0 +lparam=0 +return=int 0 +descr=displays File Transfer window + +[Service:Help/AboutCommand] +wparam=0 on Desktop|parent window handle +lparam=0 +descr=Show "About..." window + +[Service:Help/IndexCommand] +wparam=0 +lparam=0 +descr=Open support (originaly - Miranda wiki) page + +[Service:Help/WebsiteCommand] +wparam=0 +lparam=0 +descr=Go to Miranda Homepage + +[Service:Help/BugCommand] +wparam=0 +lparam=0 +descr=Open bug report page + +[Service:History/ShowContactHistory] +alias=MS_HISTORY_SHOWCONTACTHISTORY +wparam=0 System|hContact +lparam=0 +descr=Shows contact history or (wParam=0) system history + +[Service:History++/EmptyHistory] +alias=MS_HPP_EMPTYHISTORY +wparam=hContact +lparam=0 +plugin=History++ (historypp.dll) +descr=Erases contact's history. hContact can be NULL(0) to empty system history + +[Service:History++/ShowGlobalSearch] +alias=MS_HPP_SHOWGLOBALSEARCH +wparam=0 +lparam=0 +plugin=History++ (historypp.dll) +descr=Show Global history search window. If already opened, bring it to front. + +[Service:Ignore/Ignore] +alias=MS_IGNORE_IGNORE +wparam=hContact +lparam=-1 Ignore all|1 Ignore messages|2 Ignore URLs|3 Ignore files|4 Ignore User Online|5 Ignore requests|6 Ignore 'You were added' +return=int 0, if successful +descr=Ignore Contact + +[Service:Ignore/Unignore] +alias=MS_IGNORE_UNIGNORE +wparam=hContact +lparam=-1 Ignore all|1 Ignore messages|2 Ignore URLs|3 Ignore files|4 Ignore User Online|5 Ignore requests|6 Ignore 'You were added' +return=int 0, if successful +descr=Unignore Contact + +[Service:Miranda/System/Restart] +alias=MS_SYSTEM_RESTART +wparam=0 restart in default profile or profile manager|1 restart with current profile +lparam=0 +descr=Restarts Miranda + +[Service:mRadio/PlayStop] +alias=MS_RADIO_PLAYSTOP +wparam=hContact|Station name +lparam=0 wParam is Handle|1 wParam is Ansi station name|2 wParam is Unicode station name +descr=Starting or stopping radio station + +[Service:MyDetails/CicleThroughtProtocols] +alias=MS_MYDETAILS_CICLE_THROUGHT_PROTOCOLS +wparam=0 Stop cycle|1 Start cycle +lparam=0 +return=int 0, if successful +plugin=My Details (mydetails.dll) +descr=Start/stops the cycling throught protocols + +[Service:MyDetails/SetMyAvatarUI] +alias=MS_MYDETAILS_SETMYAVATARUI +wparam=0 +lparam=0 All protocols|Protocol +return=signed -2 if proto can't set this, -1 on protocol not found, else 0 +plugin=My Details (mydetails.dll) +descr=Shows a dialog to set the avatar for all possible protocols + +[Service:MyDetails/ShowNextProtocol] +alias=MS_MYDETAILS_SHOWNEXTPROTOCOL +wparam=0 +lparam=0 +return=int 0, if successful +plugin=My Details (mydetails.dll) +descr=Shows the next protocol in the frame + +[Service:MyDetails/ShowPreviousProtocol] +alias=MS_MYDETAILS_SHOWPREVIOUSPROTOCOL +wparam=0 +lparam=0 +return=int 0, if successful +plugin=My Details (mydetails.dll) +descr=Shows the previous protocol in the frame + +[Service:Options/OptionsCommand] +wparam=0 +lparam=0 +descr=Open Options dialog + +[Service:Opt/OpenOptions] +alias=MS_OPT_OPENOPTIONS +wparam=0 +lparam=structure|0|dword|b.ptr|b.ptr|b.ptr| +return=int 0, if successful +descr=Opens the options dialog, optionally at the specified page + +[Service:PackUpdater/CheckUpdates] +wparam=0 +lparam=0 +plugin=Pack Updater (packupdater.dll) +descr=Check for updates + +[Service:PackUpdater/EmptyFolder] +wparam=0 +lparam=0 with confirmation| 1 - without confirmation +plugin=Pack Updater (packupdater.dll) +descr=Empty updater download folder + +[Service:Popup/EnableDisableMenuCommand] +wparam=0 +lparam=0 +plugin=Popup Plus (popup.dll) +descr=Enables or disables PopUp windows + +[Service:Popup/ShowMessage] +alias=MS_POPUP_SHOWMESSAGE +wparam=Ansi Text +lparam=1 Warning|2 Notify|3 Error +return=int 0, if successful +plugin=YAPP or PopUp +descr=Popup window + +[Service:Popup/ShowMessageW] +alias=MS_POPUP_SHOWMESSAGEW +wparam=Unicode Text +lparam=1 Warning|2 Notify|3 Error +return=int 0, if successful +plugin=YAPP only +descr=Popup window + +[Service:Popup/ToggleEnabled] +wparam=0 +lparam=0 +plugin=YAPP (yapp.dll) +descr=Enables or disables PopUp windows + +[Service:Proto/CallContactService] +alias=MS_PROTO_CALLCONTACTSERVICE +wparam=0 +lparam=structure|0|native|b.ptr|native|native| +return=result of protocol service call +descr=send a general request through the protocol chain for a contact + +[Service:Protos/ShowAccountManager] +alias=MS_PROTO_SHOWACCMGR +wparam=0 +lparam=0 +descr=displays the Account Manager + +[Service:QuickContacts/ShowDialog] +alias=MS_QC_SHOW_DIALOG +wparam=0 +lparam=0 +plugin=Quick Contacts (quickcontacts.dll) +descr=Show the dialog to select the contact + +[Service:QuickSearch_PLUGIN/Show] +wparam=0|filter text +lparam=0 wParam is unicode|1 wParam is Ansi|2 Reserved +plugin=Quick Search (Mod) (quicksearch.dll) +descr= + +[Service:Skin/Sounds/Play] +alias=MS_SKIN_PLAYSOUND +wparam=0 +lparam=Name +descr=Plays sound added through Skin/Sounds/AddNew. If sound not found, standard Windows sound plays + +[Service:SREMail/SendCommand] +alias=MS_EMAIL_SENDEMAIL +wparam=hContact +lparam=0 +return=int 0, if successful +descr=Send Email to contact + +[Service:SRFile/GetReceivedFilesFolder] +alias=MS_FILE_GETRECEIVEDFILESFOLDER +wparam=hContact +lparam=structure|*b.arr 300| +return=struct +descr=Returns the received files folder for a contact + +[Service:SRFile/OpenContRecDir] +wparam=hContact +lparam=0 +descr=Open contact received file directory + +[Service:SRFile/SendCommand] +alias=MS_FILE_SENDFILE +wparam=hContact +lparam=0 +return=int 0, if successful +descr=Send file to contact. + +[Service:SRMsg/SendCommand] +alias=MS_MSG_SENDMESSAGE +wparam=hContact;parameter +lparam=0 +descr=Opens message window for contact with handle in wparam + +[Service:StopSpam/RemoveTempContacts] +alias=MS_STOPSPAM_REMTEMPCONTACTS +wparam=0 +lparam=0 +return=int 0 +plugin=StopSpam (stopspam.dll) +descr=remove all temporary contacts from db + +[Service:SV_Avatars/ContactOptions] +alias=MS_AV_CONTACTOPTIONS +wparam=hContact +lparam=0 +plugin=Avatar service (AVS.dll) +descr=Call avatar option dialog for contact + +[Service:SV_Avatars/SetAvatar] +alias=MS_AV_SETAVATAR +wparam=hContact +lparam=0|Filename +plugin=Avatar service (AVS.dll) +descr=Set (and optionally protect) a local contact picture for the given hContact. If lParam = NIL, the service will open a file selection dialog. + +[Service:UserInfo/ShowDialog] +alias=MS_USERINFO_SHOWDIALOG +wparam=0 System|hContact +lparam=0 +plugin=Extended UserInfo (uinfoex.dll) +descr=Shows contact property window. + +[Service:Utils/OpenURL] +alias=MS_UTILS_OPENURL +wparam=0 Open URL in current window +lparam=URL +return=int 0 +descr=Open URL in default browser + +[Service:Versioninfo/GetInfo] +alias=MS_VERSIONINFO_GETINFO +wparam=0 With formating|1 Don't use formating +lparam=structure|*b.ptr 0| +plugin=VersionInfo +return=int 0, if succesful +descr=Returns a string containing the versioninfo post + +[Service:VersionInfo/MenuCommand] +alias=MS_VERSIONINFO_MENU_COMMAND +wparam=0 +lparam=0 +plugin=VersionInfo +descr=Show or save (call default action) Modules version Info + +[Service:WATrack/ShowMusicInfo] +alias=MS_WAT_SHOWMUSICINFO +wparam=0 +lparam=0 +plugin=Winamp Track (watrack.dll) +descr=Show popup or Info window with current music information. + +[Service:WATrack/MakeReport] +alias=MS_WAT_MAKEREPORT +wparam=log filename| +lparam=report filename| +return=int 0, if unsuccessful +plugin=Winamp Track (watrack.dll) +descr=Create report from log and run it (if option is set). If wParam or lParam is empty then file names from options are used. + +[Service:WhenWasIt/List/Show] +alias=MS_WWI_LIST_SHOW +wparam=0 +lparam=0 +plugin=WhenWasIt Birthday Reminder (whenwasit.dll) +descr=display birthdays window + +[Service:/Bookmarks] +wparam=0 +lparam=0 +plugin=Jabber +descr=Manage Jabber Bookmarks + +[Service:/SetAwayMsg] +alias=PS_SETAWAYMSG +wparam=40071 Offline|40072 Online|40073 Away|40074 DND|40075 NA|40076 Occupied|40077 Free for Chat|40078 Invisible|40079 On the Phone|40080 Out to Lunch +lparam=text +return=int 0, if successful +descr=Set status message + +[Service:/SetStatus] +alias=PS_SETSTATUS +wparam=40071 Offline|40072 Online|40073 Away|40074 DND|40075 NA|40076 Occupied|40077 Free for Chat|40078 Invisible|40079 On the Phone|40080 Out to Lunch +lparam=0 +return=int 0, if successful +descr=Set protocol status + +[Service:/SetXStatus] +alias=PS_ICQ_SETCUSTOMSTATUS +;alias=JS_SETXSTATUSEX +wparam=0 None|1 Angry|2 Taking a bath|3 Tired|4 Party|5 Drinking beer|6 Thinking|7 Eating|8 Watching TV|9 Meeting|10 Coffee|11 Listening to music|12 Business|13 Shooting|14 Having fun|15 On the phone|16 Gaming|17 Studying|18 Shopping|19 Feeling sick|20 Sleeping|21 Surfing|22 Browsing|23 Working|24 Typing|25 Picnic|26 Cooking|27 Smoking|28 I'm high|29 On WC|30 To be or not to be|31 Watching pro7 on TV|32 Love +lparam=0 +plugin=ICQ +descr=Sets owner current custom status + +[Service:/ShowXStatusDetails] +alias=MS_XSTATUS_SHOWDETAILS +wparam=0|hContact +lparam=0 +plugin=ICQ +descr=Display XStatus detail + +[Event:Actions/Changed] +alias=ME_ACT_CHANGED +plugin=ActMan +descr='action group list was changed: some was added or deleted' +wparam=ACTM_NEW|ACTM_DELETE|ACTM_RELOAD|ACTM_RENAME|ACTM_SORT|ACTM_LOADED +lparam=0 + +[Event:CList/PreBuildContactMenu] +alias=ME_CLIST_PREBUILDCONTACTMENU +plugin=contact list +descr='the context menu for a contact is about to be built' +wparam=hContact +lparam=0 + +[Event:CList/DoubleClicked] +alias=ME_CLIST_DOUBLECLICKED +plugin=contact list +descr='double click on the CList' +wparam=hContact +lparam=0 + +[Event:DB/Contact/Added] +alias=ME_DB_CONTACT_ADDED +plugin=database driver +descr='New contact added to database' +wparam=hContact +lparam=0 + +[Event:DB/Contact/Deleted] +alias=ME_DB_CONTACT_DELETED +plugin=database driver +descr='Contact deleting' +wparam=hContact +lparam=0 + +[Structure:CCSDATA] +; variant: Handle -> param +full=0| \ +param (HANDLE) hContact| \ +b.ptr (const char *) szProtoService| \ +native (WPARAM) wParam| \ +native (LPARAM) lParam| +short=0|param|b.ptr|native|native| +descr= +plugin= + +[Const:CALLSERVICE_NOTFOUND] +value=$80000000 +value64=$8000000000000000 +;signed=0 +;plugin=core + +[Const:ID_STATUS_OFFLINE] +value=40071 +[Const:ID_STATUS_ONLINE] +value=40072 +[Const:ID_STATUS_AWAY] +value=40073 +[Const:ID_STATUS_DND] +value=40074 +[Const:ID_STATUS_NA] +value=40075 +[Const:ID_STATUS_OCCUPIED] +value=40076 +[Const:ID_STATUS_FREECHAT] +value=40077 +[Const:ID_STATUS_INVISIBLE] +value=40078 +[Const:ID_STATUS_ONTHEPHONE] +value=40079 +[Const:ID_STATUS_OUTTOLUNCH] +value=40080 +[Const:ID_STATUS_IDLE] +value=40081 diff --git a/plugins/Actman30/tasks/i_opt_dlg.inc b/plugins/Actman30/tasks/i_opt_dlg.inc new file mode 100644 index 0000000000..c8025c278d --- /dev/null +++ b/plugins/Actman30/tasks/i_opt_dlg.inc @@ -0,0 +1,536 @@ +{} +const + settings:HWND = 0; + +var + OldTableProc:pointer; + onactchanged:THANDLE; + +const + ACI_NEW :PAnsiChar = 'ACI_New'; + ACI_DELETE :PAnsiChar = 'ACI_Delete'; + +procedure CheckTaskList(Dialog:HWND;enable:boolean); +begin + if not enable then + enable:=SendMessage(GetDlgItem(Dialog,IDC_TASK_NAME),LVM_GETITEMCOUNT,0,0)>0; + + EnableWindow(GetDlgItem(Dialog,IDC_TASK_ABSOLUTE ),enable); + EnableWindow(GetDlgItem(Dialog,IDC_TASK_DATEV ),enable); + EnableWindow(GetDlgItem(Dialog,IDC_TASK_DAYSV ),enable); + EnableWindow(GetDlgItem(Dialog,IDC_TASK_TIMEV ),enable); + EnableWindow(GetDlgItem(Dialog,IDC_TASK_REPEAT ),enable); + EnableWindow(GetDlgItem(Dialog,IDC_TASK_INTERVAL ),enable); + EnableWindow(GetDlgItem(Dialog,IDC_TASK_BREAK ),enable); + EnableWindow(GetDlgItem(Dialog,IDC_TASK_EVENT ),enable); + EnableWindow(GetDlgItem(Dialog,IDC_TASK_ONCE ),enable); + if not enable then + begin + ShowWindow(GetDlgItem(Dialog,IDC_TASK_DAYST),SW_HIDE); + ShowWindow(GetDlgItem(Dialog,IDC_TASK_DAYSV),SW_HIDE); + end; +end; + +procedure FillTaskList(wnd:HWND); +var + i:integer; + li:LV_ITEMW; +begin + SendMessage(wnd,LVM_DELETEALLITEMS,0,0); + for i:=0 to MaxTasks-1 do + begin + with TaskList[i] do + begin + if (flags and ACF_ASSIGNED)<>0 then + begin + li.mask :=LVIF_TEXT+LVIF_PARAM; + li.iSubItem:=0; + li.iItem :=i; + li.lParam :=i; + li.pszText :=name; + li.iItem :=SendMessageW(wnd,LVM_INSERTITEMW,0,LPARAM(@li)); + ListView_SetCheckState(wnd,li.iItem,(flags and ACF_DISABLED)=0); + end; + end; + end; + ListView_SetItemState(wnd,0, + LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); +end; + +procedure ClearTaskData(Dialog:HWND); +var + st:TSystemTime; +begin + SendMessage(GetDlgItem(Dialog,IDC_TASK_ABSOLUTE),CB_SETCURSEL,0,0); + CheckDlgButton(Dialog,IDC_TASK_BREAK ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_TASK_EVENT ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_TASK_ONCE ,BST_UNCHECKED); + EnableWindow(GetDlgItem(Dialog,IDC_TASK_ONCE),false); + + SetDlgItemInt(Dialog,IDC_TASK_DAYSV ,1,false); + SetDlgItemInt(Dialog,IDC_TASK_REPEAT,0,false); + + FillChar(st,SizeOf(st),0); + SendDlgItemMessage(Dialog,IDC_TASK_TIMEV ,DTM_SETSYSTEMTIME,GDT_VALID,lParam(@st)); + SendDlgItemMessage(Dialog,IDC_TASK_INTERVAL,DTM_SETSYSTEMTIME,GDT_VALID,lParam(@st)); +{ + ShowWindow(GetDlgItem(Dialog,IDC_TASK_DATET),SW_SHOW); + ShowWindow(GetDlgItem(Dialog,IDC_TASK_DATEV),SW_SHOW); + ShowWindow(GetDlgItem(Dialog,IDC_TASK_DAYST),SW_HIDE); + ShowWindow(GetDlgItem(Dialog,IDC_TASK_DAYSV),SW_HIDE); +} +end; + +procedure ShowDateType(Dialog:HWND;start:integer); +var + sh1,sh2,sh3:integer; +begin + case start of + 1: begin // start after + sh1:=SW_HIDE; + sh2:=SW_SHOW; + sh3:=SW_SHOW; + end; + 2: begin // start from + sh1:=SW_SHOW; + sh2:=SW_HIDE; + sh3:=SW_SHOW; + end; + else + begin +// 3: begin // start immediately + sh1:=SW_HIDE; + sh2:=SW_HIDE; + sh3:=SW_HIDE; + end; + end; + + ShowWindow(GetDlgItem(Dialog,IDC_TASK_DATET),sh1); + ShowWindow(GetDlgItem(Dialog,IDC_TASK_DATEV),sh1); + ShowWindow(GetDlgItem(Dialog,IDC_TASK_DAYST),sh2); + ShowWindow(GetDlgItem(Dialog,IDC_TASK_DAYSV),sh2); + ShowWindow(GetDlgItem(Dialog,IDC_TASK_TIMET),sh3); + ShowWindow(GetDlgItem(Dialog,IDC_TASK_TIMEV),sh3); +end; + +procedure ShowTaskData(Dialog:HWND; item:integer=-1); +var + st:TSystemTime; + lwnd:HWND; + start:integer; +begin + lwnd:=settings; + settings:=0; + + ClearTaskData(Dialog); + + with TaskList[LV_GetLParam(GetDlgItem(Dialog,IDC_TASK_NAME),item)] do + begin + // flags + + if (flags and TCF_NONZEROBREAK)<>0 then + CheckDlgButton(Dialog,IDC_TASK_BREAK,BST_CHECKED); + if (flags and TCF_MAKEEVENT)<>0 then + CheckDlgButton(Dialog,IDC_TASK_EVENT,BST_CHECKED); + if (flags and TCF_EVENTONCE)<>0 then + CheckDlgButton(Dialog,IDC_TASK_ONCE,BST_CHECKED); + + EnableWindow(GetDlgItem(Dialog,IDC_TASK_ONCE), + IsDlgButtonChecked(Dialog,IDC_TASK_EVENT)<>BST_UNCHECKED); + + // action + CB_SelectData(GetDlgItem(Dialog,IDC_TASK_ACTION),action); + // times + FileTimeToSystemTime(starttime,st); + + if (flags and TCF_IMMEDIATELY)<>0 then + begin + start:=3; + end + else if (flags and TCF_ABSOLUTE)<>0 then + begin + start:=2; + SendDlgItemMessage(Dialog,IDC_TASK_DATEV,DTM_SETSYSTEMTIME,GDT_VALID,lParam(@st)) + end + else + begin + start:=1; + SetDlgItemInt(Dialog,IDC_TASK_DAYSV,dayoffset,false); + end; + CB_SelectData(GetDlgItem(Dialog,IDC_TASK_ABSOLUTE),start); + + SendDlgItemMessage(Dialog,IDC_TASK_TIMEV,DTM_SETSYSTEMTIME,GDT_VALID,lParam(@st)); + + SetDlgItemInt(Dialog,IDC_TASK_REPEAT,count,true); + + FileTimeToSystemTime(interval,st); + SendDlgItemMessage(Dialog,IDC_TASK_INTERVAL,DTM_SETSYSTEMTIME,GDT_VALID,lParam(@st)); + SetDlgItemInt(Dialog,IDC_TASK_INTDAYS,intdays,false); + end; + + ShowDateType(Dialog,start); + + settings:=lwnd; +end; + +procedure SaveTaskData(Dialog:HWND; item:integer=-1); +var + wnd:HWND; + li:LV_ITEM; + st,st1:TSystemTime; + tmp:longbool; +begin + wnd:=GetDlgItem(Dialog,IDC_TASK_NAME); + + if item<0 then + li.iItem:=SendMessage(wnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED) // LVNI_SELECTED + else + li.iItem:=item; + + if li.iItem>=0 then + begin + li.mask :=LVIF_PARAM; + li.iSubItem :=0; + SendMessageW(wnd,LVM_GETITEMW,0,LPARAM(@li)); + + with TaskList[li.lParam] do + begin + if (flags and ACF_ASSIGNED)<>0 then + begin + flags:=ACF_ASSIGNED; + // flags + if ListView_GetCheckState(wnd,li.iItem)=0 then + flags:=flags or ACF_DISABLED; + + if IsDlgButtonChecked(Dialog,IDC_TASK_BREAK)<>BST_UNCHECKED then + flags:=flags or TCF_NONZEROBREAK; + if IsDlgButtonChecked(Dialog,IDC_TASK_EVENT)<>BST_UNCHECKED then + begin + flags:=flags or TCF_MAKEEVENT; + if IsDlgButtonChecked(Dialog,IDC_TASK_ONCE )<>BST_UNCHECKED then + flags:=flags or TCF_EVENTONCE; + end; + // action + action:=CB_GetData(GetDlgItem(Dialog,IDC_TASK_ACTION)); + // times + SendDlgItemMessage(Dialog,IDC_TASK_TIMEV,DTM_GETSYSTEMTIME,0,lParam(@st)); + + case CB_GetData(GetDlgItem(Dialog,IDC_TASK_ABSOLUTE)) of + 1: begin + dayoffset:=GetDlgItemInt(Dialog,IDC_TASK_DAYSV,tmp,false); + end; + 2: begin + flags:=flags or TCF_ABSOLUTE; + SendDlgItemMessage(Dialog,IDC_TASK_DATEV,DTM_GETSYSTEMTIME,0,lParam(@st1)); + st.wYear :=st1.wYear; + st.wMonth :=st1.wMonth; + st.wDayOfWeek:=st1.wDayOfWeek; + st.wDay :=st1.wDay; + end; + 3: begin + flags:=flags or TCF_IMMEDIATELY; + end; + end; + SystemTimeToFileTime(st,starttime); + + count:=GetDlgItemInt(Dialog,IDC_TASK_REPEAT,tmp,true); + + SendDlgItemMessage(Dialog,IDC_TASK_INTERVAL,DTM_GETSYSTEMTIME,0,lParam(@st)); + SystemTimeToFileTime(st,interval); + intdays:=GetDlgItemInt(Dialog,IDC_TASK_INTDAYS,tmp,false); + end; + end; + end; +end; + +function NewTask(Dialog:HWND;item:integer=-1):integer; +var + wnd:HWND; + li:LV_ITEMW; +begin + wnd:=GetDlgItem(Dialog,IDC_TASK_NAME); + if item<0 then + li.iItem :=SendMessage(wnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED)+1 + else + li.iItem :=item; + li.iSubItem:=0; + li.mask :=LVIF_TEXT + LVIF_PARAM; + li.lParam :=CreateNewTask; + li.pszText :=TranslateW('Task sample'); + result:=SendMessageW(wnd,LVM_INSERTITEMW,0,LPARAM(@li)); + + ListView_SetCheckState(wnd,li.iItem, + (TaskList[li.lParam].flags and ACF_DISABLED)=0); + StrDupW(TaskList[li.lParam].name,li.pszText); + + CheckTaskList(Dialog,true); + + if li.iItem=0 then + Listview_SetItemState(wnd,0,LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); +end; + +function DeleteTask(Dialog:HWND):integer; +var + li:LV_ITEM; + wnd:HWND; + i:integer; +begin + result:=0; + wnd:=GetDlgItem(Dialog,IDC_TASK_NAME); + for i:=ListView_GetItemCount(wnd)-1 downto 0 do + begin + if ListView_GetItemState(wnd,i,LVIS_SELECTED)<>0 then + begin + li.iItem :=i; + li.mask :=LVIF_PARAM; + li.iSubItem :=0; + SendMessageW(wnd,LVM_GETITEMW,0,LPARAM(@li)); + + TaskList[li.lParam].flags:=TaskList[li.lParam].flags and not ACF_ASSIGNED; + + SendMessage(wnd,LVM_DELETEITEM,i,0); + end; + end; + Listview_SetItemState(wnd,0,LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); + + CheckTaskList(Dialog,false); +end; + +function NewHKTableProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + i:integer; +begin + result:=0; + case hMessage of + WM_KEYDOWN: begin + if (lParam and (1 shl 30))=0 then + begin + case wParam of + VK_F2: begin + i:=SendMessage(Dialog,LVM_GETNEXTITEM,-1,LVNI_FOCUSED); + if i>=0 then + PostMessageW(Dialog,LVM_EDITLABELW,i,0); + exit; + end; + + VK_INSERT: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_TASK_NEW,0); + exit; + end; + + VK_DELETE: begin + PostMessage(GetParent(Dialog),WM_COMMAND,(BN_CLICKED shl 16)+IDC_TASK_DELETE,0); + exit; + end; + end; + end; + end; + end; + result:=CallWindowProc(OldTableProc,Dialog,hMessage,wParam,lParam); +end; + +procedure FillStartTimeList(wnd:HWND); +begin + SendMessage(wnd,CB_RESETCONTENT,0,0); + CB_AddStrDataW(wnd,TranslateW('Starting after' ),1); + CB_AddStrDataW(wnd,TranslateW('Starting from' ),2); + CB_AddStrDataW(wnd,TranslateW('Start immediately'),3); + SendMessage(wnd,CB_SETCURSEL,0,0); +end; + +procedure FillActionList(wnd:HWND); +var + ptr,ptr1:pChain; + i,cnt:integer; +begin + cnt:=CallService(MS_ACT_GETLIST,0,LPARAM(@ptr)); + SendMessage(wnd,CB_RESETCONTENT,0,0); + if cnt>0 then + begin + ptr1:=ptr; + inc(pbyte(ptr),4); + for i:=0 to cnt-1 do + begin + CB_AddStrDataW(wnd,ptr^.descr,ptr^.id); + inc(ptr); + end; + + CallService(MS_ACT_FREELIST,0,LPARAM(ptr1)); + SendMessage(wnd,CB_SETCURSEL,0,0); + end; +end; + +function ActListChange(wParam:WPARAM;lParam:LPARAM):integer; cdecl; +begin + result:=0; + if settings<>0 then + FillActionList(GetDlgItem(settings,IDC_TASK_ACTION)); +end; + +procedure SetIcons(Dialog:HWND); +var + ti:TTOOLINFOW; + hwndTooltip:HWND; +begin + hwndTooltip:=CreateWindowW(TOOLTIPS_CLASS,nil,TTS_ALWAYSTIP, + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + Dialog,0,hInstance,nil); + + FillChar(ti,SizeOf(ti),0); + ti.cbSize :=sizeof(TOOLINFO); + ti.uFlags :=TTF_IDISHWND or TTF_SUBCLASS; + ti.hwnd :=dialog; + ti.hinst :=hInstance; +{ + ti.uId :=GetDlgItem(Dialog,IDC_EVENT_HELP); + ti.lpszText:=TranslateW('Help'); + SendMessage(ti.uId,BM_SETIMAGE,IMAGE_ICON, + CallService(MS_SKIN_LOADICON,SKINICON_OTHER_HELP,0)); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,LPARAM(@ti)); +} + ti.uId :=GetDlgItem(Dialog,IDC_TASK_NEW); + ti.lpszText:=TranslateW('New'); + SetButtonIcon(ti.uId,ACI_NEW); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,LPARAM(@ti)); + + ti.uId :=GetDlgItem(Dialog,IDC_TASK_DELETE); + ti.lpszText:=TranslateW('Delete'); + SetButtonIcon(ti.uId,ACI_DELETE); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,LPARAM(@ti)); +end; + +function DlgProcOpt(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + wnd:HWND; + lv:LV_COLUMNW; + li:LV_ITEMW; + i:integer; +begin + result:=0; + case hMessage of + WM_CLOSE: begin + UnhookEvent(onactchanged); + settings:=0; + end; + + WM_INITDIALOG: begin + settings:=0; + wnd:=GetDlgItem(Dialog,IDC_TASK_NAME); + SendMessage(wnd,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_CHECKBOXES,LVS_EX_CHECKBOXES); + SendMessage(wnd,LVM_SETUNICODEFORMAT,1,0); + zeromemory(@lv,sizeof(lv)); + lv.mask:=LVCF_WIDTH; + lv.cx :=110; + SendMessageW(wnd,LVM_INSERTCOLUMNW ,0,tlparam(@lv)); + SendMessageW(wnd,LVM_SETCOLUMNWIDTH,0,LVSCW_AUTOSIZE_USEHEADER); + + CreateUpDownControl( + WS_CHILD+WS_BORDER+WS_VISIBLE+UDS_ARROWKEYS+UDS_SETBUDDYINT+UDS_ALIGNRIGHT, + 190,112,14,18, + Dialog, IDC_TASK_UPDOWN, hInstance, GetDlgItem(Dialog,IDC_TASK_REPEAT), + 10000, -1, 0); + + OldTableProc:=pointer(SetWindowLongPtrW(wnd,GWL_WNDPROC,LONG_PTR(@NewHKTableProc))); + TranslateDialogDefault(Dialog); + + SetIcons(Dialog); + + FillActionList(GetDlgItem(Dialog,IDC_TASK_ACTION)); + FillStartTimeList(GetDlgItem(Dialog,IDC_TASK_ABSOLUTE)); + FillTaskList(wnd); + CheckTaskList(Dialog,false); + onactchanged:=HookEvent(ME_ACT_CHANGED,@ActListChange); + settings:=Dialog; + end; + + WM_COMMAND: begin + case wParam shr 16 of + CBN_SELCHANGE: begin + ShowDateType(Dialog,CB_GetData(lParam)); + end; + + EN_CHANGE: begin + end; + + BN_CLICKED: begin + case loword(wParam) of + IDC_TASK_NEW : NewTask(Dialog); + IDC_TASK_DELETE: DeleteTask(Dialog); + + IDC_TASK_EVENT: begin + EnableWindow(GetDlgItem(Dialog,IDC_TASK_ONCE), + IsDlgButtonChecked(Dialog,IDC_TASK_EVENT)<>BST_UNCHECKED); + end; + end; + end; + end; + if settings<>0 then + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + + WM_NOTIFY: begin + case integer(PNMHdr(lParam)^.code) of + PSN_APPLY: begin + SaveTaskData(Dialog); + SaveTasks; + SetAllTasks; + end; + + DTN_DATETIMECHANGE: begin + if settings<>0 then + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + + NM_DBLCLK: begin + if PNMListView(lParam)^.iItem>=0 then + PostMessageW(PNMHdr(lParam)^.hWndFrom,LVM_EDITLABELW, + PNMListView(lParam)^.iItem,0); + end; + + LVN_ITEMCHANGED: begin + if PNMLISTVIEW(lParam)^.uChanged=LVIF_STATE then + begin + i:=(PNMLISTVIEW(lParam)^.uOldState and LVNI_FOCUSED)- + (PNMLISTVIEW(lParam)^.uNewState and LVNI_FOCUSED); + + if i>0 then // old focus + SaveTaskData(Dialog,PNMLISTVIEW(lParam)^.iItem) + else if i<0 then // new focus + begin + ShowTaskData(Dialog,PNMLISTVIEW(lParam)^.iItem); + end + else if (settings<>0) and + ((PNMLISTVIEW(lParam)^.uOldState or PNMLISTVIEW(lParam)^.uNewState)=$3000) then + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + + LVN_ENDLABELEDITW: begin + with PLVDISPINFOW(lParam)^ do + begin + if item.pszText<>nil then + begin + item.mask:=LVIF_TEXT; + SendMessageW(hdr.hWndFrom,LVM_SETITEMW,0,TLPARAM(@item)); + + li.iItem :=item.iItem; + li.mask :=LVIF_PARAM; + li.iSubItem :=0; + SendMessageW(hdr.hWndFrom,LVM_GETITEMW,0,TLPARAM(@li)); + with TaskList[li.lParam] do + begin + mFreeMem(name); + StrDupW (name,item.pszText); + end; + end; + end; + result:=1; + end; + end; + end; + end; +end; diff --git a/plugins/Actman30/tasks/i_options.inc b/plugins/Actman30/tasks/i_options.inc new file mode 100644 index 0000000000..527e8d0c88 --- /dev/null +++ b/plugins/Actman30/tasks/i_options.inc @@ -0,0 +1,99 @@ +{} +const + opt_task :PAnsiChar = 'Task'; + opt_tasks :PAnsiChar = 'Tasks'; + opt_count :PAnsiChar = 'numtasks'; + + opt_name :PAnsiChar = 'name'; + opt_flags :PAnsiChar = 'flags'; + opt_action :PAnsiChar = 'action'; + opt_repeat :PAnsiChar = 'repeat'; + opt_days :PAnsiChar = 'dayoffset'; + opt_intdays :PAnsiChar = 'intdays'; + + opt_time_lo :PAnsiChar = 'starttime_lo'; + opt_time_hi :PAnsiChar = 'starttime_hi'; + opt_interval_lo:PAnsiChar = 'interval_lo'; + opt_interval_hi:PAnsiChar = 'interval_hi'; + opt_lastcall_lo:PAnsiChar = 'lastcall_lo'; + opt_lastcall_hi:PAnsiChar = 'lastcall_hi'; + +procedure SaveTasks; +var + section:array [0..63] of AnsiChar; + p,p1:PAnsiChar; + i,amount:integer; +begin + DBDeleteGroup(0,DBBranch,opt_tasks); + amount:=0; + p1:=StrCopyE(section,opt_tasks); + p1^:='/'; inc(p1); + p1:=StrCopyE(p1,opt_task); + for i:=0 to MaxTasks-1 do + begin + if (TaskList[i].flags and ACF_ASSIGNED)=0 then + continue; + + p:=StrEnd(IntToStr(p1,amount)); + p^:='/'; inc(p); + with TaskList[i] do + begin + StrCopy(p,opt_flags ); DBWriteDWord (0,DBBranch,section,flags); + StrCopy(p,opt_name ); DBWriteUnicode(0,DBBranch,section,name); + StrCopy(p,opt_action); DBWriteDWord (0,DBBranch,section,action); + StrCopy(p,opt_repeat); DBWriteWord (0,DBBranch,section,count); + StrCopy(p,opt_days ); DBWriteByte (0,DBBranch,section,dayoffset); + //systemtime to filetime if needs + StrCopy(p,opt_time_lo ); DBWriteDWord(0,DBBranch,section,starttime.dwLowDateTime); + StrCopy(p,opt_time_hi ); DBWriteDWord(0,DBBranch,section,starttime.dwHighDateTime); + StrCopy(p,opt_interval_lo); DBWriteDWord(0,DBBranch,section,interval .dwLowDateTime); + StrCopy(p,opt_interval_hi); DBWriteDWord(0,DBBranch,section,interval .dwHighDateTime); + StrCopy(p,opt_intdays ); DBWriteByte (0,DBBranch,section,intdays); + StrCopy(p,opt_lastcall_lo); DBWriteDWord(0,DBBranch,section,lastcall .dwLowDateTime); + StrCopy(p,opt_lastcall_hi); DBWriteDWord(0,DBBranch,section,lastcall .dwHighDateTime); + end; + inc(amount); + end; + DBWriteByte(0,DBBranch,opt_count,amount); +end; + +function LoadTasks:integer; +var + section:array [0..63] of AnsiChar; + p,p1:PAnsiChar; + i:integer; +begin + MaxTasks:=DBReadByte(0,DBBranch,opt_count); + result:=MaxTasks; + if MaxTasks>0 then + begin + GetMem (TaskList ,MaxTasks*SizeOf(tTaskRec)); + FillChar(TaskList^,MaxTasks*SizeOf(tTaskRec),0); + p1:=StrCopyE(section,opt_tasks); + p1^:='/'; inc(p1); + p1:=StrCopyE(p1,opt_task); + for i:=0 to MaxTasks-1 do + begin + p:=StrEnd(IntToStr(p1,i)); + p^:='/'; inc(p); + + with TaskList[i] do + begin + StrCopy(p,opt_flags ); flags :=DBReadDWord (0,DBBranch,section); + StrCopy(p,opt_name ); name :=DBReadUnicode(0,DBBranch,section); + StrCopy(p,opt_action); action :=DBReadDWord (0,DBBranch,section); + StrCopy(p,opt_days ); dayoffset:=DBReadByte (0,DBBranch,section); + StrCopy(p,opt_repeat); count :=Shortint(DBReadWord(0,DBBranch,section)); + + StrCopy(p,opt_time_lo ); starttime.dwLowDateTime :=DBReadDWord(0,DBBranch,section); + StrCopy(p,opt_time_hi ); starttime.dwHighDateTime:=DBReadDWord(0,DBBranch,section); + StrCopy(p,opt_interval_lo); interval .dwLowDateTime :=DBReadDWord(0,DBBranch,section); + StrCopy(p,opt_interval_hi); interval .dwHighDateTime:=DBReadDWord(0,DBBranch,section); + StrCopy(p,opt_intdays ); intdays:=DBReadByte(0,DBBranch,section); + StrCopy(p,opt_lastcall_lo); lastcall .dwLowDateTime :=DBReadDWord(0,DBBranch,section); + StrCopy(p,opt_lastcall_hi); lastcall .dwHighDateTime:=DBReadDWord(0,DBBranch,section); + // filetime to systemtime if needs + end; + end; + end; +end; diff --git a/plugins/Actman30/tasks/i_service.inc b/plugins/Actman30/tasks/i_service.inc new file mode 100644 index 0000000000..376e75cba0 --- /dev/null +++ b/plugins/Actman30/tasks/i_service.inc @@ -0,0 +1,87 @@ +{} +// wParam: 1/0 (enable/disable), lParam = task name +// works for all tasks with same started name +function TaskEnable(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + i,j:integer; +begin + result:=0; + if lParam=0 then exit; + j:=StrLenW(pWideChar(lParam)); + + for i:=0 to MaxTasks-1 do + begin + if (TaskList[i].flags and ACF_ASSIGNED)<>0 then + begin + if StrCmpW(TaskList[i].name,pWideChar(lParam),j)=0 then + begin + if wParam=0 then // disable + begin + if (TaskList[i].flags and ACF_DISABLED)=0 then + begin + inc(result); + TaskList[i].flags:=TaskList[i].flags or ACF_DISABLED; + if TaskList[i].timer<>0 then + begin + KillTimer(0,TaskList[i].timer); + TaskList[i].timer:=0; + end; + end; + end + else + begin + if (TaskList[i].flags and ACF_DISABLED)<>0 then + begin + inc(result); + TaskList[i].flags:=TaskList[i].flags and not ACF_DISABLED; + SetTask(TaskList[i]); + end; + end; + end; + end; + end; +end; + +function TaskDelete(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + i,j:integer; +begin + result:=0; + if lParam=0 then exit; + j:=StrLenW(pWideChar(lParam)); + + for i:=0 to MaxTasks-1 do + begin + if (TaskList[i].flags and ACF_ASSIGNED)<>0 then + begin + if StrCmpW(TaskList[i].name,pWideChar(lParam),j)=0 then + begin + TaskList[i].flags:=TaskList[i].flags and not ACF_ASSIGNED; + end; + end; + end; +end; + +function TaskCount(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + i,j:integer; +begin + result:=0; + if lParam=0 then exit; + j:=StrLenW(pWideChar(lParam)); + + for i:=0 to MaxTasks-1 do + begin + with TaskList[i] do + begin + if (flags and ACF_ASSIGNED)<>0 then + begin + if StrCmpW(name,pWideChar(lParam),j)=0 then + begin + result:=count; + count:=wParam; + end; + end; + end; + end; +end; diff --git a/plugins/Actman30/tasks/i_task.inc b/plugins/Actman30/tasks/i_task.inc new file mode 100644 index 0000000000..2c860db85f --- /dev/null +++ b/plugins/Actman30/tasks/i_task.inc @@ -0,0 +1,242 @@ +{} +const + ACF_ASSIGNED = $80000000; // Task assigned + ACF_DISABLED = $10000000; // Task disabled + + TCF_ABSOLUTE = $00000001; + TCF_IMMEDIATELY = $00000002; + TCF_NONZEROBREAK = $00000004; + TCF_MAKEEVENT = $00000008; + TCF_EVENTONCE = $00000010; + +const + WM_RESETTASKS = WM_USER+1312; + WM_FIRSTTASK = WM_USER+1313; + WM_LASTTASK = WM_FIRSTTASK+1000; + +type + pTaskRec = ^tTaskRec; + tTaskRec = record + // option values + flags :dword; + name :PWideChar; // name for task + action :dword; // assigned action + intdays, // interval,days + dayoffset :integer; //!! offset, days + starttime, // task starttime + interval :TFileTime; // interval for repeat + count :integer; // repeat count + // support values + lastcall :TFileTime; // last timer event time + nextcall :TFileTime; // ?? next start time? + // runtime values + timer :uint_ptr; // timer handle + curcount :integer; // repeat count + inprocess :bool; // starting processing + inaction :bool; // timer event processing + end; + pTaskList = ^tTaskList; + tTaskList = array [0..1023] of tTaskRec; + +var + TaskList:pTaskList = nil; + MaxTasks:integer = 0; + +procedure TimerProc(wnd:HWND;uMsg:uint;idEvent:uint_ptr;dwTime:dword); stdcall; +var + ltime:uint; + i:integer; + res:int_ptr; + st:tSystemTime; +begin + for i:=0 to MaxTasks-1 do + begin + with TaskList[i] do + begin + if (flags and (ACF_ASSIGNED or ACF_DISABLED))=ACF_ASSIGNED then + if timer=idEvent then + begin + inaction:=true; + if ((flags and TCF_MAKEEVENT)<>0) and + (((flags and TCF_EVENTONCE) =0) or (curcount=count)) then + NotifyEventHooks(hevent,count-curcount,lParam(name)); + + GetLocalTime(st); + SystemTimeToFileTime(st,lastcall); + + res:=CallService(MS_ACT_RUNBYID,action,0); + + if ((res<>0) and ((flags and TCF_NONZEROBREAK)<>0)) or // non-zero result + (count=0) or (curcount=0) then // no need to repeat or all repeats done + begin + KillTimer(0,idEvent); + timer:=0; + flags:=flags or ACF_DISABLED; + end + else + begin + if (count<>0) and (count=curcount) then // next timer - repeat interval + begin + KillTimer(0,idEvent); + FileTimeToSystemTime(interval,st); + ltime:={st.wMilliseconds+}st.wSecond*1000+st.wMinute*1000*60+st.wHour*60*60*1000; + timer:=SetTimer(0,0,ltime,@TimerProc); + if count=-1 then + curcount:=1; + end; + if count>0 then + dec(curcount); + end; + inaction:=false; + break; + end; + end; + end; +end; + +procedure SetTask(var task:tTaskRec); +var + ltime:uint; + uli1,uli2:ULARGE_INTEGER; + sft:tFileTime; + st:tSystemTime; + dif:int64; +begin + task.inprocess:=true; + // Check task time + if (task.flags and TCF_IMMEDIATELY)<>0 then + begin + FileTimeToSystemTime(task.interval,st); + ltime:={st.wMilliseconds+}st.wSecond*1000+st.wMinute*1000*60+ + st.wHour*60*60*1000; + end + else if (task.flags and TCF_ABSOLUTE)<>0 then + begin + uli1.LowPart :=task.starttime.dwLowDateTime; + uli1.HighPart:=task.starttime.dwHighDateTime; + GetLocalTime(st); + SystemTimeToFileTime(st,sft); + uli2.LowPart :=sft.dwLowDateTime; + uli2.HighPart:=sft.dwHighDateTime; + dif:=uli1.QuadPart-uli2.QuadPart; + if dif>0 then // time in future + ltime:=dif div 10000 // 100ns to 1 ms + else // was in past + begin + task.flags:=task.flags or ACF_DISABLED; + exit; + end; + end + else + begin + // days+hours+minutes+seconds+millseconds + FileTimeToSystemTime(task.starttime,st); + ltime:={st.wMilliseconds+}st.wSecond*1000+st.wMinute*1000*60+ + st.wHour*60*60*1000+task.dayoffset*24*60*60*1000; + end; + // set timer + task.curcount:=task.count; + task.timer :=SetTimer(0,0,ltime,@TimerProc); + + if (task.flags and TCF_IMMEDIATELY)<>0 then + TimerProc(0,WM_TIMER,task.timer,0); + task.inprocess:=false; +end; + +procedure SetAllTasks; +var + i:integer; +begin + for i:=0 to MaxTasks-1 do + begin + if (TaskList[i].flags and ACF_ASSIGNED)<>0 then + begin + if (TaskList[i].flags and ACF_DISABLED)=0 then + SetTask(TaskList[i]) + else if TaskList[i].timer<>0 then + begin + KillTimer(0,TaskList[i].timer); + TaskList[i].timer:=0; + end; + end; + end; +end; + +procedure StopAllTasks; +var + i:integer; +begin + for i:=0 to MaxTasks-1 do + begin + if (TaskList[i].flags and (ACF_ASSIGNED or ACF_DISABLED))=ACF_ASSIGNED then + if TaskList[i].timer<>0 then + begin + KillTimer(0,TaskList[i].timer); + TaskList[i].timer:=0; + end; + end; +end; + +procedure ClearTasks; +var + i:integer; +begin + for i:=0 to MaxTasks-1 do + begin + with TaskList[i] do + begin +//!! if (flags and ACF_ASSIGNED)<>0 then + mFreeMem(name); + end; + end; + FreeMem(TaskList); + MaxTasks:=0; +end; + +function CreateNewTask:integer; +var + i:integer; + tmp:pTaskList; + st:tSystemTime; +begin + result:=-1; + // if list is not empty, search for hole + if MaxTasks>0 then + begin + for i:=0 to MaxTasks-1 do + begin + if (TaskList[i].flags and ACF_ASSIGNED)=0 then + begin + FillChar(TaskList[i],SizeOf(tTaskRec),0); + result:=i; + break; + end; + end; + end; + if result<0 then + begin + // not found or empty list + i:=(MaxTasks+16)*SizeOf(tTaskRec); + GetMem (tmp ,i); + FillChar(tmp^,i,0); + if MaxTasks>0 then + begin + move(TaskList^,tmp^,MaxTasks*SizeOf(tTaskRec)); + FreeMem(TaskList); + end; + TaskList:=tmp; + result:=MaxTasks; + inc(MaxTasks,16); + end; + with TaskList^[result] do + begin + flags:=flags or ACF_ASSIGNED or ACF_DISABLED or TCF_ABSOLUTE; + GetLocalTime(st); + SystemTimeToFileTime(st,starttime); + //!!! CHEAT + st.wHour :=0; + st.wMinute:=0; + st.wSecond:=1; + SystemTimeToFileTime(st,interval); + end; +end; diff --git a/plugins/Actman30/tasks/i_tconst.inc b/plugins/Actman30/tasks/i_tconst.inc new file mode 100644 index 0000000000..f4df810d32 --- /dev/null +++ b/plugins/Actman30/tasks/i_tconst.inc @@ -0,0 +1,27 @@ +{resource constants} +const + IDD_TASKS = 2030; + + IDC_TASK_NAME = 1025; + + IDC_TASK_DATET = 1026; + IDC_TASK_DATEV = 1027; + IDC_TASK_DAYST = 1028; + IDC_TASK_DAYSV = 1029; + IDC_TASK_TIMET = 1030; + IDC_TASK_TIMEV = 1031; + + IDC_TASK_REPEAT = 1032; + IDC_TASK_BREAK = 1034; + IDC_TASK_INTERVAL = 1035; + IDC_TASK_EVENT = 1036; + IDC_TASK_ONCE = 1037; + IDC_TASK_UPDOWN = 1038; + IDC_TASK_ABSOLUTE = 1039; + + IDC_TASK_ACTION = 1040; + + IDC_TASK_INTDAYS = 1041; + + IDC_TASK_NEW = 1050; + IDC_TASK_DELETE = 1051; diff --git a/plugins/Actman30/tasks/scheduler.pas b/plugins/Actman30/tasks/scheduler.pas new file mode 100644 index 0000000000..8edf794f77 --- /dev/null +++ b/plugins/Actman30/tasks/scheduler.pas @@ -0,0 +1,76 @@ +unit scheduler; + +interface + +implementation + +uses + windows, commctrl, messages, + mirutils, common, dbsettings, m_api, wrapper, + global; + +{$R tasks.res} + +{$include m_actman.inc} + +var + hevent: THANDLE; + +{$include i_task.inc} +{$include i_tconst.inc} +{$include i_options.inc} +{$include i_opt_dlg.inc} +{$include i_service.inc} + +// ------------ base interface functions ------------- + +procedure Init; +begin + + if LoadTasks=0 then + begin + MaxTasks:=8; + GetMem (TaskList ,MaxTasks*SizeOf(tTaskRec)); + FillChar(TaskList^,MaxTasks*SizeOf(tTaskRec),0); + end + else + SetAllTasks; + + CreateServiceFunction(MS_ACT_TASKCOUNT ,@TaskCount); + CreateServiceFunction(MS_ACT_TASKENABLE,@TaskEnable); + CreateServiceFunction(MS_ACT_TASKDELETE,@TaskDelete); + + hevent:=CreateHookableEvent(ME_ACT_BELL); + +end; + +procedure DeInit; +begin + DestroyHookableEvent(hevent); + StopAllTasks; + ClearTasks; +end; + +function AddOptionPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +begin + result:=0; + tmpl:=PAnsiChar(IDD_TASKS); + proc:=@DlgProcOpt; + name:='Scheduler'; +end; + +var + amLink:tActionLink; + +procedure InitLink; +begin + amLink.Next :=ActionLink; + amLink.Init :=@Init; + amLink.DeInit :=@DeInit; + amLink.AddOption:=@AddOptionPage; + ActionLink :=@amLink; +end; + +initialization + InitLink; +end. diff --git a/plugins/Actman30/tasks/tasks.rc b/plugins/Actman30/tasks/tasks.rc new file mode 100644 index 0000000000..2bc558fbc3 --- /dev/null +++ b/plugins/Actman30/tasks/tasks.rc @@ -0,0 +1,47 @@ +#include "i_tconst.inc" + +LANGUAGE 0,0 + +IDD_TASKS DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + CONTROL "", IDC_TASK_NAME, "SysListView32", + WS_BORDER | WS_TABSTOP | + LVS_NOCOLUMNHEADER | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_EDITLABELS,// | LVS_SINGLESEL, + 2, 2, 130, 174, WS_EX_CONTROLPARENT + + CTEXT "Action",-1 , 140, 2, 160, 12, SS_CENTERIMAGE + COMBOBOX IDC_TASK_ACTION, 140, 14, 160, 128, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL + + GROUPBOX "Start" , -1, 138, 30, 164, 54 + + COMBOBOX IDC_TASK_ABSOLUTE, 142, 40, 156, 60, CBS_DROPDOWNLIST | WS_VSCROLL + + CTEXT "Date", IDC_TASK_DATET, 140, 54, 76, 12, SS_CENTERIMAGE + CONTROL "Date", IDC_TASK_DATEV, "SysDateTimePick32", WS_TABSTOP, 150, 66, 56, 14 + + CTEXT "Days", IDC_TASK_DAYST, 140, 54, 76, 12, SS_CENTERIMAGE + EDITTEXT IDC_TASK_DAYSV, 162, 66, 32, 14 + + CTEXT "Time", IDC_TASK_TIMET, 220, 54, 76, 12, SS_CENTERIMAGE + CONTROL "Time", IDC_TASK_TIMEV, "SysDateTimePick32", WS_TABSTOP|$09, 230, 66, 56, 14 + + GROUPBOX "Repeat" , -1, 138, 88, 164, 88 + + CTEXT "Repeat, times", -1, 140, 98, 70, 14, SS_CENTERIMAGE + EDITTEXT IDC_TASK_REPEAT, 155, 114, 40, 14 + + CTEXT "Interval", -1, 212, 98, 84, 14, SS_CENTERIMAGE + EDITTEXT IDC_TASK_INTDAYS, 212, 114, 24, 14 + CONTROL "Interval", IDC_TASK_INTERVAL, "SysDateTimePick32", WS_TABSTOP|$09, 240, 114, 56, 14 + + AUTOCHECKBOX "Break on non-zero result", IDC_TASK_BREAK, 142, 132, 156, 14 + AUTOCHECKBOX "Send event on start time", IDC_TASK_EVENT, 142, 146, 156, 14 + AUTOCHECKBOX "Send event just once" , IDC_TASK_ONCE , 142, 160, 156, 14 + + CONTROL "New" ,IDC_TASK_NEW ,"MButtonClass",WS_TABSTOP, 2,178,16,16,$18000000 + CONTROL "Delete",IDC_TASK_DELETE,"MButtonClass",WS_TABSTOP,22,178,16,16,$18000000 +// CONTROL "Help" ,IDC_EVENT_HELP ,"MButtonClass",WS_TABSTOP,42,164,16,16,$18000000 +} diff --git a/plugins/Actman30/ua/action.ico b/plugins/Actman30/ua/action.ico new file mode 100644 index 0000000000..9e4c60d9d3 Binary files /dev/null and b/plugins/Actman30/ua/action.ico differ diff --git a/plugins/Actman30/ua/i_inoutjson.inc b/plugins/Actman30/ua/i_inoutjson.inc new file mode 100644 index 0000000000..61879200a1 --- /dev/null +++ b/plugins/Actman30/ua/i_inoutjson.inc @@ -0,0 +1,355 @@ +{} +var + jsonparser:TJSONSERVICEINTERFACE; + +const + ioAction :PWideChar = 'Action'; + ioUA :PWideChar = 'UA'; + + ioName :PWideChar = 'name'; + + ioTwoState :PWideChar = 'twostate'; + ioSaveState :PWideChar = 'savestate'; + + ioHotkey :PWideChar = 'Hotkey'; + ioToolbar :PWideChar = 'Toolbar'; + ioTabSRMM :PWideChar = 'TabSRMM'; + ioMenuItem :PWideChar = 'Menu'; + + ioTooltip :PWideChar = 'tooltip'; + ioTooltipPressed :PWideChar = 'tt_pressed'; + + ioType :PWideChar = 'type'; + ioMenuPopup :PWideChar = 'Popup'; + ioMenuName :PWideChar = 'Name'; + ioMenuShow :PWideChar = 'Show'; + ioMenuUsed :PWideChar = 'Used'; + ioMenuSeparated :PWideChar = 'Separated'; + + +function ImportMenuItems(node:JSONNODE;var MenuItem:tUAMenuItem):integer; +begin + result:=0; + + with jsonparser do + begin + with MenuItem do + begin + menu_opt:=0; + // popup + StrDupW(szMenuPopup,getAttrValue(node,ioMenuPopup)); + // name + StrDupW(szMenuNameVars,getAttrValue(node,ioMenuName)); + // show + StrDupW(szMenuShowWhenVars,getAttrValue(node,ioMenuShow)); + // used + if StrToInt(getAttrValue(node,ioMenuUsed))<>0 then + menu_opt:=menu_opt or UAF_MENUUSE; + // separated + if StrToInt(getAttrValue(node,ioMenuSeparated))<>0 then + menu_opt:=menu_opt or UAF_MENUSEP; + end; + end; +end; + +function ImportUAction(actnode:JSONNODE;var UA:tMyActionItem):integer; +var + num,i:integer; + sub:JSONNODE; +begin + result:=0; + if actnode=0 then exit; + + with jsonparser do + begin + // we don't need that node as is, just it's child for UA +// actnode:=GetNthChild(actnode,ioUA,0); + + UA.flags:=0; + // ----- Common ----- + if StrToInt(getAttrValue(actnode,ioTwoState))<>0 then + UA.flags:=UA.flags or UAF_2STATE; + + if StrToInt(getAttrValue(actnode,ioSaveState))<>0 then + UA.flags:=UA.flags or UAF_SAVESTATE; + + // sub:=AddChild(actnode,ioRegister,nil); + if StrToInt(getAttrValue(actnode,ioHotkey))<>0 then + UA.flags:=UA.flags or UAF_REGHOTKEY; + if StrToInt(getAttrValue(actnode,ioToolbar))<>0 then + UA.flags:=UA.flags or UAF_REGTTBB; + if StrToInt(getAttrValue(actnode,ioTabSRMM))<>0 then + UA.flags:=UA.flags or UAF_REGTABB; + + // ----- Hotkey ----- + // nothing + + // ----- Modern CList toolbar ----- + // source - ANSI text + sub:=GetNthChild(actnode,ioToolbar,0); + WideToAnsi(GetAttrValue(sub,ioTooltip ),UA.szTTBTooltip ,MirandaCP); + WideToAnsi(GetAttrValue(sub,ioTooltipPressed),UA.szTTBTooltipPressed,MirandaCP); + + // ----- TabSRMM toolbar ----- + sub:=GetNthChild(actnode,ioTabSRMM,0); + StrDupW(UA.szTabBTooltip ,getAttrValue(sub,ioTooltip)); + StrDupW(UA.szTabBTooltipPressed,getAttrValue(sub,ioTooltipPressed)); + + // ----- Menus ----- + num:=0; + repeat + sub:=getNextChild(actnode,ioMenuItem,@num); + if sub=0 then break; + + i:=StrToInt(getAttrValue(sub,ioType)); + ImportMenuItems(sub, + UA.UAMenuItem[tMenuType(i)]); + until false; + end; +end; + +function Import(fname:PWideChar;aflags:dword):integer; +var + i,j,act:integer; + root,actnode:JSONNODE; + pcw,res:pWideChar; + f:THANDLE; + num,num1:integer; + ptr,ptr1:pChain; +begin + result:=0; + + if (fname=nil) or (fname^=#0) then + exit; + i:=GetFSize(fname); + if i=0 then + exit; + + num:=CallService(MS_ACT_GETLIST,0,LPARAM(@ptr)); + if num=0 then exit; + ptr1:=ptr; + + mGetMem (res ,i+SizeOf(WideChar)); + FillChar(res^,i+SizeOf(WideChar),0); + f:=Reset(fname); + BlockRead(f,res^,i); + CloseHandle(f); + + CallService(MS_JSON_GETINTERFACE,0,lparam(@jsonparser)); + with jsonparser do + begin + root:=parseString(ChangeUnicode(res),@i,nil); + j:=0; + repeat + actnode:=getNthChild(root,ioAction,j); + if actnode=0 then break; + // search id by name? + pcw:=GetAttrValue(actnode,ioName); + ptr:=ptr1; + inc(pbyte(ptr),4); + for i:=0 to num-1 do + begin + if (ptr.flags and ACCF_IMPORTED)<>0 then + begin + if StrCmpw(pcw,ptr.descr)=0 then + begin + // delete old UA for overwrited actions + if (ptr.flags and ACCF_OVERLOAD)<>0 then + begin + for act:=0 to HIGH(UActionList) do + begin + if ptr.id=UActionList[act].dwActID then + begin + DeleteUAction(act,true); + break; + end; + end; + end; + num1:=AddUAction(-1,ptr); + ImportUAction(getNthChild(actnode,ioUA,0),UActionList[num1]); + break; + end; + end; + inc(ptr); + end; + + inc(j); + until false; + + DestroyNode(root); + end; + CallService(MS_ACT_FREELIST,0,LPARAM(ptr1)); + mFreeMem(res); + result:=1; + if settings<>0 then + begin + FillActionList(settings); + ShowAction(settings,-1); + end; +end; + +//-------------------------- + +function ExportMenuItems(node:JSONNODE;MenuItem:tUAMenuItem):HXML; +begin + with jsonparser do + begin + result:=AddChild(node,ioMenuItem,nil); + with MenuItem do + begin + // popup + if (szMenuPopup<>nil) and (szMenuPopup^<>#0) then + AddAttr(result,ioMenuPopup,szMenuPopup); + // name + if (szMenuNameVars<>nil) and (szMenuNameVars^<>#0) then + AddAttr(result,ioMenuName,szMenuNameVars); + // show + if (szMenuShowWhenVars<>nil) and (szMenuShowWhenVars^<>#0) then + AddAttr(result,ioMenuShow,szMenuShowWhenVars); + // used + AddAttrInt(result,ioMenuUsed,ord((menu_opt AND UAF_MENUUSE)<>0)); + // separated + AddAttrInt(result,ioMenuSeparated,ord((menu_opt AND UAF_MENUSEP)<>0)); + end; + end; +end; + +procedure WriteUAction(root:JSONNODE;id:dword;name:pWideChar); +var + i:integer; + lmenu:tMenuType; + pc:pWideChar; + actnode,sub:JSONNODE; + UA:pMyActionItem; +begin + with jsonparser do + begin + for i:=0 to HIGH(UActionList) do + begin + if UActionList[i].dwActID=id then + begin + UA:=@UActionList[i]; + actnode:=getChildByAttrValue(root,ioAction,ioName,name); + if actnode=0 then break; + // we don't need that node as is, just it's child for UA + actnode:=addChild(actnode,ioUA,nil); + + // ----- Common ----- + AddAttrInt(actnode,ioTwoState ,ORD((UA.flags and UAF_2STATE )<>0)); + AddAttrInt(actnode,ioSaveState,ORD((UA.flags and UAF_SAVESTATE)<>0)); + + // sub:=AddChild(actnode,ioRegister,nil); + AddAttrInt(actnode,ioHotkey ,ORD((UA.flags and UAF_REGHOTKEY)<>0)); + AddAttrInt(actnode,ioToolbar,ORD((UA.flags and UAF_REGTTBB )<>0)); + AddAttrInt(actnode,ioTabSRMM,ORD((UA.flags and UAF_REGTABB )<>0)); + + // ----- Hotkey ----- + // nothing + + // ----- Modern CList toolbar ----- + // source - ANSI text + if ((UA.szTTBTooltip <>nil) and (UA.szTTBTooltip^ <>#0)) or + ((UA.szTTBTooltipPressed<>nil) and (UA.szTTBTooltipPressed^<>#0)) then + begin + sub:=AddChild(actnode,ioToolbar,nil); + if (UA.szTTBTooltip<>nil) and (UA.szTTBTooltip^<>#0) then + begin + AnsiToWide(UA.szTTBTooltip,pc,MirandaCP); + AddAttr(sub,ioTooltip,pc); + mFreeMem(pc); + end; + if (UA.szTTBTooltipPressed<>nil) and (UA.szTTBTooltipPressed^<>#0) then + begin + AnsiToWide(UA.szTTBTooltipPressed,pc,MirandaCP); + AddAttr(sub,ioTooltipPressed,pc); + mFreeMem(pc); + end; + end; + + // ----- TabSRMM toolbar ----- + if ((UA.szTabBTooltip <>nil) and (UA.szTabBTooltip^ <>#0)) or + ((UA.szTabBTooltipPressed<>nil) and (UA.szTabBTooltipPressed^<>#0)) then + begin + sub:=AddChild(actnode,ioTabSRMM,nil); + if (UA.szTabBTooltip<>nil) and (UA.szTabBTooltip^<>#0) then + AddAttr(sub,ioTooltip,UA.szTabBTooltip); + if (UA.szTabBTooltipPressed<>nil) and (UA.szTabBTooltipPressed^<>#0) then + AddAttr(sub,ioTooltipPressed,UA.szTabBTooltipPressed); + end; + + // ----- Menus ----- + for lmenu:=main_menu to HIGH(tMenuType) do + begin + sub:=ExportMenuItems(actnode,UA.UAMenuItem[lmenu]); + AddAttrInt(sub,ioType,ORD(lmenu)); + end; + + break; + end; + end; + end; +end; + +function Export(fname:pWideChar;aflags:dword):integer; +var + i,num:integer; + f:THANDLE; + root:JSONNODE; + res:pWideChar; + ptr,ptr1:pChain; +begin + result:=0; + CallService(MS_JSON_GETINTERFACE,0,lparam(@jsonparser)); + with jsonparser do + begin + // we need append file, not rewrite + i:=GetFSize(fname); + if i=0 then exit; + + mGetMem (res ,i+SizeOf(WideChar)); + FillChar(res^,i+SizeOf(WideChar),0); + f:=Reset(fname); + BlockRead(f,res^,i); + CloseHandle(f); + root:=parseString(res,@i,nil); + mFreeMem(res); + + num:=CallService(MS_ACT_GETLIST,0,LPARAM(@ptr)); + if num>0 then + begin + ptr1:=ptr; + inc(pbyte(ptr),4); + for i:=0 to num-1 do + begin + if ((aflags and ACIO_SELECTED)=0) or + ((ptr.flags and ACCF_EXPORT)<>0) then + begin + WriteUAction(root,ptr.id,ptr.descr); + end; + inc(ptr); + end; + CallService(MS_ACT_FREELIST,0,LPARAM(ptr1)); + end; + + res:=toString(root,@i); + + f:=Rewrite(fname); + BlockWrite(f,res^,i*SizeOf(WideChar)); + CloseHandle(f); + xmlparser.FreeMem(res); + DestroyNode(root); + end; + result:=1; +end; + +function ActInOut(wParam:WPARAM;lParam:LPARAM):int_ptr; cdecl; +begin + if (wParam and ACIO_EXPORT)=0 then + begin + result:=Import(pWideChar(lParam),wParam); + end + else + begin + result:=Export(pWideChar(lParam),wParam); + end; +end; diff --git a/plugins/Actman30/ua/i_inoutxm.inc b/plugins/Actman30/ua/i_inoutxm.inc new file mode 100644 index 0000000000..a052a5a0e0 --- /dev/null +++ b/plugins/Actman30/ua/i_inoutxm.inc @@ -0,0 +1,357 @@ +{} +var + xmlparser:XML_API_W; + +const + ioAction :PWideChar = 'Action'; + ioUA :PWideChar = 'UA'; + + ioName :PWideChar = 'name'; + + ioTwoState :PWideChar = 'twostate'; + ioSaveState :PWideChar = 'savestate'; + + ioHotkey :PWideChar = 'Hotkey'; + ioToolbar :PWideChar = 'Toolbar'; + ioTabSRMM :PWideChar = 'TabSRMM'; + ioMenuItem :PWideChar = 'Menu'; + + ioTooltip :PWideChar = 'tooltip'; + ioTooltipPressed :PWideChar = 'tt_pressed'; + + ioType :PWideChar = 'type'; + ioMenuPopup :PWideChar = 'Popup'; + ioMenuName :PWideChar = 'Name'; + ioMenuShow :PWideChar = 'Show'; + ioMenuUsed :PWideChar = 'Used'; + ioMenuSeparated :PWideChar = 'Separated'; + + +function ImportMenuItems(node:HXML;var MenuItem:tUAMenuItem):integer; +begin + result:=0; + + with xmlparser do + begin + with MenuItem do + begin + menu_opt:=0; + // popup + StrDupW(szMenuPopup,getAttrValue(node,ioMenuPopup)); + // name + StrDupW(szMenuNameVars,getAttrValue(node,ioMenuName)); + // show + StrDupW(szMenuShowWhenVars,getAttrValue(node,ioMenuShow)); + // used + if StrToInt(getAttrValue(node,ioMenuUsed))<>0 then + menu_opt:=menu_opt or UAF_MENUUSE; + // separated + if StrToInt(getAttrValue(node,ioMenuSeparated))<>0 then + menu_opt:=menu_opt or UAF_MENUSEP; + end; + end; +end; + +function ImportUAction(actnode:HXML;var UA:tMyActionItem):integer; +var + num,i:integer; + sub:HXML; +begin + result:=0; + if actnode=0 then exit; + + with xmlparser do + begin + // we don't need that node as is, just it's child for UA +// actnode:=GetNthChild(actnode,ioUA,0); + + UA.flags:=0; + // ----- Common ----- + if StrToInt(getAttrValue(actnode,ioTwoState))<>0 then + UA.flags:=UA.flags or UAF_2STATE; + + if StrToInt(getAttrValue(actnode,ioSaveState))<>0 then + UA.flags:=UA.flags or UAF_SAVESTATE; + + // sub:=AddChild(actnode,ioRegister,nil); + if StrToInt(getAttrValue(actnode,ioHotkey))<>0 then + UA.flags:=UA.flags or UAF_REGHOTKEY; + if StrToInt(getAttrValue(actnode,ioToolbar))<>0 then + UA.flags:=UA.flags or UAF_REGTTBB; + if StrToInt(getAttrValue(actnode,ioTabSRMM))<>0 then + UA.flags:=UA.flags or UAF_REGTABB; + + // ----- Hotkey ----- + // nothing + + // ----- Modern CList toolbar ----- + // source - ANSI text + sub:=GetNthChild(actnode,ioToolbar,0); + WideToAnsi(GetAttrValue(sub,ioTooltip ),UA.szTTBTooltip ,MirandaCP); + WideToAnsi(GetAttrValue(sub,ioTooltipPressed),UA.szTTBTooltipPressed,MirandaCP); + + // ----- TabSRMM toolbar ----- + sub:=GetNthChild(actnode,ioTabSRMM,0); + StrDupW(UA.szTabBTooltip ,getAttrValue(sub,ioTooltip)); + StrDupW(UA.szTabBTooltipPressed,getAttrValue(sub,ioTooltipPressed)); + + // ----- Menus ----- + num:=0; + repeat + sub:=getNextChild(actnode,ioMenuItem,@num); + if sub=0 then break; + + i:=StrToInt(getAttrValue(sub,ioType)); + ImportMenuItems(sub, + UA.UAMenuItem[tMenuType(i)]); + until false; + end; +end; + +function Import(fname:PWideChar;aflags:dword):integer; +var + i,j,act:integer; + root,actnode:HXML; + pcw,res:pWideChar; + f:THANDLE; + num,num1:integer; + ptr,ptr1:pChain; +begin + result:=0; + + if (fname=nil) or (fname^=#0) then + exit; + i:=GetFSize(fname); + if i=0 then + exit; + + num:=CallService(MS_ACT_GETLIST,0,LPARAM(@ptr)); + if num=0 then exit; + ptr1:=ptr; + + mGetMem (res ,i+SizeOf(WideChar)); + FillChar(res^,i+SizeOf(WideChar),0); + f:=Reset(fname); + BlockRead(f,res^,i); + CloseHandle(f); + + xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W); + CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser)); + with xmlparser do + begin + root:=parseString(ChangeUnicode(res),@i,nil); + j:=0; + repeat + actnode:=getNthChild(root,ioAction,j); + if actnode=0 then break; + // search id by name? + pcw:=GetAttrValue(actnode,ioName); + ptr:=ptr1; + inc(pbyte(ptr),4); + for i:=0 to num-1 do + begin + if (ptr.flags and ACF_SELECTED)<>0 then + begin + if StrCmpw(pcw,ptr.descr)=0 then + begin + // delete old UA for overwrited actions + if (ptr.flags and ACF_OVERLOAD)<>0 then + begin + for act:=0 to HIGH(UActionList) do + begin + if ptr.id=UActionList[act].dwActID then + begin + DeleteUAction(act,true); + break; + end; + end; + end; + num1:=AddUAction(-1,ptr); + ImportUAction(getNthChild(actnode,ioUA,0),UActionList[num1]); + break; + end; + end; + inc(ptr); + end; + + inc(j); + until false; + + DestroyNode(root); + end; + CallService(MS_ACT_FREELIST,0,LPARAM(ptr1)); + mFreeMem(res); + result:=1; + if settings<>0 then + begin + FillActionList(settings); + ShowAction(settings,-1); + end; +end; + +//-------------------------- + +function ExportMenuItems(node:HXML;const MenuItem:tUAMenuItem):HXML; +begin + with xmlparser do + begin + result:=AddChild(node,ioMenuItem,nil); + with MenuItem do + begin + // popup + if (szMenuPopup<>nil) and (szMenuPopup^<>#0) then + AddAttr(result,ioMenuPopup,szMenuPopup); + // name + if (szMenuNameVars<>nil) and (szMenuNameVars^<>#0) then + AddAttr(result,ioMenuName,szMenuNameVars); + // show + if (szMenuShowWhenVars<>nil) and (szMenuShowWhenVars^<>#0) then + AddAttr(result,ioMenuShow,szMenuShowWhenVars); + // used + AddAttrInt(result,ioMenuUsed,ord((menu_opt AND UAF_MENUUSE)<>0)); + // separated + AddAttrInt(result,ioMenuSeparated,ord((menu_opt AND UAF_MENUSEP)<>0)); + end; + end; +end; + +procedure WriteUAction(root:HXML;id:dword;name:pWideChar); +var + i:integer; + lmenu:tMenuType; + pc:pWideChar; + actnode,sub:HXML; + UA:pMyActionItem; +begin + with xmlparser do + begin + for i:=0 to HIGH(UActionList) do + begin + if UActionList[i].dwActID=id then + begin + UA:=@UActionList[i]; + actnode:=getChildByAttrValue(root,ioAction,ioName,name); + if actnode=0 then break; + // we don't need that node as is, just it's child for UA + actnode:=addChild(actnode,ioUA,nil); + + // ----- Common ----- + AddAttrInt(actnode,ioTwoState ,ORD((UA.flags and UAF_2STATE )<>0)); + AddAttrInt(actnode,ioSaveState,ORD((UA.flags and UAF_SAVESTATE)<>0)); + + // sub:=AddChild(actnode,ioRegister,nil); + AddAttrInt(actnode,ioHotkey ,ORD((UA.flags and UAF_REGHOTKEY)<>0)); + AddAttrInt(actnode,ioToolbar,ORD((UA.flags and UAF_REGTTBB )<>0)); + AddAttrInt(actnode,ioTabSRMM,ORD((UA.flags and UAF_REGTABB )<>0)); + + // ----- Hotkey ----- + // nothing + + // ----- Modern CList toolbar ----- + // source - ANSI text + if ((UA.szTTBTooltip <>nil) and (UA.szTTBTooltip^ <>#0)) or + ((UA.szTTBTooltipPressed<>nil) and (UA.szTTBTooltipPressed^<>#0)) then + begin + sub:=AddChild(actnode,ioToolbar,nil); + if (UA.szTTBTooltip<>nil) and (UA.szTTBTooltip^<>#0) then + begin + AnsiToWide(UA.szTTBTooltip,pc,MirandaCP); + AddAttr(sub,ioTooltip,pc); + mFreeMem(pc); + end; + if (UA.szTTBTooltipPressed<>nil) and (UA.szTTBTooltipPressed^<>#0) then + begin + AnsiToWide(UA.szTTBTooltipPressed,pc,MirandaCP); + AddAttr(sub,ioTooltipPressed,pc); + mFreeMem(pc); + end; + end; + + // ----- TabSRMM toolbar ----- + if ((UA.szTabBTooltip <>nil) and (UA.szTabBTooltip^ <>#0)) or + ((UA.szTabBTooltipPressed<>nil) and (UA.szTabBTooltipPressed^<>#0)) then + begin + sub:=AddChild(actnode,ioTabSRMM,nil); + if (UA.szTabBTooltip<>nil) and (UA.szTabBTooltip^<>#0) then + AddAttr(sub,ioTooltip,UA.szTabBTooltip); + if (UA.szTabBTooltipPressed<>nil) and (UA.szTabBTooltipPressed^<>#0) then + AddAttr(sub,ioTooltipPressed,UA.szTabBTooltipPressed); + end; + + // ----- Menus ----- + for lmenu:=main_menu to HIGH(tMenuType) do + begin + sub:=ExportMenuItems(actnode,UA.UAMenuItem[lmenu]); + AddAttrInt(sub,ioType,ORD(lmenu)); + end; + + break; + end; + end; + end; +end; + +function Export(fname:pWideChar;aflags:dword):integer; +var + i,num:integer; + f:THANDLE; + root:HXML; + res:pWideChar; + ptr,ptr1:pChain; +begin + result:=0; + xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W); + CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser)); + with xmlparser do + begin + // we need append file, not rewrite + i:=GetFSize(fname); + if i=0 then exit; + + mGetMem (res ,i+SizeOf(WideChar)); + FillChar(res^,i+SizeOf(WideChar),0); + f:=Reset(fname); + BlockRead(f,res^,i); + CloseHandle(f); + root:=parseString(res,@i,nil); + mFreeMem(res); + + num:=CallService(MS_ACT_GETLIST,0,LPARAM(@ptr)); + if num>0 then + begin + ptr1:=ptr; + inc(pbyte(ptr),4); + for i:=0 to num-1 do + begin + if ((aflags and ACIO_SELECTED)=0) or + ((ptr.flags and ACCF_EXPORT)<>0) then + begin + WriteUAction(root,ptr.id,ptr.descr); + end; + inc(ptr); + end; + CallService(MS_ACT_FREELIST,0,LPARAM(ptr1)); + end; + + res:=toString(root,@i); + + f:=Rewrite(fname); + BlockWrite(f,res^,i*SizeOf(WideChar)); + CloseHandle(f); + xmlparser.FreeMem(res); + DestroyNode(root); + end; + result:=1; +end; + +function ActInOut(wParam:WPARAM;lParam:LPARAM):int_ptr; cdecl; +begin + if (wParam and ACIO_EXPORT)=0 then + begin + result:=Import(pWideChar(lParam),wParam); + end + else + begin + result:=Export(pWideChar(lParam),wParam); + end; +end; diff --git a/plugins/Actman30/ua/i_opt_dlg.inc b/plugins/Actman30/ua/i_opt_dlg.inc new file mode 100644 index 0000000000..b7ff28483a --- /dev/null +++ b/plugins/Actman30/ua/i_opt_dlg.inc @@ -0,0 +1,572 @@ +{} +const + settings:HWND = 0; +const + NumControls = 17; + + IDsArray:array [0..NumControls-1] of integer =( + // Menu settings controls + IDC_UA_SEPARATE ,IDC_UA_POPUPT ,IDC_UA_POPUPV, + IDC_UA_VARNAMEST,IDC_UA_VARNAMESV,IDC_UA_VARNAMESH, + IDC_UA_SHOWVART ,IDC_UA_SHOWVARV ,IDC_UA_SHOWVARH, + IDC_UA_TWOSTATE ,IDC_UA_SAVSTATE ,IDC_UA_COMMON, + // toolbar settings controls + IDC_UA_TTNORMALT,IDC_UA_TTNORMALV,IDC_UA_TTPRESSEDT,IDC_UA_TTPRESSEDV, + IDC_UA_GLOBAL + ); + + // Show-hide controls by place type + SHArray:array [0..NumTypes-1, 0..NumControls-1] of integer = ( + // CList Modern toolbar + (SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE,SW_HIDE,SW_HIDE, SW_SHOW,SW_SHOW,SW_SHOW, + SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW,SW_SHOW, SW_HIDE), + // TabSRMM toolbar + (SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE,SW_HIDE,SW_HIDE, + SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW), + // Core Hotkey + (SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE,SW_HIDE,SW_HIDE, + SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE,SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE), + // Main menu + (SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW, + SW_SHOW,SW_SHOW,SW_SHOW, SW_HIDE,SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE), + // Contact menu + (SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW, + SW_SHOW,SW_SHOW,SW_SHOW, SW_HIDE,SW_HIDE,SW_HIDE,SW_HIDE, SW_SHOW), + // Tray menu + (SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW, + SW_SHOW,SW_SHOW,SW_SHOW, SW_HIDE,SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE), + // Protocol menu + (SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW, + SW_SHOW,SW_SHOW,SW_SHOW, SW_HIDE,SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE), + // Status menu + (SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW, SW_SHOW,SW_SHOW,SW_SHOW, + SW_SHOW,SW_SHOW,SW_SHOW, SW_HIDE,SW_HIDE,SW_HIDE,SW_HIDE, SW_HIDE) + ); + // additional show/hide controls check by Variables installings (1 - need to check) + SHVarArray:array [0..NumControls-1] of byte = ( + 0,0,0, 0,0,1, 1,1,1, + 0,0,0,0,0,0,0, 0); + // additional enable/disable controls check (1 - always enable) + EnDisArray:array [0..NumControls-1] of byte = ( + 0,0,0, 0,0,0, 0,0,0, + 1,1,1,0,0,0,0, 1); + +var + hIC:THANDLE; + +procedure CheckPlacesAbility; +var + i:integer; +begin + for i:=0 to NumTypes-1 do + begin + with NamesArray[i] do + begin + enable:=(service=nil) or (ServiceExists(service)<>0); + end; + end; +end; + +// Show or hide option items +procedure SetupControls(Dialog:HWND;atype:integer;item:integer=-1); +var + i: cardinal; + typ:integer; + wnd,wnd1:HWND; + enable:boolean; +begin + if atype<0 then + begin + for i:=0 to NumControls-1 do + begin + ShowWindow(GetDlgItem(Dialog,IDsArray[i]),SW_HIDE); + end; + end + else + begin + wnd1:=GetDlgItem(Dialog,IDC_UA_PLACELIST); + if item<0 then + item:=SendMessage(wnd1,LVM_GETNEXTITEM,-1,LVNI_FOCUSED); + enable:=ListView_GetCheckState(wnd1,item)<>0; + + for i:=0 to NumControls-1 do + begin + typ:=SHArray[LoByte(atype)+HiByte(atype)][i]; + if typ=SW_SHOW then + if (SHVarArray[i]<>0) and (not IsVarsInstalled) then + typ:=SW_HIDE; + wnd:=GetDlgItem(Dialog,IDsArray[i]); + ShowWindow(wnd,typ); + EnableWindow(wnd,enable or (EnDisArray[i]<>0)); + end; + + // common settings + EnableWindow(GetDlgItem(Dialog,IDC_UA_SAVSTATE), + IsDlgButtonChecked(Dialog,IDC_UA_TWOSTATE)<>BST_UNCHECKED); + + // personal settings + case LoByte(atype) of + uaTTB, uaTAB: begin + enable:=false; + if IsDlgButtonChecked(Dialog,IDC_UA_TWOSTATE)<>BST_UNCHECKED then + if IsWindowEnabled(GetDlgItem(Dialog,IDC_UA_TTNORMALV)) then + enable:=true; + EnableWindow(GetDlgItem(Dialog,IDC_UA_TTPRESSEDV),enable); + end; + end; + end; +end; + +// Clear all screen buttons/text fields (reset) +procedure ClearControls(Dialog:HWND); +var + s:HWND; +begin + s:=settings; + settings:=0; + CheckDlgButton (Dialog,IDC_UA_TWOSTATE ,BST_UNCHECKED); + CheckDlgButton (Dialog,IDC_UA_SAVSTATE ,BST_UNCHECKED); + + CheckDlgButton (Dialog,IDC_UA_SEPARATE ,BST_UNCHECKED); + SetDlgItemTextW(Dialog,IDC_UA_POPUPV ,nil); + SetDlgItemTextW(Dialog,IDC_UA_VARNAMESV,nil); + SetDlgItemTextW(Dialog,IDC_UA_SHOWVARV ,nil); + settings:=s; +end; + +procedure ShowSubAction(Dialog:HWND;aType:integer;item:integer=-1); +var + UA:pMyActionItem; + s:HWND; +begin + s:=settings; + settings:=0; + ClearControls(Dialog); + + // get UAction number + item:=LV_GetLParam(GetDlgItem(Dialog,IDC_UA_ACTIONLIST),item); + + UA:=@UActionList[item]; + + // common settings + if (UA.flags and UAF_2STATE)<>0 then + CheckDlgButton(Dialog,IDC_UA_TWOSTATE,BST_CHECKED); + + if (UA.flags and UAF_SAVESTATE)<>0 then + CheckDlgButton(Dialog,IDC_UA_SAVSTATE,BST_CHECKED); + + if (UA.flags and UAF_GLOBAL)=0 then + CheckDlgButton(Dialog,IDC_UA_GLOBAL,BST_CHECKED); + + // Show real UA settings + case LoByte(aType) of + uaTTB: begin // CList modern toolbar + SetDlgItemTextA(Dialog,IDC_UA_TTNORMALV ,UA.szTTBTooltip); + SetDlgItemTextA(Dialog,IDC_UA_TTPRESSEDV,UA.szTTBTooltipPressed); + SetDlgItemTextW(Dialog,IDC_UA_SHOWVARV ,UA.szTTBShowWhenVars); + end; + + uaTAB: begin // TabSRMM toolbar + SetDlgItemTextW(Dialog,IDC_UA_TTNORMALV ,UA.szTabBTooltip); + SetDlgItemTextW(Dialog,IDC_UA_TTPRESSEDV,UA.szTabBTooltipPressed); + end; + + uaMenu: begin + with UA.UAMenuItem[tMenuType(HiByte(aType))] do + begin + if (menu_opt and UAF_MENUSEP)<>0 then + CheckDlgButton(Dialog,IDC_UA_SEPARATE,BST_CHECKED); + SetDlgItemTextW(Dialog,IDC_UA_POPUPV ,szMenuPopup); + SetDlgItemTextW(Dialog,IDC_UA_VARNAMESV,szMenuNameVars); + SetDlgItemTextW(Dialog,IDC_UA_SHOWVARV ,szMenuShowWhenVars); + end; + end; + + uaHotkey: begin // Hotkey + // Settings in Customize/Hotkeys + end; + end; + SetupControls(Dialog,aType,-1); + settings:=s; +end; + +function isPlaceActive(idx,place:integer):boolean; +begin + result:=false; + with UActionList[idx] do + case LoByte(place) of + uaTTB : result:=(flags and UAF_REGTTBB)<>0; + uaTAB : result:=(flags and UAF_REGTABB)<>0; + uaHotkey : result:=(flags and UAF_REGHOTKEY)<>0; + uaMenu: begin + result:=(UAMenuItem[tMenuType(HiByte(place))].menu_opt and UAF_MENUUSE)<>0 + end; + end; +end; + +procedure ShowAction(Dialog:HWND;item:integer=-1); +var + i,j:integer; + wnd:HWND; + li:LV_ITEMW; + buf:array [0..255] of WideChar; + lset:HWND; +begin + wnd:=GetDlgItem(Dialog,IDC_UA_PLACELIST); + SendMessage(wnd,LVM_DELETEALLITEMS,0,0); + j:=LV_GetLParam(GetDlgItem(Dialog,IDC_UA_ACTIONLIST),item); + if j>=0 then + begin + with UActionList[j] do + begin + lset:=settings; + settings:=0; + // make "places" list + for i:=0 to NumTypes-1 do + begin + with NamesArray[i] do + begin + if enable then // cached ability flag + begin + li.mask :=LVIF_TEXT+LVIF_PARAM; + li.iSubItem:=0; + li.iItem :=i; + li.lParam :=atype; //!!!!!! need to add subtype + li.pszText :=TranslateW(FastAnsiToWideBuf(name,buf)); + li.iItem :=SendMessageW(wnd,LVM_INSERTITEMW,0,LPARAM(@li)); + + ListView_SetCheckState(wnd,li.iItem,isPlaceActive(j,atype)); + end; + end; + end; + ListView_SetItemState(wnd,0, + LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); + // show first selected "place" + ShowSubAction(Dialog,LV_GetLParam(wnd)); + settings:=lset; + end; + end + else + begin + ClearControls(Dialog); + SetupControls(Dialog,-1,-1); + end; +end; + +procedure SetChangedFlag(Dialog:HWND); +var + num,atype:integer; +begin + num :=LV_GetLParam(GetDlgItem(Dialog,IDC_UA_ACTIONLIST),-1); + atype:=LV_GetLParam(GetDlgItem(Dialog,IDC_UA_PLACELIST ),-1); + UActionList[num].UAMenuItem[tMenuType(HiByte(atype))].changed:=true; +end; + +procedure SaveMenuSubAction(Dialog:HWND;var MenuItem:tUAMenuItem); +begin + with MenuItem do + begin + mFreeMem(szMenuPopup ); szMenuPopup :=GetDlgText(Dialog,IDC_UA_POPUPV); + mFreeMem(szMenuNameVars ); szMenuNameVars :=GetDlgText(Dialog,IDC_UA_VARNAMESV); + mFreeMem(szMenuShowWhenVars); szMenuShowWhenVars:=GetDlgText(Dialog,IDC_UA_SHOWVARV); + menu_opt:=0; + if IsDlgButtonchecked(Dialog,IDC_UA_SEPARATE)<>BST_UNCHECKED then + menu_opt:=menu_opt or UAF_MENUSEP; + end; +end; + +procedure SetPlaceActive(idx,place:integer;active:boolean); +begin + with UActionList[idx] do + case LoByte(place) of + uaTTB : if active then flags:=flags or UAF_REGTTBB else flags:=flags and not UAF_REGTTBB; + uaTAB : if active then flags:=flags or UAF_REGTABB else flags:=flags and not UAF_REGTABB; + uaHotkey: if active then flags:=flags or UAF_REGHOTKEY else flags:=flags and not UAF_REGHOTKEY; + uaMenu : + with UAMenuItem[tMenuType(HiByte(place))] do + if active then menu_opt:=menu_opt or UAF_MENUUSE + else menu_opt:=menu_opt and not UAF_MENUUSE; + end; +end; + +procedure SaveAction(Dialog:HWND;item:integer=-1;atype:integer=-1); +var + i,num:integer; + wnd:HWND; +begin + num:=LV_GetLParam(GetDlgItem(Dialog,IDC_UA_ACTIONLIST),item); + if num<0 then exit; + + wnd:=GetDlgItem(Dialog,IDC_UA_PLACELIST); + atype:=LV_GetLParam(wnd,atype); + with UActionList[num] do + begin + // main flags + flags:=flags and not UAF_USING; + // common section + if IsDlgButtonChecked(Dialog,IDC_UA_TWOSTATE)<>BST_UNCHECKED then + flags:=flags or UAF_2STATE + else + flags:=flags and not UAF_2STATE; + + if IsDlgButtonChecked(Dialog,IDC_UA_SAVSTATE)<>BST_UNCHECKED then + flags:=flags or UAF_SAVESTATE + else + flags:=flags and not UAF_SAVESTATE; + + if IsDlgButtonChecked(Dialog,IDC_UA_GLOBAL)=BST_UNCHECKED then + flags:=flags or UAF_GLOBAL + else + flags:=flags and not UAF_GLOBAL; + + // custom data + case LoByte(atype) of + uaTTB: begin // CList modern toolbar + mFreeMem(szTTBTooltip ); szTTBTooltip :=GetDlgText(Dialog,IDC_UA_TTNORMALV ,true); + mFreeMem(szTTBTooltipPressed); szTTBTooltipPressed:=GetDlgText(Dialog,IDC_UA_TTPRESSEDV,true); + mFreeMem(szTTBShowWhenVars ); szTTBShowWhenVars :=GetDlgText(Dialog,IDC_UA_SHOWVARV); + end; + + uaTAB: begin // TabSRMM toolbar + mFreeMem(szTabBTooltip ); szTabBTooltip :=GetDlgText(Dialog,IDC_UA_TTNORMALV); + mFreeMem(szTabBTooltipPressed); szTabBTooltipPressed:=GetDlgText(Dialog,IDC_UA_TTPRESSEDV); + end; + + uaMenu: SaveMenuSubAction(Dialog,UAMenuItem[tMenuType(HiByte(atype))]); + + uaHotkey: begin // Hotkey + // Settings in Customize/Hotkeys + end; + end; + for i:=0 to SendMessage(wnd,LVM_GETITEMCOUNT,0,0)-1 do + begin + SetPlaceActive(num,LV_GetLParam(wnd,i),ListView_GetCheckState(wnd,i)<>0); + end; + //just after Action (not place) changes + if item<0 then + SaveUA(num); + end; +end; + +function CompareItem(lParam1,lParam2:LPARAM;SortType:LPARAM):int; stdcall; +begin + result:=UActionList[lParam1].wSortIndex-UActionList[lParam2].wSortIndex; +end; + +procedure FillActionList(wnd:HWND); +var + i:integer; + li:LV_ITEMW; + il:HIMAGELIST; + lmenu:tMenuType; +begin + wnd:=GetDlgItem(wnd,IDC_UA_ACTIONLIST); + SendMessage(wnd,LVM_DELETEALLITEMS,0,0); + + il:=ImageList_Create(16,16,ILC_COLOR32 or ILC_MASK,0,1); + for i:=0 to HIGH(UActionList) do + begin + li.mask :=LVIF_TEXT+LVIF_PARAM+LVIF_IMAGE; + li.iSubItem:=0; + li.iItem :=i; + li.lParam :=i; + li.pszText :=UActionList[i].szActDescr; + li.iImage:=ImageList_AddIcon(il, + HICON(CallService(MS_SKIN2_GETICONBYHANDLE,0,LPARAM(UActionList[i].hIcolibIcon)))); + li.iItem :=SendMessageW(wnd,LVM_INSERTITEMW,0,LPARAM(@li)); + + for lmenu:=main_menu to HIGH(tMenuType) do + UActionList[i].UAMenuItem[lmenu].changed:=false; + end; + ImageList_Destroy(SendMessage(wnd,LVM_SETIMAGELIST,LVSIL_SMALL,il)); + + SendMessage(wnd,LVM_SORTITEMS,0,LPARAM(@CompareItem)); + + ListView_SetItemState(wnd,0, + LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED); +end; + +// refresh icons in UA list (at least) +function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + i:integer; + li:LV_ITEMW; + il:HIMAGELIST; + wnd:HWND; +begin + result:=0; + wnd:=GetDlgItem(settings,IDC_UA_ACTIONLIST); + + il:=ImageList_Create(16,16,ILC_COLOR32 or ILC_MASK,0,1); + for i:=0 to HIGH(UActionList) do + begin + li.mask :=LVIF_IMAGE; + li.iSubItem:=0; + li.iItem :=i; + li.iImage:=ImageList_AddIcon(il, + HICON(CallService(MS_SKIN2_GETICONBYHANDLE,0,TLPARAM(UActionList[i].hIcolibIcon)))); + SendMessageW(wnd,LVM_SETITEM,0,TLPARAM(@li)); + end; + ImageList_Destroy(SendMessage(wnd,LVM_SETIMAGELIST,LVSIL_SMALL,il)); +//!!refresh? +end; + +function DlgProcOpt(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + wnd:HWND; + lv:LV_COLUMNW; + i:integer; +begin + result:=0; + case hMessage of + WM_CLOSE: begin + settings:=0; + UnhookEvent(hIC); + end; + + WM_INITDIALOG: begin + settings:=0; + TranslateDialogDefault(Dialog); + + wnd:=GetDlgItem(Dialog,IDC_UA_PLACELIST); + SendMessage(wnd,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_CHECKBOXES,LVS_EX_CHECKBOXES); + SendMessage(wnd,LVM_SETUNICODEFORMAT,1,0); + zeromemory(@lv,sizeof(lv)); + lv.mask:=LVCF_WIDTH; + lv.cx :=110; + SendMessageW(wnd,LVM_INSERTCOLUMNW ,0,tlparam(@lv)); + SendMessageW(wnd,LVM_SETCOLUMNWIDTH,0,LVSCW_AUTOSIZE_USEHEADER); + + wnd:=GetDlgItem(Dialog,IDC_UA_ACTIONLIST); +// SendMessage(wnd,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_CHECKBOXES,LVS_EX_CHECKBOXES); + SendMessage(wnd,LVM_SETUNICODEFORMAT,1,0); + zeromemory(@lv,sizeof(lv)); + lv.mask:=LVCF_WIDTH; + lv.cx :=110; + SendMessageW(wnd,LVM_INSERTCOLUMNW ,0,tlparam(@lv)); + SendMessageW(wnd,LVM_SETCOLUMNWIDTH,0,LVSCW_AUTOSIZE_USEHEADER); + FillActionList(Dialog); + ShowAction(Dialog,-1); + +// if isVarsInstalled then + begin + SendDlgItemMessage(Dialog,IDC_UA_VARNAMESH,BM_SETIMAGE,IMAGE_ICON, + CallService(MS_VARS_GETSKINITEM,0,VSI_HELPICON)); + SendDlgItemMessage(Dialog,IDC_UA_SHOWVARH,BM_SETIMAGE,IMAGE_ICON, + CallService(MS_VARS_GETSKINITEM,0,VSI_HELPICON)); +// SendDlgItemMessage(Dialog,IDC_UA_VARNAMESH,BUTTONSETASFLATBTN,0,0); +// SendDlgItemMessage(Dialog,IDC_UA_SHOWVARH ,BUTTONSETASFLATBTN,0,0); + end; + + settings:=Dialog; + hIC:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged); + end; + + WM_COMMAND: begin + case wParam shr 16 of + EN_CHANGE: begin + if settings<>0 then + begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + if loword(wParam)=IDC_UA_POPUPV then + SetChangedFlag(Dialog); + end; + end; + + BN_CLICKED: begin + if settings<>0 then + begin + case loword(wParam) of + IDC_UA_TWOSTATE: begin + SetupControls(Dialog, + LV_GetLParam(GetDlgItem(Dialog,IDC_UA_PLACELIST)),-1); + { + EnableWindow(GetDlgItem(Dialog,IDC_UA_TTPRESSEDV), + IsDlgButtonChecked(Dialog,IDC_UA_TWOSTATE)<>BST_UNCHECKED); + } + if IsDlgButtonChecked(Dialog,IDC_UA_TWOSTATE)=BST_UNCHECKED then + DeleteIcolibIconP( + UActionList[LV_GetLParam(GetDlgItem(Dialog,IDC_UA_ACTIONLIST),-1)]) + else + AddIcolibIconP( + UActionList[LV_GetLParam(GetDlgItem(Dialog,IDC_UA_ACTIONLIST),-1)]); + + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + + IDC_UA_VARNAMESH: ShowVarHelp(Dialog,IDC_UA_VARNAMESV); + IDC_UA_SHOWVARH : ShowVarHelp(Dialog,IDC_UA_SHOWVARV); + +//was commented. why? + IDC_UA_SAVSTATE, + IDC_UA_GLOBAL: SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + + IDC_UA_SEPARATE: begin + SetChangedFlag(Dialog); + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + end; + end; + end; + end; + + WM_NOTIFY: begin + case integer(PNMHdr(lParam)^.code) of + PSN_APPLY: begin + SaveAction(Dialog); + SaveUAs; + FillChar(arMenuRec[0],Length(arMenuRec)*SizeOf(tuaMenuRecA),0); + for i:=0 to HIGH(UActionList) do + begin + SetAllActionUsers(UActionList[i],false); + end; + end; + + LVN_ITEMCHANGED: begin + if settings=0 then exit; + if PNMLISTVIEW(lParam)^.uChanged=LVIF_STATE then + begin + i:=(PNMLISTVIEW(lParam)^.uOldState and LVNI_FOCUSED)- + (PNMLISTVIEW(lParam)^.uNewState and LVNI_FOCUSED); + + if i>0 then // old focus + begin + if wParam=IDC_UA_ACTIONLIST then + SaveAction(Dialog,PNMLISTVIEW(lParam)^.iItem) + else //if wParam=IDC_UA_PLACELIST then + SaveAction(Dialog,-1,PNMLISTVIEW(lParam)^.iItem); + end + else if i<0 then // new focus + begin + if wParam=IDC_UA_ACTIONLIST then + ShowAction(Dialog,PNMLISTVIEW(lParam)^.iItem) + else//if wParam=IDC_UA_PLACELIST then + ShowSubAction(Dialog, + LV_GetLParam(GetDlgItem(Dialog,IDC_UA_PLACELIST), + PNMLISTVIEW(lParam)^.iItem)); + end + else if (settings<>0) and + ((PNMLISTVIEW(lParam)^.uOldState or PNMLISTVIEW(lParam)^.uNewState)=$3000) then + begin + // which type + wnd:=GetDlgItem(Dialog,IDC_UA_PLACELIST); + if PNMLISTVIEW(lParam)^.iItem<> + SendMessage(wnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED) then + ListView_SetItemState(wnd,PNMLISTVIEW(lParam)^.iItem, + LVIS_FOCUSED or LVIS_SELECTED, + LVIS_FOCUSED or LVIS_SELECTED) + else + SetupControls(Dialog,LV_GetLParam(wnd,PNMLISTVIEW(lParam)^.iItem), + PNMLISTVIEW(lParam)^.iItem); + + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + end; + end; + end; + end; +end; diff --git a/plugins/Actman30/ua/i_options.inc b/plugins/Actman30/ua/i_options.inc new file mode 100644 index 0000000000..977ff7891b --- /dev/null +++ b/plugins/Actman30/ua/i_options.inc @@ -0,0 +1,252 @@ +{} +const + opt_TTBTooltip :pAnsiChar = 'MTBTooltip'; + opt_TTBTooltipPressed :pAnsiChar = 'MTBTooltipPressed'; + opt_TTBShowWhenVars :pAnsiChar = 'MTBVarStr'; + + opt_TabBTooltip :pAnsiChar = 'TabBTooltip'; + opt_TabBTooltipPressed:pAnsiChar = 'TabBTooltipPressed'; + + opt_MenuPopup :pAnsiChar = 'MenuPopup'; + opt_MenuNameVars :pAnsiChar = 'MenuName'; + opt_MenuShowWhenVars:pAnsiChar = 'MenuVarStr'; + opt_MenuOptions :pAnsiChar = 'MenuOptions'; + +{} +procedure DeleteUASettings(idx:integer); +var + setting:array [0..63] of AnsiChar; + p,pm:pAnsiChar; + lmenu:tMenuType; +begin + with UActionList[idx] do + begin + p:=GetUABranch(setting,dwActID); + if p<>nil then + begin + p:=StrCopyE(p,opt_UA); + p^:='/'; inc(p); +{!! + p^:='*'; inc(p); p^:=#0; + DBDeleteGroup(0,DBBranch,setting); +!!} + StrCopy(p,opt_Flags); DBDeleteSetting(0,DBBranch,setting); + + StrCopy(p,opt_TTBTooltip ); DBDeleteSetting(0,DBBranch,setting); + StrCopy(p,opt_TTBTooltipPressed ); DBDeleteSetting(0,DBBranch,setting); + StrCopy(p,opt_TTBShowWhenVars ); DBDeleteSetting(0,DBBranch,setting); + + StrCopy(p,opt_TabBTooltip ); DBDeleteSetting(0,DBBranch,setting); + StrCopy(p,opt_TabBTooltipPressed); DBDeleteSetting(0,DBBranch,setting); + + for lmenu:=main_menu to HIGH(tMenuType) do + begin + pm:=p; + pm^:=AnsiChar(ORD(lmenu)+ORD('0')); inc(pm); + pm^:='_'; inc(pm); + StrCopy(pm,opt_MenuPopup ); DBDeleteSetting(0,DBBranch,setting); + StrCopy(pm,opt_MenuNameVars ); DBDeleteSetting(0,DBBranch,setting); + StrCopy(pm,opt_MenuShowWhenVars); DBDeleteSetting(0,DBBranch,setting); + StrCopy(pm,opt_MenuOptions ); DBDeleteSetting(0,DBBranch,setting); + end; + end; + end; +end; + +procedure addSaveUA(setting:pAnsiChar;txt:pWideChar); overload; +begin + if (txt=nil) or (txt^=#0) then DBDeleteSetting(0,DBBranch,setting) + else DBWriteUnicode(0,DBBranch,setting,txt); +end; + +procedure addSaveUA(setting:pAnsiChar;txt:pAnsiChar); overload; +begin + if (txt=nil) or (txt^=#0) then DBDeleteSetting(0,DBBranch,setting) + else DBWriteString(0,DBBranch,setting,txt); +end; + +procedure SaveUA(idx:integer); +var + setting:array [0..63] of AnsiChar; + p,pm:pAnsiChar; + lmenu:tMenuType; +begin + with UActionList[idx] do + begin + p:=GetUABranch(setting,dwActID); + if p<>nil then + begin + p:=StrCopyE(p,opt_UA); + p^:='/'; inc(p); + + StrCopy(p,opt_Flags); DBWriteDWord(0,DBBranch,setting, + flags and not (UAF_REALTIME OR UAF_SPECIAL)); + + StrCopy(p,opt_TTBTooltip ); addSaveUA(setting,szTTBTooltip); + StrCopy(p,opt_TTBTooltipPressed); addSaveUA(setting,szTTBTooltipPressed); + StrCopy(p,opt_TTBShowWhenVars ); addSaveUA(setting,szTTBShowWhenVars); + + StrCopy(p,opt_TabBTooltip ); addSaveUA(setting,szTabBTooltip); + StrCopy(p,opt_TabBTooltipPressed); addSaveUA(setting,szTabBTooltipPressed); + + for lmenu:=main_menu to HIGH(tMenuType) do + begin + pm:=p; + pm^:=AnsiChar(ORD(lmenu)+ORD('0')); inc(pm); + pm^:='_'; inc(pm); + with UAMenuItem[lmenu] do + begin + StrCopy(pm,opt_MenuPopup ); addSaveUA(setting,szMenuPopup); + StrCopy(pm,opt_MenuNameVars ); addSaveUA(setting,szMenuNameVars); + StrCopy(pm,opt_MenuShowWhenVars); addSaveUA(setting,szMenuShowWhenVars); + StrCopy(pm,opt_MenuOptions ); DBWriteWord(0,DBBranch,setting,menu_opt); + end; + end; + end; + end; +end; + +procedure SaveUAs; +var + i:integer; +begin + for i:=0 to HIGH(UActionList) do + SaveUA(i); +end; + +function LoadUA(idx:integer):integer; +var + setting:array [0..63] of AnsiChar; + p,pm:pAnsiChar; + lmenu:tMenuType; +begin + result:=0; + with UActionList[idx] do + begin + p:=GetUABranch(setting,dwActID); + if p<>nil then + begin + p:=StrCopyE(p,opt_UA); + p^:='/'; inc(p); + + StrCopy(p,opt_Flags); + flags:=DBReadDWord(0,DBBranch,setting,dword(UAF_SPECIAL)); + if flags=dword(UAF_SPECIAL) then // no settings + begin + flags:=0; + exit; + end; + // no need to use previous "pressed" state + if (flags and UAF_SAVESTATE)=0 then + flags:=flags and not UAF_PRESSED; + + flags:=flags and not UAF_REALTIME; + result:=1; + + StrCopy(p,opt_TTBTooltip ); szTTBTooltip :=DBReadString (0,DBBranch,setting); + StrCopy(p,opt_TTBTooltipPressed); szTTBTooltipPressed:=DBReadString (0,DBBranch,setting); + StrCopy(p,opt_TTBShowWhenVars ); szTTBShowWhenVars :=DBReadUnicode(0,DBBranch,setting); + + StrCopy(p,opt_TabBTooltip ); szTabBTooltip :=DBReadUnicode(0,DBBranch,setting); + StrCopy(p,opt_TabBTooltipPressed); szTabBTooltipPressed:=DBReadUnicode(0,DBBranch,setting); + + for lmenu:=main_menu to HIGH(tMenuType) do + begin + pm:=p; + pm^:=AnsiChar(ORD(lmenu)+ORD('0')); inc(pm); + pm^:='_'; inc(pm); + with UAMenuItem[lmenu] do + begin + StrCopy(pm,opt_MenuPopup ); szMenuPopup :=DBReadUnicode(0,DBBranch,setting); + StrCopy(pm,opt_MenuNameVars ); szMenuNameVars :=DBReadUnicode(0,DBBranch,setting); + StrCopy(pm,opt_MenuShowWhenVars); szMenuShowWhenVars:=DBReadUnicode(0,DBBranch,setting); + StrCopy(pm,opt_MenuOptions ); menu_opt :=DBReadWord (0,DBBranch,setting); + end; + end; + end; + end; +end; +(* +function LoadUAs:integer; +{ +var + section:array [0..63] of AnsiChar; + p:PAnsiChar; + i:integer; +} +begin + result:=0; +{ + MaxTasks:=DBReadByte(0,opt_tasks,opt_count); + result:=MaxTasks; + if MaxTasks>0 then + begin + GetMem (TaskList ,MaxTasks*SizeOf(tTaskRec)); + FillChar(TaskList^,MaxTasks*SizeOf(tTaskRec),0); + for i:=0 to MaxTasks-1 do + begin + p:=StrEnd(IntToStr(section,i)); + with TaskList[i] do + begin + StrCopy(p,opt_flags ); flags :=DBReadDWord (0,opt_tasks,section); + StrCopy(p,opt_name ); name :=DBReadUnicode(0,opt_tasks,section); + StrCopy(p,opt_action); action :=DBReadDWord (0,opt_tasks,section); + end; + end; + end; +} +end; +*) +procedure SetAllActionUsers(var ActionItem:tMyActionItem; initial:boolean); +var + luse:boolean; + lmenu:tMenuType; +begin + if NamesArray[uaHotkey].enable then + begin + if (ActionItem.flags and UAF_REGHOTKEY)<>0 then + AddCoreHotkey(ActionItem) + else + DeleteCoreHotkey(ActionItem); + end; + if not initial then + begin + if NamesArray[uaTTB].enable then + begin + DeleteTTBButton(ActionItem); // no modify command there, just delete, then insert back + if (ActionItem.flags and UAF_REGTTBB)<>0 then + AddTTBButton(ActionItem); + end; + + if NamesArray[uaTAB].enable then + begin + if (ActionItem.flags and UAF_REGTABB)<>0 then + AddTabBBButton(ActionItem) + else + DeleteTabBBButton(ActionItem); + end; + end; + + luse:=false; + for lmenu:=main_menu to HIGH(tMenuType) do + begin + if NamesArray[uaMenu+ORD(lmenu)].enable then + begin + if (ActionItem.UAMenuItem[lmenu].menu_opt and UAF_MENUUSE)<>0 then + begin + luse:=true; + if ActionItem.UAMenuItem[lmenu].changed then + DeleteMenuItem(ActionItem,lmenu); + CreateMenuItem(ActionItem,lmenu); + end + else + DeleteMenuItem(ActionItem,lmenu); + end; + end; + + if (not luse) and (ActionItem.hMenuService<>0) then + begin + DestroyServiceFunction(ActionItem.hMenuService); + ActionItem.hMenuService:=0; + end; +end; diff --git a/plugins/Actman30/ua/i_ua.inc b/plugins/Actman30/ua/i_ua.inc new file mode 100644 index 0000000000..18cd78a9c7 --- /dev/null +++ b/plugins/Actman30/ua/i_ua.inc @@ -0,0 +1,219 @@ +{} +function AddUAction(idx:integer; ptr:pChain):integer; +var + buf:array [0..127] of AnsiChar; +begin + if idx<0 then idx:=Length(UActionList); + if idx=Length(UActionList) then + SetLength(UActionList,Length(UActionList)+1); + + FillChar(UActionList[idx],SizeOf(tMyActionItem),0); + + with UActionList[idx] do + begin + // get Action settings + dwActID:=ptr^.id; + StrDupW(szActDescr,ptr^.descr); + wSortIndex:=idx; + + // prepare for work + IntToStr(StrCopyE(buf,'Actions/Action_'),ptr^.id); + StrDup(szNameID,@buf); + AddIcolibIcon (UActionList[idx]); + end; + + SetLength(arMenuRec,Length(UActionList)+1); + FillChar (arMenuRec[HIGH(arMenuRec)],SizeOf(tuaMenuRecA),0); + result:=idx; +end; + +function CreateUActionList:integer; +var + ptr,ptr1:pChain; + i:integer; +begin + result:=CallService(MS_ACT_GETLIST,0,LPARAM(@ptr)); + SetLength(UActionList,result); + + SetLength(arMenuRec, result+1); + FillChar (arMenuRec[0],(result+1)*SizeOf(tuaMenuRecA),0); + + if result>0 then + begin + ptr1:=ptr; + inc(pbyte(ptr),4); + for i:=0 to result-1 do + begin + AddUAction(i,ptr); + LoadUA(i); // just here coz at list changes for new we don't have settings + if (UActionList[i].flags and UAF_2STATE)<>0 then + AddIcolibIconP(UActionList[i]); + SetAllActionUsers(UActionList[i],true); + inc(ptr); + end; + CallService(MS_ACT_FREELIST,0,LPARAM(ptr1)); + end; +end; + +// "compact" means need to compact list/delete settings (Delete, not just exit) +procedure DeleteUAction(num:integer;compact:boolean); +var + ActionItem:pMyActionItem; + luse:boolean; + lmenu:tMenuType; +begin + if compact then + DeleteUASettings(num); + + ActionItem:=@UActionList[num]; + + DeleteIcolibIcon(ActionItem^); + + if (ActionItem.flags and UAF_REGHOTKEY)<>0 then + DeleteCoreHotkey(ActionItem^); + + if (ActionItem.flags and UAF_REGTTBB)<>0 then + DeleteTTBButton(ActionItem^); + mFreeMem(ActionItem.szTTBTooltip); + mFreeMem(ActionItem.szTTBTooltipPressed); + mFreeMem(ActionItem.szTTBShowWhenVars); + + if (ActionItem.flags and UAF_REGTABB)<>0 then + DeleteTabBBButton(ActionItem^); + mFreeMem(ActionItem.szTabBTooltip); + mFreeMem(ActionItem.szTabBTooltipPressed); + + luse:=false; + for lmenu:=main_menu to HIGH(tMenuType) do + begin + with ActionItem.UAMenuItem[lmenu] do + begin + if (menu_opt and UAF_MENUUSE)<>0 then + begin + luse:=true; + DeleteMenuItem(ActionItem^,lmenu); + end; + mFreeMem(szMenuPopup); + mFreeMem(szMenuNameVars); + mFreeMem(szMenuShowWhenVars); + end; + end; + + if (not luse) and (ActionItem.hMenuService<>0) then + begin + DestroyServiceFunction(ActionItem.hMenuService); + ActionItem.hMenuService:=0; + end; + + // Free Memory + mFreeMem(ActionItem.szNameID); + mFreeMem(ActionItem.szActDescr); + + if compact then + begin + // compact list + if num0 then + begin + ptr1:=ptr; + inc(pbyte(ptr),4); + if wParam<>0 then +// if (wParam and (ACTM_NEW or ACTM_RENAME or ACTM_SORT or ACTM_DELETE))<>0 then + for i:=0 to count-1 do + begin + // search corresponding element + idx:=-1; + for j:=0 to HIGH(UActionList) do + begin + if UActionList[j].dwActID=ptr^.id then + begin + idx:=j; + break; + end; + end; + // if we have no item in list for this action - then add new one + if idx<0 then + begin + idx:=AddUAction(-1,ptr); + end + else + begin + if (wParam and ACTM_RENAME)<>0 then + begin + // check for time economy - no need to change ALL items + if StrCmpW(UActionList[idx].szActDescr,ptr^.descr)<>0 then + begin + mFreeMem(UActionList[idx].szActDescr); + StrDupW (UActionList[idx].szActDescr,ptr^.descr); + end; + end; + end; +// not so necessary to check really +// if (wParam and (ACTM_SORT or ACTM_DELETE or ACTM_NEW))<>0 then + UActionList[idx].wSortIndex:=i; + + inc(ptr); + end; + end + else + ptr1:=nil; + + // now search deleted items + if (wParam and ACTM_DELETE)<>0 then + begin + for j:=HIGH(UActionList) downto 0 do + begin + bFound:=false; + if count>0 then + begin + ptr:=ptr1; + inc(pbyte(ptr),4); + for i:=0 to count-1 do + begin + if UActionList[j].dwActID=ptr^.id then + begin + bFound:=true; + break; + end; + inc(ptr); + end; + end; + if not bFound then + DeleteUAction(j,true); + end; + end; + + if count>0 then + CallService(MS_ACT_FREELIST,0,TLPARAM(ptr1)); + + // show changes in dialog + if settings<>0 then + begin + FillActionList(settings); + ShowAction(settings,-1); + end; + + SaveUAs; + FillChar(arMenuRec[0],Length(arMenuRec)*SizeOf(tuaMenuRecA),0); + for i:=0 to HIGH(UActionList) do + begin + SetAllActionUsers(UActionList[i],false); + end; +end; diff --git a/plugins/Actman30/ua/i_uaplaces.inc b/plugins/Actman30/ua/i_uaplaces.inc new file mode 100644 index 0000000000..0b8ee9468d --- /dev/null +++ b/plugins/Actman30/ua/i_uaplaces.inc @@ -0,0 +1,832 @@ +{} +(* +const + MenuServices:array [tMenuType] of pAnsiChar = ( + 'CList/AddMainMenuItem' {MS_CLIST_ADDMAINMENUITEM }, + 'CList/AddContactMenuItem'{MS_CLIST_ADDCONTACTMENUITEM}, + 'CList/AddTrayMenuItem' {MS_CLIST_ADDTRAYMENUITEM }, + 'CList/AddProtoMenuItem' {MS_CLIST_ADDPROTOMENUITEM }, + 'CList/AddStatusMenuItem' {MS_CLIST_ADDSTATUSMENUITEM } + ); +*) +type + tuaMenuRec = record + hMenuRoot:HMENU; + position :integer; + end; + tuaMenuRecA = array [tMenuType] of tuaMenuRec; + +var + arMenuRec: array of tuaMenuRecA; + +//===== Support ===== + +function ServiceCallWithLParam(wParam:WPARAM; lParam:LPARAM):int_ptr; cdecl; +begin + result:=CallService(MS_ACT_RUNBYID, lParam, wParam); +end; + +procedure SetTTBState(const ActionItem:tMyActionItem); +var + lflag:integer; +begin + if ActionItem.hTTBButton=0 then exit; + if (ActionItem.flags and UAF_2STATE)=0 then exit; + + lflag:=CallService(MS_TTB_GETBUTTONSTATE,ActionItem.hTTBButton,0); + if lflag=TTBST_PUSHED then + begin + if (ActionItem.flags and (UAF_2STATE+UAF_PRESSED))<>(UAF_2STATE+UAF_PRESSED) then exit; + lflag:=TTBST_RELEASED; + end + else + begin + if (ActionItem.flags and (UAF_2STATE+UAF_PRESSED))=(UAF_2STATE+UAF_PRESSED) then exit; + if (ActionItem.flags and UAF_PRESSED)=0 then exit; + lflag:=TTBST_PUSHED; + end; + CallService(MS_TTB_SETBUTTONSTATE,ActionItem.hTTBButton,lflag); +end; + +procedure SetTABState(hContact:THANDLE;const ActionItem:tMyActionItem;pressed:integer); +var + tabb:BBButton; + pc:pWideChar; +begin + FillChar(tabb,SizeOf(tabb),0); + tabb.cbSize :=SizeOf(tabb); + tabb.dwButtonID :=ActionItem.dwActID; + tabb.pszModuleName:=MODULE_NAME; + + if pressed<>0 then + begin + pc:=ActionItem.szTabBTooltipPressed; + if pc=nil then pc:=ActionItem.szTabBTooltip; + tabb.hIcon:=ActionItem.hIcolibIconPressed; + tabb.bbbFlags:=BBSF_PUSHED; + end + else + begin + pc:=ActionItem.szTabBTooltip; + tabb.hIcon:=ActionItem.hIcolibIcon; + tabb.bbbFlags:=BBSF_RELEASED; + end; + if pc=nil then pc:=ActionItem.szActDescr; + tabb.szTooltip.w:=pc; + CallService(MS_BB_SETBUTTONSTATE,hContact,TLPARAM(@tabb)); +end; + +function IsLocalItem(const UAItem:tMyActionItem):boolean; +begin + result:=((UAItem.flags and UAF_GLOBAL)=0) and + (UAItem.UAMenuItem[main_menu ].hMenuItem=0) and + (UAItem.UAMenuItem[tray_menu ].hMenuItem=0) and + (UAItem.UAMenuItem[proto_menu ].hMenuItem=0) and + (UAItem.UAMenuItem[status_menu].hMenuItem=0) and + (UAItem.hTTBButton=0); +end; + +function ServiceCallWithFParam(wParam:WPARAM; lParam:LPARAM; fParam:LPARAM):int_ptr; cdecl; +var + i:integer; + setting:array [0..63] of AnsiChar; + p:pAnsiChar; + cnt:THANDLE; + state:integer; +begin + for i:=0 to HIGH(UActionList) do + begin + with UActionList[i] do + if dwActID=cardinal(fParam) then + if (flags and UAF_2STATE)<>0 then + begin + // sync buttons/menus + if IsLocalItem(UActionList[i]) then + begin + // if (flags and UAF_SAVESTATE)<>0 then + begin + state:=DBReadByte(lastContact,opt_ua,szNameID); + state:=state xor 1; + DBWriteByte(lastContact,opt_ua,szNameID,state); + cnt:=lastContact; + end; + end + else + begin + flags:=flags xor UAF_PRESSED; + // save "pressed" state + if (flags and UAF_SAVESTATE)<>0 then + begin + p:=GetUABranch(setting,dwActID); + if p<>nil then + begin + p:=StrCopyE(p,opt_ua); + p^:='/'; inc(p); + StrCopy(p,opt_flags); + DBWriteDWord(0,DBBranch,setting,flags and not UAF_REALTIME); + end; + end; + + if hTTBButton<>0 then + SetTTBState(UActionList[i]); + + cnt:=0; + state:=ORD(flags and UAF_PRESSED); + end; + if (flags and UAF_REGTABB)<>0 then + SetTABState(cnt,UActionList[i],state); + + break; + end; + end; + + result:=CallService(MS_ACT_RUNBYID, fParam, wParam); +end; + +function AddIcolibIconP(var ActionItem:tMyActionItem):THANDLE; +var + sid:TSKINICONDESC; + buf,buf1:array [0..63] of WideChar; +begin + if (ActionItem.hIcolibIconPressed=0) or + (ActionItem.hIcolibIconPressed=ActionItem.hIcolibIcon) then + begin + // add icon for action to icolib + fillChar(sid,SizeOf(sid),0); + sid.cbSize :=sizeof(sid); + sid.szSection .w:=ICOLIB_ACTSECTION; + sid.szDefaultFile.w:=szMyPath; + sid.iDefaultIndex :=-IDI_ACTION; + sid.cx :=16; + sid.cy :=16; + sid.flags :=SIDF_ALL_UNICODE; + // icon "off" + StrCopyW(StrCopyEW(buf,ActionItem.szActDescr),' (pressed)'); + sid.szDescription.w:=@buf; + StrCopy(StrCopyE(@buf1,ActionItem.szNameID),'_pressed'); + sid.pszName :=@buf1; + ActionItem.hIcolibIconPressed:=Skin_AddIcon(@sid); + end; + result:=ActionItem.hIcolibIconPressed; +end; + +function AddIcolibIcon(var ActionItem:tMyActionItem):THANDLE; +var + sid:TSKINICONDESC; +begin + if ActionItem.hIcolibIcon=0 then + begin + // add icon for action to icolib + fillChar(sid,SizeOf(sid),0); + sid.cbSize :=sizeof(sid); + sid.szSection .w:=ICOLIB_ACTSECTION; + sid.szDefaultFile.w:=szMyPath; + sid.iDefaultIndex :=-IDI_ACTION; + sid.cx :=16; + sid.cy :=16; + sid.flags :=SIDF_ALL_UNICODE; + // icon "on" + sid.szDescription.w:=ActionItem.szActDescr; + sid.pszName :=ActionItem.szNameID; + ActionItem.hIcolibIcon:=Skin_AddIcon(@sid); + end; + result:=ActionItem.hIcolibIcon; +end; + +procedure DeleteIcolibIconP(var ActionItem:tMyActionItem); +var + buf1:array [0..63] of WideChar; +begin + if (ActionItem.hIcolibIconPressed<>0) and + (ActionItem.hIcolibIconPressed<>ActionItem.hIcolibIcon) then + begin + StrCopy(StrCopyE(@buf1,ActionItem.szNameID),'_pressed'); + CallService(MS_SKIN2_REMOVEICON,0,LPARAM(@buf1)); + ActionItem.hIcolibIconPressed:=ActionItem.hIcolibIcon; + end; +end; + +procedure DeleteIcolibIcon(var ActionItem:tMyActionItem); +begin + DeleteIcolibIconP(ActionItem); + CallService(MS_SKIN2_REMOVEICON,0,LPARAM(ActionItem.szNameID)); + ActionItem.hIcolibIcon :=0; + ActionItem.hIcolibIconPressed:=0; +end; + +//===== Really places ===== + +//----- Hotkeys ----- + +function AddCoreHotkey(var ActionItem:tMyActionItem):boolean; +var + hkd:THOTKEYDESC; +begin + if (ActionItem.flags and UAF_HKREGGED)=0 then + begin + FillChar(hkd,SizeOf(hkd),0); + hkd.cbSize := SizeOf(hkd); // HOTKEYDESC_SIZE_V1 for pre-0.9 + hkd.dwFlags := HKD_UNICODE; // since 0.9 only + hkd.pszName := ActionItem.szNameID; + hkd.pszDescription.w:= ActionItem.szActDescr; + hkd.pszSection .w:= MODULE_NAME; + hkd.pszService := SERVICE_WITH_LPARAM_NAME; + hkd.lParam := ActionItem.dwActID; + result:=Hotkey_Register(@hkd)<>0; + if result then + ActionItem.flags:=ActionItem.flags or UAF_HKREGGED; + end + else + result:=true; //!! +end; + +procedure DeleteCoreHotkey(var ActionItem:tMyActionItem); +begin + if // bCoreHotkeyPresents and + // (ServiceExists(MS_HOTKEY_UNREGISTER)<>0) and + ((ActionItem.flags and UAF_HKREGGED)<>0) then + begin + CallService(MS_HOTKEY_UNREGISTER,0,LParam(ActionItem.szNameID)); + ActionItem.flags:=ActionItem.flags and not UAF_HKREGGED; + end; +end; + +//----- Common menu functions ----- + +function AddRootMenuIcon(szPopupName:pWideChar):THANDLE; +var + sid:TSKINICONDESC; +begin + FillChar(sid,SizeOf(sid),0); + //first - register icon for root popup + sid.cbSize := sizeof(sid); + sid.szSection.w := ICOLIB_MNUSECTION; + sid.flags := SIDF_ALL_UNICODE; + sid.cx := 16; + sid.cy := 16; + sid.szDescription.w:= szPopupName; + sid.szDefaultFile.w:= szMyPath; + sid.iDefaultIndex := -IDI_ACTION; + WideToAnsi(szPopupName,sid.pszName); + result:=Skin_AddIcon(@sid); + mFreeMem(sid.pszName); +end; + +procedure DeleteMenuItem(var ActionItem:tMyActionItem;mtype:tMenuType); +var + i:integer; + hMenuRoot:THANDLE; + p:pMyActionItem; +begin + with ActionItem.UAMenuItem[mtype] do + begin + if hMenuItem=0 then exit; + CallService(MO_REMOVEMENUITEM,hMenuItem,0); + hMenuItem:=0; + end; + + hMenuRoot:=ActionItem.UAMenuItem[mtype].hMenuRoot; + if hMenuRoot<>0 then + begin + for i:=0 to HIGH(UActionList) do + begin + p:=@UActionList[i]; + // presents somethere else + if (p<>@ActionItem) and (p.UAMenuItem[mtype].hMenuRoot=hMenuRoot) then + exit; + end; + // menu array cleanup now? + for i:=0 to HIGH(arMenuRec) do + begin + if arMenuRec[i][mtype].hMenuRoot=hMenuRoot then + begin + FillChar(arMenuRec[i][mtype],SizeOf(tuaMenuRec),0); +// arMenuRec[i][mtype].hMenuRoot:=0; + break; + end; + end; + CallService(MO_REMOVEMENUITEM,hMenuRoot,0); + ActionItem.UAMenuItem[mtype].hMenuRoot:=0; + end; +end; + +function GetMenuPosition(hMenu:HMENU;mtype:tMenuType;toset:boolean):integer; +var + i:integer; +begin + result:=0; + for i:=0 to HIGH(arMenuRec) do + begin + if arMenuRec[i][mtype].hMenuRoot=hMenu then + begin + if toset then + inc(arMenuRec[i][mtype].position,100000); + result:=arMenuRec[i][mtype].position; + break; + end; + end; +end; + +function MakeMenuItem(mtype:tMenuType;clmi:PCListMenuItem):THANDLE; +begin + case mtype of + main_menu : result:=Menu_AddMainMenuItem(clmi); + contact_menu: result:=Menu_AddContactMenuItem(clmi); + tray_menu : result:=Menu_AddTrayMenuItem(clmi); + proto_menu : result:=Menu_AddProtoMenuItem(clmi); + status_menu : result:=Menu_AddStatusMenuItem(clmi); + else + result:=0; + end; +end; + +procedure CreateMenuItem(var ActionItem:tMyActionItem;mtype:tMenuType); +var + i:integer; + ActItem:pMyActionItem; + ActMItem,UAMenuItem:pUAMenuItem; + clmi:TCListMenuItem; + res:boolean; + extra:pWideChar; +begin +{} + UAMenuItem:=@ActionItem.UAMenuItem[mtype]; + if UAMenuItem.hMenuItem<>0 then exit; + + // create popup menu +{}{} + res:=true; + if (UAMenuItem.szMenuPopup<>nil) and (UAMenuItem.szMenuPopup^<>#0) then + begin + res:=false; + for i:=0 to HIGH(UActionList) do + begin + // try to find root popup with same name (if we already created one) + ActItem :=@UActionList[i]; + ActMItem:=@ActItem.UAMenuItem[mtype]; + + if (ActMItem.szMenuPopup<>nil) and + (ActMItem.hMenuRoot<>0) and + ( (ActItem<>@ActionItem) and + (StrCmpW(ActMItem.szMenuPopup,UAMenuItem.szMenuPopup)=0) ) then + begin + UAMenuItem.hMenuRoot:=ActMItem.hMenuRoot; + res:=true; + break; + end; + end; + end; + // popup menu not found + if not res then + begin + FillChar(clmi,SizeOf(clmi),0); + clmi.cbSize:=SizeOf(clmi); + clmi.flags :=CMIF_UNICODE{ or CMIF_ICONFROMICOLIB}; + + if (UAMenuItem.szMenuPopup<>nil) and (UAMenuItem.szMenuPopup^<>#0) then + clmi.szName.w:=ParseVarString(UAMenuItem.szMenuPopup) + else + clmi.szName.w:=ActionItem.szActDescr; + + clmi.hIcon :=AddRootMenuIcon(clmi.szName.w); + clmi.position:=ActionItem.wSortIndex*10; + + // position in Root Menu + inc(clmi.position,GetMenuPosition(0,mtype, + (UAMenuItem.menu_opt and UAF_MENUSEP)<>0)); + + UAMenuItem.hMenuRoot:=MakeMenuItem(mtype,@clmi); + //CallService(MenuServices[mtype],0,LPARAM(@clmi)); + if clmi.szName.w<>ActionItem.szActDescr then + mFreeMem(clmi.szName.w); + + for i:=1 to HIGH(arMenuRec) do + begin + with arMenuRec[i][mtype] do + if hMenuRoot=0 then + begin +// MenuName :=ActionItem.szActDescr; + hMenuRoot:=UAMenuItem.hMenuRoot; + break; + end; + end; + + end; +{}{} + + // Now Menu Item preparing +{}{} + FillChar(clmi,SizeOf(clmi),0); + clmi.cbSize:=SizeOf(clmi); + clmi.flags:=CMIF_UNICODE{ or CMIF_ICONFROMICOLIB}; + if (ActionItem.flags and (UAF_2STATE+UAF_PRESSED))<>(UAF_2STATE+UAF_PRESSED) then + begin + clmi.hIcon:=ActionItem.hIcolibIcon; + extra:='0'; + end + else + begin + clmi.hIcon:=ActionItem.hIcolibIconPressed; + clmi.flags:=CMIF_UNICODE {or CMIF_ICONFROMICOLIB }or CMIF_CHECKED; + extra:='1'; + end; + + with ActionItem.UAMenuItem[mtype] do + begin + if (szMenuNameVars<>nil) and (szMenuNameVars^<>#0) then + clmi.szName.w:=ParseVarString(szMenuNameVars,0,extra) + else + clmi.szName.w:=ActionItem.szActDescr; + + if hMenuRoot<>0 then + begin + clmi.flags:=clmi.flags or CMIF_ROOTHANDLE; + clmi.szPopupName.w:=pWideChar(hMenuRoot); + end; + end; + + clmi.pszService:=ActionItem.szNameID; + if ActionItem.hMenuService=0 then + ActionItem.hMenuService:=CreateServiceFunctionParam( + clmi.pszService,@ServiceCallWithFParam,ActionItem.dwActID); + + clmi.position:=ActionItem.wSortIndex*10; +{}{} + inc(clmi.position,GetMenuPosition(UAMenuItem.hMenuRoot,mtype, + (UAMenuItem.menu_opt and UAF_MENUSEP)<>0)); + + UAMenuItem.hMenuItem:=MakeMenuItem(mtype,@clmi); + //CallService(MenuServices[mtype],0,LPARAM(@clmi)); + if clmi.szName.w<>ActionItem.szActDescr then + mFreeMem(clmi.szName.w); +{} + +end; + +function PreBuildMenu(mtype:tMenuType;hContact:THANDLE=0):int; +var + i:integer; + mi:TCListMenuItem; + p,extra:pWideChar; +begin + result:=0; + + FillChar(mi,SizeOf(mi),0); + mi.cbSize:=SizeOf(mi); + + for i:=0 to HIGH(UActionList) do + begin + mi.flags:=CMIM_FLAGS; + p:=nil; + with UActionList[i] do + begin + with UAMenuItem[mtype] do + begin + if hMenuItem<>0 then // it means, we process that item here + begin + mi.szName.w:=nil; + // Show / hide + if isVarsInstalled then + begin + if (szMenuShowWhenVars<>nil) and (szMenuShowWhenVars^<>#0) then + begin + p:=ParseVarString(szMenuShowWhenVars,hContact); + if p<>nil then + begin + if StrCmpW(p,'1')<>0 then + mi.flags:=CMIM_FLAGS or CMIF_HIDDEN; + mFreeMem(p); + end; + end; + end; + + // change if need to show only + // (popup can be used by many items, keep unchanged) + if (mi.flags and CMIF_HIDDEN)=0 then + begin + //!!!! icon (check for contact menu) + mi.flags:=mi.flags or CMIM_ICON or CMIM_FLAGS{ or CMIF_ICONFROMICOLIB}; + + if (mtype=contact_menu) and IsLocalItem(UActionList[i]) then + begin + lastContact:=hContact; + if ((flags and UAF_2STATE)<>0) and + (DBReadByte(hContact,opt_ua,szNameID)<>0) then + begin + mi.flags:=mi.flags or CMIF_CHECKED; + mi.hIcon:=hIcolibIconPressed; + extra:='1'; + flags:=flags or UAF_PRESSED; + end + else + begin + mi.hIcon:=hIcolibIcon; + flags:=flags and not UAF_PRESSED; + extra:='0'; + end; + + end + else + begin + if (flags and (UAF_2STATE+UAF_PRESSED))=(UAF_2STATE+UAF_PRESSED) then + begin + mi.flags:=mi.flags or CMIF_CHECKED; + mi.hIcon:=hIcolibIconPressed; + extra:='1'; + end + else + begin + mi.hIcon:=hIcolibIcon; + extra:='0'; + end; + end; + + // new name + mi.flags:=mi.flags or CMIM_NAME or CMIF_UNICODE; + if (szMenuNameVars<>nil) and (szMenuNameVars^<>#0) then + mi.szName.w:=ParseVarString(szMenuNameVars,hContact,extra); + + if mi.szName.w=nil then + mi.szName.w:=szActDescr; + end; + + CallService(MS_CLIST_MODIFYMENUITEM,hMenuItem,LPARAM(@mi)); + if mi.szName.w<>szActDescr then + mFreeMem(mi.szName.w); + end; + end; + end; + + end; +end; + +function PreBuildMainMenu(wParam:WPARAM;lParam:LPARAM):int; cdecl; +begin + result:=PreBuildMenu(main_menu,wParam); +end; + +function PreBuildContactMenu(wParam:WPARAM;lParam:LPARAM):int; cdecl; +begin + result:=PreBuildMenu(contact_menu,wParam); +end; + +function PreBuildTrayMenu(wParam:WPARAM;lParam:LPARAM):int; cdecl; +begin + result:=PreBuildMenu(tray_menu,wParam); +end; + +//----- TopToolbar ----- + +procedure AddTTBButton(var ActionItem:tMyActionItem); +var + mtButton:TTBButton; + pc,pc1,pc2:pAnsiChar; + res:boolean; + p:pWideChar; +begin + if not NamesArray[uaTTB].enable then exit; + + if ActionItem.hTTBButton=0 then + begin + // Add or not + if isVarsInstalled then + begin + if (ActionItem.szTTBShowWhenVars<>nil) and (ActionItem.szTTBShowWhenVars^<>#0) then + begin + p:=ParseVarString(ActionItem.szTTBShowWhenVars); + if p<>nil then + begin + res:=StrCmpW(p,'1')<>0; + mFreeMem(p); + end + else + res:=true; + if res then + exit; + end; + end; + + FillChar(mtButton,SizeOf(mtButton),0); + mtButton.cbSize :=SizeOf(mtButton); + + mtButton.pszService:=TTB_SERVICE_NAME;//SERVICE_WITH_LPARAM_NAME; + mtButton.lParamUp :=ActionItem.dwActID; + mtButton.lParamDown:=ActionItem.dwActID; + + mtButton.hIconUp:=ActionItem.hIcolibIcon; + mtButton.hIconDn:=ActionItem.hIcolibIconPressed; + + WideToAnsi(ActionItem.szActDescr,pc); + + if (ActionItem.flags and UAF_2STATE)<>0 then + mtButton.dwFlags:=TTBBF_VISIBLE or TTBBF_SHOWTOOLTIP{ or TTBBF_ASPUSHBUTTON} + else + mtButton.dwFlags:=TTBBF_VISIBLE or TTBBF_SHOWTOOLTIP; + + if ActionItem.szTTBTooltip =nil then + pc1:=pc + else pc1:=ActionItem.szTTBTooltip; + + if ((ActionItem.flags and UAF_2STATE)=0) or + (ActionItem.szTTBTooltipPressed=nil) then + pc2:=pc1 + else + pc2:=ActionItem.szTTBTooltipPressed; + + mtButton.Name :=pc; + mtButton.pszTooltipUp :=pc1; + mtButton.pszTooltipDn :=pc2; + + ActionItem.hTTBButton:=TopToolbar_AddButton(@mtButton); + if ActionItem.hTTBButton=THANDLE(-1) then + ActionItem.hTTBButton:=0; + mFreeMem(pc); + end; +end; + +procedure DeleteTTBButton(var ActionItem:tMyActionItem); +begin + if ActionItem.hTTBButton<>0 then + begin + CallService(MS_TTB_REMOVEBUTTON,ActionItem.hTTBButton,0); + ActionItem.hTTBButton:=0; + end; +end; + +function TTBServiceCall(wParam:WPARAM; lParam:LPARAM):int_ptr; cdecl; +var + i,lflag:integer; +begin + result:=0; + for i:=0 to HIGH(UActionList) do + begin + if TLPARAM(UActionList[i].dwActID)=lParam then + begin + with UActionList[i] do + begin + if (flags and UAF_2STATE)<>0 then + begin + if CallService(MS_TTB_GETBUTTONSTATE,hTTBButton,0)=TTBST_PUSHED then + begin + lflag:=TTBST_RELEASED; + end + else + begin + lflag:=TTBST_PUSHED; + end; + CallService(MS_TTB_SETBUTTONSTATE,hTTBButton,lflag); + end; + end; + + result:=ServiceCallWithFParam(0,0,lParam); + break; + end; + end; +end; + +function OnTTBLoaded(wParam:WPARAM;lParam:LPARAM):int; cdecl; +var + i:integer; +begin + result:=0; + for i:=HIGH(UActionList) downto 0 do + begin + if (UActionList[i].flags and UAF_REGTTBB)<>0 then + AddTTBButton(UActionList[i]); + end; +end; + +//----- TabSRMM Toolbar ----- + +const + TABTOOLBAR_INITPOS = 350; + +procedure AddTabBBButton(var ActionItem:tMyActionItem); +var + tabb:BBButton; +begin + if not NamesArray[uaTAB].enable then exit; + + if (ActionItem.flags and UAF_TBREGGED)=0 then + begin + FillChar(tabb,SizeOf(tabb),0); + // register Tab ButtonBar button + tabb.cbSize :=SizeOf(tabb); + tabb.dwButtonID :=ActionItem.dwActID; + tabb.pszModuleName:=MODULE_NAME; + tabb.dwDefPos :=(TABTOOLBAR_INITPOS+ActionItem.wSortIndex*10) and $7FFF; + tabb.iButtonWidth :=0; + tabb.hIcon :=ActionItem.hIcolibIcon; + if (ActionItem.flags and UAF_2STATE)<>0 then + tabb.bbbFlags:=BBBF_ISIMBUTTON or BBBF_ISLSIDEBUTTON or + BBBF_ISCHATBUTTON or BBBF_ISPUSHBUTTON + else + tabb.bbbFlags:=BBBF_ISIMBUTTON or BBBF_ISLSIDEBUTTON or + BBBF_ISCHATBUTTON; + + if ActionItem.szTabBTooltip<>nil then + tabb.szTooltip.w:=ActionItem.szTabBTooltip + else + tabb.szTooltip.w:=ActionItem.szActDescr; + + if CallService(MS_BB_ADDBUTTON,0,LPARAM(@tabb))=0 then + ActionItem.flags:=ActionItem.flags or UAF_TBREGGED; + end; +end; + +procedure DeleteTabBBButton(var ActionItem:tMyActionItem); +var + tabb:BBButton; +begin + if (ActionItem.flags and UAF_TBREGGED)<>0 then + begin + FillChar(tabb,SizeOf(tabb),0); + tabb.cbSize :=SizeOf(tabb); + tabb.dwButtonID :=ActionItem.dwActID; + tabb.pszModuleName:=MODULE_NAME; + CallService(MS_BB_REMOVEBUTTON,0,LPARAM(@tabb)); + ActionItem.flags:=ActionItem.flags and not UAF_TBREGGED; + end; +end; + +function OnTabButtonPressed(wParam:WPARAM;lParam:LPARAM):int; cdecl; +var + cbcd:pCustomButtonClickData; +// tabb:BBButton; +// pc:pWideChar; + i:integer; +begin + result:=0; + cbcd:=pointer(lParam); + if StrCmp(cbcd.pszModule,MODULE_NAME)<>0 then + exit; + + for i:=0 to HIGH(UActionList) do + begin + with UActionList[i] do + begin + if cbcd.dwButtonId=dwActID then + begin +{ + FillChar(tabb,SizeOf(tabb),0); + tabb.cbSize :=SizeOf(tabb); + tabb.dwButtonID :=cbcd.dwButtonId; + tabb.pszModuleName:=MODULE_NAME; + if (flags and UAF_2STATE)<>0 then + begin + CallService(MS_BB_GETBUTTONSTATE,cbcd.hContact,TLPARAM(@tabb)); + if IsLocalItem(UActionList[i]) then + begin + if DBReadByte(hContact,opt_ua,szNameID)<>0 then + end + else + begin + if (tabb.bbbFlags and BBSF_PUSHED)<>0 then + begin + pc:=szTabBTooltipPressed; + if pc=nil then pc:=szTabBTooltip; + tabb.hIcon:=hIcolibIconPressed; + end + else + begin + pc:=szTabBTooltip; + tabb.hIcon:=hIcolibIcon; + end; + if pc=nil then pc:=szActDescr; + tabb.szTooltip.w:=pc; + tabb.bbbFlags :=BBBF_ISIMBUTTON or BBBF_ISLSIDEBUTTON or + BBBF_ISCHATBUTTON or BBBF_ISPUSHBUTTON; + end + else + begin + tabb.hIcon:=hIcolibIcon; + tabb.szTooltip.w:=szTabBTooltip; + if tabb.szTooltip.w=nil then tabb.szTooltip.w:=szActDescr; + tabb.bbbFlags :=BBBF_ISIMBUTTON or BBBF_ISLSIDEBUTTON or + BBBF_ISCHATBUTTON; + end; + + tabb.iButtonWidth:=0; + tabb.dwDefPos :=(TABTOOLBAR_INITPOS+wSortIndex*10) and $7FFF; + CallService(MS_BB_MODIFYBUTTON,0,TLPARAM(@tabb)); +} + ServiceCallWithFParam(cbcd.hContact,0,cbcd.dwButtonId); + result:=1; + break; + end; + end; + end; + +end; + +function OnTabBBLoaded(wParam:WPARAM;lParam:LPARAM):int; cdecl; +var + i:integer; +begin + result:=0; + for i:=HIGH(UActionList) downto 0 do + begin + if (UActionList[i].flags and UAF_REGTABB)<>0 then + AddTabBBButton(UActionList[i]); + end; +end; diff --git a/plugins/Actman30/ua/i_uavars.inc b/plugins/Actman30/ua/i_uavars.inc new file mode 100644 index 0000000000..5b53cde26a --- /dev/null +++ b/plugins/Actman30/ua/i_uavars.inc @@ -0,0 +1,121 @@ +{} +const + MODULE_NAME = 'Actions'; +const + opt_groups:PAnsiChar = 'Group'; + opt_ua :PAnsiChar = 'UA'; + opt_id :PAnsiChar = 'id'; + opt_flags :PAnsiChar = 'Flags'; + +const + ICOLIB_ACTSECTION = MODULE_NAME+'/Registered actions'; + ICOLIB_MNUSECTION = MODULE_NAME+'/Menu icons'; + + SERVICE_WITH_LPARAM_NAME = MODULE_NAME+'/CallAction'; + TTB_SERVICE_NAME = MODULE_NAME+'/TTBAction'; + +type + tMenuType = (main_menu,contact_menu,tray_menu,proto_menu,status_menu); + pUAMenuItem = ^tUAMenuItem; + tUAMenuItem = record + hMenuItem :THANDLE; + szMenuPopup :pWideChar; + szMenuNameVars :pWideChar; + szMenuShowWhenVars:pWideChar; + hMenuRoot :THANDLE; + menu_opt :dword; + changed :boolean; + end; +type + pMyActionItem = ^tMyActionItem; + tMyActionItem = record + flags :dword; + dwActID :dword; // action ID + wSortIndex :word; // list/menu/toolbar order + // UseActions/Action_ID + szNameID :pAnsiChar; // uaction ID + szActDescr :pWideChar; // action name + + hIcolibIcon, + hIcolibIconPressed :THANDLE; + + hTTBButton :THANDLE; // TopToolbar button + szTTBTooltip :PAnsiChar; + szTTBTooltipPressed :PAnsiChar; + szTTBShowWhenVars :pWideChar; + + szTabBTooltip :PWideChar; // TabSRMM toolbar button + szTabBTooltipPressed:PWideChar; + + lastContact :THANDLE; // for contact menu + hMenuService :THANDLE; // common menu service + UAMenuItem :array [tMenuType] of tUAMenuItem; + end; + +const + UAF_NONE = 0; + + UAF_REGHOTKEY = 1 shl 0; // hotkey + UAF_REGTTBB = 1 shl 1; // modern toolbar + + UAF_REGTABB = 1 shl 5; // TabSRMM toolbar + UAF_USING = UAF_REGHOTKEY or UAF_REGTTBB or UAF_REGTABB; + + UAF_2STATE = 1 shl 11; // Buttons/menu items are 2-state + UAF_PRESSED = 1 shl 12; // Button pressed/menu item selected + UAF_SAVESTATE = 1 shl 13; // Save or not "pressed" state + UAF_GLOBAL = 1 shl 14; // not contact related even if in contact menu only + + // realtime, no save + UAF_HKREGGED = 1 shl 16; // hotkey registered + UAF_TBREGGED = 1 shl 17; // TabSRMM button registered + UAF_DISABLED = 1 shl 30; // action disabled atm + UAF_REALTIME = UAF_HKREGGED or UAF_TBREGGED or UAF_DISABLED; + + UAF_SPECIAL = 1 shl 31; // for settings read + + // menu options + UAF_MENUSEP = 1 shl 1; // menu item separated + UAF_MENUUSE = 1 shl 8; // use this menu + +type + tNameRec = record + name :PAnsiChar; + service:PAnsiChar; + mask :dword; + atype :word; + enable :boolean; + end; + +const + NumTypes = 8; +const + uaTTB = 0; + uaTAB = 1; + uaHotkey = 2; + uaMenu = 3; + +const + NamesArray: array [0..NumTypes-1] of tNameRec = ( + (name:'TopToolbar'; service:'TopToolBar/AddButton'; + mask:UAF_REGTTBB ; atype:uaTTB; enable:false), + (name:'TabSRMM toolbar' ; service:'TabSRMM/ButtonsBar/AddButton'; + mask:UAF_REGTABB ; atype:uaTAB; enable:false), + (name:'Core Hotkey' ; service:nil{MS_HOTKEY_REGISTER}; + mask:UAF_REGHOTKEY; atype:uaHotkey; enable:false), + (name:'Main menu' ; service:nil; + mask:0; atype:uaMenu+(ORD(main_menu ) shl 8); enable:false), + (name:'Contact menu' ; service:nil; + mask:0; atype:uaMenu+(ORD(contact_menu) shl 8); enable:false), + (name:'Tray menu' ; service:'CList/AddTrayMenuItem'; + mask:0; atype:uaMenu+(ORD(tray_menu ) shl 8); enable:false), + (name:'Protocol menus' ; service:'CList/AddProtoMenuItem'; + mask:0; atype:uaMenu+(ORD(proto_menu ) shl 8); enable:false), + (name:'Status menu' ; service:'CList/AddStatusMenuItem'; + mask:0; atype:uaMenu+(ORD(status_menu ) shl 8); enable:false) + ); + +var + UActionList:array of tMyActionItem; +var + szMyPath:array [0..MAX_PATH] of WideChar; diff --git a/plugins/Actman30/ua/i_uconst.inc b/plugins/Actman30/ua/i_uconst.inc new file mode 100644 index 0000000000..34dde3ee9e --- /dev/null +++ b/plugins/Actman30/ua/i_uconst.inc @@ -0,0 +1,34 @@ +{resource constants} +const + IDD_UA = 1031; + + IDC_UA_ACTIONLIST = 1025; + IDC_UA_PLACELIST = 1026; + + // menu settings + IDC_UA_SEPARATE = 1027; + IDC_UA_POPUPT = 1028; + IDC_UA_POPUPV = 1029; + + IDC_UA_VARNAMEST = 1030; + IDC_UA_VARNAMESV = 1031; + IDC_UA_VARNAMESH = 1032; + + IDC_UA_SHOWVART = 1033; + IDC_UA_SHOWVARV = 1034; + IDC_UA_SHOWVARH = 1035; + + // toolbar settings + IDC_UA_TTNORMALT = 2028; + IDC_UA_TTNORMALV = 2029; + IDC_UA_TTPRESSEDT = 2030; + IDC_UA_TTPRESSEDV = 2031; + + // common + IDC_UA_COMMON = 2000; + IDC_UA_TWOSTATE = 2001; + IDC_UA_SAVSTATE = 2002; + + IDC_UA_GLOBAL = 2003; + + IDI_ACTION = 101; diff --git a/plugins/Actman30/ua/ua.pas b/plugins/Actman30/ua/ua.pas new file mode 100644 index 0000000000..4aad8e1793 --- /dev/null +++ b/plugins/Actman30/ua/ua.pas @@ -0,0 +1,108 @@ +unit ua; + +interface + +implementation + +uses + windows, commctrl, messages, + mirutils, common, dbsettings, io, m_api, wrapper, + global; + +{$R ua.res} + +{$include m_actman.inc} + +{$include i_uconst.inc} +{$include i_uavars.inc} + +// in - Action ID, out - action (group) number +function GetUABranch(setting:pAnsiChar;id:cardinal):pAnsiChar; +var + i:integer; + p,p1:pAnsiChar; +begin + result:=nil; + p1:=StrCopyE(setting,opt_groups); + for i:=0 to CallService(MS_ACT_GETLIST,0,0)-1 do + begin + p:=StrEnd(IntToStr(p1,i)); + p^:='/'; inc(p); + StrCopy(p,opt_id); + if DBReadDWord(0,DBBranch,setting)=id then + begin + p^:=#0; + result:=p; + break; + end; + end; +end; + +var + amLink:tActionLink; + +{$include i_uaplaces.inc} +{$include i_options.inc} +{$include i_opt_dlg.inc} +{$include i_ua.inc} +{$include i_inoutxm.inc} + +// ------------ base interface functions ------------- + +procedure Init; +begin + GetModuleFileNameW(hInstance,szMyPath,MAX_PATH); + + CreateServiceFunction(SERVICE_WITH_LPARAM_NAME,@ServiceCallWithLParam); + CreateServiceFunction(TTB_SERVICE_NAME ,@TTBServiceCall); + CheckPlacesAbility; + + CreateUActionList; + + HookEvent(ME_TTB_MODULELOADED ,@OnTTBLoaded); + HookEvent(ME_MSG_TOOLBARLOADED,@OnTabBBLoaded); + HookEvent(ME_MSG_BUTTONPRESSED,@OnTabButtonPressed); + HookEvent(ME_ACT_CHANGED ,@ActListChange); + + HookEvent(ME_CLIST_PREBUILDMAINMENU , PreBuildMainMenu); + HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PreBuildContactMenu); + HookEvent(ME_CLIST_PREBUILDTRAYMENU , PreBuildTrayMenu); + + HookEvent(ME_ACT_INOUT,@ActInOut); +end; + +procedure DeInit; +var + i:integer; +begin + if Length(UActionList)>0 then + begin + for i:=HIGH(UActionList) downto 0 do + begin + DeleteUAction(i,false); + end; + SetLength(UActionList,0); + end; + SetLength(arMenuRec,0); +end; + +function AddOptionPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +begin + result:=0; + tmpl:=PAnsiChar(IDD_UA); + proc:=@DlgProcOpt; + name:='Use Actions'; +end; + +procedure InitLink; +begin + amLink.Next :=ActionLink; + amLink.Init :=@Init; + amLink.DeInit :=@DeInit; + amLink.AddOption:=@AddOptionPage; + ActionLink :=@amLink; +end; + +initialization + InitLink; +end. diff --git a/plugins/Actman30/ua/ua.rc b/plugins/Actman30/ua/ua.rc new file mode 100644 index 0000000000..76d8c0ad77 --- /dev/null +++ b/plugins/Actman30/ua/ua.rc @@ -0,0 +1,51 @@ +#include "i_uconst.inc" + +LANGUAGE 0,0 + +IDD_UA DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + CTEXT "Action list",-1, 2,2,132,10, SS_CENTERIMAGE + CONTROL "", IDC_UA_ACTIONLIST, "SysListView32", + WS_BORDER | WS_TABSTOP | + LVS_NOCOLUMNHEADER | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_SINGLESEL, + 2, 12, 132, 212, WS_EX_CONTROLPARENT + + CTEXT "Where to use",-1, 138,2,160,10, SS_CENTERIMAGE + CONTROL "", IDC_UA_PLACELIST, "SysListView32", + WS_BORDER | WS_TABSTOP | + LVS_NOCOLUMNHEADER | LVS_SHOWSELALWAYS | LVS_REPORT | LVS_SINGLESEL, + 138, 12, 160, 74, WS_EX_CONTROLPARENT + + GROUPBOX "Common" , IDC_UA_COMMON , 138, 88,160,38 + AUTOCHECKBOX "2 state button/item" , IDC_UA_TWOSTATE, 140, 96,156,14, BS_LEFTTEXT | BS_RIGHT + AUTOCHECKBOX "Save button/item state", IDC_UA_SAVSTATE, 140,110,156,14, BS_LEFTTEXT | BS_RIGHT + + AUTOCHECKBOX "Contact related", IDC_UA_GLOBAL, 138,128,160,14, BS_LEFTTEXT | BS_RIGHT + + // Buttons settings block + RTEXT "Normal button tooltip",IDC_UA_TTNORMALT, 138,148,160,8 + EDITTEXT IDC_UA_TTNORMALV, 138,158,160,12, ES_AUTOHSCROLL + + RTEXT "Pressed button tooltip",IDC_UA_TTPRESSEDT, 138,172,160,8 + EDITTEXT IDC_UA_TTPRESSEDV, 138,182,160,12, ES_AUTOHSCROLL + + // Menu settings block + AUTOCHECKBOX "Separated",IDC_UA_SEPARATE, 138,142,160,14, BS_LEFTTEXT | BS_RIGHT + + RTEXT "Root popup:",IDC_UA_POPUPT,138,158,80,12, SS_CENTERIMAGE + EDITTEXT IDC_UA_POPUPV, 218,158,80,12, ES_AUTOHSCROLL + + RTEXT "Menu item name:",IDC_UA_VARNAMEST, 138,172,140,8 + EDITTEXT IDC_UA_VARNAMESV, 138,182,140,12, ES_AUTOHSCROLL + CONTROL "V",IDC_UA_VARNAMESH,"MButtonClass",WS_TABSTOP, 282,180,16,16, $18000000 + + RTEXT "Show only if variables return 1",IDC_UA_SHOWVART, 138,200,140,8 + EDITTEXT IDC_UA_SHOWVARV,138,210,140,12,ES_AUTOHSCROLL + CONTROL "V",IDC_UA_SHOWVARH,"MButtonClass",WS_TABSTOP, 282,208,16,16, $18000000 + +} + +IDI_ACTION ICON "action.ico" -- cgit v1.2.3