From a5f0d0cde8b48159d1616aa9f6b0b0f77fd773d0 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 14 Aug 2022 12:37:55 +0300 Subject: code cleaning --- plugins/TabSRMM/src/chat_tools.cpp | 2 +- plugins/TabSRMM/src/container.cpp | 26 +++ plugins/TabSRMM/src/msgdlgother.cpp | 357 ++++++++++++++++++++++++++++++++- plugins/TabSRMM/src/msgs.h | 2 +- plugins/TabSRMM/src/utils.cpp | 384 ------------------------------------ 5 files changed, 384 insertions(+), 387 deletions(-) (limited to 'plugins/TabSRMM/src') diff --git a/plugins/TabSRMM/src/chat_tools.cpp b/plugins/TabSRMM/src/chat_tools.cpp index 173fad2b7f..08277c5780 100644 --- a/plugins/TabSRMM/src/chat_tools.cpp +++ b/plugins/TabSRMM/src/chat_tools.cpp @@ -285,7 +285,7 @@ BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO *si, GCEVENT *gce, BOOL bHighlight if (dat) { bInactive = dat->m_pContainer->m_hwnd != GetForegroundWindow(); bActiveTab = (dat->m_pContainer->m_hwndActive == dat->GetHwnd()); - if (sound && dat->MustPlaySound()) + if (sound && dat->m_pContainer->MustPlaySound(dat)) Skin_PlaySound(sound); } else if (sound) diff --git a/plugins/TabSRMM/src/container.cpp b/plugins/TabSRMM/src/container.cpp index 3f43d66d5c..9b49ec16b9 100644 --- a/plugins/TabSRMM/src/container.cpp +++ b/plugins/TabSRMM/src/container.cpp @@ -518,6 +518,32 @@ void TContainerData::QueryClientArea(RECT &rc) AdjustTabClientRect(rc); } +///////////////////////////////////////////////////////////////////////////////////////// +// return != 0 when the sound effect must be played for the given +// session. Uses container sound settings + +bool TContainerData::MustPlaySound(const CMsgDialog *pDialog) const +{ + if (m_bHidden) // hidden container is treated as closed, so play the sound + return true; + + if (cfg.flags.m_bNoSound || NEN::bNoSounds) + return false; + + // window minimized, check if sound has to be played + if (::IsIconic(m_hwnd)) + return cfg.flagsEx.m_bSoundMinimized; + + // window in foreground + if (m_hwnd != ::GetForegroundWindow()) + return cfg.flagsEx.m_bSoundUnfocused; + + if (m_hwndActive == pDialog->GetHwnd()) + return cfg.flagsEx.m_bSoundFocused; + + return cfg.flagsEx.m_bSoundInactive; +} + // search tab with either next or most recent unread message and select it void TContainerData::QueryPending() { diff --git a/plugins/TabSRMM/src/msgdlgother.cpp b/plugins/TabSRMM/src/msgdlgother.cpp index fca323a908..b47eb8bf92 100644 --- a/plugins/TabSRMM/src/msgdlgother.cpp +++ b/plugins/TabSRMM/src/msgdlgother.cpp @@ -508,6 +508,32 @@ void CMsgDialog::FindFirstEvent() } } +///////////////////////////////////////////////////////////////////////////////////////// +// returns != 0 when one of the installed keyboard layouts belongs to an rtl language +// used to find out whether we need to configure the message input box for bidirectional mode + +int CMsgDialog::FindRTLLocale() +{ + int result = 0; + + if (m_iHaveRTLLang == 0) { + HKL layouts[20]; + memset(layouts, 0, sizeof(layouts)); + GetKeyboardLayoutList(20, layouts); + for (int i = 0; i < 20 && layouts[i]; i++) { + uint16_t wCtype2[5]; + LCID lcid = MAKELCID(LOWORD(layouts[i]), 0); + GetStringTypeA(lcid, CT_CTYPE2, "���", 3, wCtype2); + if (wCtype2[0] == C2_RIGHTTOLEFT || wCtype2[1] == C2_RIGHTTOLEFT || wCtype2[2] == C2_RIGHTTOLEFT) + result = 1; + } + m_iHaveRTLLang = (result ? 1 : -1); + } + else result = m_iHaveRTLLang == 1 ? 1 : 0; + + return result; +} + ///////////////////////////////////////////////////////////////////////////////////////// void CMsgDialog::FlashOnClist(MEVENT hEvent, DBEVENTINFO *dbei) @@ -554,6 +580,277 @@ void CMsgDialog::FlashTab(bool bInvertMode) m_pContainer->m_pSideBar->updateSession(this); } +///////////////////////////////////////////////////////////////////////////////////////// +// this translates formatting tags into rtf sequences... +// flags: loword = words only for simple * /_ formatting +// hiword = bbcode support (strip bbcodes if 0) + +static wchar_t *w_bbcodes_begin[] = { L"[b]", L"[i]", L"[u]", L"[s]", L"[color=" }; +static wchar_t *w_bbcodes_end[] = { L"[/b]", L"[/i]", L"[/u]", L"[/s]", L"[/color]" }; + +static wchar_t *formatting_strings_begin[] = { L"b1 ", L"i1 ", L"u1 ", L"s1 ", L"c1 " }; +static wchar_t *formatting_strings_end[] = { L"b0 ", L"i0 ", L"u0 ", L"s0 ", L"c0 " }; + +void CMsgDialog::FormatRaw(CMStringW &msg, int flags, bool isSent) +{ + bool clr_was_added = false; + int beginmark = 0, endmark = 0, tempmark = 0; + int i, endindex; + + if (m_dwFlags & MWF_LOG_BBCODE) { + beginmark = 0; + while (true) { + for (i = 0; i < _countof(w_bbcodes_begin); i++) + if ((tempmark = msg.Find(w_bbcodes_begin[i], 0)) != -1) + break; + + if (i >= _countof(w_bbcodes_begin)) + break; + + beginmark = tempmark; + endindex = i; + endmark = msg.Find(w_bbcodes_end[i], beginmark); + if (endindex == 4) { // color + int closing = msg.Find(L"]", beginmark); + bool was_added = false; + + if (closing == -1) { // must be an invalid [color=] tag w/o closing bracket + msg.SetAt(beginmark, ' '); + continue; + } + + CMStringW colorname = msg.Mid(beginmark + 7, closing - beginmark - 7); +search_again: + bool clr_found = false; + for (int ii = 0; ii < Utils::rtf_clrs.getCount(); ii++) { + auto &rtfc = Utils::rtf_clrs[ii]; + if (!wcsicmp(colorname, rtfc.szName)) { + closing = beginmark + 7 + (int)mir_wstrlen(rtfc.szName); + if (endmark != -1) { + msg.Delete(endmark, 8); + msg.Insert(endmark, L"c0 "); + } + msg.Delete(beginmark, closing - beginmark + 1); + + wchar_t szTemp[5]; + msg.Insert(beginmark, L"cxxx "); + mir_snwprintf(szTemp, L"%02d", MSGDLGFONTCOUNT + 13 + ii); + msg.SetAt(beginmark + 3, szTemp[0]); + msg.SetAt(beginmark + 4, szTemp[1]); + clr_found = true; + if (was_added) { + wchar_t wszTemp[100]; + mir_snwprintf(wszTemp, L"##col##%06u:%04u", endmark - closing, ii); + wszTemp[99] = 0; + msg.Insert(beginmark, wszTemp); + } + break; + } + } + if (!clr_found) { + int c_closing = colorname.Find(L"]"); + if (c_closing == -1) + c_closing = colorname.GetLength(); + const wchar_t *wszColname = colorname.c_str(); + if (endmark != -1 && c_closing > 2 && c_closing <= 6 && iswalnum(colorname[0]) && iswalnum(colorname[c_closing - 1])) { + Utils::RTF_ColorAdd(wszColname); + if (!was_added) { + clr_was_added = was_added = true; + goto search_again; + } + else goto invalid_code; + } + else { +invalid_code: + if (endmark != -1) + msg.Delete(endmark, 8); + if (closing != -1 && closing < endmark) + msg.Delete(beginmark, (closing - beginmark) + 1); + else + msg.SetAt(beginmark, ' '); + } + } + continue; + } + + if (endmark != -1) { + msg.Delete(endmark, 4); + msg.Insert(endmark, formatting_strings_end[i]); + } + msg.Delete(beginmark, 3); + msg.Insert(beginmark, L" "); + msg.Insert(beginmark, formatting_strings_begin[i]); + } + } + + if ((m_dwFlags & MWF_LOG_TEXTFORMAT) && msg.Find(L"://") == -1) { + while ((beginmark = msg.Find(L"*/_", beginmark)) != -1) { + wchar_t endmarker = msg[beginmark]; + if (LOWORD(flags)) { + if (beginmark > 0 && !iswspace(msg[beginmark - 1]) && !iswpunct(msg[beginmark - 1])) { + beginmark++; + continue; + } + + // search a corresponding endmarker which fulfills the criteria + INT_PTR mark = beginmark + 1; + while ((endmark = msg.Find(endmarker, mark)) != -1) { + if (iswpunct(msg[endmark + 1]) || iswspace(msg[endmark + 1]) || msg[endmark + 1] == 0 || wcschr(L"*/_", msg[endmark + 1]) != nullptr) + goto ok; + mark = endmark + 1; + } + break; + } + else { + if ((endmark = msg.Find(endmarker, beginmark + 1)) == -1) + break; + } +ok: + if ((endmark - beginmark) < 2) { + beginmark++; + continue; + } + + int index = 0; + switch (endmarker) { + case '*': + index = 0; + break; + case '/': + index = 1; + break; + case '_': + index = 2; + break; + } + + // check if the code enclosed by simple formatting tags is a valid smiley code and skip formatting if + // it really is one. + if (PluginConfig.g_SmileyAddAvail && (endmark > (beginmark + 1))) { + CMStringW smcode = msg.Mid(beginmark, (endmark - beginmark) + 1); + + SMADD_BATCHPARSE2 smbp = {}; + smbp.cbSize = sizeof(smbp); + smbp.Protocolname = m_cache->getActiveProto(); + smbp.flag = SAFL_TCHAR | SAFL_PATH | (isSent ? SAFL_OUTGOING : 0); + smbp.str = (wchar_t*)smcode.c_str(); + smbp.hContact = m_hContact; + + SMADD_BATCHPARSERES *smbpr = (SMADD_BATCHPARSERES *)CallService(MS_SMILEYADD_BATCHPARSE, 0, (LPARAM)&smbp); + if (smbpr) { + CallService(MS_SMILEYADD_BATCHFREE, 0, (LPARAM)smbpr); + beginmark = endmark + 1; + continue; + } + } + msg.Delete(endmark, 1); + msg.Insert(endmark, formatting_strings_end[index]); + msg.Delete(beginmark, 1); + msg.Insert(beginmark, formatting_strings_begin[index]); + } + } + + m_bClrAdded = clr_was_added; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// format the title bar string for IM chat sessions using placeholders. +// the caller must mir_free() the returned string + +static wchar_t* Trunc500(wchar_t *str) +{ + if (mir_wstrlen(str) > 500) + str[500] = 0; + return str; +} + +bool CMsgDialog::FormatTitleBar(const wchar_t *szFormat, CMStringW &dest) +{ + for (const wchar_t *src = szFormat; *src; src++) { + if (*src != '%') { + dest.AppendChar(*src); + continue; + } + + switch (*++src) { + case 'n': + dest.Append(m_cache->getNick()); + break; + + case 'p': + case 'a': + dest.Append(m_cache->getRealAccount()); + break; + + case 's': + dest.Append(m_wszStatus); + break; + + case 'u': + dest.Append(m_cache->getUIN()); + break; + + case 'c': + dest.Append(!mir_wstrcmp(m_pContainer->m_wszName, L"default") ? TranslateT("Default container") : m_pContainer->m_wszName); + break; + + case 'o': + { + const char *szProto = m_cache->getActiveProto(); + if (szProto) + dest.Append(_A2T(szProto)); + } + break; + + case 'x': + { + uint8_t xStatus = m_cache->getXStatusId(); + if (m_wStatus != ID_STATUS_OFFLINE && xStatus > 0 && xStatus <= 31) { + ptrW szXStatus(db_get_wsa(m_hContact, m_szProto, "XStatusName")); + dest.Append((szXStatus != nullptr) ? Trunc500(szXStatus) : xStatusDescr[xStatus - 1]); + } + } + break; + + case 'm': + { + uint8_t xStatus = m_cache->getXStatusId(); + if (m_wStatus != ID_STATUS_OFFLINE && xStatus > 0 && xStatus <= 31) { + ptrW szXStatus(db_get_wsa(m_hContact, m_szProto, "XStatusName")); + dest.Append((szXStatus != nullptr) ? Trunc500(szXStatus) : xStatusDescr[xStatus - 1]); + } + else dest.Append(m_wszStatus[0] ? m_wszStatus : L"(undef)"); + } + break; + + // status message (%T will skip the "No status message" for empty messages) + case 't': + case 'T': + { + ptrW tszStatus(m_cache->getNormalizedStatusMsg(m_cache->getStatusMsg(), true)); + if (tszStatus) + dest.Append(tszStatus); + else if (*src == 't') + dest.Append(TranslateT("No status message")); + } + break; + + case 'g': + { + ptrW tszGroup(Clist_GetGroup(m_hContact)); + if (tszGroup != nullptr) + dest.Append(tszGroup); + } + break; + + case 0: // wrongly formed format string + return true; + } + } + + return true; +} + ///////////////////////////////////////////////////////////////////////////////////////// // retrieve the visiblity of the avatar window, depending on the global setting // and local mode @@ -748,6 +1045,64 @@ void CMsgDialog::HandlePasteAndSend() SendMessage(m_hwnd, WM_COMMAND, IDOK, 0); } +///////////////////////////////////////////////////////////////////////////////////////// +// convert the avatar bitmap to icon format so that it can be used on the task bar +// tries to keep correct aspect ratio of the avatar image +// +// @param dat: _MessageWindowData* pointer to the window data +// @return HICON: the icon handle + +HICON CMsgDialog::IconFromAvatar() const +{ + if (!ServiceExists(MS_AV_GETAVATARBITMAP)) + return nullptr; + + AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, m_hContact, 0); + if (ace == nullptr || ace->hbmPic == nullptr) + return nullptr; + + LONG lIconSize = Win7Taskbar->getIconSize(); + double dNewWidth, dNewHeight; + Utils::scaleAvatarHeightLimited(ace->hbmPic, dNewWidth, dNewHeight, lIconSize); + + // resize picture to fit it on the task bar, use an image list for converting it to + // 32bpp icon format. hTaskbarIcon will cache it until avatar is changed + HBITMAP hbmResized = ::Image_Resize(ace->hbmPic, RESIZEBITMAP_STRETCH, dNewWidth, dNewHeight); + HIMAGELIST hIml_c = ::ImageList_Create(lIconSize, lIconSize, ILC_COLOR32 | ILC_MASK, 1, 0); + + RECT rc = { 0, 0, lIconSize, lIconSize }; + + HDC hdc = ::GetDC(m_pContainer->m_hwnd); + HDC dc = ::CreateCompatibleDC(hdc); + HDC dcResized = ::CreateCompatibleDC(hdc); + + ReleaseDC(m_pContainer->m_hwnd, hdc); + + HBITMAP hbmNew = CSkin::CreateAeroCompatibleBitmap(rc, dc); + HBITMAP hbmOld = reinterpret_cast(::SelectObject(dc, hbmNew)); + HBITMAP hbmOldResized = reinterpret_cast(::SelectObject(dcResized, hbmResized)); + + LONG ix = (lIconSize - (LONG)dNewWidth) / 2; + LONG iy = (lIconSize - (LONG)dNewHeight) / 2; + CSkin::m_default_bf.SourceConstantAlpha = M.GetByte("taskBarIconAlpha", 255); + GdiAlphaBlend(dc, ix, iy, (LONG)dNewWidth, (LONG)dNewHeight, dcResized, 0, 0, (LONG)dNewWidth, (LONG)dNewHeight, CSkin::m_default_bf); + + CSkin::m_default_bf.SourceConstantAlpha = 255; + ::SelectObject(dc, hbmOld); + ::ImageList_Add(hIml_c, hbmNew, nullptr); + ::DeleteObject(hbmNew); + ::DeleteDC(dc); + + ::SelectObject(dcResized, hbmOldResized); + if (hbmResized != ace->hbmPic) + ::DeleteObject(hbmResized); + ::DeleteDC(dcResized); + HICON hIcon = ::ImageList_GetIcon(hIml_c, 0, ILD_NORMAL); + ::ImageList_RemoveAll(hIml_c); + ::ImageList_Destroy(hIml_c); + return hIcon; +} + ///////////////////////////////////////////////////////////////////////////////////////// // is window active or not? @@ -1215,7 +1570,7 @@ void CMsgDialog::NotifyDeliveryFailure() const void CMsgDialog::PlayIncomingSound() const { - int iPlay = MustPlaySound(); + int iPlay = m_pContainer->MustPlaySound(this); if (iPlay) { if (GetForegroundWindow() == m_pContainer->m_hwnd && m_pContainer->m_hwndActive == m_hwnd) Skin_PlaySound("RecvMsgActive"); diff --git a/plugins/TabSRMM/src/msgs.h b/plugins/TabSRMM/src/msgs.h index 4afba2da19..1bcc55a762 100644 --- a/plugins/TabSRMM/src/msgs.h +++ b/plugins/TabSRMM/src/msgs.h @@ -347,6 +347,7 @@ struct TContainerData : public MZeroedObject void InitRedraw(void); void LoadOverrideTheme(void); void LoadThemeDefaults(void); + bool MustPlaySound(const CMsgDialog *dat) const; void OptionsDialog(void); void QueryClientArea(RECT &rc); void QueryPending(void); @@ -687,7 +688,6 @@ public: void KbdState(bool &isShift, bool &isControl, bool &isAlt); void LimitMessageText(int iLen); int LoadLocalFlags(void); - bool MustPlaySound(void) const; void NotifyDeliveryFailure(void) const; void RemakeLog(void); void SaveSplitter(void); diff --git a/plugins/TabSRMM/src/utils.cpp b/plugins/TabSRMM/src/utils.cpp index e1b3a9e511..be370dfaf8 100644 --- a/plugins/TabSRMM/src/utils.cpp +++ b/plugins/TabSRMM/src/utils.cpp @@ -35,279 +35,6 @@ OBJLIST Utils::rtf_clrs(10); MWindowList CWarning::hWindowList = nullptr; -static wchar_t *w_bbcodes_begin[] = { L"[b]", L"[i]", L"[u]", L"[s]", L"[color=" }; -static wchar_t *w_bbcodes_end[] = { L"[/b]", L"[/i]", L"[/u]", L"[/s]", L"[/color]" }; - -static wchar_t *formatting_strings_begin[] = { L"b1 ", L"i1 ", L"u1 ", L"s1 ", L"c1 " }; -static wchar_t *formatting_strings_end[] = { L"b0 ", L"i0 ", L"u0 ", L"s0 ", L"c0 " }; - -#define NR_CODES 5 - -///////////////////////////////////////////////////////////////////////////////////////// -// this translates formatting tags into rtf sequences... -// flags: loword = words only for simple * /_ formatting -// hiword = bbcode support (strip bbcodes if 0) - -void CMsgDialog::FormatRaw(CMStringW &msg, int flags, bool isSent) -{ - bool clr_was_added = false, was_added; - int beginmark = 0, endmark = 0, tempmark = 0, index; - int i, endindex; - wchar_t endmarker; - - if (m_dwFlags & MWF_LOG_BBCODE) { - beginmark = 0; - while (true) { - for (i = 0; i < NR_CODES; i++) - if ((tempmark = msg.Find(w_bbcodes_begin[i], 0)) != -1) - break; - - if (i >= NR_CODES) - break; - - beginmark = tempmark; - endindex = i; - endmark = msg.Find(w_bbcodes_end[i], beginmark); - if (endindex == 4) { // color - int closing = msg.Find(L"]", beginmark); - was_added = false; - - if (closing == -1) { // must be an invalid [color=] tag w/o closing bracket - msg.SetAt(beginmark, ' '); - continue; - } - - CMStringW colorname = msg.Mid(beginmark + 7, closing - beginmark - 7); -search_again: - bool clr_found = false; - for (int ii = 0; ii < Utils::rtf_clrs.getCount(); ii++) { - auto &rtfc = Utils::rtf_clrs[ii]; - if (!wcsicmp(colorname, rtfc.szName)) { - closing = beginmark + 7 + (int)mir_wstrlen(rtfc.szName); - if (endmark != -1) { - msg.Delete(endmark, 8); - msg.Insert(endmark, L"c0 "); - } - msg.Delete(beginmark, closing - beginmark + 1); - - wchar_t szTemp[5]; - msg.Insert(beginmark, L"cxxx "); - mir_snwprintf(szTemp, L"%02d", MSGDLGFONTCOUNT + 13 + ii); - msg.SetAt(beginmark + 3, szTemp[0]); - msg.SetAt(beginmark + 4, szTemp[1]); - clr_found = true; - if (was_added) { - wchar_t wszTemp[100]; - mir_snwprintf(wszTemp, L"##col##%06u:%04u", endmark - closing, ii); - wszTemp[99] = 0; - msg.Insert(beginmark, wszTemp); - } - break; - } - } - if (!clr_found) { - int c_closing = colorname.Find(L"]"); - if (c_closing == -1) - c_closing = colorname.GetLength(); - const wchar_t *wszColname = colorname.c_str(); - if (endmark != -1 && c_closing > 2 && c_closing <= 6 && iswalnum(colorname[0]) && iswalnum(colorname[c_closing - 1])) { - Utils::RTF_ColorAdd(wszColname); - if (!was_added) { - clr_was_added = was_added = true; - goto search_again; - } - else goto invalid_code; - } - else { -invalid_code: - if (endmark != -1) - msg.Delete(endmark, 8); - if (closing != -1 && closing < endmark) - msg.Delete(beginmark, (closing - beginmark) + 1); - else - msg.SetAt(beginmark, ' '); - } - } - continue; - } - - if (endmark != -1) { - msg.Delete(endmark, 4); - msg.Insert(endmark, formatting_strings_end[i]); - } - msg.Delete(beginmark, 3); - msg.Insert(beginmark, L" "); - msg.Insert(beginmark, formatting_strings_begin[i]); - } - } - - if ((m_dwFlags & MWF_LOG_TEXTFORMAT) && msg.Find(L"://") == -1) { - while ((beginmark = msg.Find(L"*/_", beginmark)) != -1) { - endmarker = msg[beginmark]; - if (LOWORD(flags)) { - if (beginmark > 0 && !iswspace(msg[beginmark - 1]) && !iswpunct(msg[beginmark - 1])) { - beginmark++; - continue; - } - - // search a corresponding endmarker which fulfills the criteria - INT_PTR mark = beginmark + 1; - while ((endmark = msg.Find(endmarker, mark)) != -1) { - if (iswpunct(msg[endmark + 1]) || iswspace(msg[endmark + 1]) || msg[endmark + 1] == 0 || wcschr(L"*/_", msg[endmark + 1]) != nullptr) - goto ok; - mark = endmark + 1; - } - break; - } - else { - if ((endmark = msg.Find(endmarker, beginmark + 1)) == -1) - break; - } -ok: - if ((endmark - beginmark) < 2) { - beginmark++; - continue; - } - index = 0; - switch (endmarker) { - case '*': - index = 0; - break; - case '/': - index = 1; - break; - case '_': - index = 2; - break; - } - - // check if the code enclosed by simple formatting tags is a valid smiley code and skip formatting if - // it really is one. - if (PluginConfig.g_SmileyAddAvail && (endmark > (beginmark + 1))) { - CMStringW smcode = msg.Mid(beginmark, (endmark - beginmark) + 1); - - SMADD_BATCHPARSE2 smbp = {}; - smbp.cbSize = sizeof(smbp); - smbp.Protocolname = m_cache->getActiveProto(); - smbp.flag = SAFL_TCHAR | SAFL_PATH | (isSent ? SAFL_OUTGOING : 0); - smbp.str = (wchar_t*)smcode.c_str(); - smbp.hContact = m_hContact; - - SMADD_BATCHPARSERES *smbpr = (SMADD_BATCHPARSERES *)CallService(MS_SMILEYADD_BATCHPARSE, 0, (LPARAM)&smbp); - if (smbpr) { - CallService(MS_SMILEYADD_BATCHFREE, 0, (LPARAM)smbpr); - beginmark = endmark + 1; - continue; - } - } - msg.Delete(endmark, 1); - msg.Insert(endmark, formatting_strings_end[index]); - msg.Delete(beginmark, 1); - msg.Insert(beginmark, formatting_strings_begin[index]); - } - } - - m_bClrAdded = clr_was_added; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// format the title bar string for IM chat sessions using placeholders. -// the caller must mir_free() the returned string - -static wchar_t* Trunc500(wchar_t *str) -{ - if (mir_wstrlen(str) > 500) - str[500] = 0; - return str; -} - -bool CMsgDialog::FormatTitleBar(const wchar_t *szFormat, CMStringW &dest) -{ - for (const wchar_t *src = szFormat; *src; src++) { - if (*src != '%') { - dest.AppendChar(*src); - continue; - } - - switch (*++src) { - case 'n': - dest.Append(m_cache->getNick()); - break; - - case 'p': - case 'a': - dest.Append(m_cache->getRealAccount()); - break; - - case 's': - dest.Append(m_wszStatus); - break; - - case 'u': - dest.Append(m_cache->getUIN()); - break; - - case 'c': - dest.Append(!mir_wstrcmp(m_pContainer->m_wszName, L"default") ? TranslateT("Default container") : m_pContainer->m_wszName); - break; - - case 'o': - { - const char *szProto = m_cache->getActiveProto(); - if (szProto) - dest.Append(_A2T(szProto)); - } - break; - - case 'x': - { - uint8_t xStatus = m_cache->getXStatusId(); - if (m_wStatus != ID_STATUS_OFFLINE && xStatus > 0 && xStatus <= 31) { - ptrW szXStatus(db_get_wsa(m_hContact, m_szProto, "XStatusName")); - dest.Append((szXStatus != nullptr) ? Trunc500(szXStatus) : xStatusDescr[xStatus - 1]); - } - } - break; - - case 'm': - { - uint8_t xStatus = m_cache->getXStatusId(); - if (m_wStatus != ID_STATUS_OFFLINE && xStatus > 0 && xStatus <= 31) { - ptrW szXStatus(db_get_wsa(m_hContact, m_szProto, "XStatusName")); - dest.Append((szXStatus != nullptr) ? Trunc500(szXStatus) : xStatusDescr[xStatus - 1]); - } - else dest.Append(m_wszStatus[0] ? m_wszStatus : L"(undef)"); - } - break; - - // status message (%T will skip the "No status message" for empty messages) - case 't': - case 'T': - { - ptrW tszStatus(m_cache->getNormalizedStatusMsg(m_cache->getStatusMsg(), true)); - if (tszStatus) - dest.Append(tszStatus); - else if (*src == 't') - dest.Append(TranslateT("No status message")); - } - break; - - case 'g': - { - ptrW tszGroup(Clist_GetGroup(m_hContact)); - if (tszGroup != nullptr) - dest.Append(tszGroup); - } - break; - - case 0: // wrongly formed format string - return true; - } - } - - return true; -} - ///////////////////////////////////////////////////////////////////////////////////////// char* Utils::FilterEventMarkers(char *szText) @@ -384,33 +111,6 @@ wchar_t* Utils::GetPreviewWithEllipsis(wchar_t *szText, size_t iMaxLen) return szResult; } -///////////////////////////////////////////////////////////////////////////////////////// -// returns != 0 when one of the installed keyboard layouts belongs to an rtl language -// used to find out whether we need to configure the message input box for bidirectional mode - -int CMsgDialog::FindRTLLocale() -{ - HKL layouts[20]; - int i, result = 0; - LCID lcid; - uint16_t wCtype2[5]; - - if (m_iHaveRTLLang == 0) { - memset(layouts, 0, sizeof(layouts)); - GetKeyboardLayoutList(20, layouts); - for (i = 0; i < 20 && layouts[i]; i++) { - lcid = MAKELCID(LOWORD(layouts[i]), 0); - GetStringTypeA(lcid, CT_CTYPE2, "���", 3, wCtype2); - if (wCtype2[0] == C2_RIGHTTOLEFT || wCtype2[1] == C2_RIGHTTOLEFT || wCtype2[2] == C2_RIGHTTOLEFT) - result = 1; - } - m_iHaveRTLLang = (result ? 1 : -1); - } - else result = m_iHaveRTLLang == 1 ? 1 : 0; - - return result; -} - ///////////////////////////////////////////////////////////////////////////////////////// // init default color table. the table may grow when using custom colors via bbcodes @@ -574,64 +274,6 @@ void Utils::scaleAvatarHeightLimited(const HBITMAP hBm, double& dNewWidth, doubl } } -///////////////////////////////////////////////////////////////////////////////////////// -// convert the avatar bitmap to icon format so that it can be used on the task bar -// tries to keep correct aspect ratio of the avatar image -// -// @param dat: _MessageWindowData* pointer to the window data -// @return HICON: the icon handle - -HICON CMsgDialog::IconFromAvatar() const -{ - if (!ServiceExists(MS_AV_GETAVATARBITMAP)) - return nullptr; - - AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, m_hContact, 0); - if (ace == nullptr || ace->hbmPic == nullptr) - return nullptr; - - LONG lIconSize = Win7Taskbar->getIconSize(); - double dNewWidth, dNewHeight; - Utils::scaleAvatarHeightLimited(ace->hbmPic, dNewWidth, dNewHeight, lIconSize); - - // resize picture to fit it on the task bar, use an image list for converting it to - // 32bpp icon format. hTaskbarIcon will cache it until avatar is changed - HBITMAP hbmResized = ::Image_Resize(ace->hbmPic, RESIZEBITMAP_STRETCH, dNewWidth, dNewHeight); - HIMAGELIST hIml_c = ::ImageList_Create(lIconSize, lIconSize, ILC_COLOR32 | ILC_MASK, 1, 0); - - RECT rc = { 0, 0, lIconSize, lIconSize }; - - HDC hdc = ::GetDC(m_pContainer->m_hwnd); - HDC dc = ::CreateCompatibleDC(hdc); - HDC dcResized = ::CreateCompatibleDC(hdc); - - ReleaseDC(m_pContainer->m_hwnd, hdc); - - HBITMAP hbmNew = CSkin::CreateAeroCompatibleBitmap(rc, dc); - HBITMAP hbmOld = reinterpret_cast(::SelectObject(dc, hbmNew)); - HBITMAP hbmOldResized = reinterpret_cast(::SelectObject(dcResized, hbmResized)); - - LONG ix = (lIconSize - (LONG)dNewWidth) / 2; - LONG iy = (lIconSize - (LONG)dNewHeight) / 2; - CSkin::m_default_bf.SourceConstantAlpha = M.GetByte("taskBarIconAlpha", 255); - GdiAlphaBlend(dc, ix, iy, (LONG)dNewWidth, (LONG)dNewHeight, dcResized, 0, 0, (LONG)dNewWidth, (LONG)dNewHeight, CSkin::m_default_bf); - - CSkin::m_default_bf.SourceConstantAlpha = 255; - ::SelectObject(dc, hbmOld); - ::ImageList_Add(hIml_c, hbmNew, nullptr); - ::DeleteObject(hbmNew); - ::DeleteDC(dc); - - ::SelectObject(dcResized, hbmOldResized); - if (hbmResized != ace->hbmPic) - ::DeleteObject(hbmResized); - ::DeleteDC(dcResized); - HICON hIcon = ::ImageList_GetIcon(hIml_c, 0, ILD_NORMAL); - ::ImageList_RemoveAll(hIml_c); - ::ImageList_Destroy(hIml_c); - return hIcon; -} - AVATARCACHEENTRY* Utils::loadAvatarFromAVS(const MCONTACT hContact) { if (!ServiceExists(MS_AV_GETAVATARBITMAP)) @@ -679,32 +321,6 @@ void Utils::addMenuItem(const HMENU& m, MENUITEMINFO &mii, HICON hIcon, const wc ::InsertMenuItem(m, pos, TRUE, &mii); } -///////////////////////////////////////////////////////////////////////////////////////// -// return != 0 when the sound effect must be played for the given -// session. Uses container sound settings - -bool CMsgDialog::MustPlaySound() const -{ - if (m_pContainer->m_bHidden) // hidden container is treated as closed, so play the sound - return true; - - if (m_pContainer->cfg.flags.m_bNoSound || NEN::bNoSounds) - return false; - - // window minimized, check if sound has to be played - if (::IsIconic(m_pContainer->m_hwnd)) - return m_pContainer->cfg.flagsEx.m_bSoundMinimized; - - // window in foreground - if (m_pContainer->m_hwnd != ::GetForegroundWindow()) - return m_pContainer->cfg.flagsEx.m_bSoundUnfocused; - - if (m_pContainer->m_hwndActive == GetHwnd()) - return m_pContainer->cfg.flagsEx.m_bSoundFocused; - - return m_pContainer->cfg.flagsEx.m_bSoundInactive; -} - ///////////////////////////////////////////////////////////////////////////////////////// // enable or disable a dialog control -- cgit v1.2.3