int Meta_ContactDeleted(WPARAM hContact, LPARAM lParam) { DBCachedContact *cc = currDb->m_cache->GetCachedContact(hContact); if (cc == NULL) return 0; // is a subcontact - update meta contact if (cc->IsSub()) { DBCachedContact *ccMeta = CheckMeta(cc->parentID); if (ccMeta) { Meta_RemoveContactNumber(ccMeta, Meta_GetContactNumber(ccMeta, hContact), true); NotifyEventHooks(hSubcontactsChanged, ccMeta->contactID, 0); } return 0; } // not a subcontact - is it a metacontact? if (!cc->IsMeta()) return 0; if (cc->nSubs > 0) NotifyEventHooks(hSubcontactsChanged, hContact, 0); // remove & restore all subcontacts for (int i = 0; i < cc->nSubs; i++) { currDb->MetaDetouchSub(cc, i); // stop ignoring, if we were if (options.bSuppressStatus) CallService(MS_IGNORE_UNIGNORE, cc->pSubs[i], IGNOREEVENT_USERONLINE); } return 0; }
INT_PTR Meta_ContactMenuFunc(WPARAM hMeta, LPARAM lParam) { DBCachedContact *cc = CheckMeta(hMeta); if (cc == NULL) return 0; MCONTACT hContact = Meta_GetContactHandle(cc, (int)lParam); if (options.menu_function == FT_MSG) { // open message window if protocol supports message sending or chat, else simulate double click char *proto = GetContactProto(hContact); if (proto) { INT_PTR caps = CallProtoService(proto, PS_GETCAPS, PFLAGNUM_1, 0); if ((caps & PF1_IMSEND) || (caps & PF1_CHAT)) { // set default contact for sending/status and open message window Meta_SetSrmmSub(hMeta, hContact); db_mc_setDefaultNum(hMeta, lParam, false); CallService(MS_MSG_SENDMESSAGET, hMeta, 0); } else // protocol does not support messaging - simulate double click CallService(MS_CLIST_CONTACTDOUBLECLICKED, hContact, 0); } else // protocol does not support messaging - simulate double click CallService(MS_CLIST_CONTACTDOUBLECLICKED, hContact, 0); } else if (options.menu_function == FT_MENU) // show contact's context menu CallFunctionAsync(sttMenuThread, (void*)hContact); else if (options.menu_function == FT_INFO) // show user info for subcontact CallService(MS_USERINFO_SHOWDIALOG, hContact, 0); return 0; }
INT_PTR Meta_GetAvatarInfo(WPARAM wParam, LPARAM lParam) { PROTO_AVATAR_INFORMATIONT *AI = (PROTO_AVATAR_INFORMATIONT*)lParam; DBCachedContact *cc = CheckMeta(AI->hContact); if (cc == NULL) return GAIR_NOAVATAR; if (cc->nDefault == -1) return 0; MCONTACT hSub = Meta_GetMostOnlineSupporting(cc, PFLAGNUM_4, PF4_AVATARS); if (!hSub) return GAIR_NOAVATAR; char *proto = GetContactProto(hSub); if (!proto) return GAIR_NOAVATAR; AI->hContact = hSub; INT_PTR result = ProtoCallService(proto, PS_GETAVATARINFOT, wParam, lParam); AI->hContact = cc->contactID; if (result != CALLSERVICE_NOTFOUND) return result; return GAIR_NOAVATAR; // fail }
static int FillList(HWND list, BOOL sort) { int i = 0; // The DB is searched through, to get all the metacontacts for (MCONTACT hMetaUser = db_find_first(); hMetaUser; hMetaUser = db_find_next(hMetaUser)) { // if it's not a MetaContact, go to the next DBCachedContact *cc = CheckMeta(hMetaUser); if (cc == NULL) continue; // get contact display name from clist TCHAR *swzContactDisplayName = cli.pfnGetContactDisplayName(hMetaUser, 0); // don't insert huge strings that we have to compare with later if (_tcslen(swzContactDisplayName) > 1023) swzContactDisplayName[1024] = 0; int pos = -1; if (sort) { for (pos = 0; pos < i; pos++) { TCHAR buff[1024]; SendMessage(list, LB_GETTEXT, pos, (LPARAM)buff); if (_tcscmp(buff, swzContactDisplayName) > 0) break; } } int index = SendMessage(list, LB_INSERTSTRING, pos, (LPARAM)swzContactDisplayName); SendMessage(list, LB_SETITEMDATA, index, hMetaUser); i++; } return i; }
//returns a handle to the default contact, or null on failure MIR_CORE_DLL(MCONTACT) db_mc_getDefault(MCONTACT hMetaContact) { DBCachedContact *cc = CheckMeta(hMetaContact); if (cc == NULL) return 0; return (cc->nDefault != -1) ? Meta_GetContactHandle(cc, cc->nDefault) : 0; }
INT_PTR Meta_SendNudge(WPARAM wParam, LPARAM lParam) { DBCachedContact *cc = CheckMeta(wParam); if (cc == NULL) return 1; MCONTACT hSubContact = Meta_GetMostOnline(cc); return ProtoCallService(GetContactProto(hSubContact), PS_SEND_NUDGE, hSubContact, lParam); }
static int Meta_UserInfo(WPARAM wParam, LPARAM hMeta) { DBCachedContact *cc = CheckMeta(hMeta); if (cc == NULL || cc->nDefault == -1) return 0; CallService(MS_USERINFO_SHOWDIALOG, Meta_GetContactHandle(cc, cc->nDefault), 0); return 1; }
int Meta_CallMostOnline(WPARAM hContact, LPARAM lParam) { DBCachedContact *cc = CheckMeta(hContact); if (cc == NULL) return 0; Meta_CopyContactNick(cc, db_mc_getSrmmSub(cc->contactID)); Meta_FixStatus(cc); return 0; }
static rc_t fix_run_stat(const XmlMeta* xml) { rc_t rc = 0; bool found = false; const SRATable *tbl = NULL; SDbMeta db; memset(&db, 0, sizeof db); rc = CheckMeta(xml, &db, &found); RELEASE(SRATable, tbl); return rc; }
// we assume that it could be called only for the metacontacts static int Meta_SrmmIconClicked(WPARAM hMeta, LPARAM lParam) { StatusIconClickData *sicd = (StatusIconClickData*)lParam; if (lstrcmpA(sicd->szModule, META_PROTO)) return 0; DBCachedContact *cc = CheckMeta(hMeta); if (cc == NULL) return 0; HMENU hMenu = CreatePopupMenu(); int iDefault = Meta_GetContactNumber(cc, db_mc_getSrmmSub(cc->contactID)); MENUITEMINFO mii = { sizeof(mii) }; mii.fMask = MIIM_ID | MIIM_STATE | MIIM_STRING; for (int i = 0; i < cc->nSubs; i++) { char *szProto = GetContactProto(cc->pSubs[i]); if (szProto == NULL) continue; PROTOACCOUNT *pa = ProtoGetAccount(szProto); if (pa == NULL) continue; CMString tszNick; if (options.menu_contact_label == DNT_DID) tszNick = cli.pfnGetContactDisplayName(cc->pSubs[i], 0); else Meta_GetSubNick(hMeta, i, tszNick); tszNick.AppendFormat(_T(" [%s]"), pa->tszAccountName); mii.wID = i + 1; mii.fState = (i == iDefault) ? MFS_CHECKED : MFS_ENABLED; mii.dwTypeData = tszNick.GetBuffer(); mii.cch = tszNick.GetLength(); InsertMenuItem(hMenu, i, TRUE, &mii); } UINT res = TrackPopupMenu(hMenu, TPM_NONOTIFY | TPM_RETURNCMD | TPM_BOTTOMALIGN | TPM_LEFTALIGN, sicd->clickLocation.x, sicd->clickLocation.y, 0, cli.hwndContactTree, NULL); if (res > 0) { MCONTACT hChosen = Meta_GetContactHandle(cc, res - 1); MetaSrmmData tmp = { cc->contactID }; if (MetaSrmmData *p = arMetaWindows.find(&tmp)) p->m_hSub = hChosen; db_mc_setDefault(cc->contactID, hChosen, true); } return 0; }
int Meta_HandleACK(WPARAM, LPARAM lParam) { ACKDATA *ack = (ACKDATA*)lParam; DBCachedContact *cc = CheckMeta(ack->hContact); if (cc == NULL) return 0; if (!strcmp(ack->szModule, META_PROTO)) return 0; // don't rebroadcast our own acks // if it's for something we don't support, ignore if (ack->type != ACKTYPE_MESSAGE && ack->type != ACKTYPE_CHAT && ack->type != ACKTYPE_FILE && ack->type != ACKTYPE_AWAYMSG && ack->type != ACKTYPE_AVATAR && ack->type != ACKTYPE_GETINFO) return 0; // change the hContact in the avatar info struct, if it's the avatar we're using - else drop it if (ack->type == ACKTYPE_AVATAR) { if (ack->result == ACKRESULT_SUCCESS || ack->result == ACKRESULT_FAILED || ack->result == ACKRESULT_STATUS) { DBVARIANT dbv; // change avatar if the most online supporting avatars changes, or if we don't have one MCONTACT hMostOnline = Meta_GetMostOnlineSupporting(cc, PFLAGNUM_4, PF4_AVATARS); //if (AI.hContact == 0 || AI.hContact != hMostOnline) { if (ack->hContact == 0 || ack->hContact != hMostOnline) { return 0; } if (!db_get(ack->hContact, "ContactPhoto", "File", &dbv)) { db_set_ts(cc->contactID, "ContactPhoto", "File", dbv.ptszVal); db_free(&dbv); } if (ack->hProcess) { PROTO_AVATAR_INFORMATIONT AI; memcpy(&AI, (PROTO_AVATAR_INFORMATIONT *)ack->hProcess, sizeof(PROTO_AVATAR_INFORMATIONT)); if (AI.hContact) AI.hContact = cc->contactID; return ProtoBroadcastAck(META_PROTO, cc->contactID, ack->type, ack->result, (HANDLE)&AI, ack->lParam); } return ProtoBroadcastAck(META_PROTO, cc->contactID, ack->type, ack->result, 0, ack->lParam); } } return ProtoBroadcastAck(META_PROTO, cc->contactID, ack->type, ack->result, ack->hProcess, ack->lParam); }
INT_PTR Meta_FileSend(WPARAM wParam, LPARAM lParam) { CCSDATA *ccs = (CCSDATA*)lParam; DBCachedContact *cc = CheckMeta(ccs->hContact); if (cc == NULL || cc->nDefault == -1) return 0; MCONTACT hMostOnline = Meta_GetMostOnlineSupporting(cc, PFLAGNUM_1, PF1_FILESEND); if (!hMostOnline) return 0; char *proto = GetContactProto(hMostOnline); if (proto) return CallContactService(hMostOnline, PSS_FILE, ccs->wParam, ccs->lParam); return 0; // fail }
//sets the default contact, using the subcontact's number MIR_CORE_DLL(int) db_mc_setDefaultNum(MCONTACT hMetaContact, int iNum, BOOL bWriteDb) { DBCachedContact *cc = CheckMeta(hMetaContact); if (cc == NULL) return 1; if (iNum >= cc->nSubs || iNum < 0) return 1; if (cc->nDefault != iNum) { cc->nDefault = iNum; if (bWriteDb) currDb->MetaSetDefault(cc); NotifyEventHooks(hEventDefaultChanged, hMetaContact, Meta_GetContactHandle(cc, iNum)); } return 0; }
INT_PTR Meta_GetAwayMsg(WPARAM wParam, LPARAM lParam) { CCSDATA *ccs = (CCSDATA*)lParam; DBCachedContact *cc = CheckMeta(ccs->hContact); if (cc == NULL || cc->nDefault == -1) return 0; MCONTACT hMostOnline = Meta_GetMostOnlineSupporting(cc, PFLAGNUM_1, PF1_MODEMSGRECV); if (!hMostOnline) return 0; char *proto = GetContactProto(hMostOnline); if (!proto) return 0; ccs->hContact = hMostOnline; return CallContactService(ccs->hContact, PSS_GETAWAYMSG, ccs->wParam, ccs->lParam); }
/** Call when we want to send a user is typing message * * @param wParam HANDLE to the contact that we are typing to * @param lParam either PROTOTYPE_SELFTYPING_ON or PROTOTYPE_SELFTYPING_OFF */ static INT_PTR Meta_UserIsTyping(WPARAM hMeta, LPARAM lParam) { DBCachedContact *cc = CheckMeta(hMeta); if (cc == NULL) return 0; // forward to sending protocol, if supported MCONTACT hMostOnline = Meta_GetMostOnline(cc); Meta_CopyContactNick(cc, hMostOnline); if (!hMostOnline) return 0; char *proto = GetContactProto(hMostOnline); if (proto) if (ProtoServiceExists(proto, PSS_USERISTYPING)) ProtoCallService(proto, PSS_USERISTYPING, hMostOnline, lParam); return 0; }
//sets the default contact, using the subcontact's handle MIR_CORE_DLL(int) db_mc_setDefault(MCONTACT hMetaContact, MCONTACT hSub, BOOL bWriteDb) { DBCachedContact *cc = CheckMeta(hMetaContact); if (cc == NULL) return 1; int contact_number = Meta_GetContactNumber(cc, hSub); if (contact_number == -1) return 1; if (cc->nDefault != contact_number) { cc->nDefault = contact_number; if (bWriteDb) currDb->MetaSetDefault(cc); NotifyEventHooks(hEventDefaultChanged, hMetaContact, hSub); } return 0; }
INT_PTR Meta_GetInfo(WPARAM wParam, LPARAM lParam) { CCSDATA *ccs = (CCSDATA*)lParam; // This is a simple contact // (this should normally not happen, since linked contacts do not appear on the list.) DBCachedContact *cc = CheckMeta(ccs->hContact); if (cc == NULL || cc->nDefault == -1) return 0; MCONTACT hMostOnline = Meta_GetMostOnlineSupporting(cc, PFLAGNUM_4, PF4_AVATARS); if (!hMostOnline) return 0; char *proto = GetContactProto(hMostOnline); if (!proto) return 0; PROTO_AVATAR_INFORMATIONT AI; AI.cbSize = sizeof(AI); AI.hContact = ccs->hContact; AI.format = PA_FORMAT_UNKNOWN; _tcscpy(AI.filename, _T("X")); if (CallProtoService(META_PROTO, PS_GETAVATARINFOT, 0, (LPARAM)&AI) == GAIR_SUCCESS) db_set_ts(ccs->hContact, "ContactPhoto", "File", AI.filename); hMostOnline = Meta_GetMostOnline(cc); Meta_CopyContactNick(cc, hMostOnline); if (!hMostOnline) return 0; ccs->hContact = hMostOnline; if (!ProtoServiceExists(proto, PSS_GETINFO)) return 0; // fail return CallContactService(ccs->hContact, PSS_GETINFO, ccs->wParam, ccs->lParam); }
INT_PTR Meta_SendMessage(WPARAM wParam,LPARAM lParam) { CCSDATA *ccs = (CCSDATA*)lParam; DBCachedContact *cc = CheckMeta(ccs->hContact); if (cc == NULL || cc->nDefault == -1) { // This is a simple contact, let through the stack of protocols // (this should normally not happen, since linked contacts do not appear on the list.) return CallService(MS_PROTO_CHAINSEND, wParam, lParam); } MCONTACT hMostOnline = db_mc_getSrmmSub(cc->contactID); if (!hMostOnline) { // send failure to notify user of reason HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); TFakeAckParams *tfap = (TFakeAckParams *)mir_alloc(sizeof(TFakeAckParams)); tfap->hContact = ccs->hContact; tfap->hEvent = hEvent; tfap->id = 10; strcpy(tfap->msg, Translate("No online contacts found.")); DWORD dwThreadId; CloseHandle(CreateThread(NULL, 0, sttFakeAckFail, tfap, 0, &dwThreadId)); SetEvent(hEvent); return 10; } Meta_CopyContactNick(cc, hMostOnline); ccs->hContact = hMostOnline; char *proto = GetContactProto(hMostOnline); Meta_SetNick(proto); // (no matter what was there before) return CallContactService(ccs->hContact, PSS_MESSAGE, ccs->wParam, ccs->lParam); }
//returns the default contact number, or -1 on failure MIR_CORE_DLL(int) db_mc_getDefaultNum(MCONTACT hMetaContact) { DBCachedContact *cc = CheckMeta(hMetaContact); return (cc == NULL) ? -1 : cc->nDefault; }
//returns the number of subcontacts, or -1 on failure MIR_CORE_DLL(int) db_mc_getSubCount(MCONTACT hMetaContact) { DBCachedContact *cc = CheckMeta(hMetaContact); return (cc == NULL) ? -1 : cc->nSubs; }
// returns a subcontact with the given index MIR_CORE_DLL(MCONTACT) db_mc_getSub(MCONTACT hMetaContact, int iNum) { DBCachedContact *cc = CheckMeta(hMetaContact); return (cc == NULL) ? 0 : Meta_GetContactHandle(cc, iNum); }