From 864081102a5f252415f41950b3039a896b4ae9c5 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Mon, 8 Oct 2012 18:43:29 +0000 Subject: Awkwars's plugins - welcome to our trunk git-svn-id: http://svn.miranda-ng.org/main/trunk@1822 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Actman/tasks/i_opt_dlg.inc | 536 +++++++++++++++++++++++++++++++++++++ plugins/Actman/tasks/i_options.inc | 99 +++++++ plugins/Actman/tasks/i_service.inc | 87 ++++++ plugins/Actman/tasks/i_task.inc | 242 +++++++++++++++++ plugins/Actman/tasks/i_tconst.inc | 27 ++ plugins/Actman/tasks/scheduler.pas | 86 ++++++ plugins/Actman/tasks/tasks.rc | 47 ++++ plugins/Actman/tasks/tasks.res | Bin 0 -> 1288 bytes 8 files changed, 1124 insertions(+) create mode 100644 plugins/Actman/tasks/i_opt_dlg.inc create mode 100644 plugins/Actman/tasks/i_options.inc create mode 100644 plugins/Actman/tasks/i_service.inc create mode 100644 plugins/Actman/tasks/i_task.inc create mode 100644 plugins/Actman/tasks/i_tconst.inc create mode 100644 plugins/Actman/tasks/scheduler.pas create mode 100644 plugins/Actman/tasks/tasks.rc create mode 100644 plugins/Actman/tasks/tasks.res (limited to 'plugins/Actman/tasks') 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 Binary files /dev/null and b/plugins/Actman/tasks/tasks.res differ -- cgit v1.2.3