/* NewXstatusNotify YM - Plugin for Miranda IM Copyright (c) 2001-2004 Luca Santarelli Copyright (c) 2005-2007 Vasilich Copyright (c) 2007-2011 yaho This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdafx.h" void ShowChangePopup(MCONTACT hContact, HICON hIcon, WORD newStatus, const TCHAR *stzText, PLUGINDATA *pdp) { POPUPDATAT ppd = { 0 }; ppd.lchContact = hContact; ppd.lchIcon = hIcon; CMString buf(pcli->pfnGetContactDisplayName(hContact, 0)); // add group name to popup title if (opt.ShowGroup) { ptrT tszGroup(db_get_tsa(hContact, "CList", "Group")); if (tszGroup) buf.AppendFormat(_T(" (%s)"), tszGroup); } _tcsncpy_s(ppd.lptzContactName, buf, _TRUNCATE); _tcsncpy(ppd.lptzText, stzText, _countof(ppd.lptzText)); switch (opt.Colors) { case POPUP_COLOR_OWN: ppd.colorBack = StatusList[Index(newStatus)].colorBack; ppd.colorText = StatusList[Index(newStatus)].colorText; break; case POPUP_COLOR_WINDOWS: ppd.colorBack = GetSysColor(COLOR_BTNFACE); ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); break; case POPUP_COLOR_POPUP: ppd.colorBack = ppd.colorText = 0; break; } ppd.PluginWindowProc = PopupDlgProc; ppd.PluginData = pdp; ppd.iSeconds = opt.PopupTimeout; PUAddPopupT(&ppd); } static int AwayMsgHook(WPARAM, LPARAM lParam, LPARAM pObj) { PLUGINDATA *pdp = (PLUGINDATA *)pObj; if (pdp == NULL) return 0; ACKDATA *ack = (ACKDATA *)lParam; if (ack->type != ACKTYPE_AWAYMSG || ack->hProcess != pdp->hAwayMsgProcess) return 0; //The first thing we do is removing the hook from the chain to avoid useless calls. UnhookEvent(pdp->hAwayMsgHook); pdp->hAwayMsgHook = NULL; if (ack->result != ACKRESULT_SUCCESS) return 0; MCONTACT hContact = PUGetContact(pdp->hWnd); ptrT pstzLast(db_get_tsa(hContact, MODULE, "LastPopupText")); TCHAR *tszStatus = (TCHAR *)ack->lParam; if (tszStatus == NULL || *tszStatus == 0) return 0; TCHAR stzText[1024]; if (pstzLast) mir_sntprintf(stzText, _T("%s\n%s"), pstzLast, tszStatus); else _tcsncpy(stzText, tszStatus, _countof(stzText)); SendMessage(pdp->hWnd, WM_SETREDRAW, FALSE, 0); PUChangeTextT(pdp->hWnd, stzText); SendMessage(pdp->hWnd, WM_SETREDRAW, TRUE, 0); return 0; } void QueryAwayMessage(HWND hWnd, PLUGINDATA *pdp) { MCONTACT hContact = PUGetContact(hWnd); char *szProto = GetContactProto(hContact); if (szProto) { if ((CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGRECV) && (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(pdp->newStatus))) { pdp->hWnd = hWnd; //The following HookEventMessage will hook the ME_PROTO_ACK event and send a WM_AWAYMSG to hWnd when the hooks get notified. pdp->hAwayMsgHook = HookEventParam(ME_PROTO_ACK, AwayMsgHook, (LPARAM)pdp); //The following instruction asks Miranda to retrieve the away message and associates a hProcess (handle) to this request. This handle will appear in the ME_PROTO_ACK event. pdp->hAwayMsgProcess = (HANDLE)ProtoChainSend(hContact, PSS_GETAWAYMSG, 0, 0); } } } void PopupAction(HWND hWnd, BYTE action) { MCONTACT hContact = PUGetContact(hWnd); if (hContact && hContact != INVALID_CONTACT_ID) { switch (action) { case PCA_OPENMESSAGEWND: CallServiceSync(MS_MSG_SENDMESSAGET, hContact, 0); break; case PCA_OPENMENU: { POINT pt = { 0 }; GetCursorPos(&pt); HMENU hMenu = Menu_BuildContactMenu(hContact); TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hWnd, NULL); DestroyMenu(hMenu); } return; case PCA_OPENDETAILS: CallServiceSync(MS_USERINFO_SHOWDIALOG, hContact, 0); break; case PCA_OPENHISTORY: CallServiceSync(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0); break; case PCA_CLOSEPOPUP: break; case PCA_DONOTHING: return; } PUDeletePopup(hWnd); } } LRESULT CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PLUGINDATA *pdp = NULL; switch (message) { case WM_MEASUREITEM: //Needed by the contact's context menu return Menu_MeasureItem((LPMEASUREITEMSTRUCT)lParam); case WM_DRAWITEM: //Needed by the contact's context menu return Menu_DrawItem((LPDRAWITEMSTRUCT)lParam); case WM_COMMAND: //This one returns TRUE if it processed the menu command, and FALSE if it did not process it. if (CallServiceSync(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)PUGetContact(hwnd))) break; PopupAction(hwnd, opt.LeftClickAction); break; case WM_CONTEXTMENU: PopupAction(hwnd, opt.RightClickAction); break; case UM_FREEPLUGINDATA: pdp = (PLUGINDATA *)PUGetPluginData(hwnd); if (pdp != NULL) { if (pdp->hAwayMsgHook != NULL) { UnhookEvent(pdp->hAwayMsgHook); pdp->hAwayMsgHook = NULL; } mir_free(pdp); } return FALSE; case UM_INITPOPUP: pdp = (PLUGINDATA *)PUGetPluginData(hwnd); if (pdp != NULL) { char *szProto = GetContactProto(PUGetContact(hwnd)); if (szProto && opt.ReadAwayMsg && StatusHasAwayMessage(szProto, pdp->newStatus)) { WORD myStatus = (WORD)CallProtoService(szProto, PS_GETSTATUS, 0, 0); if (myStatus != ID_STATUS_INVISIBLE) QueryAwayMessage(hwnd, pdp); } } return FALSE; } return DefWindowProc(hwnd, message, wParam, lParam); }