summaryrefslogtreecommitdiff
path: root/plugins/Actman/tasks
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Actman/tasks')
-rw-r--r--plugins/Actman/tasks/i_opt_dlg.inc536
-rw-r--r--plugins/Actman/tasks/i_options.inc99
-rw-r--r--plugins/Actman/tasks/i_service.inc87
-rw-r--r--plugins/Actman/tasks/i_task.inc242
-rw-r--r--plugins/Actman/tasks/i_tconst.inc27
-rw-r--r--plugins/Actman/tasks/scheduler.pas86
-rw-r--r--plugins/Actman/tasks/tasks.rc47
-rw-r--r--plugins/Actman/tasks/tasks.resbin0 -> 1288 bytes
8 files changed, 1124 insertions, 0 deletions
diff --git a/plugins/Actman/tasks/i_opt_dlg.inc b/plugins/Actman/tasks/i_opt_dlg.inc
new file mode 100644
index 0000000000..c8025c278d
--- /dev/null
+++ b/plugins/Actman/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/Actman/tasks/i_options.inc b/plugins/Actman/tasks/i_options.inc
new file mode 100644
index 0000000000..527e8d0c88
--- /dev/null
+++ b/plugins/Actman/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/Actman/tasks/i_service.inc b/plugins/Actman/tasks/i_service.inc
new file mode 100644
index 0000000000..376e75cba0
--- /dev/null
+++ b/plugins/Actman/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/Actman/tasks/i_task.inc b/plugins/Actman/tasks/i_task.inc
new file mode 100644
index 0000000000..2c860db85f
--- /dev/null
+++ b/plugins/Actman/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/Actman/tasks/i_tconst.inc b/plugins/Actman/tasks/i_tconst.inc
new file mode 100644
index 0000000000..f4df810d32
--- /dev/null
+++ b/plugins/Actman/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/Actman/tasks/scheduler.pas b/plugins/Actman/tasks/scheduler.pas
new file mode 100644
index 0000000000..05e9cb6a58
--- /dev/null
+++ b/plugins/Actman/tasks/scheduler.pas
@@ -0,0 +1,86 @@
+unit scheduler;
+
+interface
+
+procedure Init;
+procedure DeInit;
+function AddOptionPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer;
+
+implementation
+
+uses
+ windows, commctrl, messages,
+ mirutils, common, dbsettings, io, 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 -------------
+
+var
+ hendis,
+ hcount,
+ hdel: THANDLE;
+
+procedure Init;
+begin
+
+ if LoadTasks=0 then
+ begin
+ MaxTasks:=8;
+ GetMem (TaskList ,MaxTasks*SizeOf(tTaskRec));
+ FillChar(TaskList^,MaxTasks*SizeOf(tTaskRec),0);
+ end
+ else
+ SetAllTasks;
+
+ hcount:=CreateServiceFunction(MS_ACT_TASKCOUNT ,@TaskCount);
+ hendis:=CreateServiceFunction(MS_ACT_TASKENABLE,@TaskEnable);
+ hdel :=CreateServiceFunction(MS_ACT_TASKDELETE,@TaskDelete);
+ hevent:=CreateHookableEvent(ME_ACT_BELL);
+
+end;
+
+procedure DeInit;
+begin
+ StopAllTasks;
+ DestroyServiceFunction(hendis);
+ DestroyServiceFunction(hdel);
+ DestroyServiceFunction(hcount);
+ 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/Actman/tasks/tasks.rc b/plugins/Actman/tasks/tasks.rc
new file mode 100644
index 0000000000..2bc558fbc3
--- /dev/null
+++ b/plugins/Actman/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/Actman/tasks/tasks.res b/plugins/Actman/tasks/tasks.res
new file mode 100644
index 0000000000..bc72f06406
--- /dev/null
+++ b/plugins/Actman/tasks/tasks.res
Binary files differ