All pastes #717032 Raw Edit

thief

public cpp v1 · immutable
#717032 ·published 2007-09-27 10:34 UTC
rendered paste body
/* BuddyExpectator.cpp(c)2005 Anar Ibragimoff (ai91@mail.ru)(c)2006 Scott Ellis (mail@scottellis.com.au)(c)2007 Alexander Turyak (turyak@gmail.com)*/#include "common.h"#include "options.h"HINSTANCE hInst;PLUGINLINK *pluginLink;DWORD timer_id = 0;HANDLE   hEventContactSetting;HANDLE   hEventContactAdded;HANDLE   hEventUserInfoInit;HANDLE   hPrebuildContactMenu;HANDLE   hContactMenu;HANDLE	 hIcoLibIconsChanged;HICON hIcon;HANDLE hEnabledIcon, hDisabledIcon;// Popup Actions@@ POPUPACTION actions[3];PLUGININFOEX pluginInfo = {	sizeof(PLUGININFOEX),	"Buddy Expectator+ ["__DATE__"]",	PLUGIN_MAKE_VERSION(0,0,1,2),	"Reacts to the return of contacts, or the the extended absence of contacts, with notifications and other actions",	"Anar Ibragimoff, sje, Thief",	"turyak@gmail.com",	"© 2005 Anar Ibragimoff, © 2006 Scott Ellis, © 2007 Alexander Turyak",	"http://www.miranda-im.org/download/",	0,	0,	{0xddf8aec9, 0x7d37, 0x49af, {0x9d, 0x22, 0xbb, 0xbc, 0x92, 0x0e, 0x6f, 0x05}} //{DDF8AEC9-7D37-49AF-9D22-BBBC920E6F05}};PLUGININFO oldpluginInfo = {	sizeof(PLUGININFO),	pluginInfo.shortName,  	pluginInfo.version,  	pluginInfo.description,  	pluginInfo.author,  	pluginInfo.authorEmail,  	pluginInfo.copyright,  	pluginInfo.homepage,  	pluginInfo.flags,  	pluginInfo.replacesDefaultModule};/* 2D84F403-91F3-4E60-BF02-16C2F1716D86 */#define MIID_BUDDYEXPECTATOR {0x2d84f403, 0x91f3, 0x4e60, {0xbf, 0x02, 0x16, 0xc2, 0xf1, 0x71, 0x6d, 0x86}}extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void){	static const MUUID interfaces[] = {MIID_BUDDYEXPECTATOR, MIID_LAST};	return interfaces;}extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved){	hInst = hinstDLL;	return TRUE;}time_t getLastSeen(HANDLE hContact){	return DBGetContactSettingDword(hContact, MODULE_NAME, "LastSeen", DBGetContactSettingDword(hContact, MODULE_NAME, "CreationTime", (DWORD)-1));}void setLastSeen(HANDLE hContact){	DBWriteContactSettingDword(hContact, MODULE_NAME, "LastSeen", (DWORD)time(NULL));	if(DBGetContactSettingByte(hContact, MODULE_NAME, "StillAbsentNotified", 0))		DBWriteContactSettingByte(hContact, MODULE_NAME, "StillAbsentNotified", 0);}time_t getLastInputMsg(HANDLE hContact){	HANDLE hDbEvent;	DBEVENTINFO dbei = {0};	hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0);    while (hDbEvent) {        dbei.cbSize = sizeof(dbei);        dbei.pBlob = 0;        dbei.cbBlob = 0;        CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei);        if(dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT))            return dbei.timestamp;        hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hDbEvent, 0);    }	return -1;}/** * PopUp window procedures */int CALLBACK HidePopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){	switch(message)	{		case WM_COMMAND:			if (HIWORD(wParam) == STN_CLICKED)			{				//DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);				PUDeletePopUp(hWnd);			}			break;        case WM_CONTEXTMENU:				PUDeletePopUp(hWnd);            break;		case UM_POPUPACTION:			if (wParam == 2)			{				PUShowMessage("Hide action choosen", SM_NOTIFY);			}			if (wParam == 3)			{				PUShowMessage("NeverHide action choosen", SM_NOTIFY);			}			break;		case UM_FREEPLUGINDATA:			return TRUE;		default:			break;	}	return DefWindowProc(hWnd, message, wParam, lParam);}int CALLBACK MissYouPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){	switch(message)	{		case WM_COMMAND:			if (HIWORD(wParam) == STN_CLICKED)			{				CallServiceSync("BuddyExpectator/actionMissYou", (WPARAM)PUGetContact(hWnd), 0);				if (!DBGetContactSettingByte(NULL, MODULE_NAME, "MissYouNotifyAlways", 0))							DBWriteContactSettingByte(PUGetContact(hWnd), MODULE_NAME, "MissYou", 0);				PUDeletePopUp(hWnd);			}			break;        case WM_CONTEXTMENU:				PUDeletePopUp(hWnd);            break;		case UM_POPUPACTION:			if (wParam == 1)			{				DBWriteContactSettingByte(PUGetContact(hWnd), MODULE_NAME, "MissYou", 0);				PUDeletePopUp(hWnd);			}			break;		case UM_FREEPLUGINDATA:			return TRUE;		default:			break;	}	return DefWindowProc(hWnd, message, wParam, lParam);}int CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){	switch(message)	{		case WM_COMMAND:			if (HIWORD(wParam) == STN_CLICKED)			{                CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)PUGetContact(hWnd), 0);				CallServiceSync("BuddyExpectator/actionReturned", (WPARAM)PUGetContact(hWnd), 0);				PUDeletePopUp(hWnd);			}			break;        case WM_CONTEXTMENU:                CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)PUGetContact(hWnd), 0);				setLastSeen(PUGetContact(hWnd));				PUDeletePopUp(hWnd);            break;		case UM_FREEPLUGINDATA:            if(options.iShowEvent == 0)			{				setLastSeen(PUGetContact(hWnd));            }			return TRUE;		default:			break;	}	return DefWindowProc(hWnd, message, wParam, lParam);}int CALLBACK PopupDlgProcNoSet(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){	switch(message)	{		case WM_COMMAND:			if (HIWORD(wParam) == STN_CLICKED)			{                CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)PUGetContact(hWnd), 0);				CallServiceSync("BuddyExpectator/actionStillAbsent", (WPARAM)PUGetContact(hWnd), 0);				PUDeletePopUp(hWnd);			}			break;        case WM_CONTEXTMENU:                CallServiceSync(MS_CLIST_REMOVEEVENT, (WPARAM)PUGetContact(hWnd), 0);				PUDeletePopUp(hWnd);            break;		case UM_FREEPLUGINDATA:			return TRUE;		default:			break;	}	return DefWindowProc(hWnd, message, wParam, lParam);}/** * Checks - whether user has been gone for specified number of days */bool isContactGoneFor(HANDLE hContact, int days){    time_t lastSeen = getLastSeen(hContact);    time_t lastInputMsg = getLastInputMsg(hContact);    time_t currentTime = time(NULL);    int daysSinceOnline = -1;    if(lastSeen != -1) daysSinceOnline = (int)((currentTime - lastSeen)/(60*60*24));    int daysSinceMessage = -1;	if(lastInputMsg != -1) daysSinceMessage = (int)((currentTime - lastInputMsg)/(60*60*24));		if (options.hideInactive)	{		if (daysSinceMessage >= options.iSilencePeriod)		if (!DBGetContactSettingByte(hContact, "CList", "Hidden", 0))		{			char szInfo[200];						POPUPDATAEX ppd = {0};			ppd.cbSize = sizeof(POPUPDATAEX);				ppd.lchContact = hContact;			ppd.lchIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"enabled_icon");						mir_snprintf(szInfo, 200, Translate("Hiding %s (%s)"), (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0), (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0));			strncpy(ppd.lpzContactName, szInfo, MAX_CONTACTNAME);			mir_snprintf(szInfo, 200, Translate("%d days since last message"), daysSinceMessage);			strncpy(ppd.lpzText, szInfo, MAX_SECONDLINE);			if (options.iUsePopupColors)			{				ppd.colorBack = ppd.colorText = 0;			}			else if (options.iUseWinColors)			{				ppd.colorBack = GetSysColor(COLOR_BTNFACE);				ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);			}			else			{				ppd.colorBack = options.iPopUpColorBack;				ppd.colorText = options.iPopUpColorFore;			}			ppd.PluginWindowProc = (WNDPROC)HidePopupDlgProc;			ppd.PluginData = NULL;			ppd.iSeconds = -1;						@@actions[0].flags = 0x00;			@@actions[1].flags = actions[2].flags = PAF_ENABLED;			@@ppd.lpActions = actions;			@@ppd.actionCount = 2;						CallService(MS_POPUP_ADDPOPUPEX, (WPARAM) &ppd, APF_NEWDATA);		}	}	return (daysSinceOnline >= days && (daysSinceMessage == -1 || daysSinceMessage >= days));}void ReturnNotify(HANDLE hContact, char *message){	if(DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) == 1 || DBGetContactSettingByte(hContact, "CList", "Hidden", 0) == 1)		return;		SkinPlaySound("buddyExpectatorReturn");	if(options.iShowPopUp > 0)	{		// Display PopUp		POPUPDATAEX ppd = {0};		ppd.cbSize = sizeof(POPUPDATAEX);		ppd.lchContact = hContact;		ppd.lchIcon = hIcon;		strncpy(ppd.lpzContactName, (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0), MAX_CONTACTNAME);		strncpy(ppd.lpzText, message, MAX_SECONDLINE);		if (options.iUsePopupColors)		{			ppd.colorBack = ppd.colorText = 0;		}		else if (options.iUseWinColors)		{			ppd.colorBack = GetSysColor(COLOR_BTNFACE);			ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);		}		else		{			ppd.colorBack = options.iPopUpColorBack;			ppd.colorText = options.iPopUpColorFore;		}		ppd.PluginWindowProc = (WNDPROC)PopupDlgProc;		ppd.PluginData = NULL;		ppd.iSeconds = options.iPopUpDelay;		CallService(MS_POPUP_ADDPOPUPEX, (WPARAM) &ppd, 0);	}	if(options.iShowEvent > 0)	{		CLISTEVENT cle = {0};		cle.cbSize = sizeof(cle);		cle.hContact = hContact;		cle.hIcon = hIcon;		//cle.hDbEvent;	 //caller defined but should be unique for hContact		//cle.lParam;		 //caller defined		cle.pszService = (char *)"BuddyExpectator/actionReturned";		char* nick = (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0);		char tmpMsg[512];		mir_snprintf(tmpMsg, 512, "%s %s", nick, message);		cle.pszTooltip = tmpMsg;		CallServiceSync(MS_CLIST_ADDEVENT, 0, (LPARAM) &cle);		free(tmpMsg);	}}void GoneNotify(HANDLE hContact, char *message){	if(DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) == 1 || DBGetContactSettingByte(hContact, "CList", "Hidden", 0) == 1)		return;	if(options.iShowPopUp2 > 0)	{		// Display PopUp		POPUPDATAEX ppd = {0};		ppd.cbSize = sizeof(POPUPDATAEX);		ppd.lchContact = hContact;		ppd.lchIcon = hIcon;		strncpy(ppd.lpzContactName, (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0), MAX_CONTACTNAME);		strncpy(ppd.lpzText, message, MAX_SECONDLINE);		if (options.iUsePopupColors)		{			ppd.colorBack = ppd.colorText = 0;		}		else if (options.iUseWinColors)		{			ppd.colorBack = GetSysColor(COLOR_BTNFACE);			ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);		}		else		{			ppd.colorBack = options.iPopUpColorBack;			ppd.colorText = options.iPopUpColorFore;		}		ppd.PluginWindowProc = (WNDPROC)PopupDlgProcNoSet;		ppd.PluginData = NULL;		ppd.iSeconds = options.iPopUpDelay;			CallService(MS_POPUP_ADDPOPUPEX, (WPARAM) &ppd, 0);	}	if(options.iShowEvent2 > 0)	{		CLISTEVENT cle = {0};		cle.cbSize = sizeof(cle);		cle.hContact = hContact;		cle.hIcon = hIcon;		//cle.hDbEvent;	 //caller defined but should be unique for hContact		//cle.lParam;		 //caller defined		cle.pszService = (char *)"BuddyExpectator/actionStillAbsent";		char* nick = (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0);		char tmpMsg[512];		mir_snprintf(tmpMsg, 512, "%s %s", nick, message);		cle.pszTooltip = tmpMsg;		CallServiceSync(MS_CLIST_ADDEVENT, 0, (LPARAM) &cle);		free(tmpMsg);	}}/** * Miss you action (clist event click) *  when called from popup, wParam = (HANDLE)hContact and lParam == 0, *  when called from clist event, wParam = hWndCList, lParam = &CLISTEVENT */int MissYouAction(WPARAM wParam, LPARAM lParam){	HANDLE hContact;	if(lParam)	{	    CLISTEVENT* cle = (CLISTEVENT*)lParam;		hContact = cle->hContact;	} else		hContact = (HANDLE)wParam;    CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact, 0);    return 0;}/** * Contact returned action (clist event click) *  when called from popup, wParam = (HANDLE)hContact and lParam == 0, *  when called from clist event, wParam = hWndCList, lParam = &CLISTEVENT */int ContactReturnedAction(WPARAM wParam, LPARAM lParam){	HANDLE hContact;	if(lParam)	{	    CLISTEVENT* cle = (CLISTEVENT*)lParam;		hContact = cle->hContact;	} else		hContact = (HANDLE)wParam;    if(options.iShowMessageWindow>0)	{        CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact, 0);    }    if(options.iShowUDetails>0)	{        CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0);    }	setLastSeen(hContact);    return 0;}/** * Contact not returned action (clist event click) *  when called from popup, wParam = (HANDLE)hContact and lParam == 0, *  when called from clist event, wParam = hWndCList, lParam = &CLISTEVENT */int ContactStillAbsentAction(WPARAM wParam, LPARAM lParam){	HANDLE hContact;	if(lParam)	{	    CLISTEVENT* cle = (CLISTEVENT*)lParam;		hContact = cle->hContact;	} else		hContact = (HANDLE)wParam;    if(options.action2 == GCA_DELETE)	{        CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);    }	else if(options.action2 == GCA_UDETAILS)	{        CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0);    }	return 0;}/** * Load icons either from icolib or built in */int onIconsChanged(WPARAM wParam, LPARAM lParam){	if(ServiceExists(MS_SKIN2_ADDICON))	{		hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"main_icon");	}	else	{		hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MAINICON), IMAGE_ICON, 16, 16, 0);	}	return 0;}/** * Menu item click action */int MenuMissYouClick(WPARAM wParam, LPARAM lParam){	if (DBGetContactSettingByte((HANDLE)wParam, MODULE_NAME, "MissYou", 0))		DBWriteContactSettingByte((HANDLE)wParam, MODULE_NAME, "MissYou", 0);	else		DBWriteContactSettingByte((HANDLE)wParam, MODULE_NAME, "MissYou", 1);	return 0;}/** * Menu is about to appear */int onPrebuildContactMenu(WPARAM wParam, LPARAM lParam){   char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);   if (!proto) return 0;   CLISTMENUITEM mi = {0};   mi.cbSize = sizeof(CLISTMENUITEM);	   if (DBGetContactSettingByte((HANDLE)wParam, proto, "ChatRoom", 0) || !(CallProtoService(proto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IM))		mi.flags = CMIM_FLAGS | CMIF_HIDDEN;   else	   mi.flags = CMIM_FLAGS;   if (DBGetContactSettingByte((HANDLE)wParam, MODULE_NAME, "MissYou", 0))   {		mi.flags |= CMIM_ICON | CMIM_NAME | CMIF_ICONFROMICOLIB;		mi.pszName = Translate("Disable Miss You");		mi.icolibItem = hEnabledIcon;   }   else   {		mi.flags |= CMIM_ICON | CMIM_NAME | CMIF_ICONFROMICOLIB;		mi.pszName = Translate("Enable Miss You");		mi.icolibItem = hDisabledIcon;   }      CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenu, (LPARAM)&mi);   return 0;}/** * ContactSettingChanged callback */int SettingChanged(WPARAM wParam, LPARAM lParam){	HANDLE hContact = (HANDLE) wParam;	DBCONTACTWRITESETTING *inf = (DBCONTACTWRITESETTING *) lParam;	if (hContact == NULL || inf->value.type == DBVT_DELETED || strcmp(inf->szSetting, "Status") != 0) 		return 0;	if(DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) == 1)        return 0;	char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);	if(proto == 0 || (DBGetContactSettingByte(hContact, proto, "ChatRoom", 0) == 1)	   || !(CallProtoService(proto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND))		return 0;	int currentStatus = inf->value.wVal;	int prevStatus = DBGetContactSettingWord(hContact, "UserOnline", "OldStatus", ID_STATUS_OFFLINE);		if (currentStatus == prevStatus)	{        return 0;	}		if (prevStatus == ID_STATUS_OFFLINE)	{		if (DBGetContactSettingByte(hContact, MODULE_NAME, "MissYou", 0))		{			// Display PopUp			POPUPDATAEX ppd = {0};			ppd.cbSize = sizeof(POPUPDATAEX);						ppd.lchContact = hContact;			ppd.lchIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"enabled_icon");			strncpy(ppd.lpzContactName, (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0), MAX_CONTACTNAME);			strncpy(ppd.lpzText, Translate("You awaited this contact!"), MAX_SECONDLINE);			if (options.iUsePopupColors)			{				ppd.colorBack = ppd.colorText = 0;			}			else if (options.iUseWinColors)			{				ppd.colorBack = GetSysColor(COLOR_BTNFACE);				ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);			}			else			{				ppd.colorBack = options.iPopUpColorBack;				ppd.colorText = options.iPopUpColorFore;			}			ppd.PluginWindowProc = (WNDPROC)MissYouPopupDlgProc;			ppd.PluginData = NULL;			ppd.iSeconds = -1;						@@actions[1].flags = actions[2].flags = 0x00;			@@actions[0].flags = PAF_ENABLED;			@@ppd.lpActions = actions;			@@ppd.actionCount = 1;			CallService(MS_POPUP_ADDPOPUPEX, (WPARAM) &ppd, APF_NEWDATA);						SkinPlaySound("buddyExpectatorMissYou");					}	}    if (currentStatus == ID_STATUS_OFFLINE)	{		setLastSeen(hContact);        return 0;    }	if (CallService(MS_IGNORE_ISIGNORED, (WPARAM) hContact, (LPARAM) IGNOREEVENT_USERONLINE))	{		setLastSeen(hContact);        return 0;	}	if(DBGetContactSettingDword(hContact, MODULE_NAME, "LastSeen", (DWORD)-1) == (DWORD)-1 && options.notifyFirstOnline)	{		ReturnNotify(hContact, Translate("has gone online for the first time."));		setLastSeen(hContact);	}		unsigned int AbsencePeriod = DBGetContactSettingDword(hContact, MODULE_NAME, "iAbsencePeriod", options.iAbsencePeriod);    if(isContactGoneFor(hContact, AbsencePeriod))	{        char* message = Translate("has returned after a long absence.");        time_t tmpTime;		char tmpBuf[251] = {0};        tmpTime = getLastSeen(hContact);        if(tmpTime != -1)		{            strftime(tmpBuf, 250, Translate("has returned after being absent since %#x"), gmtime(&tmpTime));            message = tmpBuf;        }		else		{            tmpTime = getLastInputMsg(hContact);            if(tmpTime != -1)			{                strftime(tmpBuf, 250, Translate("has returned after being absent since %#x"), gmtime(&tmpTime));                message = tmpBuf;            }        }				ReturnNotify(hContact, message);        if((options.iShowMessageWindow == 0 && options.iShowUDetails == 0) || (options.iShowEvent == 0 && options.iShowPopUp == 0))		{			setLastSeen(hContact);		}    } else		setLastSeen(hContact);	return 0;}BOOL CALLBACK UserinfoDlgProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam){    switch(msg)	{        case WM_INITDIALOG:		{            time_t tmpTime;			char tmpBuf[51] = {0};            tmpTime = getLastSeen((HANDLE)lparam);            if(tmpTime == -1)                SetDlgItemText(hdlg, IDC_EDIT_LASTSEEN, Translate("not detected"));            else			{                strftime(tmpBuf, 50, "%#x", gmtime(&tmpTime));                SetDlgItemText(hdlg, IDC_EDIT_LASTSEEN, tmpBuf);            }            tmpTime = getLastInputMsg((HANDLE)lparam);            if(tmpTime == -1)                SetDlgItemText(hdlg, IDC_EDIT_LASTINPUT, Translate("not found"));            else			{                strftime(tmpBuf, 50, "%#x", gmtime(&tmpTime));                SetDlgItemText(hdlg, IDC_EDIT_LASTINPUT, tmpBuf);            }						unsigned int AbsencePeriod = DBGetContactSettingDword((HANDLE)lparam, MODULE_NAME, "iAbsencePeriod", options.iAbsencePeriod);						SendDlgItemMessage(hdlg, IDC_SPINABSENCE, UDM_SETRANGE, 0, MAKELONG(999, 1));			SetDlgItemInt(hdlg, IDC_EDITABSENCE, AbsencePeriod, FALSE);            if(isContactGoneFor((HANDLE)lparam, AbsencePeriod) || isContactGoneFor((HANDLE)lparam, options.iAbsencePeriod2))			{                SetDlgItemText(hdlg, IDC_EDIT_WILLNOTICE, Translate("This contact has been absent for an extended period of time."));            }			else			{                SetDlgItemText(hdlg, IDC_EDIT_WILLNOTICE, "");            }			TranslateDialogDefault(hdlg);			return TRUE;		}				case WM_NOTIFY:			switch(((LPNMHDR)lparam)->idFrom)			{				case 0:					switch (((LPNMHDR)lparam)->code)					{						case (PSN_APPLY):						{							HANDLE hContact = (HANDLE)((LPPSHNOTIFY)lparam)->lParam;							if (hContact)								DBWriteContactSettingDword(hContact, MODULE_NAME, "iAbsencePeriod", GetDlgItemInt(hdlg, IDC_EDITABSENCE, 0, FALSE));							break;						}					}				break;			}		break;		case WM_COMMAND:			if(wparam == MAKEWPARAM(IDC_EDITABSENCE, EN_CHANGE))				SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0);			else if(LOWORD(wparam) == IDCANCEL)				SendMessage(GetParent(hdlg), msg, wparam, lparam);		break;    }    return FALSE;}int UserinfoInit(WPARAM wparam, LPARAM lparam){    if(lparam > 0)	{        OPTIONSDIALOGPAGE uip = {0};        uip.cbSize = sizeof(uip);        uip.hInstance = hInst;        uip.pszTemplate = MAKEINTRESOURCE(IDD_USERINFO);        uip.pszTitle = Translate("Buddy Expectator");        uip.pfnDlgProc = UserinfoDlgProc;	    	    CallService(MS_USERINFO_ADDPAGE, wparam, (LPARAM)&uip);    }	return 0;}void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD){	if(options.action2 == GCA_NOACTION) return;		HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);	char *proto;	while(hContact != 0)	{		proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);		if(proto && (DBGetContactSettingByte(hContact, proto, "ChatRoom", 0) == 0) && (CallProtoService(proto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND) && isContactGoneFor(hContact, options.iAbsencePeriod2) && (DBGetContactSettingByte(hContact, MODULE_NAME, "StillAbsentNotified", 0) == 0))		{			DBWriteContactSettingByte(hContact, MODULE_NAME, "StillAbsentNotified", 1);			SkinPlaySound("buddyExpectatorStillAbsent");			char* message = Translate("has not returned after a long absence.");			time_t tmpTime;			char tmpBuf[251] = {0};			tmpTime = getLastSeen(hContact);			if(tmpTime != -1)			{				strftime(tmpBuf, 250, Translate("has not returned after being absent since %#x"), gmtime(&tmpTime));				message = tmpBuf;			}			else			{				tmpTime = getLastInputMsg(hContact);				if(tmpTime != -1)				{					strftime(tmpBuf, 250, Translate("has not returned after being absent since %#x"), gmtime(&tmpTime));					message = tmpBuf;				}			}			GoneNotify(hContact, message);		}		hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);	}}/** * Called when all the modules have had their modules loaded event handlers called (dependence of popups on fontservice :( ) */int ModulesLoaded2(WPARAM wParam, LPARAM lParam){	// check for 'still absent' contacts  on startup	TimerProc(0, 0, 0, 0);	return 0;}/** * Called when all the modules are loaded */int ModulesLoaded(WPARAM wParam, LPARAM lParam){	hEventUserInfoInit = HookEvent(ME_USERINFO_INITIALISE, UserinfoInit);	timer_id = SetTimer(0, 0, 1000 * 60 * 60 * 4, TimerProc); // check every 4 hours		HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded2);		// IcoLib support	if(ServiceExists(MS_SKIN2_ADDICON))	{		SKINICONDESC sid = {0};		char szFile[MAX_PATH];		GetModuleFileNameA(hInst, szFile, MAX_PATH);		sid.pszDefaultFile = szFile;		sid.cbSize = SKINICONDESC_SIZE_V1;				sid.pszSection = Translate("BuddyExpectator");				sid.pszDescription = Translate("Tray/popup icon");		sid.pszName = "main_icon";		sid.iDefaultIndex = -IDI_MAINICON;		CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);				sid.pszDescription = Translate("Enabled");		sid.pszName = "enabled_icon";		sid.iDefaultIndex = -IDI_ENABLED;		hEnabledIcon = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);				sid.pszDescription = Translate("Disabled");		sid.pszName = "disabled_icon";		sid.iDefaultIndex = -IDI_DISABLED;		hDisabledIcon = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);				sid.pszDescription = Translate("Hide");		sid.pszName = "hide_icon";		sid.iDefaultIndex = -IDI_HIDE;		CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);				sid.pszDescription = Translate("NeverHide");		sid.pszName = "neverhide_icon";		sid.iDefaultIndex = -IDI_NEVERHIDE;		CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);				hIcoLibIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, onIconsChanged);	}		onIconsChanged(0,0);		if (options.enableMissYou)	{		hPrebuildContactMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, onPrebuildContactMenu);				CLISTMENUITEM mi = {0};		mi.cbSize = sizeof(CLISTMENUITEM);		mi.flags = CMIF_ICONFROMICOLIB;		mi.icolibItem = hDisabledIcon;		mi.position = 200000;		mi.pszName = Translate("Enable Miss You");		mi.pszService = "BuddyExpectator/actionMissYouClick";		hContactMenu = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi);	}		// Updater plugin support	if (ServiceExists(MS_UPDATE_REGISTER))	{		// register with updater		Update update = {0};		char szVersion[16];				update.cbSize = sizeof(Update);				update.szComponentName = pluginInfo.shortName;		update.pbVersion = (BYTE *)CreateVersionString(pluginInfo.version, szVersion);		update.cpbVersion = strlen((char *)update.pbVersion);				update.szUpdateURL = UPDATER_AUTOREGISTER;				// these are the three lines that matter - the archive, the page containing the version string, and the text (or data) 		// before the version that we use to locate it on the page		// (note that if the update URL and the version URL point to standard file listing entries, the backend xml		// data will be used to check for updates rather than the actual web page - this is not true for beta urls)		update.szBetaUpdateURL = "http://thief.miranda-im.org.ua/BuddyExpectator.zip";		update.szBetaVersionURL = "http://thief.miranda-im.org.ua/updater/buddyexpectator_version.txt";		update.szBetaChangelogURL = "http://dev.mirandaim.ru/~thief/index.php";		update.pbBetaVersionPrefix = (BYTE *)"Buddy Expectator ";				update.cpbBetaVersionPrefix = strlen((char *)update.pbBetaVersionPrefix);				CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);	}			@@actions[0].cbSize = sizeof(POPUPACTION);	@@actions[0].lchIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"disabled_icon");	@@lstrcpy(actions[0].lpzTitle, Translate("Disable Miss You"));	@@actions[0].wParam = actions[0].lParam = 1;		@@actions[1].cbSize = sizeof(POPUPACTION);	@@actions[1].lchIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"hide_icon");	@@lstrcpy(actions[1].lpzTitle, Translate("Hide ñontact"));	@@actions[1].wParam = actions[1].lParam = 2;		@@actions[2].cbSize = sizeof(POPUPACTION);	@@actions[2].lchIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"neverhide_icon");	@@lstrcpy(actions[2].lpzTitle, Translate("Never hide this contact"));	@@actions[2].wParam = actions[2].lParam = 3;		return 0;}extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion){	return &pluginInfo;}extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion){	return &oldpluginInfo;}int ContactAdded(WPARAM wParam, LPARAM lParam){	DBWriteContactSettingDword((HANDLE)wParam, MODULE_NAME, "CreationTime", (DWORD)time(0));	return 0;}extern "C" int __declspec(dllexport) Load(PLUGINLINK *link){	pluginLink = link;	setlocale(LC_ALL, "English"); // Set English locale	InitOptions();	CreateServiceFunction("BuddyExpectator/actionReturned", ContactReturnedAction);	CreateServiceFunction("BuddyExpectator/actionStillAbsent", ContactStillAbsentAction);	CreateServiceFunction("BuddyExpectator/actionMissYou", MissYouAction);	CreateServiceFunction("BuddyExpectator/actionMissYouClick", MenuMissYouClick);    hEventContactSetting = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, SettingChanged);    HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);	hEventContactAdded = HookEvent(ME_DB_CONTACT_ADDED, ContactAdded);	// add sounds support	SkinAddNewSoundEx("buddyExpectatorReturn", Translate("BuddyExpectator"), Translate("Contact returned"));	SkinAddNewSoundEx("buddyExpectatorStillAbsent", Translate("BuddyExpectator"), Translate("Contact still absent"));	SkinAddNewSoundEx("buddyExpectatorMissYou", Translate("BuddyExpectator"), Translate("Miss you event"));	// ensure all contacts are timestamped	DBVARIANT dbv;	HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);	DWORD current_time = (DWORD)time(0);	while(hContact != 0)	{		if(!DBGetContactSetting(hContact, MODULE_NAME, "CreationTime", &dbv))			DBFreeVariant(&dbv);		else			DBWriteContactSettingDword(hContact, MODULE_NAME, "CreationTime", current_time);		hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);	}	return 0;}extern "C" int __declspec(dllexport) Unload(void){	KillTimer(0, timer_id);    UnhookEvent(hEventContactSetting);    UnhookEvent(hEventContactAdded);    UnhookEvent(hEventUserInfoInit);	if (hPrebuildContactMenu) UnhookEvent(hPrebuildContactMenu);	UnhookEvent(hIcoLibIconsChanged);	DeinitOptions();		if (hIcoLibIconsChanged)		CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);	else		DestroyIcon(hIcon);	return 0;}