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 CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); case WM_DRAWITEM: //Needed by the contact's context menu return CallService(MS_CLIST_MENUDRAWITEM, wParam, 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); }
int ContactStatusChanged(MCONTACT hContact, WORD oldStatus, WORD newStatus) { if (opt.LogToDB && (!opt.LogToDB_WinOpen || CheckMsgWnd(hContact))) { wchar_t stzStatusText[MAX_SECONDLINE] = { 0 }; GetStatusText(hContact, newStatus, oldStatus, stzStatusText); T2Utf blob(stzStatusText); DBEVENTINFO dbei = {}; dbei.cbBlob = (DWORD)mir_strlen(blob) + 1; dbei.pBlob = (PBYTE)blob; dbei.eventType = EVENTTYPE_STATUSCHANGE; dbei.flags = DBEF_READ | DBEF_UTF; dbei.timestamp = (DWORD)time(0); dbei.szModule = MODULE; MEVENT hDBEvent = db_event_add(hContact, &dbei); if (opt.LogToDB_WinOpen && opt.LogToDB_Remove) { DBEVENT *dbevent = (DBEVENT *)mir_alloc(sizeof(DBEVENT)); dbevent->hContact = hContact; dbevent->hDBEvent = hDBEvent; eventListStatus.insert(dbevent); } } bool bEnablePopup = true, bEnableSound = true; char *szProto = GetContactProto(hContact); int myStatus = Proto_GetStatus(szProto); if (!mir_strcmp(szProto, META_PROTO)) { //this contact is Meta MCONTACT hSubContact = db_mc_getMostOnline(hContact); char *szSubProto = GetContactProto(hSubContact); if (szSubProto == nullptr) return 0; if (newStatus == ID_STATUS_OFFLINE) { // read last online proto for metacontact if exists, // to avoid notifying when meta went offline but default contact's proto still online DBVARIANT dbv; if (!db_get_s(hContact, szProto, "LastOnline", &dbv)) { szSubProto = NEWSTR_ALLOCA(dbv.pszVal); db_free(&dbv); } } else db_set_s(hContact, szProto, "LastOnline", szSubProto); if (db_get_b(0, MODULE, szSubProto, 1) == 0) return 0; szProto = szSubProto; } else { if (myStatus == ID_STATUS_OFFLINE || db_get_b(0, MODULE, szProto, 1) == 0) return 0; } if (!opt.FromOffline || oldStatus != ID_STATUS_OFFLINE) { // Either it wasn't a change from Offline or we didn't enable that. char buff[8]; mir_snprintf(buff, "%d", newStatus); if (db_get_b(0, MODULE, buff, 1) == 0) return 0; // "Notify when a contact changes to one of..." is unchecked } if (SkipHiddenContact(hContact)) return 0; // check if that proto from which we received statuschange notification, isn't in autodisable list if (opt.AutoDisable) { char statusIDs[12], statusIDp[12]; mir_snprintf(statusIDs, "s%d", myStatus); mir_snprintf(statusIDp, "p%d", myStatus); bEnableSound = db_get_b(0, MODULE, statusIDs, 1) ? FALSE : TRUE; bEnablePopup = db_get_b(0, MODULE, statusIDp, 1) ? FALSE : TRUE; } if (bEnablePopup && db_get_b(hContact, MODULE, "EnablePopups", 1) && !opt.TempDisabled) { int wStatus = Proto_GetStatus(szProto); wchar_t str[MAX_SECONDLINE] = { 0 }; if (opt.ShowStatus) GetStatusText(hContact, newStatus, oldStatus, str); if (opt.ReadAwayMsg && wStatus != ID_STATUS_INVISIBLE && StatusHasAwayMessage(szProto, newStatus)) db_set_ws(hContact, MODULE, "LastPopupText", str); PLUGINDATA *pdp = (PLUGINDATA *)mir_calloc(sizeof(PLUGINDATA)); pdp->oldStatus = oldStatus; pdp->newStatus = newStatus; pdp->hAwayMsgHook = nullptr; pdp->hAwayMsgProcess = nullptr; ShowChangePopup(hContact, Skin_LoadProtoIcon(szProto, newStatus), newStatus, str, pdp); } if (opt.BlinkIcon && !opt.TempDisabled) { HICON hIcon = opt.BlinkIcon_Status ? Skin_LoadProtoIcon(szProto, newStatus) : Skin_LoadIcon(SKINICON_OTHER_USERONLINE); wchar_t str[256]; mir_snwprintf(str, TranslateT("%s is now %s"), Clist_GetContactDisplayName(hContact), StatusList[Index(newStatus)].lpzStandardText); BlinkIcon(hContact, hIcon, str); } if (bEnableSound && db_get_b(0, "Skin", "UseSound", TRUE) && db_get_b(hContact, MODULE, "EnableSounds", 1) && !opt.TempDisabled) { if (oldStatus == ID_STATUS_OFFLINE) PlayChangeSound(hContact, StatusListEx[ID_STATUS_FROMOFFLINE].lpzSkinSoundName); else PlayChangeSound(hContact, StatusList[Index(newStatus)].lpzSkinSoundName); } if (opt.LogToFile) { wchar_t stzDate[MAX_STATUSTEXT], stzTime[MAX_STATUSTEXT], stzText[MAX_TEXT_LEN]; GetTimeFormat(LOCALE_USER_DEFAULT, 0, nullptr, L"HH':'mm", stzTime, _countof(stzTime)); GetDateFormat(LOCALE_USER_DEFAULT, 0, nullptr, L"dd/MM/yyyy", stzDate, _countof(stzDate)); mir_snwprintf(stzText, TranslateT("%s, %s. %s changed status to %s (was %s)\r\n"), stzDate, stzTime, Clist_GetContactDisplayName(hContact), StatusList[Index(newStatus)].lpzStandardText, StatusList[Index(oldStatus)].lpzStandardText); LogToFile(stzText); } return 0; }