static void OnCreateModule(MODULEINFO *mi) { mi->OnlineIconIndex = ImageList_AddIcon(hIconsList, Skin_LoadProtoIcon(mi->pszModule, ID_STATUS_ONLINE)); mi->hOnlineIcon = ImageList_GetIcon(hIconsList, mi->OnlineIconIndex, ILD_TRANSPARENT); mi->hOnlineTalkIcon = ImageList_GetIcon(hIconsList, mi->OnlineIconIndex, ILD_TRANSPARENT | INDEXTOOVERLAYMASK(1)); ImageList_AddIcon(hIconsList, mi->hOnlineTalkIcon); mi->OfflineIconIndex = ImageList_AddIcon(hIconsList, Skin_LoadProtoIcon(mi->pszModule, ID_STATUS_OFFLINE)); mi->hOfflineIcon = ImageList_GetIcon(hIconsList, mi->OfflineIconIndex, ILD_TRANSPARENT); mi->hOfflineTalkIcon = ImageList_GetIcon(hIconsList, mi->OfflineIconIndex, ILD_TRANSPARENT | INDEXTOOVERLAYMASK(1)); ImageList_AddIcon(hIconsList, mi->hOfflineTalkIcon); }
void ShowPopup(SHOWPOPUP_DATA *sd) { TCString PopupText; if (sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_SHOWPREVCLIENT)) { mir_snwprintf(PopupText.GetBuffer(MAX_MSG_LEN), MAX_MSG_LEN, TranslateT("changed client to %s (was %s)"), (const wchar_t*)sd->MirVer, (const wchar_t*)sd->OldMirVer); PopupText.ReleaseBuffer(); } else { mir_snwprintf(PopupText.GetBuffer(MAX_MSG_LEN), MAX_MSG_LEN, TranslateT("changed client to %s"), (const wchar_t*)sd->MirVer); PopupText.ReleaseBuffer(); } PLUGIN_DATA *pdata = (PLUGIN_DATA*)calloc(1, sizeof(PLUGIN_DATA)); POPUPDATAT ppd = { 0 }; ppd.lchContact = sd->hContact; char *szProto = GetContactProto(sd->hContact); pdata->hIcon = ppd.lchIcon = Finger_GetClientIcon(sd->MirVer, false); _ASSERT(ppd.lchIcon); if (!ppd.lchIcon || (INT_PTR)ppd.lchIcon == CALLSERVICE_NOTFOUND) { // if we didn't succeed retrieving client icon, show the usual status icon instead ppd.lchIcon = Skin_LoadProtoIcon(szProto, db_get_w(sd->hContact, szProto, "Status", ID_STATUS_OFFLINE)); pdata->hIcon = nullptr; } wcsncpy(ppd.lptzContactName, Clist_GetContactDisplayName(sd->hContact), _countof(ppd.lptzContactName) - 1); wcsncpy(ppd.lptzText, PopupText, _countof(ppd.lptzText) - 1); ppd.colorBack = (sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_DEFBGCOLOUR) ? 0 : sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_BGCOLOUR)); ppd.colorText = (sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_DEFTEXTCOLOUR) ? 0 : sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_TEXTCOLOUR)); ppd.PluginWindowProc = PopupWndProc; pdata->PopupLClickAction = sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_LCLICK_ACTION); pdata->PopupRClickAction = sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_RCLICK_ACTION); ppd.iSeconds = sd->PopupOptPage->GetValue(IDC_POPUPOPTDLG_POPUPDELAY); ppd.PluginData = pdata; PUAddPopupT(&ppd); }
int ImageList_AddIcon_ProtoIconLibLoaded(HIMAGELIST hIml, const char *szProto, int iconId) { HICON hIcon = Skin_LoadProtoIcon(szProto, iconId); int res = ImageList_AddIcon(hIml, hIcon); IcoLib_ReleaseIcon(hIcon); return res; }
void LoadModuleIcons(MODULEINFO *mi) { HIMAGELIST hList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 0); int overlayIcon = ImageList_AddIcon(hList, GetCachedIcon("chat_overlay")); ImageList_SetOverlayImage(hList, overlayIcon, 1); int index = ImageList_AddIcon(hList, Skin_LoadProtoIcon(mi->pszModule, ID_STATUS_ONLINE)); mi->hOnlineIcon = ImageList_GetIcon(hList, index, ILD_TRANSPARENT); mi->hOnlineTalkIcon = ImageList_GetIcon(hList, index, ILD_TRANSPARENT | INDEXTOOVERLAYMASK(1)); index = ImageList_AddIcon(hList, Skin_LoadProtoIcon(mi->pszModule, ID_STATUS_OFFLINE)); mi->hOfflineIcon = ImageList_GetIcon(hList, index, ILD_TRANSPARENT); mi->hOfflineTalkIcon = ImageList_GetIcon(hList, index, ILD_TRANSPARENT | INDEXTOOVERLAYMASK(1)); ImageList_Destroy(hList); }
int PreBuildContactMenu(WPARAM hContact, LPARAM) { char *szProto = GetContactProto(hContact); int iMode = szProto ? CallProtoService(szProto, PS_GETSTATUS, 0, 0) : 0; int Flag1 = szProto ? CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) : 0; int iContactMode = db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE); TCHAR szSetStr[256], szReadStr[256]; szSetStr[0] = szReadStr[0] = 0; HICON hReadMsgIcon = NULL; if (szProto) { int i; for (i = _countof(StatusModeList) - 1; i >= 0; i--) if (iMode == StatusModeList[i].Status) break; // the protocol supports status message sending for current status, or autoreplying if ((Flag1 & PF1_MODEMSGSEND && CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(iMode)) || ((Flag1 & PF1_IM) == PF1_IM && (i < 0 || !g_AutoreplyOptPage.GetDBValueCopy(StatusModeList[i].DisableReplyCtlID)))) mir_sntprintf(szSetStr, TranslateT("Set %s message for the contact"), pcli->pfnGetStatusModeDescription(iMode, 0), pcli->pfnGetContactDisplayName(hContact, 0)); // the protocol supports status message reading for contact's status if (Flag1 & PF1_MODEMSGRECV && CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(iContactMode)) { mir_sntprintf(szReadStr, TranslateT("Re&ad %s message"), pcli->pfnGetStatusModeDescription(iContactMode, 0)); hReadMsgIcon = Skin_LoadProtoIcon(szProto, iContactMode); } } if (g_hContactMenuItem) { if (szSetStr[0] == 0) Menu_ShowItem(g_hContactMenuItem, false); else Menu_ModifyItem(g_hContactMenuItem, szSetStr, iconList[8].hIcolib, 0); // if this contact supports sending/receiving messages if ((Flag1 & PF1_IM) == PF1_IM) { int iAutoreply = CContactSettings(g_ProtoStates[szProto].m_status, hContact).Autoreply; HANDLE hIcon; switch (iAutoreply) { case VAL_USEDEFAULT: hIcon = Skin_LoadIcon(IDI_DOT); break; case 0: hIcon = iconList[0].hIcolib; break; default: iAutoreply = 1; hIcon = iconList[1].hIcolib; break; } Menu_ModifyItem(g_hToggleSOEContactMenuItem, NULL, hIcon, 0); Menu_ModifyItem(g_hAutoreplyOnContactMenuItem, NULL, iconList[1].hIcolib, (iAutoreply == 1) ? CMIF_CHECKED : 0); Menu_ModifyItem(g_hAutoreplyOffContactMenuItem, NULL, iconList[0].hIcolib, (iAutoreply == 0) ? CMIF_CHECKED : 0); Menu_ModifyItem(g_hAutoreplyUseDefaultContactMenuItem, NULL, iconList[5].hIcolib, (iAutoreply == VAL_USEDEFAULT) ? CMIF_CHECKED : 0); } else // hide the Autoreply menu item Menu_ShowItem(g_hToggleSOEContactMenuItem, false); } if (szReadStr[0] == 0) Menu_ShowItem(g_hReadStatMenuItem, false); else Menu_ModifyItem(g_hReadStatMenuItem, szReadStr, hReadMsgIcon, 0); return 0; }
MIR_APP_DLL(void) ProtoConstructor(PROTO_INTERFACE *pThis, LPCSTR pszModuleName, LPCTSTR ptszUserName) { pThis->m_iVersion = 2; pThis->m_iStatus = pThis->m_iDesiredStatus = ID_STATUS_OFFLINE; pThis->m_szModuleName = mir_strdup(pszModuleName); pThis->m_hProtoIcon = IcoLib_IsManaged(Skin_LoadProtoIcon(pszModuleName, ID_STATUS_ONLINE)); pThis->m_tszUserName = mir_tstrdup(ptszUserName); db_set_resident(pThis->m_szModuleName, "Status"); }
MIR_APP_DLL(HICON) Skin_LoadIcon(int idx, bool big) { // Query for global status icons if (idx < SKINICON_EVENT_MESSAGE) { if (idx >= _countof(statusIcons)) return NULL; return Skin_LoadProtoIcon(NULL, statusIcons[idx].id, big); } return IcoLib_GetIconByHandle(Skin_GetIconHandle(idx), big); }
CJabberProto* JabberChooseInstance(bool bIsLink) { if (g_Instances.getCount() == 0) return NULL; if (g_Instances.getCount() == 1) { if (g_Instances[0]->m_iStatus != ID_STATUS_OFFLINE && g_Instances[0]->m_iStatus != ID_STATUS_CONNECTING) return g_Instances[0]; return NULL; } if (bIsLink) for (int i = 0; i < g_Instances.getCount(); i++) if (g_Instances[i]->m_options.ProcessXMPPLinks) return g_Instances[i]; int nItems = 0, lastItemId = 0; for (int i = 0; i < g_Instances.getCount(); i++) { CJabberProto *ppro = g_Instances[i]; if (ppro->m_iStatus != ID_STATUS_OFFLINE && ppro->m_iStatus != ID_STATUS_CONNECTING) { ++nItems; lastItemId = i + 1; Menu_ModifyItem(ppro->m_hChooseMenuItem, NULL, Skin_LoadProtoIcon(ppro->m_szModuleName, ppro->m_iStatus)); } else Menu_ShowItem(ppro->m_hChooseMenuItem, false); } if (nItems > 1) { POINT pt; GetCursorPos(&pt); HMENU hMenu = CreatePopupMenu(); Menu_Build(hMenu, hChooserMenu); int res = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, pcli->hwndContactList, NULL); DestroyMenu(hMenu); if (res) { CJabberProto* pro = NULL; Menu_ProcessCommandById(res, (LPARAM)&pro); return pro; } return NULL; } return lastItemId ? g_Instances[lastItemId - 1] : NULL; }
/** * retrieve the tab/title icon for the corresponding session. */ HICON CContactCache::getIcon(int& iSize) const { if (!m_dat || !m_hwnd) return Skin_LoadProtoIcon(cc->szProto, m_wStatus); if (m_dat->dwFlags & MWF_ERRORSTATE) return PluginConfig.g_iconErr; if (m_dat->mayFlashTab) return m_dat->iFlashIcon; if (m_dat->si && m_dat->iFlashIcon) { int sizeX, sizeY; Utils::getIconSize(m_dat->iFlashIcon, sizeX, sizeY); iSize = sizeX; return m_dat->iFlashIcon; } if (m_dat->hTabIcon == m_dat->hTabStatusIcon && m_dat->hXStatusIcon) return m_dat->hXStatusIcon; return m_dat->hTabIcon; }
static int AwayMsgPreBuildMenu(WPARAM hContact, LPARAM lParam) { TCHAR str[128]; char *szProto = GetContactProto(hContact); int iHidden = szProto ? db_get_b(hContact, szProto, "ChatRoom", 0) : 0; int iStatus; if (!iHidden) { iHidden = 1; iStatus = db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE); if (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGRECV) { if (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(iStatus == ID_STATUS_OFFLINE ? ID_STATUS_INVISIBLE : iStatus)) { iHidden = 0; HICON hIcon = Skin_LoadProtoIcon(szProto, iStatus); mir_sntprintf(str, _countof(str), TranslateT("Re&ad %s message"), pcli->pfnGetStatusModeDescription(iStatus, 0)); Menu_ModifyItem(hAwayMsgMenuItem, str, hIcon, 0); IcoLib_ReleaseIcon(hIcon); } } } else Menu_ShowItem(hAwayMsgMenuItem, false); ptrA szMsg(db_get_sa(hContact, "CList", "StatusMsg")); if (!iHidden && szMsg != NULL) { mir_sntprintf(str, _countof(str), TranslateT("Copy %s message"), pcli->pfnGetStatusModeDescription(iStatus, 0)); Menu_ModifyItem(hCopyMsgMenuItem, str); } else Menu_ShowItem(hCopyMsgMenuItem, false); if (!iHidden && szMsg != NULL && StrFindURL(szMsg) != NULL) { mir_sntprintf(str, _countof(str), TranslateT("&Go to URL in %s message"), pcli->pfnGetStatusModeDescription(iStatus, 0)); Menu_ModifyItem(hGoToURLMenuItem, str); } else Menu_ShowItem(hGoToURLMenuItem, false); return 0; }
void ShowPopup(MCONTACT hcontact, const char * lpzProto, int newStatus) { if (CallService(MS_IGNORE_ISIGNORED, (WPARAM)hcontact, IGNOREEVENT_USERONLINE)) return; if (!ServiceExists(MS_POPUP_QUERY)) return; if (!db_get_b(NULL, S_MOD, "UsePopups", 0) || !db_get_b(hcontact, "CList", "Hidden", 0)) return; DBVARIANT dbv; char szSetting[10]; mir_snprintf(szSetting, "Col_%d", newStatus - ID_STATUS_OFFLINE); DWORD sett = db_get_dw(NULL, S_MOD, szSetting, StatusColors15bits[newStatus - ID_STATUS_OFFLINE]); POPUPDATAT ppd = { 0 }; GetColorsFromDWord(&ppd.colorBack, &ppd.colorText, sett); ppd.lchContact = hcontact; ppd.lchIcon = Skin_LoadProtoIcon(lpzProto, newStatus); if (!db_get_ts(NULL, S_MOD, "PopupStamp", &dbv)) { _tcsncpy(ppd.lptzContactName, ParseString(dbv.ptszVal, hcontact), MAX_CONTACTNAME); db_free(&dbv); } else _tcsncpy(ppd.lptzContactName, ParseString(DEFAULT_POPUPSTAMP, hcontact), MAX_CONTACTNAME); if (!db_get_ts(NULL, S_MOD, "PopupStampText", &dbv)) { _tcsncpy(ppd.lptzText, ParseString(dbv.ptszVal, hcontact), MAX_SECONDLINE); db_free(&dbv); } else _tcsncpy(ppd.lptzText, ParseString(DEFAULT_POPUPSTAMPTEXT, hcontact), MAX_SECONDLINE); ppd.PluginWindowProc = PopupDlgProc; PUAddPopupT(&ppd); }
int ProcessStatusMessage(DBCONTACTWRITESETTING *cws, MCONTACT hContact) { STATUSMSGINFO smi; bool bEnablePopup = true, bEnableSound = true; char *szProto = GetContactProto(hContact); smi.proto = szProto; smi.hContact = hContact; smi.compare = CompareStatusMsg(&smi, cws, "LastStatusMsg"); if (smi.compare == COMPARE_SAME) goto skip_notify; if (cws->value.type == DBVT_DELETED) db_unset(hContact, "UserOnline", "LastStatusMsg"); else db_set(hContact, "UserOnline", "LastStatusMsg", &cws->value); //don't show popup when mradio connecting and disconnecting if (_stricmp(szProto, "mRadio") == 0 && !cws->value.type == DBVT_DELETED) { wchar_t buf[MAX_PATH]; mir_snwprintf(buf, L" (%s)", TranslateT("connecting")); T2Utf pszUtf(buf); mir_snwprintf(buf, L" (%s)", TranslateT("aborting")); T2Utf pszUtf2(buf); mir_snwprintf(buf, L" (%s)", TranslateT("playing")); T2Utf pszUtf3(buf); if (_stricmp(cws->value.pszVal, pszUtf) == 0 || _stricmp(cws->value.pszVal, pszUtf2) == 0 || _stricmp(cws->value.pszVal, pszUtf3) == 0) goto skip_notify; } // check per-contact ignored events if (db_get_b(hContact, MODULE, "EnableSMsgNotify", 1) == 0) bEnableSound = bEnablePopup = false; // we're offline or just connecting int myStatus = Proto_GetStatus(szProto); if (myStatus == ID_STATUS_OFFLINE) goto skip_notify; char dbSetting[64]; mir_snprintf(dbSetting, "%s_enabled", szProto); // this proto is not set for status message notifications if (db_get_b(NULL, MODULE, dbSetting, 1) == 0) goto skip_notify; mir_snprintf(dbSetting, "%d", IDC_CHK_STATUS_MESSAGE); // status message change notifications are disabled if (db_get_b(NULL, MODULE, dbSetting, 1) == 0) goto skip_notify; if (SkipHiddenContact(hContact)) goto skip_notify; // check if our status isn't on 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 : bEnableSound; bEnablePopup = db_get_b(0, MODULE, statusIDp, 1) ? FALSE : bEnablePopup; } // check flags if ((!(templates.PopupSMsgFlags & NOTIFY_REMOVE_MESSAGE) && (smi.compare == COMPARE_DEL)) || (!(templates.PopupSMsgFlags & NOTIFY_NEW_MESSAGE) && (smi.compare == COMPARE_DIFF))) bEnablePopup = false; if (db_get_b(0, MODULE, szProto, 1) == 0 && !opt.PSMsgOnConnect) bEnablePopup = false; if (bEnablePopup && db_get_b(hContact, MODULE, "EnablePopups", 1) && !opt.TempDisabled) { // cut message if needed wchar_t *copyText = nullptr; if (opt.PSMsgTruncate && (opt.PSMsgLen > 0) && smi.newstatusmsg && (mir_wstrlen(smi.newstatusmsg) > opt.PSMsgLen)) { wchar_t buff[MAX_TEXT_LEN + 3]; copyText = mir_wstrdup(smi.newstatusmsg); wcsncpy(buff, smi.newstatusmsg, opt.PSMsgLen); buff[opt.PSMsgLen] = 0; mir_wstrcat(buff, L"..."); replaceStrW(smi.newstatusmsg, buff); } wchar_t *str; if (smi.compare == COMPARE_DEL) { char protoname[MAX_PATH]; mir_snprintf(protoname, "%s_TPopupSMsgRemoved", szProto); DBVARIANT dbVar = { 0 }; if (db_get_ws(NULL, MODULE, protoname, &dbVar)) { str = GetStr(&smi, DEFAULT_POPUP_SMSGREMOVED); } else { str = GetStr(&smi, dbVar.ptszVal); db_free(&dbVar); } } else { char protoname[MAX_PATH]; mir_snprintf(protoname, "%s_TPopupSMsgChanged", szProto); DBVARIANT dbVar = { 0 }; if (db_get_ws(NULL, MODULE, protoname, &dbVar)) { str = GetStr(&smi, DEFAULT_POPUP_SMSGCHANGED); } else { str = GetStr(&smi, dbVar.ptszVal); db_free(&dbVar); } } ShowChangePopup(hContact, Skin_LoadProtoIcon(szProto, db_get_w(hContact, szProto, "Status", ID_STATUS_ONLINE)), ID_STATUS_STATUSMSG, str); mir_free(str); if (copyText) { mir_free(smi.newstatusmsg); smi.newstatusmsg = copyText; } } if (opt.BlinkIcon && opt.BlinkIcon_ForMsgs && !opt.TempDisabled) { HICON hIcon = opt.BlinkIcon_Status ? Skin_LoadProtoIcon(szProto, db_get_w(hContact, szProto, "Status", ID_STATUS_ONLINE)) : Skin_LoadIcon(SKINICON_OTHER_USERONLINE); wchar_t str[256]; mir_snwprintf(str, TranslateT("%s changed status message to %s"), Clist_GetContactDisplayName(hContact), smi.newstatusmsg); BlinkIcon(hContact, hIcon, str); } if (bEnableSound && db_get_b(0, "Skin", "UseSound", TRUE) && db_get_b(hContact, MODULE, "EnableSounds", 1) && !opt.TempDisabled) { if (smi.compare == COMPARE_DEL) PlayChangeSound(hContact, StatusListEx[ID_STATUS_SMSGREMOVED].lpzSkinSoundName); else PlayChangeSound(hContact, StatusListEx[ID_STATUS_SMSGCHANGED].lpzSkinSoundName); } BOOL bEnableLog = opt.SMsgLogToDB && db_get_b(hContact, MODULE, "EnableSMsgLogging", 1); if (bEnableLog && (!opt.SMsgLogToDB_WinOpen || CheckMsgWnd(hContact))) LogSMsgToDB(&smi, smi.compare == COMPARE_DEL ? templates.LogSMsgRemoved : templates.LogSMsgChanged); if (opt.SMsgLogToFile && db_get_b(hContact, MODULE, "EnableSMsgLogging", 1)) { 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)); wchar_t *str; if (smi.compare == COMPARE_DEL) str = GetStr(&smi, templates.LogSMsgRemoved); else str = GetStr(&smi, templates.LogSMsgChanged); mir_snwprintf(stzText, L"%s, %s. %s %s\r\n", stzDate, stzTime, Clist_GetContactDisplayName(hContact), str); LogToFile(stzText); mir_free(str); } skip_notify: replaceStrW(smi.newstatusmsg, nullptr); replaceStrW(smi.oldstatusmsg, nullptr); return 1; }
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; }
/* * add a contact to recent or favorites menu * mode = 1, add * mode = 0, only modify it.. * hMenu specifies the menu handle (the menus are identical...) * cares about updating the menu entry. It sets the hIcon (proto status icon) in * dwItemData of the the menu entry, so that the WM_DRAWITEM handler can retrieve it * w/o costly service calls. * * Also, the function does housekeeping on the Recent Sessions menu to enforce the * maximum number of allowed entries (20 at the moment). The oldest (topmost) entry * is deleted, if necessary. */ void TSAPI AddContactToFavorites(MCONTACT hContact, const TCHAR *szNickname, const char *szProto, TCHAR *szStatus, WORD wStatus, HICON hIcon, BOOL mode, HMENU hMenu) { TCHAR szMenuEntry[80]; TCHAR szFinalNick[100]; if (szNickname == NULL) _tcsncpy_s(szFinalNick, pcli->pfnGetContactDisplayName(hContact, 0), _TRUNCATE); else _tcsncpy_s(szFinalNick, szNickname, _TRUNCATE); if (szProto == NULL) szProto = GetContactProto(hContact); if (szProto) { if (wStatus == 0) wStatus = db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE); if (szStatus == NULL) szStatus = pcli->pfnGetStatusModeDescription(wStatus, 0); } else return; if (hIcon == 0) hIcon = Skin_LoadProtoIcon(szProto, wStatus); PROTOACCOUNT *acc = Proto_GetAccount(szProto); if (acc && acc->tszAccountName) { MENUITEMINFO mii = { 0 }; mii.cbSize = sizeof(mii); mir_sntprintf(szMenuEntry, _T("%s: %s (%s)"), acc->tszAccountName, szFinalNick, szStatus); if (mode) { if (hMenu == PluginConfig.g_hMenuRecent) { if (CheckMenuItem(hMenu, (UINT_PTR)hContact, MF_BYCOMMAND | MF_UNCHECKED) == 0) { DeleteMenu(hMenu, (UINT_PTR)hContact, MF_BYCOMMAND); goto addnew; // move to the end of the menu... } if (GetMenuItemCount(PluginConfig.g_hMenuRecent) > nen_options.wMaxRecent) { // throw out oldest entry in the recent menu... UINT uid = GetMenuItemID(hMenu, 0); if (uid) { DeleteMenu(hMenu, (UINT_PTR)0, MF_BYPOSITION); db_set_dw((MCONTACT)uid, SRMSGMOD_T, "isRecent", 0); } } addnew: db_set_dw(hContact, SRMSGMOD_T, "isRecent", time(NULL)); AppendMenu(hMenu, MF_BYCOMMAND, (UINT_PTR)hContact, szMenuEntry); } else if (hMenu == PluginConfig.g_hMenuFavorites) { // insert the item sorted... TCHAR szBuffer[142]; int i, c = GetMenuItemCount(PluginConfig.g_hMenuFavorites); MENUITEMINFO mii2 = { 0 }; mii2.fMask = MIIM_STRING; mii2.cbSize = sizeof(mii2); if (c == 0) InsertMenu(PluginConfig.g_hMenuFavorites, 0, MF_BYPOSITION, (UINT_PTR)hContact, szMenuEntry); else { for (i = 0; i <= c; i++) { mii2.cch = 0; mii2.dwTypeData = NULL; GetMenuItemInfo(PluginConfig.g_hMenuFavorites, i, TRUE, &mii2); mii2.cch++; mii2.dwTypeData = szBuffer; GetMenuItemInfo(PluginConfig.g_hMenuFavorites, i, TRUE, &mii2); if (_tcsncmp((TCHAR*)mii2.dwTypeData, szMenuEntry, 140) > 0 || i == c) { InsertMenu(PluginConfig.g_hMenuFavorites, i, MF_BYPOSITION, (UINT_PTR)hContact, szMenuEntry); break; } } } } } mii.fMask = MIIM_BITMAP | MIIM_DATA; if (!mode) { mii.fMask |= MIIM_STRING; mii.dwTypeData = (LPTSTR)szMenuEntry; mii.cch = (int)mir_tstrlen(szMenuEntry) + 1; } mii.hbmpItem = HBMMENU_CALLBACK; mii.dwItemData = (ULONG_PTR)hIcon; SetMenuItemInfo(hMenu, (UINT)hContact, FALSE, &mii); } }
static int CListIconsChanged(WPARAM, LPARAM) { for (int i = 0; i < _countof(statusModeList); i++) ImageList_ReplaceIcon_IconLibLoaded(hCListImages, i + 1, Skin_LoadIcon(skinIconStatusList[i])); ImageList_ReplaceIcon_IconLibLoaded(hCListImages, IMAGE_GROUPOPEN, Skin_LoadIcon(SKINICON_OTHER_GROUPOPEN)); ImageList_ReplaceIcon_IconLibLoaded(hCListImages, IMAGE_GROUPSHUT, Skin_LoadIcon(SKINICON_OTHER_GROUPSHUT)); for (int i = 0; i < protoIconIndex.getCount(); i++) for (int j = 0; j < _countof(statusModeList); j++) ImageList_ReplaceIcon_IconLibLoaded(hCListImages, protoIconIndex[i].iIconBase + j, Skin_LoadProtoIcon(protoIconIndex[i].szProto, statusModeList[j])); cli.pfnTrayIconIconsChanged(); cli.pfnInvalidateRect(cli.hwndContactList, NULL, TRUE); return 0; }
static INT_PTR CALLBACK ReadAwayMsgDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { AwayMsgDlgData *dat = (AwayMsgDlgData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (message) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); dat = (AwayMsgDlgData *)mir_alloc(sizeof(AwayMsgDlgData)); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); dat->hContact = lParam; dat->hSeq = (HANDLE)CallContactService(dat->hContact, PSS_GETAWAYMSG, 0, 0); dat->hAwayMsgEvent = dat->hSeq ? HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_AWAYMSG) : NULL; WindowList_Add(hWindowList, hwndDlg, dat->hContact); { TCHAR str[256], format[128]; TCHAR *contactName = (TCHAR *)pcli->pfnGetContactDisplayName(dat->hContact, 0); char *szProto = GetContactProto(dat->hContact); WORD dwStatus = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_OFFLINE); TCHAR *status = pcli->pfnGetStatusModeDescription(dwStatus, 0); GetWindowText(hwndDlg, format, _countof(format)); mir_sntprintf(str, _countof(str), format, status, contactName); SetWindowText(hwndDlg, str); if (dat->hSeq) { GetDlgItemText(hwndDlg, IDC_RETRIEVING, format, _countof(format)); mir_sntprintf(str, _countof(str), format, status); } else { mir_sntprintf(str, _countof(str), TranslateT("Failed to retrieve %s message."), status); SetDlgItemText(hwndDlg, IDOK, TranslateT("&Close")); } SetDlgItemText(hwndDlg, IDC_RETRIEVING, str); SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_LoadProtoIcon(szProto, dwStatus)); SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)Skin_LoadProtoIcon(szProto, dwStatus)); EnableWindow(GetDlgItem(hwndDlg, IDC_COPY), FALSE); } Utils_RestoreWindowPosition(hwndDlg, lParam, "SRAway", "AwayMsgDlg"); return TRUE; case HM_AWAYMSG: { ACKDATA *ack = (ACKDATA *)lParam; if (ack->hContact != dat->hContact || ack->type != ACKTYPE_AWAYMSG) break; if (ack->result != ACKRESULT_SUCCESS) break; if (dat->hAwayMsgEvent && ack->hProcess == dat->hSeq) { UnhookEvent(dat->hAwayMsgEvent); dat->hAwayMsgEvent = NULL; } TCHAR *tszMsg = StrNormNewline((TCHAR *)ack->lParam); SetDlgItemText(hwndDlg, IDC_MSG, tszMsg); mir_free(tszMsg); if (ack->lParam && *((char *)ack->lParam) != '\0') EnableWindow(GetDlgItem(hwndDlg, IDC_COPY), TRUE); ShowWindow(GetDlgItem(hwndDlg, IDC_RETRIEVING), SW_HIDE); ShowWindow(GetDlgItem(hwndDlg, IDC_MSG), SW_SHOW); SetDlgItemText(hwndDlg, IDOK, TranslateT("&Close")); break; } case WM_COMMAND: switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_COPY: if (!OpenClipboard(hwndDlg)) break; if (EmptyClipboard()) { TCHAR msg[1024]; int len = GetDlgItemText(hwndDlg, IDC_MSG, msg, _countof(msg)); if (len) { LPTSTR lptstrCopy; HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(TCHAR)); if (hglbCopy == NULL) { CloseClipboard(); break; } lptstrCopy = (LPTSTR)GlobalLock(hglbCopy); memcpy(lptstrCopy, msg, len * sizeof(TCHAR)); lptstrCopy[len] = (TCHAR)0; GlobalUnlock(hglbCopy); SetClipboardData(CF_UNICODETEXT, hglbCopy); } } CloseClipboard(); break; } break; case WM_CLOSE: DestroyWindow(hwndDlg); break; case WM_DESTROY: if (dat->hAwayMsgEvent) UnhookEvent(dat->hAwayMsgEvent); Utils_SaveWindowPosition(hwndDlg, dat->hContact, "SRAway", "AwayMsgDlg"); WindowList_Remove(hWindowList, hwndDlg); IcoLib_ReleaseIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, NULL)); IcoLib_ReleaseIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, NULL)); mir_free(dat); break; } return FALSE; }
static void OnCreateModule(MODULEINFO *mi) { LoadModuleIcons(mi); mi->hOnlineIconBig = Skin_LoadProtoIcon(mi->pszModule, ID_STATUS_ONLINE, true); mi->hOfflineIconBig = Skin_LoadProtoIcon(mi->pszModule, ID_STATUS_OFFLINE, true); }
INT_PTR CALLBACK DlgProcFileTransfer(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { FileDlgData *dat = (FileDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); dat = (FileDlgData*)lParam; SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); dat->hNotifyEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_RECVEVENT); dat->transferStatus.currentFileNumber = -1; if (dat->send) { if (db_mc_isMeta(dat->hContact)) dat->hContact = db_mc_getMostOnline(dat->hContact); dat->fs = (HANDLE)CallContactService(dat->hContact, PSS_FILE, (WPARAM)dat->szMsg, (LPARAM)dat->files); SetFtStatus(hwndDlg, LPGENT("Request sent, waiting for acceptance..."), FTS_TEXT); SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1); dat->waitingForAcceptance = 1; // hide "open" button since it may cause potential access violations... ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFILE), SW_HIDE); ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFOLDER), SW_HIDE); } else { //recv CreateDirectoryTreeT(dat->szSavePath); dat->fs = (HANDLE)CallContactService(dat->hContact, PSS_FILEALLOW, (WPARAM)dat->fs, (LPARAM)dat->szSavePath); dat->transferStatus.tszWorkingDir = mir_tstrdup(dat->szSavePath); if (db_get_b(dat->hContact, "CList", "NotOnList", 0)) dat->resumeBehaviour = FILERESUME_ASK; else dat->resumeBehaviour = db_get_b(NULL, "SRFile", "IfExists", FILERESUME_ASK); SetFtStatus(hwndDlg, LPGENT("Waiting for connection..."), FTS_TEXT); } /* check we actually got an fs handle back from the protocol */ if (!dat->fs) { SetFtStatus(hwndDlg, LPGENT("Unable to initiate transfer."), FTS_TEXT); dat->waitingForAcceptance = 0; } { LOGFONT lf; HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0); GetObject(hFont, sizeof(lf), &lf); lf.lfWeight = FW_BOLD; hFont = CreateFontIndirect(&lf); SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_SETFONT, (WPARAM)hFont, 0); SHFILEINFO shfi = { 0 }; SHGetFileInfo(_T(""), FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON); dat->hIconFolder = shfi.hIcon; } dat->hIcon = NULL; { char *szProto = GetContactProto(dat->hContact); WORD status = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_ONLINE); SendDlgItemMessage(hwndDlg, IDC_CONTACT, BM_SETIMAGE, IMAGE_ICON, (LPARAM)Skin_LoadProtoIcon(szProto, status)); } SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Contact menu"), 0); SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONSETASFLATBTN, TRUE, 0); Button_SetIcon_IcoLib(hwndDlg, IDC_OPENFILE, SKINICON_OTHER_DOWNARROW, LPGEN("Open...")); SendDlgItemMessage(hwndDlg, IDC_OPENFILE, BUTTONSETASPUSHBTN, TRUE, 0); SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BM_SETIMAGE, IMAGE_ICON, (LPARAM)dat->hIconFolder); SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Open folder"), 0); SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BUTTONSETASFLATBTN, TRUE, 0); Button_SetIcon_IcoLib(hwndDlg, IDCANCEL, SKINICON_OTHER_DELETE, LPGEN("Cancel")); SetDlgItemText(hwndDlg, IDC_CONTACTNAME, pcli->pfnGetContactDisplayName(dat->hContact, 0)); if (!dat->waitingForAcceptance) SetTimer(hwndDlg, 1, 1000, NULL); return TRUE; case WM_TIMER: memmove(dat->bytesRecvedHistory + 1, dat->bytesRecvedHistory, sizeof(dat->bytesRecvedHistory) - sizeof(dat->bytesRecvedHistory[0])); dat->bytesRecvedHistory[0] = dat->transferStatus.totalProgress; if (dat->bytesRecvedHistorySize < _countof(dat->bytesRecvedHistory)) dat->bytesRecvedHistorySize++; { TCHAR szSpeed[32], szTime[32], szDisplay[96]; SYSTEMTIME st; ULARGE_INTEGER li; FILETIME ft; GetSensiblyFormattedSize((dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) / dat->bytesRecvedHistorySize, szSpeed, _countof(szSpeed), 0, 1, NULL); if (dat->bytesRecvedHistory[0] == dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) mir_tstrcpy(szTime, _T("??:??:??")); else { li.QuadPart = BIGI(10000000)*(dat->transferStatus.currentFileSize - dat->transferStatus.currentFileProgress)*dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]); ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart; FileTimeToSystemTime(&ft, &st); GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, _countof(szTime)); } if (dat->bytesRecvedHistory[0] != dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) { li.QuadPart = BIGI(10000000)*(dat->transferStatus.totalBytes - dat->transferStatus.totalProgress)*dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]); ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart; FileTimeToSystemTime(&ft, &st); GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, _countof(szTime)); } mir_sntprintf(szDisplay, _T("%s/%s (%s %s)"), szSpeed, TranslateT("sec"), szTime, TranslateT("remaining")); SetDlgItemText(hwndDlg, IDC_ALLSPEED, szDisplay); } break; case WM_MEASUREITEM: return Menu_MeasureItem((LPMEASUREITEMSTRUCT)lParam); case WM_DRAWITEM: return Menu_DrawItem((LPDRAWITEMSTRUCT)lParam); case WM_FT_CLEANUP: if (!dat->fs) { PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg); DestroyWindow(hwndDlg); } break; case WM_COMMAND: if (!dat) break; if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)dat->hContact)) break; switch (LOWORD(wParam)) { case IDOK: case IDCANCEL: PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg); DestroyWindow(hwndDlg); break; case IDC_CONTACT: { RECT rc; HMENU hMenu = Menu_BuildContactMenu(dat->hContact); GetWindowRect((HWND)lParam, &rc); TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL); DestroyMenu(hMenu); } break; case IDC_TRANSFERCOMPLETED: if (dat->transferStatus.currentFileNumber <= 1 && CheckVirusScanned(hwndDlg, dat, 0)) { ShellExecute(NULL, NULL, dat->files[0], NULL, NULL, SW_SHOW); break; } case IDC_OPENFOLDER: { TCHAR *path = dat->transferStatus.tszWorkingDir; if (!path || !path[0]) { path = NEWTSTR_ALLOCA(dat->transferStatus.tszCurrentFile); TCHAR *p = _tcsrchr(path, '\\'); if (p) *p = 0; } if (path) ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOW); } break; case IDC_OPENFILE: TCHAR **files; if (dat->send) { if (dat->files == NULL) files = dat->transferStatus.ptszFiles; else files = dat->files; } else files = dat->files; HMENU hMenu = CreatePopupMenu(); AppendMenu(hMenu, MF_STRING, 1, TranslateT("Open folder")); AppendMenu(hMenu, MF_SEPARATOR, 0, 0); if (files && *files) { int limit; TCHAR *pszFilename, *pszNewFileName; if (dat->send) limit = dat->transferStatus.totalFiles; else limit = dat->transferStatus.currentFileNumber; // Loop over all transfered files and add them to the menu for (int i = 0; i < limit; i++) { pszFilename = _tcsrchr(files[i], '\\'); if (pszFilename == NULL) pszFilename = files[i]; else pszFilename++; if (pszFilename) { size_t cbFileNameLen = mir_tstrlen(pszFilename); pszNewFileName = (TCHAR*)mir_alloc(cbFileNameLen * 2 * sizeof(TCHAR)); TCHAR *p = pszNewFileName; for (size_t pszlen = 0; pszlen < cbFileNameLen; pszlen++) { *p++ = pszFilename[pszlen]; if (pszFilename[pszlen] == '&') *p++ = '&'; } *p = '\0'; AppendMenu(hMenu, MF_STRING, i + 10, pszNewFileName); mir_free(pszNewFileName); } } } RECT rc; GetWindowRect((HWND)lParam, &rc); CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_CHECKED); int ret = TrackPopupMenu(hMenu, TPM_RETURNCMD | TPM_RIGHTALIGN, rc.right, rc.bottom, 0, hwndDlg, NULL); CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_UNCHECKED); DestroyMenu(hMenu); if (ret == 1) { TCHAR *path = dat->transferStatus.tszWorkingDir; if (!path || !path[0]) { path = NEWTSTR_ALLOCA(dat->transferStatus.tszCurrentFile); TCHAR *p = _tcsrchr(path, '\\'); if (p) *p = 0; } if (path) ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOW); } else if (ret && CheckVirusScanned(hwndDlg, dat, ret)) ShellExecute(NULL, NULL, files[ret - 10], NULL, NULL, SW_SHOW); } break; case M_FILEEXISTSDLGREPLY: EnableWindow(hwndDlg, TRUE); { PROTOFILERESUME *pfr = (PROTOFILERESUME*)lParam; TCHAR *szOriginalFilename = (TCHAR*)wParam; char *szProto = GetContactProto(dat->hContact); switch (pfr->action) { case FILERESUME_CANCEL: if (dat->fs) CallContactService(dat->hContact, PSS_FILECANCEL, (WPARAM)dat->fs, 0); dat->fs = NULL; mir_free(szOriginalFilename); if (pfr->szFilename) mir_free((char*)pfr->szFilename); mir_free(pfr); return 0; case FILERESUME_RESUMEALL: case FILERESUME_OVERWRITEALL: dat->resumeBehaviour = pfr->action; pfr->action &= ~FILERESUMEF_ALL; break; case FILERESUME_RENAMEALL: pfr->action = FILERESUME_RENAME; { TCHAR *pszExtension, *pszFilename; if ((pszFilename = _tcsrchr(szOriginalFilename, '\\')) == NULL) pszFilename = szOriginalFilename; if ((pszExtension = _tcsrchr(pszFilename + 1, '.')) == NULL) pszExtension = pszFilename + mir_tstrlen(pszFilename); if (pfr->szFilename) mir_free((TCHAR*)pfr->szFilename); size_t size = (pszExtension - szOriginalFilename) + 21 + mir_tstrlen(pszExtension); pfr->szFilename = (TCHAR*)mir_alloc(sizeof(TCHAR)*size); for (int i = 1;; i++) { mir_sntprintf((TCHAR*)pfr->szFilename, size, _T("%.*s (%u)%s"), pszExtension - szOriginalFilename, szOriginalFilename, i, pszExtension); if (_taccess(pfr->szFilename, 0) != 0) break; } } break; } mir_free(szOriginalFilename); CallProtoService(szProto, PS_FILERESUME, (WPARAM)dat->fs, (LPARAM)pfr); if (pfr->szFilename) mir_free((char*)pfr->szFilename); mir_free(pfr); } break; case HM_RECVEVENT: { ACKDATA *ack = (ACKDATA*)lParam; if (ack->hProcess != dat->fs) break; if (ack->type != ACKTYPE_FILE) break; if (ack->hContact != dat->hContact) break; if (dat->waitingForAcceptance) { SetTimer(hwndDlg, 1, 1000, NULL); dat->waitingForAcceptance = 0; } switch (ack->result) { case ACKRESULT_SENTREQUEST: SetFtStatus(hwndDlg, LPGENT("Decision sent"), FTS_TEXT); break; case ACKRESULT_CONNECTING: SetFtStatus(hwndDlg, LPGENT("Connecting..."), FTS_TEXT); break; case ACKRESULT_CONNECTPROXY: SetFtStatus(hwndDlg, LPGENT("Connecting to proxy..."), FTS_TEXT); break; case ACKRESULT_CONNECTED: SetFtStatus(hwndDlg, LPGENT("Connected"), FTS_TEXT); break; case ACKRESULT_LISTENING: SetFtStatus(hwndDlg, LPGENT("Waiting for connection..."), FTS_TEXT); break; case ACKRESULT_INITIALISING: SetFtStatus(hwndDlg, LPGENT("Initializing..."), FTS_TEXT); break; case ACKRESULT_NEXTFILE: SetFtStatus(hwndDlg, LPGENT("Moving to next file..."), FTS_TEXT); SetDlgItemTextA(hwndDlg, IDC_FILENAME, ""); if (dat->transferStatus.currentFileNumber == 1 && dat->transferStatus.totalFiles > 1 && !dat->send) SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1); if (dat->transferStatus.currentFileNumber != -1 && dat->files && !dat->send && db_get_b(NULL, "SRFile", "UseScanner", VIRUSSCAN_DISABLE) == VIRUSSCAN_DURINGDL) { if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber])&FILE_ATTRIBUTE_DIRECTORY) PostMessage(hwndDlg, M_VIRUSSCANDONE, dat->transferStatus.currentFileNumber, 0); else { virusscanthreadstartinfo *vstsi; vstsi = (struct virusscanthreadstartinfo*)mir_alloc(sizeof(struct virusscanthreadstartinfo)); vstsi->hwndReply = hwndDlg; vstsi->szFile = mir_tstrdup(dat->files[dat->transferStatus.currentFileNumber]); vstsi->returnCode = dat->transferStatus.currentFileNumber; forkthread((void(*)(void*))RunVirusScannerThread, 0, vstsi); } } break; case ACKRESULT_FILERESUME: UpdateProtoFileTransferStatus(&dat->transferStatus, (PROTOFILETRANSFERSTATUS*)ack->lParam); { PROTOFILETRANSFERSTATUS *fts = &dat->transferStatus; SetFilenameControls(hwndDlg, dat, fts); if (_taccess(fts->tszCurrentFile, 0)) break; SetFtStatus(hwndDlg, LPGENT("File already exists"), FTS_TEXT); if (dat->resumeBehaviour == FILERESUME_ASK) { TDlgProcFileExistsParam param = { hwndDlg, fts }; ShowWindow(hwndDlg, SW_SHOWNORMAL); CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_FILEEXISTS), hwndDlg, DlgProcFileExists, (LPARAM)¶m); EnableWindow(hwndDlg, FALSE); } else { PROTOFILERESUME *pfr = (PROTOFILERESUME*)mir_alloc(sizeof(PROTOFILERESUME)); pfr->action = dat->resumeBehaviour; pfr->szFilename = NULL; PostMessage(hwndDlg, M_FILEEXISTSDLGREPLY, (WPARAM)mir_tstrdup(fts->tszCurrentFile), (LPARAM)pfr); } } SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1); return TRUE; case ACKRESULT_DATA: { PROTOFILETRANSFERSTATUS *fts = (PROTOFILETRANSFERSTATUS*)ack->lParam; TCHAR str[64], str2[64], szSizeDone[32], szSizeTotal[32];//, *contactName; if (dat->fileVirusScanned == NULL) dat->fileVirusScanned = (int*)mir_calloc(sizeof(int) * fts->totalFiles); // This needs to be here - otherwise we get holes in the files array if (!dat->send) { if (dat->files == NULL) dat->files = (TCHAR**)mir_calloc((fts->totalFiles + 1) * sizeof(TCHAR*)); if (fts->currentFileNumber < fts->totalFiles && dat->files[fts->currentFileNumber] == NULL) dat->files[fts->currentFileNumber] = PFTS_StringToTchar(fts->flags, fts->tszCurrentFile); } /* HACK: for 0.3.3, limit updates to around 1.1 ack per second */ if (fts->totalProgress != fts->totalBytes && GetTickCount() < (dat->dwTicks + 650)) break; // the last update was less than a second ago! dat->dwTicks = GetTickCount(); // Update local transfer status with data from protocol UpdateProtoFileTransferStatus(&dat->transferStatus, fts); fts = &dat->transferStatus; bool firstTime = false; if ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), GWL_STYLE) & WS_VISIBLE) == 0) { SetFtStatus(hwndDlg, (fts->flags & PFTS_SENDING) ? LPGENT("Sending...") : LPGENT("Receiving..."), FTS_PROGRESS); SetFilenameControls(hwndDlg, dat, fts); firstTime = true; } const unsigned long lastPos = SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_GETPOS, 0, 0); const unsigned long nextPos = fts->totalBytes ? (BIGI(100) * fts->totalProgress / fts->totalBytes) : 0; if (lastPos != nextPos || firstTime) { SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_SETPOS, nextPos, 0); mir_sntprintf(str, _T("%u%%"), nextPos); SetDlgItemText(hwndDlg, IDC_ALLPRECENTS, str); } int units; GetSensiblyFormattedSize(fts->totalBytes, szSizeTotal, _countof(szSizeTotal), 0, 1, &units); GetSensiblyFormattedSize(fts->totalProgress, szSizeDone, _countof(szSizeDone), units, 0, NULL); mir_sntprintf(str, _T("%s/%s"), szSizeDone, szSizeTotal); str2[0] = 0; GetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str2, _countof(str2)); if (mir_tstrcmp(str, str2)) SetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str); } break; case ACKRESULT_SUCCESS: case ACKRESULT_FAILED: case ACKRESULT_DENIED: HideProgressControls(hwndDlg); KillTimer(hwndDlg, 1); if (!dat->send) SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1); SetDlgItemText(hwndDlg, IDCANCEL, TranslateT("Close")); if (dat->hNotifyEvent) UnhookEvent(dat->hNotifyEvent); dat->hNotifyEvent = NULL; if (ack->result == ACKRESULT_DENIED) { dat->fs = NULL; /* protocol will free structure */ SkinPlaySound("FileDenied"); SetFtStatus(hwndDlg, LPGENT("File transfer denied"), FTS_TEXT); } else if (ack->result == ACKRESULT_FAILED) { dat->fs = NULL; /* protocol will free structure */ SkinPlaySound("FileFailed"); SetFtStatus(hwndDlg, LPGENT("File transfer failed"), FTS_TEXT); } else { SkinPlaySound("FileDone"); if (dat->send) { dat->fs = NULL; /* protocol will free structure */ SetFtStatus(hwndDlg, LPGENT("Transfer completed."), FTS_TEXT); DBEVENTINFO dbei = { 0 }; FillSendData(dat, dbei); db_event_add(dat->hContact, &dbei); if (dbei.pBlob) mir_free(dbei.pBlob); dat->files = NULL; //protocol library frees this } else { SetFtStatus(hwndDlg, (dat->transferStatus.totalFiles == 1) ? LPGENT("Transfer completed, open file.") : LPGENT("Transfer completed, open folder."), FTS_OPEN); int useScanner = db_get_b(NULL, "SRFile", "UseScanner", VIRUSSCAN_DISABLE); if (useScanner != VIRUSSCAN_DISABLE) { struct virusscanthreadstartinfo *vstsi; vstsi = (struct virusscanthreadstartinfo*)mir_alloc(sizeof(struct virusscanthreadstartinfo)); vstsi->hwndReply = hwndDlg; if (useScanner == VIRUSSCAN_DURINGDL) { vstsi->returnCode = dat->transferStatus.currentFileNumber; if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber])&FILE_ATTRIBUTE_DIRECTORY) { PostMessage(hwndDlg, M_VIRUSSCANDONE, vstsi->returnCode, 0); mir_free(vstsi); vstsi = NULL; } else vstsi->szFile = mir_tstrdup(dat->files[dat->transferStatus.currentFileNumber]); } else { vstsi->szFile = mir_tstrdup(dat->transferStatus.tszWorkingDir); vstsi->returnCode = -1; } SetFtStatus(hwndDlg, LPGENT("Scanning for viruses..."), FTS_TEXT); if (vstsi) forkthread((void(*)(void*))RunVirusScannerThread, 0, vstsi); } else dat->fs = NULL; /* protocol will free structure */ dat->transferStatus.currentFileNumber = dat->transferStatus.totalFiles; } // else dat->send } // else ack->result PostMessage(GetParent(hwndDlg), WM_FT_COMPLETED, ack->result, (LPARAM)hwndDlg); break; } // switch ack->result } // case HM_RECVEVENT break; case M_VIRUSSCANDONE: { int done = 1; if ((int)wParam == -1) { for (int i = 0; i < dat->transferStatus.totalFiles; i++) dat->fileVirusScanned[i] = 1; } else { dat->fileVirusScanned[wParam] = 1; for (int i = 0; i < dat->transferStatus.totalFiles; i++) if (!dat->fileVirusScanned[i]) { done = 0; break; } } if (done) { dat->fs = NULL; /* protocol will free structure */ SetFtStatus(hwndDlg, LPGENT("Transfer and virus scan complete"), FTS_TEXT); } } break; case WM_SIZE: Utils_ResizeDialog(hwndDlg, hInst, MAKEINTRESOURCEA(IDD_FILETRANSFERINFO), FileTransferDlgResizer); RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); RedrawWindow(GetDlgItem(hwndDlg, IDC_CONTACTNAME), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); RedrawWindow(GetDlgItem(hwndDlg, IDC_STATUS), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE); break; case WM_DESTROY: KillTimer(hwndDlg, 1); HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0); DeleteObject(hFont); Button_FreeIcon_IcoLib(hwndDlg, IDC_CONTACT); Button_FreeIcon_IcoLib(hwndDlg, IDC_OPENFILE); Button_FreeIcon_IcoLib(hwndDlg, IDCANCEL); FreeFileDlgData(dat); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); break; } return FALSE; }
int CJabberProto::OnPrebuildContactMenu(WPARAM hContact, LPARAM) { if (hContact == NULL) return 0; bool bIsChatRoom = isChatRoom(hContact); bool bIsTransport = getBool(hContact, "IsTransport", false); if ((bIsChatRoom == GCW_CHATROOM) || bIsChatRoom == 0) { if (ptrT(getTStringA(hContact, bIsChatRoom ? (char*)"ChatRoomID" : (char*)"jid")) != NULL) { Menu_ShowItem(g_hMenuConvert, TRUE); Menu_ModifyItem(g_hMenuConvert, bIsChatRoom ? LPGENT("&Convert to Contact") : LPGENT("&Convert to Chat Room")); } } if (!m_bJabberOnline) return 0; Menu_ShowItem(g_hMenuDirectPresence[0], TRUE); for (int i = 0; i < _countof(PresenceModeArray); i++) Menu_ModifyItem(g_hMenuDirectPresence[i + 1], NULL, Skin_LoadProtoIcon(m_szModuleName, PresenceModeArray[i].mode)); if (bIsChatRoom) { ptrT roomid(getTStringA(hContact, "ChatRoomID")); if (roomid != NULL) { Menu_ShowItem(g_hMenuRosterAdd, FALSE); if (ListGetItemPtr(LIST_BOOKMARK, roomid) == NULL) if (m_ThreadInfo && m_ThreadInfo->jabberServerCaps & JABBER_CAPS_PRIVATE_STORAGE) Menu_ShowItem(g_hMenuAddBookmark, TRUE); } } if (bIsChatRoom == GCW_CHATROOM) return 0; if (bIsTransport) { Menu_ShowItem(g_hMenuLogin, TRUE); Menu_ShowItem(g_hMenuRefresh, TRUE); } ptrT jid(getTStringA(hContact, "jid")); if (jid == NULL) return 0; JabberCapsBits jcb = GetTotalJidCapabilites(jid); JABBER_LIST_ITEM *item = ListGetItemPtr(LIST_ROSTER, jid); if (item == NULL) return 0; bool bCtrlPressed = (GetKeyState(VK_CONTROL) & 0x8000) != 0; Menu_ShowItem(g_hMenuRequestAuth, item->subscription == SUB_FROM || item->subscription == SUB_NONE || bCtrlPressed); Menu_ShowItem(g_hMenuGrantAuth, bCtrlPressed); Menu_ShowItem(g_hMenuRevokeAuth, item->subscription == SUB_FROM || item->subscription == SUB_BOTH || bCtrlPressed); Menu_ShowItem(g_hMenuCommands, ((jcb & JABBER_CAPS_COMMANDS) != 0) || bCtrlPressed); Menu_ShowItem(g_hMenuSendNote, TRUE); if (item->arResources.getCount() == 0) return 0; Menu_ShowItem(g_hMenuResourcesRoot, TRUE); Menu_ModifyItem(g_hMenuResourcesRoot, NULL, m_hProtoIcon); Menu_ModifyItem(g_hMenuResourcesActive, NULL, m_hProtoIcon, (item->resourceMode == RSMODE_LASTSEEN) ? CMIF_CHECKED : 0); Menu_ModifyItem(g_hMenuResourcesServer, NULL, m_hProtoIcon, (item->resourceMode == RSMODE_SERVER) ? CMIF_CHECKED : 0); int nMenuResourceItemsNew = m_nMenuResourceItems; if (m_nMenuResourceItems < item->arResources.getCount()) { m_phMenuResourceItems = (HGENMENU*)mir_realloc(m_phMenuResourceItems, item->arResources.getCount() * sizeof(HGENMENU)); nMenuResourceItemsNew = item->arResources.getCount(); } char text[256]; CMenuItem mi; mi.pszService = text; CMString szTmp; for (int i = 0; i < nMenuResourceItemsNew; i++) { mir_snprintf(text, "/UseResource_%d", i); if (i >= m_nMenuResourceItems) { CreateProtoServiceParam(text, &CJabberProto::OnMenuHandleResource, MENUITEM_RESOURCES + i); mi.name.a = ""; mi.position = i; mi.root = g_hMenuResourcesRoot; m_phMenuResourceItems[i] = Menu_AddContactMenuItem(&mi, m_szModuleName); } if (i < item->arResources.getCount()) { pResourceStatus r(item->arResources[i]); HICON hIcon = (HICON)INVALID_HANDLE_VALUE; Menu_SetChecked(m_phMenuResourceItems[i], item->resourceMode == RSMODE_MANUAL && item->m_pManualResource == r); if (ServiceExists(MS_FP_GETCLIENTICONT)) { FormatMirVer(r, szTmp); hIcon = Finger_GetClientIcon(szTmp, 0); } szTmp.Format(_T("%s [%s, %d]"), r->m_tszResourceName, pcli->pfnGetStatusModeDescription(r->m_iStatus, 0), r->m_iPriority); Menu_ModifyItem(m_phMenuResourceItems[i], szTmp, hIcon); DestroyIcon(hIcon); } else Menu_ShowItem(m_phMenuResourceItems[i], FALSE); } m_nMenuResourceItems = nMenuResourceItemsNew; return 0; }
INT_PTR CALLBACK DlgProcOtherStuff(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: TranslateDialogDefault(hwnd); { MCONTACT hContact = (MCONTACT)((PROPSHEETPAGE*)lParam)->lParam; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)hContact); if (!hContact) break; /* link*/ DBVARIANT dbv; if (!db_get_ts(hContact, MODNAME, "ProgramString", &dbv)) { SetDlgItemText(hwnd, IDC_LINK, dbv.ptszVal); db_free(&dbv); } if (!db_get_ts(hContact, MODNAME, "ProgramParamsString", &dbv)) { SetDlgItemText(hwnd, IDC_PARAMS, dbv.ptszVal); db_free(&dbv); } /* group*/ TCHAR *szGroup; for (int i = 1; (szGroup = pcli->pfnGetGroupName(i, NULL)) != NULL; i++) SendDlgItemMessage(hwnd, IDC_GROUP, CB_INSERTSTRING, 0, LPARAM(szGroup)); if (!db_get_ts(hContact, "CList", "Group", &dbv)) { SetDlgItemText(hwnd, IDC_GROUP, dbv.ptszVal); db_free(&dbv); } /* icons */ CheckRadioButton(hwnd, 40072, 40080, db_get_w(hContact, MODNAME, "Icon", ID_STATUS_ONLINE)); SetWindowLongPtr(GetDlgItem(hwnd, CHK_ONLINE), GWLP_USERDATA, (LONG_PTR)Skin_LoadProtoIcon(MODNAME, ID_STATUS_ONLINE)); g_PrevBtnWndProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwnd, CHK_ONLINE), GWLP_WNDPROC, (LONG_PTR)ButtWndProc); for (int i = ID_STATUS_ONLINE; i <= ID_STATUS_OUTTOLUNCH; i++) { SetWindowLongPtr(GetDlgItem(hwnd, i), GWLP_USERDATA, (LONG_PTR)Skin_LoadProtoIcon(MODNAME, i)); SetWindowLongPtr(GetDlgItem(hwnd, i), GWLP_WNDPROC, (LONG_PTR)ButtWndProc); } db_free(&dbv); /* timer */ CheckDlgButton(hwnd, CHK_USE_TIMER, db_get_b(hContact, MODNAME, "UseTimer", 0) ? BST_CHECKED : BST_UNCHECKED); if (db_get_w(hContact, MODNAME, "Timer", 15)) { CheckDlgButton(hwnd, CHK_USE_TIMER, BST_CHECKED); EnableWindow(GetDlgItem(hwnd, IDC_TIMER), 1); TCHAR string[512]; SetDlgItemText(hwnd, IDC_TIMER, _itot(db_get_w(hContact, MODNAME, "Timer", 15), string, 10)); if (!db_get_w(NULL, MODNAME, "Timer", 1)) SetDlgItemText(hwnd, IDC_TIMER_INTERVAL_MSG, TranslateT("Non-IM Contact protocol timer is Disabled")); else { mir_sntprintf(string, TranslateT("Timer intervals... Non-IM Contact Protocol timer is %d seconds"), db_get_w(NULL, MODNAME, "Timer", 1)); SetDlgItemText(hwnd, IDC_TIMER_INTERVAL_MSG, string); } } /* always visible */ if (db_get_b(hContact, MODNAME, "AlwaysVisible", 0)) { CheckDlgButton(hwnd, IDC_ALWAYS_VISIBLE, BST_CHECKED); EnableWindow(GetDlgItem(hwnd, IDC_VISIBLE_UNLESS_OFFLINE), 1); CheckDlgButton(hwnd, IDC_VISIBLE_UNLESS_OFFLINE, db_get_b(hContact, MODNAME, "VisibleUnlessOffline", 1) ? BST_CHECKED : BST_UNCHECKED); } } return TRUE; case WM_COMMAND: SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); switch (LOWORD(wParam)) { case IDC_ALWAYS_VISIBLE: if (IsDlgButtonChecked(hwnd, IDC_ALWAYS_VISIBLE)) { MCONTACT hContact = (MCONTACT)GetWindowLongPtr(hwnd, GWLP_USERDATA); EnableWindow(GetDlgItem(hwnd, IDC_VISIBLE_UNLESS_OFFLINE), 1); CheckDlgButton(hwnd, IDC_VISIBLE_UNLESS_OFFLINE, db_get_b(hContact, MODNAME, "VisibleUnlessOffline", 1) ? BST_CHECKED : BST_UNCHECKED); } else EnableWindow(GetDlgItem(hwnd, IDC_VISIBLE_UNLESS_OFFLINE), 0); break; case CHK_USE_TIMER: if (IsDlgButtonChecked(hwnd, CHK_USE_TIMER)) { MCONTACT hContact = (MCONTACT)GetWindowLongPtr(hwnd, GWLP_USERDATA); char string[4]; EnableWindow(GetDlgItem(hwnd, IDC_TIMER), 1); SetDlgItemTextA(hwnd, IDC_TIMER, _itoa(db_get_w(hContact, MODNAME, "Timer", 15), string, 10)); } else EnableWindow(GetDlgItem(hwnd, IDC_TIMER), 0); break; case IDC_OPEN_FILE: char szFileName[512]; if (Openfile(szFileName, 1)) SetDlgItemTextA(hwnd, IDC_LINK, szFileName); break; case IDC_OPEN_FOLDER: if (BrowseForFolder(hwnd, szFileName)) { mir_snprintf(szFileName, "%s ,/e", szFileName); SetDlgItemTextA(hwnd, IDC_LINK, "explorer.exe"); SetDlgItemTextA(hwnd, IDC_PARAMS, szFileName); } } break; case WM_NOTIFY: switch (((LPNMHDR)lParam)->idFrom) { case 0: switch (((LPNMHDR)lParam)->code) { case PSN_APPLY: int status = GetLCStatus(0, 0); MCONTACT hContact = (MCONTACT)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (GetWindowTextLength(GetDlgItem(hwnd, IDC_LINK))) { char text[512]; GetDlgItemTextA(hwnd, IDC_LINK, text, _countof(text)); db_set_s(hContact, MODNAME, "ProgramString", text); WriteSetting(hContact, MODNAME, "ProgramString", MODNAME, "Program"); } else db_unset(hContact, MODNAME, "ProgramString"); if (GetWindowTextLength(GetDlgItem(hwnd, IDC_PARAMS))) { char text[512]; GetDlgItemTextA(hwnd, IDC_PARAMS, text, _countof(text)); db_set_s(hContact, MODNAME, "ProgramParamsString", text); WriteSetting(hContact, MODNAME, "ProgramParamsString", MODNAME, "ProgramParams"); } else db_unset(hContact, MODNAME, "ProgramParamsString"); if (GetWindowTextLength(GetDlgItem(hwnd, IDC_GROUP))) { TCHAR text[512]; GetDlgItemText(hwnd, IDC_GROUP, text, _countof(text)); Clist_CreateGroup(NULL, text); db_set_ts(hContact, "CList", "Group", text); } else db_unset(hContact, "CList", "Group"); for (int i = ID_STATUS_ONLINE; i <= ID_STATUS_OUTTOLUNCH; i++) if (IsDlgButtonChecked(hwnd, i)) db_set_w(hContact, MODNAME, "Icon", (WORD)i); /* set correct status */ if (status == ID_STATUS_ONLINE || status == ID_STATUS_AWAY || (status == db_get_w(hContact, MODNAME, "Icon", ID_STATUS_ONLINE))) db_set_w(hContact, MODNAME, "Status", (WORD)db_get_w(hContact, MODNAME, "Icon", ID_STATUS_ONLINE)); else db_set_w(hContact, MODNAME, "Status", ID_STATUS_OFFLINE); if (IsDlgButtonChecked(hwnd, CHK_USE_TIMER)) { if (GetWindowTextLength(GetDlgItem(hwnd, IDC_TIMER))) { TCHAR text[512]; GetDlgItemText(hwnd, IDC_TIMER, text, _countof(text)); db_set_w(hContact, MODNAME, "Timer", (WORD)_ttoi(text)); } else db_set_w(hContact, MODNAME, "Timer", 15); } else db_set_w(hContact, MODNAME, "Timer", 0); // always visible db_set_b(hContact, MODNAME, "AlwaysVisible", (BYTE)IsDlgButtonChecked(hwnd, IDC_ALWAYS_VISIBLE)); db_set_b(hContact, MODNAME, "VisibleUnlessOffline", (BYTE)IsDlgButtonChecked(hwnd, IDC_VISIBLE_UNLESS_OFFLINE)); } return TRUE; } break; } return FALSE; }
static LRESULT CALLBACK ParentSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { CMsgTree *dat = CWndUserData(hWnd).GetMsgTree(); switch (Msg) { case WM_NOTIFY: if (((LPNMHDR)lParam)->hwndFrom == dat->hTreeView) { switch (((LPNMHDR)lParam)->code) { case TVN_BEGINDRAG: { LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam; NMMSGTREE nm = { 0 }; COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl(); int Order = TreeCtrl->hItemToOrder(pnmtv->itemNew.hItem); _ASSERT(Order != -1); if (Order != -1) { nm.ItemOld = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order]; nm.hdr.code = MTN_BEGINDRAG; nm.hdr.hwndFrom = dat->hTreeView; nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView); if (!SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm)) { SetCapture(hWnd); dat->hPrevDropTarget = dat->hDragItem = pnmtv->itemNew.hItem; SetFocus(dat->hTreeView); TreeView_SelectItem(dat->hTreeView, dat->hDragItem); } } } break; case TVN_SELCHANGED: if (dat->UpdateLock) return 0; else { LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam; NMMSGTREE nm = { 0 }; COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl(); if (pnmtv->itemOld.hItem) { int Order = TreeCtrl->IDToOrder(pnmtv->itemOld.lParam); if (Order != -1) { nm.ItemOld = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order]; } } if (pnmtv->itemNew.hItem) { int Order = TreeCtrl->IDToOrder(pnmtv->itemNew.lParam); if (Order != -1) { nm.ItemNew = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order]; } } nm.hdr.code = MTN_SELCHANGED; nm.hdr.hwndFrom = dat->hTreeView; nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView); SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm); } break; case TVN_BEGINLABELEDIT: if (dat->GetTreeCtrl()->IDToOrder(((LPNMTVDISPINFO)lParam)->item.lParam) < 0) return true; // cancel editing g_OrigEditProc = (WNDPROC)SetWindowLongPtr(TreeView_GetEditControl(dat->hTreeView), GWLP_WNDPROC, (LONG_PTR)EditSubclassProc); break; case TVN_ENDLABELEDIT: { LPNMTVDISPINFO ptvdi = (LPNMTVDISPINFO)lParam; if (ptvdi->item.pszText) { COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl(); int Order = TreeCtrl->IDToOrder(ptvdi->item.lParam); if (Order >= 0) { TreeCtrl->Value[Order].Title = ptvdi->item.pszText; TreeCtrl->SetModified(true); NMMSGTREE nm = { 0 }; nm.ItemNew = &TreeCtrl->Value[Order]; nm.hdr.code = MTN_ITEMRENAMED; nm.hdr.hwndFrom = dat->hTreeView; nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView); SendMessage(GetParent(dat->hTreeView), WM_NOTIFY, 0, (LPARAM)&nm); return true; // commit new text } } } break; case NM_CLICK: case NM_RCLICK: { TVHITTESTINFO hitTest; hitTest.pt.x = (short)LOWORD(GetMessagePos()); hitTest.pt.y = (short)HIWORD(GetMessagePos()); ScreenToClient(dat->hTreeView, &hitTest.pt); TreeView_HitTest(dat->hTreeView, &hitTest); if (hitTest.hItem) { if (TreeView_GetSelection(dat->hTreeView) == hitTest.hItem) // make sure TVN_SELCHANGED notification is sent always, even if previous selected item was the same as new TreeView_SelectItem(dat->hTreeView, NULL); TreeView_SelectItem(dat->hTreeView, hitTest.hItem); } } break; case NM_CUSTOMDRAW: NMTVCUSTOMDRAW *lpNMCD = (NMTVCUSTOMDRAW*)lParam; switch (lpNMCD->nmcd.dwDrawStage) { case CDDS_PREPAINT: // the control is about to start painting return CDRF_NOTIFYITEMDRAW; // instruct the control to return information when it draws items case CDDS_ITEMPREPAINT: return CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPOSTPAINT: RECT rc; TreeView_GetItemRect(lpNMCD->nmcd.hdr.hwndFrom, (HTREEITEM)lpNMCD->nmcd.dwItemSpec, &rc, true); int iSize = GetSystemMetrics(SM_CXSMICON); int x = rc.left - iSize - 5; for (int i = 0; i < _countof(SettingsList); i++) { if (lpNMCD->nmcd.lItemlParam == dat->MsgTreePage.GetValue(SettingsList[i].DBSetting)) { DrawIconEx(lpNMCD->nmcd.hdc, x, rc.top, Skin_LoadProtoIcon(NULL, SettingsList[i].Status), iSize, iSize, 0, GetSysColorBrush(COLOR_WINDOW), DI_NORMAL); x -= iSize + 1; } } } } } break; case WM_MOUSEMOVE: if (dat->hDragItem) { TVHITTESTINFO hti; hti.pt.x = (short)LOWORD(lParam); hti.pt.y = (short)HIWORD(lParam); ClientToScreen(hWnd, &hti.pt); ScreenToClient(dat->hTreeView, &hti.pt); TreeView_HitTest(dat->hTreeView, &hti); if (hti.hItem) { TreeView_SelectDropTarget(dat->hTreeView, hti.hItem); SetTimer(hWnd, MSGTREE_TIMER_ID, MSGTREE_DRAGANDDROP_GROUPEXPANDTIME, NULL); } else { if (hti.flags & TVHT_ABOVE) SendMessage(dat->hTreeView, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0); if (hti.flags & TVHT_BELOW) SendMessage(dat->hTreeView, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0); TreeView_SelectDropTarget(dat->hTreeView, NULL); KillTimer(hWnd, MSGTREE_TIMER_ID); } } break; case WM_LBUTTONUP: if (dat->hDragItem) { TreeView_SelectDropTarget(dat->hTreeView, NULL); KillTimer(hWnd, MSGTREE_TIMER_ID); ReleaseCapture(); TVHITTESTINFO hti; hti.pt.x = (short)LOWORD(lParam); hti.pt.y = (short)HIWORD(lParam); ClientToScreen(hWnd, &hti.pt); ScreenToClient(dat->hTreeView, &hti.pt); TreeView_HitTest(dat->hTreeView, &hti); if (hti.hItem && dat->hDragItem != hti.hItem) { NMMSGTREE nm = { 0 }; COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl(); int OrderOld = TreeCtrl->hItemToOrder(dat->hDragItem); int OrderNew = TreeCtrl->hItemToOrder(hti.hItem); _ASSERT(OrderOld != -1 && OrderNew != -1); nm.ItemOld = (OrderOld <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(OrderOld)] : (CBaseTreeItem*)&TreeCtrl->Value[OrderOld]; nm.ItemNew = (OrderNew <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(OrderNew)] : (CBaseTreeItem*)&TreeCtrl->Value[OrderNew]; nm.hdr.code = MTN_ENDDRAG; nm.hdr.hwndFrom = dat->hTreeView; nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView); if (!SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm)) { dat->UpdateLock++; dat->GetTreeCtrl()->MoveItem(hWnd, dat->hDragItem, hti.hItem); dat->UpdateLock--; } } dat->hDragItem = NULL; } break; case WM_TIMER: if (wParam == MSGTREE_TIMER_ID) { KillTimer(hWnd, MSGTREE_TIMER_ID); TVHITTESTINFO hti; hti.pt.x = (short)LOWORD(GetMessagePos()); hti.pt.y = (short)HIWORD(GetMessagePos()); ScreenToClient(dat->hTreeView, &hti.pt); TreeView_HitTest(dat->hTreeView, &hti); if (hti.hItem && dat->hDragItem != hti.hItem && TreeView_GetChild(dat->hTreeView, hti.hItem)) // target is a group and is not the same item that we're dragging TreeView_Expand(dat->hTreeView, hti.hItem, TVE_EXPAND); } } return CallWindowProc(dat->OrigParentProc, hWnd, Msg, wParam, lParam); }
MIR_APP_DLL(void) Window_SetProtoIcon_IcoLib(HWND hWnd, const char *szProto, int iconId) { SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)Skin_LoadProtoIcon(szProto, iconId, true)); SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)Skin_LoadProtoIcon(szProto, iconId, false)); }
extern "C" int __declspec(dllexport) Load() { mir_getLP(&pluginInfoEx); mir_getCLI(); SkinAddNewSoundEx("Gmail", LPGEN("Other"), LPGEN("Gmail: New thread(s)")); HookEvent(ME_CLIST_DOUBLECLICKED, OpenBrowser); PROTOCOLDESCRIPTOR pd = { PROTOCOLDESCRIPTOR_V3_SIZE }; pd.szName = MODULE_NAME; pd.type = PROTOTYPE_VIRTUAL; Proto_RegisterModule(&pd); CreateProtoServiceFunction(MODULE_NAME, PS_GETCAPS, GetCaps); CreateProtoServiceFunction(MODULE_NAME, PS_GETSTATUS, GetStatus); CreateProtoServiceFunction(MODULE_NAME, PS_GETNAME, GetName); CreateServiceFunction("GmailMNotifier/Notifying", Notifying); opt.circleTime = db_get_dw(NULL, MODULE_NAME, "circleTime", 30); opt.notifierOnTray = db_get_dw(NULL, MODULE_NAME, "notifierOnTray", TRUE); opt.notifierOnPop = db_get_dw(NULL, MODULE_NAME, "notifierOnPop", TRUE); opt.popupDuration = db_get_dw(NULL, MODULE_NAME, "popupDuration", -1); opt.popupBgColor = db_get_dw(NULL, MODULE_NAME, "popupBgColor", RGB(173, 206, 247)); opt.popupTxtColor = db_get_dw(NULL, MODULE_NAME, "popupTxtColor", RGB(0, 0, 0)); opt.OpenUsePrg = db_get_dw(NULL, MODULE_NAME, "OpenUsePrg", 0); opt.ShowCustomIcon = db_get_dw(NULL, MODULE_NAME, "ShowCustomIcon", FALSE); opt.UseOnline = db_get_dw(NULL, MODULE_NAME, "UseOnline", FALSE); opt.AutoLogin = db_get_dw(NULL, MODULE_NAME, "AutoLogin", TRUE); opt.LogThreads = db_get_dw(NULL, MODULE_NAME, "LogThreads", FALSE); DBVARIANT dbv; if (db_get_s(NULL, "Icons", "GmailMNotifier40076", &dbv)) { db_set_s(NULL, "Icons", "GmailMNotifier40071", "plugins\\gmailm.dll,2"); db_set_s(NULL, "Icons", "GmailMNotifier40072", "plugins\\gmailm.dll,2"); db_set_s(NULL, "Icons", "GmailMNotifier40076", "plugins\\gmailm.dll,0"); db_set_s(NULL, "Icons", "GmailMNotifier40073", "plugins\\gmailm.dll,1"); } else db_free(&dbv); BuildList(); ID_STATUS_NONEW = opt.UseOnline ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE; for (int i = 0; i < acc_num; i++) db_set_dw(acc[i].hContact, MODULE_NAME, "Status", ID_STATUS_NONEW); hTimer = SetTimer(NULL, 0, opt.circleTime * 60000, TimerProc); hMirandaStarted = HookEvent(ME_SYSTEM_MODULESLOADED, OnMirandaStart); hOptionsInitial = HookEvent(ME_OPT_INITIALISE, OptInit); CreateServiceFunction(MODULE_NAME "/MenuCommand", PluginMenuCommand); CMenuItem mi; SET_UID(mi, 0xbe16f37, 0x17be, 0x4494, 0xaa, 0xb2, 0x3a, 0xa7, 0x38, 0xfa, 0xf9, 0xcc); mi.position = -0x7FFFFFFF; mi.hIcolibItem = Skin_LoadProtoIcon(MODULE_NAME, ID_STATUS_ONLINE); mi.name.a = LPGEN("&Check all Gmail inboxes"); mi.pszService = MODULE_NAME "/MenuCommand"; Menu_AddMainMenuItem(&mi); SET_UID(mi, 0x22c6ace1, 0xba0c, 0x44b5, 0xa4, 0xd2, 0x1, 0x7d, 0xb1, 0xe0, 0x51, 0xeb); mi.name.a = LPGEN("&Check Gmail inbox"); mi.pszService = "/MenuCommand"; Menu_AddContactMenuItem(&mi, MODULE_NAME); return 0; }
static INT_PTR CALLBACK DlgProcSetStatusMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); SendDlgItemMessage(hwndDlg, IDC_STATUSMESSAGE, EM_LIMITTEXT, MS_MYDETAILS_GETMYSTATUSMESSAGE_BUFFER_SIZE - 1, 0); mir_subclassWindow(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), StatusMsgEditSubclassProc); return TRUE; case WMU_SETDATA: { SetStatusMessageData *data = (SetStatusMessageData *)malloc(sizeof(SetStatusMessageData)); data->status = (int)wParam; data->proto_num = (int)lParam; SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)data); if (data->proto_num >= 0) { Protocol *proto = protocols->Get(data->proto_num); HICON hIcon = (HICON)CallProtoService(proto->name, PS_LOADICON, PLI_PROTOCOL, 0); if (hIcon != NULL) { SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); DestroyIcon(hIcon); } TCHAR title[256]; mir_sntprintf(title, _countof(title), TranslateT("Set my status message for %s"), proto->description); SetWindowText(hwndDlg, title); SetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, proto->GetStatusMsg()); } else if (data->status != 0) { SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_LoadProtoIcon(NULL, data->status)); TCHAR title[256]; mir_sntprintf(title, _countof(title), TranslateT("Set my status message for %s"), pcli->pfnGetStatusModeDescription(data->status, 0)); SetWindowText(hwndDlg, title); SetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, protocols->GetDefaultStatusMsg(data->status)); } else { SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_LoadIcon(SKINICON_OTHER_MIRANDA)); SetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, protocols->GetDefaultStatusMsg()); } return TRUE; } case WM_COMMAND: switch (wParam) { case IDOK: { TCHAR tmp[MS_MYDETAILS_GETMYSTATUSMESSAGE_BUFFER_SIZE]; GetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, tmp, _countof(tmp)); SetStatusMessageData *data = (SetStatusMessageData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); if (data->proto_num >= 0) protocols->Get(data->proto_num)->SetStatusMsg(tmp); else if (data->status == 0) protocols->SetStatusMsgs(tmp); else protocols->SetStatusMsgs(data->status, tmp); DestroyWindow(hwndDlg); } break; case IDCANCEL: DestroyWindow(hwndDlg); break; } break; case WM_CLOSE: DestroyWindow(hwndDlg); break; case WM_DESTROY: SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), GWLP_WNDPROC, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), GWLP_USERDATA)); free((SetStatusMessageData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA)); InterlockedExchange(&status_msg_dialog_open, 0); break; } return FALSE; }