CContactCache* CContactCache::getContactCache(const HANDLE hContact) { CContactCache *c = m_cCache, *cTemp; cTemp = c; while(c) { cTemp = c; if(c->m_hContact == hContact) { c->inc(); return(c); } c = c->m_next; } CContactCache* _c = new CContactCache(hContact); if(cTemp) { cTemp->m_next = _c; return(_c); } m_cCache = _c; return(_c); }
int SendQueue::ackMessage(TWindowData *dat, WPARAM wParam, LPARAM lParam) { ACKDATA *ack = (ACKDATA *) lParam; DBEVENTINFO dbei = { 0}; HANDLE hNewEvent; int iFound = SendQueue::NR_SENDJOBS, iNextFailed; TContainerData *m_pContainer = 0; if (dat) m_pContainer = dat->pContainer; iFound = (int)(LOWORD(wParam)); //i = (int)(HIWORD(wParam)); if (m_jobs[iFound].iStatus == SQ_ERROR) { // received ack for a job which is already in error state... if (dat) { // window still open if (dat->iCurrentQueueError == iFound) { dat->iCurrentQueueError = -1; showErrorControls(dat, FALSE); } } /* * we must discard this job, because there is no message window open to handle the * error properly. But we display a tray notification to inform the user about the problem. */ else goto inform_and_discard; } // failed acks are only handled when the window is still open. with no window open, they will be *silently* discarded if (ack->result == ACKRESULT_FAILED) { if (dat) { /* * "hard" errors are handled differently in multisend. There is no option to retry - once failed, they * are discarded and the user is notified with a small log message. */ if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) SkinPlaySound("SendError"); TCHAR *szAckMsg = mir_a2t((char *)ack->lParam); mir_sntprintf(m_jobs[iFound].szErrorMsg, safe_sizeof(m_jobs[iFound].szErrorMsg), CTranslator::get(CTranslator::GEN_MSG_DELIVERYFAILURE), szAckMsg); m_jobs[iFound].iStatus = SQ_ERROR; mir_free(szAckMsg); KillTimer(dat->hwnd, TIMERID_MSGSEND + iFound); if (!(dat->dwFlags & MWF_ERRORSTATE)) handleError(dat, iFound); return 0; } else { inform_and_discard: _DebugPopup(m_jobs[iFound].hOwner, CTranslator::get(CTranslator::GEN_SQ_DELIVERYFAILEDLATE)); clearJob(iFound); return 0; } } dbei.cbSize = sizeof(dbei); dbei.eventType = EVENTTYPE_MESSAGE; dbei.flags = DBEF_SENT; dbei.szModule = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) m_jobs[iFound].hOwner, 0); dbei.timestamp = time(NULL); dbei.cbBlob = lstrlenA(m_jobs[iFound].sendBuffer) + 1; if (dat) dat->cache->updateStats(TSessionStats::BYTES_SENT, dbei.cbBlob - 1); else { CContactCache *c = CContactCache::getContactCache(m_jobs[iFound].hOwner); if(c) c->updateStats(TSessionStats::BYTES_SENT, dbei.cbBlob - 1); } if (m_jobs[iFound].dwFlags & PREF_UNICODE) dbei.cbBlob *= sizeof(TCHAR) + 1; if (m_jobs[iFound].dwFlags & PREF_RTL) dbei.flags |= DBEF_RTL; if (m_jobs[iFound].dwFlags & PREF_UTF) dbei.flags |= DBEF_UTF; dbei.pBlob = (PBYTE) m_jobs[iFound].sendBuffer; hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) m_jobs[iFound].hOwner, (LPARAM) & dbei); if (m_pContainer) { if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) SkinPlaySound("SendMsg"); } if (dat && (m_jobs[iFound].hOwner == dat->hContact)) { if (dat->hDbEventFirst == NULL) { dat->hDbEventFirst = hNewEvent; SendMessage(dat->hwnd, DM_REMAKELOG, 0, 0); } } m_jobs[iFound].hSendId = NULL; m_jobs[iFound].iAcksNeeded--; if (m_jobs[iFound].iAcksNeeded == 0) { // everything sent //if (m_jobs[iFound].hOwner != 0 && dat) // EnableSending(dat, TRUE); clearJob(iFound); if (dat) { KillTimer(dat->hwnd, TIMERID_MSGSEND + iFound); dat->iOpenJobs--; } m_currentIndex--; } if (dat) { checkQueue(dat); if ((iNextFailed = findNextFailed(dat)) >= 0 && !(dat->dwFlags & MWF_ERRORSTATE)) handleError(dat, iNextFailed); //MAD: close on send mode else { if (M->GetByte("AutoClose", 0)) { if(M->GetByte("adv_AutoClose_2", 0)) SendMessage(dat->hwnd, WM_CLOSE, 0, 1); else SendMessage(dat->pContainer->hwnd, WM_CLOSE, 0, 0); } } //MAD_ } return 0; }
int SendQueue::sendQueued(TWindowData *dat, const int iEntry) { HWND hwndDlg = dat->hwnd; if (dat->sendMode & SMODE_MULTIPLE) { HANDLE hContact, hItem; int iJobs = 0; int iMinLength = 0; CContactCache* c = 0; hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); m_jobs[iEntry].hOwner = dat->hContact; m_jobs[iEntry].iStatus = SQ_INPROGRESS; m_jobs[iEntry].hwndOwner = hwndDlg; int iSendLength = getSendLength(iEntry, dat->sendMode); do { hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0); if (hItem && SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItem, 0)) { c = CContactCache::getContactCache(hContact); if(c) iMinLength = (iMinLength == 0 ? c->getMaxMessageLength() : min(c->getMaxMessageLength(), iMinLength)); } } while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0)); if(iSendLength >= iMinLength) { TCHAR tszError[256]; mir_sntprintf(tszError, 256, CTranslator::get(CTranslator::GEN_SQ_SENDLATER_ERROR_MSG_TOO_LONG), iMinLength); ::SendMessage(dat->hwnd, DM_ACTIVATETOOLTIP, IDC_MESSAGE, reinterpret_cast<LPARAM>(tszError)); sendQueue->clearJob(iEntry); return(0); } hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); do { hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0); if (hItem && SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItem, 0)) { doSendLater(iEntry, 0, hContact, false); iJobs++; } } while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0)); sendQueue->clearJob(iEntry); if(iJobs) sendLater->flushQueue(); // force queue processing return(0); } else { if (dat->hContact == NULL) return 0; //never happens dat->nMax = dat->cache->getMaxMessageLength(); // refresh length info if (dat->sendMode & SMODE_FORCEANSI && M->GetByte(dat->cache->getActiveContact(), dat->cache->getActiveProto(), "UnicodeSend", 1)) M->WriteByte(dat->cache->getActiveContact(), dat->cache->getActiveProto(), "UnicodeSend", 0); else if (!(dat->sendMode & SMODE_FORCEANSI) && !M->GetByte(dat->cache->getActiveContact(), dat->cache->getActiveProto(), "UnicodeSend", 0)) M->WriteByte(dat->cache->getActiveContact(), dat->cache->getActiveProto(), "UnicodeSend", 1); if (M->GetByte("autosplit", 1) && !(dat->sendMode & SMODE_SENDLATER)) { BOOL fSplit = FALSE; DWORD dwOldFlags; /* * determine send buffer length */ if(getSendLength(iEntry, dat->sendMode) >= dat->nMax) fSplit = true; if (!fSplit) goto send_unsplitted; m_jobs[iEntry].hOwner = dat->hContact; m_jobs[iEntry].hwndOwner = hwndDlg; m_jobs[iEntry].iStatus = SQ_INPROGRESS; m_jobs[iEntry].iAcksNeeded = 1; m_jobs[iEntry].chunkSize = dat->nMax; dwOldFlags = m_jobs[iEntry].dwFlags; if (dat->sendMode & SMODE_FORCEANSI) m_jobs[iEntry].dwFlags &= ~PREF_UNICODE; if (!(m_jobs[iEntry].dwFlags & PREF_UNICODE) || dat->sendMode & SMODE_FORCEANSI) mir_forkthread(DoSplitSendA, (LPVOID)iEntry); else mir_forkthread(DoSplitSendW, (LPVOID)iEntry); m_jobs[iEntry].dwFlags = dwOldFlags; } else { send_unsplitted: m_jobs[iEntry].hOwner = dat->hContact; m_jobs[iEntry].hwndOwner = hwndDlg; m_jobs[iEntry].iStatus = SQ_INPROGRESS; m_jobs[iEntry].iAcksNeeded = 1; if(dat->sendMode & SMODE_SENDLATER) { TCHAR tszError[256]; int iSendLength = getSendLength(iEntry, dat->sendMode); if(iSendLength >= dat->nMax) { mir_sntprintf(tszError, 256, CTranslator::get(CTranslator::GEN_SQ_SENDLATER_ERROR_MSG_TOO_LONG), dat->nMax); SendMessage(dat->hwnd, DM_ACTIVATETOOLTIP, IDC_MESSAGE, reinterpret_cast<LPARAM>(tszError)); clearJob(iEntry); return(0); } doSendLater(iEntry, dat); clearJob(iEntry); return(0); } m_jobs[iEntry].hSendId = (HANDLE) CallContactService(dat->hContact, MsgServiceName(dat->hContact, dat, m_jobs[iEntry].dwFlags), (dat->sendMode & SMODE_FORCEANSI) ? (m_jobs[iEntry].dwFlags & ~PREF_UNICODE) : m_jobs[iEntry].dwFlags, (LPARAM) m_jobs[iEntry].sendBuffer); if (dat->sendMode & SMODE_NOACK) { // fake the ack if we are not interested in receiving real acks ACKDATA ack = {0}; ack.hContact = dat->hContact; ack.hProcess = m_jobs[iEntry].hSendId; ack.type = ACKTYPE_MESSAGE; ack.result = ACKRESULT_SUCCESS; SendMessage(hwndDlg, HM_EVENTSENT, (WPARAM)MAKELONG(iEntry, 0), (LPARAM)&ack); } else SetTimer(hwndDlg, TIMERID_MSGSEND + iEntry, PluginConfig.m_MsgTimeout, NULL); } } dat->iOpenJobs++; m_currentIndex++; // give icon feedback... if (dat->pContainer->hwndActive == hwndDlg) ::UpdateReadChars(dat); if (!(dat->sendMode & SMODE_NOACK)) ::HandleIconFeedback(dat, PluginConfig.g_IconSend); if (M->GetByte(SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN)) ::SendMessage(dat->pContainer->hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); return 0; }
int SendQueue::ackMessage(TWindowData *dat, WPARAM wParam, LPARAM lParam) { ACKDATA *ack = (ACKDATA *)lParam; TContainerData *m_pContainer = 0; if (dat) m_pContainer = dat->pContainer; int iFound = (int)(LOWORD(wParam)); SendJob &job = m_jobs[iFound]; if (job.iStatus == SQ_ERROR) { // received ack for a job which is already in error state... if (dat) { // window still open if (dat->iCurrentQueueError == iFound) { dat->iCurrentQueueError = -1; showErrorControls(dat, FALSE); } } // we must discard this job, because there is no message window open to handle the // error properly. But we display a tray notification to inform the user about the problem. else goto inform_and_discard; } // failed acks are only handled when the window is still open. with no window open, they will be *silently* discarded if (ack->result == ACKRESULT_FAILED) { if (dat) { // "hard" errors are handled differently in multisend. There is no option to retry - once failed, they // are discarded and the user is notified with a small log message. if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) SkinPlaySound("SendError"); TCHAR *szAckMsg = mir_a2t((char *)ack->lParam); mir_sntprintf(job.szErrorMsg, TranslateT("Delivery failure: %s"), szAckMsg); job.iStatus = SQ_ERROR; mir_free(szAckMsg); KillTimer(dat->hwnd, TIMERID_MSGSEND + iFound); if (!(dat->dwFlags & MWF_ERRORSTATE)) handleError(dat, iFound); return 0; } inform_and_discard: _DebugPopup(job.hContact, TranslateT("A message delivery has failed after the contacts chat window was closed. You may want to resend the last message")); clearJob(iFound); return 0; } DBEVENTINFO dbei = { sizeof(dbei) }; dbei.eventType = EVENTTYPE_MESSAGE; dbei.flags = DBEF_SENT; dbei.szModule = GetContactProto(job.hContact); dbei.timestamp = time(NULL); dbei.cbBlob = (int)mir_strlen(job.szSendBuffer) + 1; if (dat) dat->cache->updateStats(TSessionStats::BYTES_SENT, dbei.cbBlob - 1); else { CContactCache *cc = CContactCache::getContactCache(job.hContact); if (cc) cc->updateStats(TSessionStats::BYTES_SENT, dbei.cbBlob - 1); } if (job.dwFlags & PREF_RTL) dbei.flags |= DBEF_RTL; dbei.flags |= DBEF_UTF; dbei.pBlob = (PBYTE)job.szSendBuffer; MessageWindowEvent evt = { sizeof(evt), (INT_PTR)job.hSendId, job.hContact, &dbei }; NotifyEventHooks(PluginConfig.m_event_WriteEvent, 0, (LPARAM)&evt); job.szSendBuffer = (char*)dbei.pBlob; MEVENT hNewEvent = db_event_add(job.hContact, &dbei); if (m_pContainer) if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) SkinPlaySound("SendMsg"); M.BroadcastMessage(DM_APPENDMCEVENT, job.hContact, LPARAM(hNewEvent)); job.hSendId = NULL; job.iAcksNeeded--; if (job.iAcksNeeded == 0) { // everything sent clearJob(iFound); if (dat) { KillTimer(dat->hwnd, TIMERID_MSGSEND + iFound); dat->iOpenJobs--; } m_currentIndex--; } if (dat) { checkQueue(dat); int iNextFailed = findNextFailed(dat); if (iNextFailed >= 0 && !(dat->dwFlags & MWF_ERRORSTATE)) handleError(dat, iNextFailed); else { if (M.GetByte("AutoClose", 0)) { if (M.GetByte("adv_AutoClose_2", 0)) SendMessage(dat->hwnd, WM_CLOSE, 0, 1); else SendMessage(dat->pContainer->hwnd, WM_CLOSE, 0, 0); } } } return 0; }
int SendQueue::sendQueued(TWindowData *dat, const int iEntry) { CContactCache *ccActive = CContactCache::getContactCache(dat->hContact); if (ccActive == NULL) return 0; HWND hwndDlg = dat->hwnd; if (dat->sendMode & SMODE_MULTIPLE) { int iJobs = 0; int iMinLength = 0; m_jobs[iEntry].iStatus = SQ_INPROGRESS; m_jobs[iEntry].hContact = ccActive->getActiveContact(); m_jobs[iEntry].hOwnerWnd = hwndDlg; size_t iSendLength = getSendLength(iEntry); for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { HANDLE hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, hContact, 0); if (hItem && SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM)hItem, 0)) { CContactCache *c = CContactCache::getContactCache(hContact); if (c) iMinLength = (iMinLength == 0 ? c->getMaxMessageLength() : min(c->getMaxMessageLength(), iMinLength)); } } if (iSendLength >= iMinLength) { TCHAR tszError[256]; mir_sntprintf(tszError, TranslateT("The message cannot be sent delayed or to multiple contacts, because it exceeds the maximum allowed message length of %d bytes"), iMinLength); ::SendMessage(dat->hwnd, DM_ACTIVATETOOLTIP, IDC_MESSAGE, LPARAM(tszError)); sendQueue->clearJob(iEntry); return 0; } for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { HANDLE hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, hContact, 0); if (hItem && SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM)hItem, 0)) { doSendLater(iEntry, 0, hContact, false); iJobs++; } } sendQueue->clearJob(iEntry); if (iJobs) sendLater->flushQueue(); // force queue processing return 0; } if (dat->hContact == NULL) return 0; //never happens dat->nMax = dat->cache->getMaxMessageLength(); // refresh length info if (M.GetByte("autosplit", 0) && !(dat->sendMode & SMODE_SENDLATER)) { // determine send buffer length BOOL fSplit = FALSE; if (getSendLength(iEntry) >= dat->nMax) fSplit = true; if (!fSplit) goto send_unsplitted; m_jobs[iEntry].hContact = ccActive->getActiveContact(); m_jobs[iEntry].hOwnerWnd = hwndDlg; m_jobs[iEntry].iStatus = SQ_INPROGRESS; m_jobs[iEntry].iAcksNeeded = 1; m_jobs[iEntry].chunkSize = dat->nMax; DWORD dwOldFlags = m_jobs[iEntry].dwFlags; mir_forkthread(DoSplitSendA, (LPVOID)iEntry); m_jobs[iEntry].dwFlags = dwOldFlags; } else { send_unsplitted: m_jobs[iEntry].hContact = ccActive->getActiveContact(); m_jobs[iEntry].hOwnerWnd = hwndDlg; m_jobs[iEntry].iStatus = SQ_INPROGRESS; m_jobs[iEntry].iAcksNeeded = 1; if (dat->sendMode & SMODE_SENDLATER) { TCHAR tszError[256]; size_t iSendLength = getSendLength(iEntry); if (iSendLength >= dat->nMax) { mir_sntprintf(tszError, TranslateT("The message cannot be sent delayed or to multiple contacts, because it exceeds the maximum allowed message length of %d bytes"), dat->nMax); SendMessage(dat->hwnd, DM_ACTIVATETOOLTIP, IDC_MESSAGE, LPARAM(tszError)); clearJob(iEntry); return 0; } doSendLater(iEntry, dat); clearJob(iEntry); return 0; } m_jobs[iEntry].hSendId = (HANDLE)CallContactService(dat->hContact, PSS_MESSAGE, m_jobs[iEntry].dwFlags, (LPARAM)m_jobs[iEntry].szSendBuffer); if (dat->sendMode & SMODE_NOACK) { // fake the ack if we are not interested in receiving real acks ACKDATA ack = { 0 }; ack.hContact = dat->hContact; ack.hProcess = m_jobs[iEntry].hSendId; ack.type = ACKTYPE_MESSAGE; ack.result = ACKRESULT_SUCCESS; SendMessage(hwndDlg, HM_EVENTSENT, (WPARAM)MAKELONG(iEntry, 0), (LPARAM)&ack); } else SetTimer(hwndDlg, TIMERID_MSGSEND + iEntry, PluginConfig.m_MsgTimeout, NULL); } dat->iOpenJobs++; m_currentIndex++; // give icon feedback... if (dat->pContainer->hwndActive == hwndDlg) ::UpdateReadChars(dat); if (!(dat->sendMode & SMODE_NOACK)) ::HandleIconFeedback(dat, PluginConfig.g_IconSend); if (M.GetByte(SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN)) ::SendMessage(dat->pContainer->hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); return 0; }
// fills the list of jobs with current contents of the job queue // filters by m_hFilter (contact handle) // void CSendLater::qMgrFillList(bool fClear) { TCHAR *formatTime = _T("%Y.%m.%d - %H:%M"); if (fClear) { ::SendMessage(m_hwndList, LVM_DELETEALLITEMS, 0, 0); ::SendMessage(m_hwndFilter, CB_RESETCONTENT, 0, 0); } m_sel = 0; ::SendMessage(m_hwndFilter, CB_INSERTSTRING, -1, LPARAM(TranslateT("<All contacts>"))); ::SendMessage(m_hwndFilter, CB_SETITEMDATA, 0, 0); LVITEM lvItem = { 0 }; lvItem.cchTextMax = 255; BYTE bCode = '-'; unsigned uIndex = 0; for (int i = 0; i < m_sendLaterJobList.getCount(); i++) { CSendLaterJob *p = m_sendLaterJobList[i]; CContactCache *c = CContactCache::getContactCache(p->hContact); if (c) { const TCHAR *tszNick = c->getNick(); if (m_hFilter && m_hFilter != p->hContact) { qMgrAddFilter(c->getContact(), tszNick); continue; } lvItem.mask = LVIF_TEXT|LVIF_PARAM; TCHAR tszBuf[255]; mir_sntprintf(tszBuf, 255, _T("%s [%s]"), tszNick, c->getRealAccount()); lvItem.pszText = tszBuf; lvItem.iItem = uIndex++; lvItem.iSubItem = 0; lvItem.lParam = LPARAM(p); ::SendMessage(m_hwndList, LVM_INSERTITEM, 0, LPARAM(&lvItem)); qMgrAddFilter(c->getContact(), tszNick); lvItem.mask = LVIF_TEXT; TCHAR tszTimestamp[30]; _tcsftime(tszTimestamp, 30, formatTime, _localtime32((__time32_t *)&p->created)); tszTimestamp[29] = 0; lvItem.pszText = tszTimestamp; lvItem.iSubItem = 1; ::SendMessage(m_hwndList, LVM_SETITEM, 0, LPARAM(&lvItem)); TCHAR *msg = mir_utf8decodeT(p->sendBuffer); TCHAR *preview = Utils::GetPreviewWithEllipsis(msg, 255); lvItem.pszText = preview; lvItem.iSubItem = 2; ::SendMessage(m_hwndList, LVM_SETITEM, 0, LPARAM(&lvItem)); mir_free(preview); mir_free(msg); const TCHAR *tszStatusText = 0; if (p->fFailed) { tszStatusText = p->bCode == CSendLaterJob::JOB_REMOVABLE ? TranslateT("Removed") : TranslateT("Failed"); } else if (p->fSuccess) tszStatusText = TranslateT("Sent OK"); else { switch(p->bCode) { case CSendLaterJob::JOB_DEFERRED: tszStatusText = TranslateT("Deferred"); break; case CSendLaterJob::JOB_AGE: tszStatusText = TranslateT("Failed"); break; case CSendLaterJob::JOB_HOLD: tszStatusText = TranslateT("Suspended"); break; default: tszStatusText = TranslateT("Pending"); break; } } if (p->bCode) bCode = p->bCode; TCHAR tszStatus[20]; mir_sntprintf(tszStatus, 20, _T("X/%s[%c] (%d)"), tszStatusText, bCode, p->iSendCount); tszStatus[0] = p->szId[0]; lvItem.pszText = tszStatus; lvItem.iSubItem = 3; ::SendMessage(m_hwndList, LVM_SETITEM, 0, LPARAM(&lvItem)); if (p->lastSent == 0) mir_sntprintf(tszTimestamp, 30, _T("%s"), _T("Never")); else { _tcsftime(tszTimestamp, 30, formatTime, _localtime32((__time32_t *)&p->lastSent)); tszTimestamp[29] = 0; } lvItem.pszText = tszTimestamp; lvItem.iSubItem = 4; ::SendMessage(m_hwndList, LVM_SETITEM, 0, LPARAM(&lvItem)); } } if (m_hFilter == 0) ::SendMessage(m_hwndFilter, CB_SETCURSEL, 0, 0); else ::SendMessage(m_hwndFilter, CB_SETCURSEL, m_sel, 0); }
// Try to send an open job from the job list // this is ONLY called from the WM_TIMER handler and should never be executed directly. int CSendLater::sendIt(CSendLaterJob *job) { time_t now = time(0); if (job->bCode == CSendLaterJob::JOB_HOLD || job->bCode == CSendLaterJob::JOB_DEFERRED || job->fSuccess || job->fFailed || job->lastSent > now) return 0; // this one is frozen or done (will be removed soon), don't process it now. if (now - job->created > SENDLATER_AGE_THRESHOLD) { // too old, this will be discarded and user informed by popup job->fFailed = true; job->bCode = CSendLaterJob::JOB_AGE; return 0; } // mark job as deferred (5 unsuccessful sends). Job will not be removed, but // the user must manually reset it in order to trigger a new send attempt. if (job->iSendCount == 5) { job->bCode = CSendLaterJob::JOB_DEFERRED; return 0; } if (job->iSendCount > 0 && (now - job->lastSent < SENDLATER_RESEND_THRESHOLD)) return 0; // this one was sent, but probably failed. Resend it after a while CContactCache *c = CContactCache::getContactCache(job->hContact); if (c == NULL) return 0; // should not happen if (!c->isValid()) { job->fFailed = true; job->bCode = CSendLaterJob::INVALID_CONTACT; return 0; // can happen (contact has been deleted). mark the job as failed } MCONTACT hContact = c->getActiveContact(); const char *szProto = c->getActiveProto(); if (!hContact || szProto == 0) return 0; WORD wMyStatus = (WORD)CallProtoService(szProto, PS_GETSTATUS, 0, 0); WORD wContactStatus = c->getActiveStatus(); // status mode checks if (wMyStatus == ID_STATUS_OFFLINE) { job->bCode = CSendLaterJob::JOB_MYSTATUS; return 0; } if (job->szId[0] == 'S') { if (!(wMyStatus == ID_STATUS_ONLINE || wMyStatus == ID_STATUS_FREECHAT)) { job->bCode = CSendLaterJob::JOB_MYSTATUS; return 0; } } job->lastSent = now; job->iSendCount++; job->hTargetContact = hContact; job->bCode = CSendLaterJob::JOB_WAITACK; DWORD dwFlags = IsUtfSendAvailable(hContact) ? PREF_UTF : PREF_UNICODE; if (dwFlags & PREF_UTF) job->hProcess = (HANDLE)CallContactService(hContact, PSS_MESSAGE, dwFlags, (LPARAM)job->sendBuffer); else job->hProcess = (HANDLE)CallContactService(hContact, PSS_MESSAGE, dwFlags, (LPARAM)job->pBuf); return 0; }