diff options
Diffstat (limited to 'plugins/Nudge/src/main.cpp')
| -rw-r--r-- | plugins/Nudge/src/main.cpp | 789 | 
1 files changed, 789 insertions, 0 deletions
diff --git a/plugins/Nudge/src/main.cpp b/plugins/Nudge/src/main.cpp new file mode 100644 index 0000000000..c673ebe0c5 --- /dev/null +++ b/plugins/Nudge/src/main.cpp @@ -0,0 +1,789 @@ +#include "headers.h"
 +#include "main.h"
 +#include "shake.h"
 +#include "m_msg_buttonsbar.h"
 +
 +
 +int nProtocol = 0;
 +static HANDLE g_hEventModulesLoaded = NULL, hEventOptionsInitialize = NULL, g_hIcon = NULL, g_hEventDbWindowEvent = NULL, g_hEventToolbarLoaded = NULL, g_hEventButtonPressed = NULL, g_hEventAccountsChanged = NULL;
 +HINSTANCE hInst;
 +
 +NudgeElementList *NudgeList = NULL;
 +CNudgeElement DefaultNudge;
 +CShake shake;
 +CNudge GlobalNudge;
 +
 +
 +
 +int hLangpack = 0;
 +
 +
 +//========================
 +//  MirandaPluginInfo
 +//========================
 +PLUGININFOEX pluginInfo={
 +	sizeof(PLUGININFOEX),
 +	"Nudge",
 +	 PLUGIN_MAKE_VERSION(0,0,2,0),
 +	"Plugin to shake the clist and chat window",
 +	"Tweety/GouZ, FREAK_THEMIGHTY",
 +	"francois.mean@skynet.be, Sylvain.gougouzian@gmail.com, wishmaster51@googlemail.com",
 +	"copyright to the miranda community",
 +	"http://nightly.miranda.im/",		// www
 +	UNICODE_AWARE,		//doesn't replace anything built-in
 +	{ 0xe47cc215, 0xd28, 0x462d, { 0xa0, 0xf6, 0x3a, 0xe4, 0x44, 0x3d, 0x29, 0x26 } } // {E47CC215-0D28-462D-A0F6-3AE4443D2926}
 +};
 +
 +INT_PTR NudgeShowMenu(WPARAM wParam,LPARAM lParam)
 +{
 +
 +	for(NudgeElementList *n = NudgeList;n != NULL; n = n->next)
 +	{
 +		if (!strcmp((char *) wParam,n->item.ProtocolName))
 +		{
 +			return n->item.ShowContactMenu(lParam != 0);
 +		}
 +	}
 +	return 0;
 +}
 +
 +INT_PTR NudgeSend(WPARAM wParam,LPARAM lParam)
 +{
 +
 +	char *protoName = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0);
 +	int diff = time(NULL) - DBGetContactSettingDword((HANDLE) wParam, "Nudge", "LastSent", time(NULL)-30);
 +
 +	if(diff < GlobalNudge.sendTimeSec)
 +	{
 +		TCHAR msg[500];
 +		mir_sntprintf(msg,500, TranslateT("You are not allowed to send too much nudge (only 1 each %d sec, %d sec left)"),GlobalNudge.sendTimeSec, 30 - diff);
 +		//MessageBox(NULL,msg,NULL,0);
 +		if(GlobalNudge.useByProtocol)
 +		{
 +			for(NudgeElementList *n = NudgeList;n != NULL; n = n->next)
 +			{
 +				if (!strcmp(protoName,n->item.ProtocolName))
 +				{
 +					Nudge_ShowPopup(n->item, (HANDLE) wParam, msg);
 +				}
 +			}
 +		}
 +		else
 +		{
 +			Nudge_ShowPopup(DefaultNudge, (HANDLE) wParam, msg);
 +		}
 +		return 0;
 +	}
 +
 +	DBWriteContactSettingDword((HANDLE) wParam, "Nudge", "LastSent", time(NULL));
 +
 +	if(GlobalNudge.useByProtocol)
 +	{
 +		NudgeElementList *n;
 +		for(n = NudgeList;n != NULL; n = n->next)
 +		{
 +			if (!strcmp(protoName,n->item.ProtocolName))
 +			{
 +				//if(n->item.showPopup)
 +				//	Nudge_ShowPopup(n->item, (HANDLE) wParam, n->item.senText);
 +				if(n->item.showStatus)
 +					Nudge_SentStatus(n->item, (HANDLE) wParam);
 +			}
 +		}
 +	}
 +	else
 +	{
 +		//if(DefaultNudge.showPopup)
 +		//	Nudge_ShowPopup(DefaultNudge, (HANDLE) wParam, DefaultNudge.senText);
 +		if(DefaultNudge.showStatus)
 +			Nudge_SentStatus(DefaultNudge, (HANDLE) wParam);
 +	}
 +
 +	CallProtoService(protoName,"/SendNudge",wParam,lParam);
 +	return 0;
 +}
 +
 +void OpenContactList()
 +{
 +	HWND hWnd = (HWND) CallService(MS_CLUI_GETHWND,0,0);
 +	ShowWindow(hWnd, SW_RESTORE);
 +	ShowWindow(hWnd, SW_SHOW);
 +}
 +
 +int NudgeRecieved(WPARAM wParam,LPARAM lParam)
 +{
 +
 +	char *protoName = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0);
 +
 +	DWORD currentTimestamp = time(NULL);
 +	DWORD nudgeSentTimestamp = lParam ? (DWORD)lParam : currentTimestamp;
 +
 +	int diff = currentTimestamp - DBGetContactSettingDword((HANDLE) wParam, "Nudge", "LastReceived", currentTimestamp-30);
 +	int diff2 = nudgeSentTimestamp - DBGetContactSettingDword((HANDLE) wParam, "Nudge", "LastReceived2", nudgeSentTimestamp-30);
 +
 +	if(diff >= GlobalNudge.recvTimeSec)
 +		DBWriteContactSettingDword((HANDLE) wParam, "Nudge", "LastReceived", currentTimestamp);
 +	if(diff2 >= GlobalNudge.recvTimeSec)
 +		DBWriteContactSettingDword((HANDLE) wParam, "Nudge", "LastReceived2", nudgeSentTimestamp);
 +
 +	if(GlobalNudge.useByProtocol)
 +	{
 +		for(NudgeElementList *n = NudgeList;n != NULL; n = n->next)
 +		{
 +			if (!strcmp(protoName,n->item.ProtocolName))
 +			{
 +
 +				if(n->item.enabled)
 +				{
 +					if(n->item.useIgnoreSettings && CallService(MS_IGNORE_ISIGNORED,wParam,IGNOREEVENT_USERONLINE))
 +						return 0;
 +
 +					DWORD Status = CallProtoService(protoName,PS_GETSTATUS,0,0);
 +
 +					if ( ((n->item.statusFlags & NUDGE_ACC_ST0) && (Status<=ID_STATUS_OFFLINE)) ||
 +						((n->item.statusFlags & NUDGE_ACC_ST1) && (Status==ID_STATUS_ONLINE)) ||
 +						((n->item.statusFlags & NUDGE_ACC_ST2) && (Status==ID_STATUS_AWAY)) ||
 +						((n->item.statusFlags & NUDGE_ACC_ST3) && (Status==ID_STATUS_DND)) ||
 +						((n->item.statusFlags & NUDGE_ACC_ST4) && (Status==ID_STATUS_NA)) ||
 +						((n->item.statusFlags & NUDGE_ACC_ST5) && (Status==ID_STATUS_OCCUPIED)) ||
 +						((n->item.statusFlags & NUDGE_ACC_ST6) && (Status==ID_STATUS_FREECHAT)) ||
 +						((n->item.statusFlags & NUDGE_ACC_ST7) && (Status==ID_STATUS_INVISIBLE)) ||
 +						((n->item.statusFlags & NUDGE_ACC_ST8) && (Status==ID_STATUS_ONTHEPHONE)) ||
 +						((n->item.statusFlags & NUDGE_ACC_ST9) && (Status==ID_STATUS_OUTTOLUNCH)))
 +					{
 +						if(diff >= GlobalNudge.recvTimeSec)
 +						{
 +							if(n->item.showPopup)
 +								Nudge_ShowPopup(n->item, (HANDLE) wParam, n->item.recText);
 +							if(n->item.openContactList)
 +								OpenContactList();
 +							if(n->item.shakeClist)
 +								ShakeClist(wParam,lParam);
 +							if(n->item.openMessageWindow)
 +								CallService(MS_MSG_SENDMESSAGET,wParam,0);
 +							if(n->item.shakeChat)
 +								ShakeChat(wParam,lParam);
 +							if(n->item.autoResend)
 +								mir_forkthread(AutoResendNudge,(void *)wParam);
 +
 +							SkinPlaySound( n->item.NudgeSoundname );
 +						}
 +					}
 +					if(diff2 >= GlobalNudge.recvTimeSec)
 +					{
 +						if(n->item.showStatus)
 +							Nudge_ShowStatus(n->item, (HANDLE) wParam, nudgeSentTimestamp);
 +					}
 +
 +				}
 +				break;
 +			}
 +		}
 +	}
 +	else
 +	{
 +		if(DefaultNudge.enabled)
 +		{
 +			if(DefaultNudge.useIgnoreSettings && CallService(MS_IGNORE_ISIGNORED,wParam,IGNOREEVENT_USERONLINE))
 +				return 0;
 +			DWORD Status = CallService(MS_CLIST_GETSTATUSMODE,0,0);
 +			if ( ((DefaultNudge.statusFlags & NUDGE_ACC_ST0) && (Status<=ID_STATUS_OFFLINE)) ||
 +				((DefaultNudge.statusFlags & NUDGE_ACC_ST1) && (Status==ID_STATUS_ONLINE)) ||
 +				((DefaultNudge.statusFlags & NUDGE_ACC_ST2) && (Status==ID_STATUS_AWAY)) ||
 +				((DefaultNudge.statusFlags & NUDGE_ACC_ST3) && (Status==ID_STATUS_DND)) ||
 +				((DefaultNudge.statusFlags & NUDGE_ACC_ST4) && (Status==ID_STATUS_NA)) ||
 +				((DefaultNudge.statusFlags & NUDGE_ACC_ST5) && (Status==ID_STATUS_OCCUPIED)) ||
 +				((DefaultNudge.statusFlags & NUDGE_ACC_ST6) && (Status==ID_STATUS_FREECHAT)) ||
 +				((DefaultNudge.statusFlags & NUDGE_ACC_ST7) && (Status==ID_STATUS_INVISIBLE)) ||
 +				((DefaultNudge.statusFlags & NUDGE_ACC_ST8) && (Status==ID_STATUS_ONTHEPHONE)) ||
 +				((DefaultNudge.statusFlags & NUDGE_ACC_ST9) && (Status==ID_STATUS_OUTTOLUNCH)))
 +			{
 +				if(diff >= GlobalNudge.recvTimeSec)
 +				{
 +					if(DefaultNudge.showPopup)
 +						Nudge_ShowPopup(DefaultNudge, (HANDLE) wParam, DefaultNudge.recText);
 +					if(DefaultNudge.openContactList)
 +						OpenContactList();
 +					if(DefaultNudge.shakeClist)
 +						ShakeClist(wParam,lParam);
 +					if(DefaultNudge.openMessageWindow)
 +						CallService(MS_MSG_SENDMESSAGET,wParam,0);
 +					if(DefaultNudge.shakeChat)
 +						ShakeChat(wParam,lParam);
 +					if(DefaultNudge.autoResend)
 +						mir_forkthread(AutoResendNudge,(void *)wParam);
 +
 +					SkinPlaySound( DefaultNudge.NudgeSoundname );
 +				}
 +			}
 +			if(diff2 >= GlobalNudge.recvTimeSec)
 +			{
 +				if(DefaultNudge.showStatus)
 +					Nudge_ShowStatus(DefaultNudge, (HANDLE) wParam, nudgeSentTimestamp);
 +			}
 +		}
 +	}
 +	return 0;
 +}
 +
 +extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
 +{
 +	hInst=hinstDLL;
 +	return TRUE;
 +}
 +
 +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
 +{
 +	return &pluginInfo;
 +}
 +
 +static INT_PTR CALLBACK DlgProcOptsTrigger(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
 +
 +    switch (msg) {
 +	case WM_INITDIALOG: {
 +		// lParam = (LPARAM)(DWORD)actionID or 0 if this is a new trigger entry
 +		BOOL bshakeClist,bshakeChat;
 +
 +		DWORD actionID = (DWORD)lParam;
 +        TranslateDialogDefault(hwnd);
 +		// Initialize the dialog according to the action ID
 +		bshakeClist = DBGetActionSettingByte(actionID, NULL, "Nudge", "ShakeClist",FALSE);
 +		bshakeChat = DBGetActionSettingByte(actionID, NULL, "Nudge", "ShakeChat",FALSE);
 +		CheckDlgButton(hwnd, IDC_TRIGGER_SHAKECLIST, bshakeClist ? BST_CHECKED : BST_UNCHECKED);
 +		CheckDlgButton(hwnd, IDC_TRIGGER_SHAKECHAT, bshakeChat ? BST_CHECKED : BST_UNCHECKED);
 +        break;
 +						}
 +
 +	case TM_ADDACTION: {
 +		// save your settings
 +		// wParam = (WPARAM)(DWORD)actionID
 +		bool bshakeClist,bshakeChat;
 +
 +		DWORD actionID = (DWORD)wParam;
 +		bshakeClist = (IsDlgButtonChecked(hwnd,IDC_TRIGGER_SHAKECLIST)==BST_CHECKED);
 +		bshakeChat = (IsDlgButtonChecked(hwnd,IDC_TRIGGER_SHAKECHAT)==BST_CHECKED);
 +		DBWriteActionSettingByte(actionID, NULL, "Nudge", "ShakeClist",bshakeClist);
 +		DBWriteActionSettingByte(actionID, NULL, "Nudge", "ShakeChat",bshakeChat);
 +		break;
 +					   }
 +	}
 +
 +    return FALSE;
 +}
 +
 +int TriggerActionRecv( DWORD actionID, REPORTINFO *ri)
 +{
 +	// check how to process this call
 +	if (ri->flags&ACT_PERFORM) {
 +		BOOL bshakeClist,bshakeChat;
 +		HANDLE hContact = ((ri->td!=NULL)&&(ri->td->dFlags&DF_CONTACT))?ri->td->hContact:NULL;
 +		bshakeClist = DBGetActionSettingByte(actionID, NULL, "Nudge", "ShakeClist",FALSE);
 +		bshakeChat = DBGetActionSettingByte(actionID, NULL, "Nudge", "ShakeChat",FALSE);
 +
 +		if(bshakeClist)
 +			ShakeClist(NULL,NULL);
 +		if(bshakeChat && (hContact != NULL))
 +			ShakeChat((WPARAM)hContact,NULL);
 +	}
 +
 +	if (ri->flags&ACT_CLEANUP) // request to delete all associated settings
 +		RemoveAllActionSettings(actionID, "Nudge");
 +
 +	return FALSE;
 +}
 +
 +int TriggerActionSend( DWORD actionID, REPORTINFO *ri)
 +{
 +	if (ri->flags & ACT_PERFORM) {
 +		HANDLE hContact = ((ri->td!=NULL)&&(ri->td->dFlags&DF_CONTACT))?ri->td->hContact:NULL;
 +		if(hContact != NULL)
 +			NudgeSend((WPARAM)hContact,NULL);
 +	}
 +
 +	return FALSE;
 +}
 +
 +void LoadProtocols(void)
 +{
 +	//Load the default nudge
 +	mir_snprintf(DefaultNudge.ProtocolName,sizeof(DefaultNudge.ProtocolName),"Default");
 +	mir_snprintf(DefaultNudge.NudgeSoundname,sizeof(DefaultNudge.NudgeSoundname),"Nudge : Default");
 +	SkinAddNewSoundEx( DefaultNudge.NudgeSoundname, LPGEN("Nudge"), LPGEN("Default Nudge"));
 +	DefaultNudge.Load();
 +
 +	GlobalNudge.Load();
 +
 +	int numberOfProtocols = 0;
 +	PROTOACCOUNT **ppProtocolDescriptors;
 +	INT_PTR ret = ProtoEnumAccounts(&numberOfProtocols,&ppProtocolDescriptors);
 +	if(ret == 0)
 +	{
 +		for(int i = 0; i < numberOfProtocols ; i++)
 +		{
 +			Nudge_AddAccount(ppProtocolDescriptors[i]);
 +		}
 +
 +	}
 +
 +	shake.Load();
 +
 +	/*CNudgeElement *n;
 +	for(n = NudgeList;n != NULL; n = n->next)
 +	{
 +		MessageBox(NULL,n->ProtocolName,n->NudgeSoundname,0);
 +	}*/
 +}
 +
 +void RegisterToTrigger(void)
 +{
 +	if ( ServiceExists(MS_TRIGGER_REGISTERACTION))
 +	{
 +		ACTIONREGISTER ar;
 +		ZeroMemory(&ar, sizeof(ar));
 +		ar.cbSize = sizeof(ar);
 +		ar.hInstance = hInst;
 +		ar.flags = ARF_TCHAR|ARF_FUNCTION;
 +		ar.actionFunction = TriggerActionRecv;
 +		ar.pfnDlgProc = DlgProcOptsTrigger;
 +		ar.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_TRIGGER);
 +		ar.pszName = Translate("Nudge : Shake contact list/chat window");
 +
 +		// register the action
 +		CallService(MS_TRIGGER_REGISTERACTION, 0, (LPARAM)&ar);
 +
 +		ar.actionFunction = TriggerActionSend;
 +		ar.pszName = Translate("Nudge : Send a nudge");
 +		ar.pfnDlgProc = NULL;
 +		ar.pszTemplate = NULL;
 +
 +		// register the action
 +		CallService(MS_TRIGGER_REGISTERACTION, 0, (LPARAM)&ar);
 +	}
 +}
 +
 +void RegisterToDbeditorpp(void)
 +{
 +    // known modules list
 +    if (ServiceExists("DBEditorpp/RegisterSingleModule"))
 +        CallService("DBEditorpp/RegisterSingleModule", (WPARAM)"Nudge", 0);
 +}
 +
 +void LoadIcons(void)
 +{
 +	//Load icons
 +	SKINICONDESC sid = {0};
 +	TCHAR szFilename[MAX_PATH];
 +	GetModuleFileName(hInst,szFilename,MAX_PATH);
 +
 +	sid.cbSize = sizeof(sid);
 +	sid.flags = SIDF_ALL_TCHAR;
 +	sid.ptszSection = LPGENT("Nudge");
 +	sid.ptszDefaultFile = szFilename;
 +
 +	sid.pszName = "Nudge_Default";
 +	sid.ptszDescription = LPGENT("Nudge as Default");
 +	sid.iDefaultIndex = -IDI_NUDGE;
 +	sid.hDefaultIcon =  LoadIcon(hInst,MAKEINTRESOURCE(IDI_NUDGE));
 +	g_hIcon = Skin_AddIcon(&sid);
 +}
 +
 +// Nudge support
 +static int TabsrmmButtonPressed(WPARAM wParam, LPARAM lParam)
 +{
 +	CustomButtonClickData *cbcd=(CustomButtonClickData *)lParam;
 +
 +	if (!strcmp(cbcd->pszModule,"Nudge"))
 +		NudgeSend(wParam, 0);
 +
 +	return 0;
 +}
 +
 +static int TabsrmmButtonInit(WPARAM wParam, LPARAM lParam)
 +{
 +	BBButton bbd = {0};
 +
 +	bbd.cbSize = sizeof(BBButton);
 +	bbd.pszModuleName = "Nudge";
 +	bbd.ptszTooltip = LPGENT("Send Nudge");
 +	bbd.dwDefPos = 300;
 +	bbd.bbbFlags = BBBF_ISIMBUTTON|BBBF_ISLSIDEBUTTON|BBBF_CANBEHIDDEN;
 +	bbd.hIcon = g_hIcon;
 +	bbd.dwButtonID = 6000;
 +	bbd.iButtonWidth = 0;
 +	CallService (MS_BB_ADDBUTTON, 0, (LPARAM)&bbd);
 +
 +	return 0;
 +}
 +
 +void HideNudgeButton(HANDLE hContact)
 +{
 +	char str[MAXMODULELABELLENGTH + 12] = {0};
 +	char *szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
 +	mir_snprintf(str,MAXMODULELABELLENGTH + 12,"%s/SendNudge", szProto);
 +
 +	if (!ServiceExists(str))
 +    {
 +      BBButton bbd={0};
 +      bbd.cbSize=sizeof(BBButton);
 +      bbd.bbbFlags=BBSF_HIDDEN|BBSF_DISABLED;
 +      bbd.pszModuleName="Nudge";
 +	  bbd.dwButtonID = 6000;
 +      CallService(MS_BB_SETBUTTONSTATE, (WPARAM)hContact, (LPARAM)&bbd);
 +    }
 +}
 +
 +static int ContactWindowOpen(WPARAM wparam,LPARAM lParam)
 +{
 +   MessageWindowEventData *MWeventdata = (MessageWindowEventData*)lParam;
 +
 +   if(MWeventdata->uType == MSG_WINDOW_EVT_OPENING&&MWeventdata->hContact)
 +   {
 +      HideNudgeButton(MWeventdata->hContact);
 +   }
 +   return 0;
 +}
 +
 +int ModulesLoaded(WPARAM,LPARAM)
 +{
 +	RegisterToTrigger();
 +	RegisterToDbeditorpp();
 +	LoadProtocols();
 +	LoadIcons();
 +	LoadPopupClass();
 +
 +	g_hEventToolbarLoaded = HookEvent(ME_MSG_TOOLBARLOADED, TabsrmmButtonInit);
 +	if (g_hEventToolbarLoaded)
 +	{
 +		g_hEventButtonPressed = HookEvent(ME_MSG_BUTTONPRESSED, TabsrmmButtonPressed);
 +		g_hEventDbWindowEvent = HookEvent(ME_MSG_WINDOWEVENT,ContactWindowOpen);
 +	}
 +	return 0;
 +}
 +
 +int AccListChanged(WPARAM wParam,LPARAM lParam)
 +{
 +	PROTOACCOUNT *proto = (PROTOACCOUNT*) wParam;
 +	if (proto==NULL)
 +		return 0;
 +
 +	switch (lParam)
 +	{
 +		case PRAC_ADDED:
 +			Nudge_AddAccount(proto);
 +			break;
 +	}
 +	return 0;
 +}
 +
 +HANDLE hShakeClist=NULL,hShakeChat=NULL,hNudgeSend=NULL,hNudgeShowMenu=NULL;
 +extern "C" int __declspec(dllexport) Load(void)
 +{
 +
 +	mir_getLP(&pluginInfo);
 +
 +	g_hEventModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED,ModulesLoaded);
 +	g_hEventAccountsChanged = HookEvent(ME_PROTO_ACCLISTCHANGED,AccListChanged);
 +	hEventOptionsInitialize = HookEvent(ME_OPT_INITIALISE, NudgeOptInit);
 +
 +	//Create function for plugins
 +	hShakeClist=CreateServiceFunction(MS_SHAKE_CLIST,ShakeClist);
 +	hShakeChat=CreateServiceFunction(MS_SHAKE_CHAT,ShakeChat);
 +	hNudgeSend=CreateServiceFunction(MS_NUDGE_SEND,NudgeSend);
 +	hNudgeShowMenu=CreateServiceFunction(MS_NUDGE_SHOWMENU,NudgeShowMenu);
 +	return 0;
 +}
 +
 +extern "C" int __declspec(dllexport) Unload(void)
 +{
 +	if(g_hEventToolbarLoaded) UnhookEvent(g_hEventToolbarLoaded);
 +	if(g_hEventDbWindowEvent) UnhookEvent(g_hEventButtonPressed);
 +	if(g_hEventDbWindowEvent) UnhookEvent(g_hEventDbWindowEvent);
 +
 +	UnhookEvent(g_hEventModulesLoaded);
 +	UnhookEvent(g_hEventAccountsChanged);
 +	UnhookEvent(hEventOptionsInitialize);
 +
 +	DestroyServiceFunction(hShakeClist);
 +	DestroyServiceFunction(hShakeChat);
 +	DestroyServiceFunction(hNudgeSend);
 +	DestroyServiceFunction(hNudgeShowMenu);
 +
 +	NudgeElementList* p = NudgeList;
 +	while ( p != NULL )
 +	{
 +		if(p->item.hEvent) UnhookEvent(p->item.hEvent);
 +		NudgeElementList* p1 = p->next;
 +		//free( p );
 +		delete p;
 +		p = p1;
 +	}
 +	return 0;
 +}
 +
 +LRESULT CALLBACK NudgePopUpProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
 +{
 +	switch(msg)
 +	{
 +		case WM_COMMAND:
 +		{
 +			HANDLE hContact = PUGetContact(hWnd);
 +			CallService(MS_MSG_SENDMESSAGET, (WPARAM)hContact, 0);
 +			PUDeletePopUp(hWnd);
 +			break;
 +		}
 +
 +		case WM_CONTEXTMENU:
 +			PUDeletePopUp(hWnd);
 +			break;
 +		case UM_FREEPLUGINDATA:
 +			//Here we'd free our own data, if we had it.
 +			return FALSE;
 +		case UM_INITPOPUP:
 +			break;
 +		case UM_DESTROYPOPUP:
 +			break;
 +		case WM_NOTIFY:
 +		default:
 +			break;
 +	}
 +	return DefWindowProc(hWnd,msg,wParam,lParam);
 +}
 +
 +void LoadPopupClass()
 +{
 +	if(ServiceExists(MS_POPUP_REGISTERCLASS))
 +	{
 +		POPUPCLASS ppc = {0};
 +		ppc.cbSize = sizeof(ppc);
 +		ppc.flags = PCF_TCHAR;
 +		ppc.pszName = "nudge";
 +		ppc.ptszDescription = LPGENT("Show Nudge");
 +		ppc.hIcon = (HICON) CallService(MS_SKIN2_GETICONBYHANDLE,0,(LPARAM)g_hIcon);
 +		ppc.colorBack = NULL;
 +		ppc.colorText = NULL;
 +		ppc.iSeconds = 0;
 +		ppc.PluginWindowProc = NudgePopUpProc;
 +		CallService(MS_POPUP_REGISTERCLASS,0,(LPARAM)&ppc);
 +	}
 +}
 +
 +int Preview()
 +{
 +	HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST,0,0);
 +	if ( GlobalNudge.useByProtocol )
 +	{
 +		for(NudgeElementList *n = NudgeList;n != NULL; n = n->next)
 +		{
 +			if(n->item.enabled)
 +			{
 +				SkinPlaySound( n->item.NudgeSoundname );
 +				if(n->item.showPopup)
 +					Nudge_ShowPopup(n->item, hContact, n->item.recText);
 +				if(n->item.openContactList)
 +					OpenContactList();
 +				if(n->item.shakeClist)
 +					ShakeClist(0,0);
 +				if(n->item.openMessageWindow)
 +					CallService(MS_MSG_SENDMESSAGET,(WPARAM)hContact,NULL);
 +				if(n->item.shakeChat)
 +					ShakeChat((WPARAM)hContact,(LPARAM)time(NULL));
 +			}
 +		}
 +	}
 +	else
 +	{
 +		if(DefaultNudge.enabled)
 +		{
 +			SkinPlaySound( DefaultNudge.NudgeSoundname );
 +			if(DefaultNudge.showPopup)
 +				Nudge_ShowPopup(DefaultNudge, hContact, DefaultNudge.recText);
 +			if(DefaultNudge.openContactList)
 +				OpenContactList();
 +			if(DefaultNudge.shakeClist)
 +				ShakeClist(0,0);
 +			if(DefaultNudge.openMessageWindow)
 +				CallService(MS_MSG_SENDMESSAGET,(WPARAM)hContact,NULL);
 +			if(DefaultNudge.shakeChat)
 +				ShakeChat((WPARAM)hContact,(LPARAM)time(NULL));
 +		}
 +	}
 +	return 0;
 +}
 +
 +void Nudge_ShowPopup(CNudgeElement n, HANDLE hContact, TCHAR * Message)
 +{
 +	hContact = Nudge_GethContact(hContact);
 +	TCHAR * lpzContactName = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,GCDNF_TCHAR);
 +
 +	if(ServiceExists(MS_POPUP_ADDPOPUPCLASS))
 +	{
 +		POPUPDATACLASS NudgePopUp = {0};
 +		NudgePopUp.cbSize = sizeof(NudgePopUp);
 +		NudgePopUp.hContact = hContact;
 +		NudgePopUp.ptszText = Message;
 +		NudgePopUp.ptszTitle = lpzContactName;
 +		NudgePopUp.pszClassName = "nudge";
 +		CallService(MS_POPUP_ADDPOPUPCLASS, 0, (LPARAM)&NudgePopUp);
 +	}
 +	else if(ServiceExists(MS_POPUP_ADDPOPUPT))
 +	{
 +		POPUPDATAT NudgePopUp = {0};
 +
 +		NudgePopUp.lchContact = hContact;
 +		NudgePopUp.lchIcon = (HICON) CallService(MS_SKIN2_GETICON,0,(LPARAM) n.hIcoLibItem );
 +		NudgePopUp.colorBack = 0;
 +		NudgePopUp.colorText = 0;
 +		NudgePopUp.iSeconds = 0;
 +		NudgePopUp.PluginWindowProc = NudgePopUpProc;
 +		NudgePopUp.PluginData = (void *)1;
 +
 +		//lstrcpy(NudgePopUp.lpzText, Translate(Message));
 +		lstrcpy(NudgePopUp.lptzText, Message);
 +
 +		lstrcpy(NudgePopUp.lptzContactName, lpzContactName);
 +
 +		CallService(MS_POPUP_ADDPOPUPT,(WPARAM)&NudgePopUp,0);
 +	}
 +	else
 +	{
 +		MessageBox(NULL,Message,lpzContactName,0);
 +	}
 +}
 +
 +void Nudge_SentStatus(CNudgeElement n, HANDLE hContact)
 +{
 +	DBEVENTINFO NudgeEvent = { 0 };
 +
 +	NudgeEvent.cbSize = sizeof(NudgeEvent);
 +	NudgeEvent.szModule = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
 +
 +	char *buff = mir_utf8encodeT(n.senText);
 +	NudgeEvent.flags = DBEF_SENT | DBEF_UTF;
 +
 +	NudgeEvent.timestamp = ( DWORD )time(NULL);
 +	NudgeEvent.eventType = EVENTTYPE_STATUSCHANGE;
 +	NudgeEvent.cbBlob = (DWORD)strlen(buff) + 1;
 +	NudgeEvent.pBlob = ( PBYTE ) buff;
 +
 +	INT_PTR res = CallService( MS_MC_GETMETACONTACT, (WPARAM)hContact, 0 ); //try to retrieve the metacontact if some
 +	if(res != CALLSERVICE_NOTFOUND)
 +	{
 +		HANDLE hMetaContact = (HANDLE) res;
 +		if(hMetaContact != NULL) //metacontact
 +			CallService(MS_DB_EVENT_ADD,(WPARAM)hMetaContact,(LPARAM)&NudgeEvent);
 +	}
 +
 +
 +	CallService(MS_DB_EVENT_ADD,(WPARAM)hContact,(LPARAM)&NudgeEvent);
 +}
 +
 +void Nudge_ShowStatus(CNudgeElement n, HANDLE hContact, DWORD timestamp)
 +{
 +	DBEVENTINFO NudgeEvent = { 0 };
 +
 +	NudgeEvent.cbSize = sizeof(NudgeEvent);
 +	NudgeEvent.szModule = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
 +
 +	char *buff = mir_utf8encodeT(n.recText);
 +	NudgeEvent.flags = DBEF_UTF;
 +
 +	NudgeEvent.timestamp = timestamp;
 +	NudgeEvent.eventType = EVENTTYPE_STATUSCHANGE;
 +	NudgeEvent.cbBlob = (DWORD)strlen(buff) + 1;
 +	NudgeEvent.pBlob = ( PBYTE ) buff;
 +
 +
 +	INT_PTR res = CallService( MS_MC_GETMETACONTACT, (WPARAM)hContact, 0 ); //try to retrieve the metacontact if some
 +	if(res != CALLSERVICE_NOTFOUND)
 +	{
 +		HANDLE hMetaContact = (HANDLE) res;
 +		if(hMetaContact != NULL) //metacontact
 +		{
 +			CallService(MS_DB_EVENT_ADD,(WPARAM)hMetaContact,(LPARAM)&NudgeEvent);
 +			NudgeEvent.flags |= DBEF_READ;
 +		}
 +	}
 +
 +	CallService(MS_DB_EVENT_ADD,(WPARAM)hContact,(LPARAM)&NudgeEvent);
 +}
 +
 +HANDLE Nudge_GethContact(HANDLE hContact)
 +{
 +	INT_PTR res = CallService( MS_MC_GETMETACONTACT, (WPARAM)hContact, 0 );
 +	if(res!=CALLSERVICE_NOTFOUND)
 +	{
 +		HANDLE hMetaContact = (HANDLE) res;
 +		if(hMetaContact!=NULL)
 +			return hMetaContact;
 +	}
 +
 +	return hContact;
 +}
 +
 +void Nudge_AddAccount(PROTOACCOUNT *proto)
 +{
 +	char str[MAXMODULELABELLENGTH + 10];
 +	mir_snprintf(str,sizeof(str),"%s/Nudge",proto->szModuleName);
 +	HANDLE hevent = HookEvent(str, NudgeRecieved);
 +	if(hevent == NULL)
 +		return;
 +
 +	nProtocol ++;
 +
 +	//Add a specific sound per protocol
 +	NudgeElementList *newNudge = new NudgeElementList;
 +	//newNudge = (NudgeElementList*) malloc(sizeof(NudgeElementList));
 +	mir_snprintf(newNudge->item.NudgeSoundname,sizeof(newNudge->item.NudgeSoundname),"%s: Nudge",proto->szModuleName);
 +
 +	strcpy( newNudge->item.ProtocolName, proto->szProtoName );
 +	_tcscpy(newNudge->item.AccountName, proto->tszAccountName );
 +
 +	newNudge->item.Load();
 +
 +	newNudge->item.hEvent = hevent;
 +
 +	TCHAR soundDesc[MAXMODULELABELLENGTH + 10];
 +	mir_sntprintf(soundDesc,sizeof(soundDesc),_T("Nudge for %s"),proto->tszAccountName);
 +	SkinAddNewSoundExT(newNudge->item.NudgeSoundname, LPGENT("Nudge"), soundDesc);
 +
 +	newNudge->next = NudgeList;
 +	NudgeList = newNudge;
 +
 +	char iconName[MAXMODULELABELLENGTH + 10];
 +	mir_snprintf(iconName,sizeof(iconName),"Nudge_%s",proto->szModuleName);
 +
 +	TCHAR szFilename[MAX_PATH], iconDesc[MAXMODULELABELLENGTH + 10];
 +	GetModuleFileName(hInst,szFilename,MAX_PATH);
 +	mir_sntprintf(iconDesc, SIZEOF(iconDesc), TranslateT("Nudge for %s"), proto->tszAccountName);
 +
 +	SKINICONDESC sid = {0};
 +	sid.cbSize = sizeof(sid);
 +	sid.flags = SIDF_ALL_TCHAR;
 +	sid.ptszSection = LPGENT("Nudge");
 +	sid.ptszDefaultFile = szFilename;
 +	sid.pszName = iconName;
 +	sid.ptszDescription = iconDesc;
 +	sid.iDefaultIndex = -IDI_NUDGE;
 +	sid.hDefaultIcon =  LoadIcon(hInst,MAKEINTRESOURCE(IDI_NUDGE));
 +	newNudge->item.hIcoLibItem = Skin_AddIcon(&sid);
 +
 +	//Add contact menu entry
 +	CLISTMENUITEM mi = {0};
 +	mi.cbSize = sizeof(mi);
 +	mi.popupPosition = 500085000;
 +	mi.pszContactOwner = proto->szModuleName;
 +	mi.pszPopupName = proto->szModuleName;
 +	mi.flags = CMIF_NOTOFFLINE | CMIF_TCHAR | CMIF_ICONFROMICOLIB;
 +	mi.position = -500050004;
 +	mi.icolibItem = newNudge->item.hIcoLibItem;
 +	mi.ptszName = LPGENT( "Send &Nudge" );
 +	mi.pszService = MS_NUDGE_SEND;
 +	newNudge->item.hContactMenu = Menu_AddContactMenuItem(&mi);
 +}
 +
 +void AutoResendNudge(void *wParam)
 +{
 +
 +	Sleep(GlobalNudge.resendDelaySec * 1000);
 +	NudgeSend((WPARAM) wParam,NULL);
 +}
  | 
