From 3f1628f127d35aa14da97e50c2a94cfd61ad52dd Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 11 May 2018 21:22:17 +0200 Subject: merge from master to fixes #1349 (Miranda crashes on coming back from auto away) --- plugins/MyDetails/src/data.cpp | 2 +- plugins/Scriver/res/resource.rc | 4 +- plugins/Scriver/src/chat_window.cpp | 14 +- plugins/Scriver/src/globals.cpp | 2 - plugins/Scriver/src/globals.h | 1 - plugins/Scriver/src/msgdialog.cpp | 12 +- plugins/Scriver/src/msgoptions.cpp | 4 - plugins/Scriver/src/msgs.h | 2 - plugins/Scriver/src/resource.h | 1 - plugins/Scriver/src/version.h | 2 +- plugins/SimpleStatusMsg/src/main.cpp | 3 +- plugins/SmileyAdd/src/options.cpp | 4 +- plugins/SmileyAdd/src/smileys.cpp | 1928 +++++++++++--------- plugins/SmileyAdd/src/smileys.h | 3 + plugins/SmileyAdd/src/stdafx.h | 1 + plugins/SmileyAdd/src/version.h | 2 +- .../src/AdvancedAutoAway/advancedautoaway.cpp | 2 +- .../StatusManager/src/KeepStatus/keepstatus.cpp | 6 +- .../src/StartupStatus/ss_profiles.cpp | 2 +- .../src/StartupStatus/startupstatus.cpp | 2 +- plugins/StatusManager/src/commonstatus.cpp | 59 +- plugins/StatusManager/src/commonstatus.h | 2 + plugins/StatusManager/src/confirmdialog.cpp | 28 +- plugins/StatusManager/src/version.h | 4 +- plugins/TabSRMM/src/resource.h | 1 - src/core/stdmsg/res/resource.rc | 35 +- src/core/stdmsg/src/chat_manager.cpp | 28 +- src/core/stdmsg/src/chat_options.cpp | 2 - src/core/stdmsg/src/chat_window.cpp | 30 +- src/core/stdmsg/src/globals.cpp | 3 +- src/core/stdmsg/src/globals.h | 2 +- src/core/stdmsg/src/msgdialog.cpp | 84 +- src/core/stdmsg/src/msgoptions.cpp | 8 +- src/core/stdmsg/src/msgs.cpp | 38 +- src/core/stdmsg/src/msgs.h | 66 +- src/core/stdmsg/src/resource.h | 14 +- src/core/stdmsg/src/stdafx.h | 9 +- src/core/stdmsg/src/tabs.cpp | 51 +- src/mir_app/src/clisttray.cpp | 2 - 39 files changed, 1245 insertions(+), 1218 deletions(-) diff --git a/plugins/MyDetails/src/data.cpp b/plugins/MyDetails/src/data.cpp index 8dda970f0a..813041948d 100644 --- a/plugins/MyDetails/src/data.cpp +++ b/plugins/MyDetails/src/data.cpp @@ -154,7 +154,7 @@ void Protocol::SetStatus(int aStatus) GetStatusMsg(aStatus, status_msg, _countof(status_msg)); pse[0]->m_szMsg = status_msg; - CallService(MS_CS_SETSTATUSEX, (WPARAM)&pse, 0); + CallService(MS_CS_SETSTATUSEX, (WPARAM)&pse, pCount); for (int i = 0; i < pCount; i++) mir_free(pse[i]); diff --git a/plugins/Scriver/res/resource.rc b/plugins/Scriver/res/resource.rc index 69aadc0e0d..b5254672e9 100644 --- a/plugins/Scriver/res/resource.rc +++ b/plugins/Scriver/res/resource.rc @@ -91,9 +91,7 @@ BEGIN CONTROL "Show toolbar",IDC_SHOWTOOLBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,34,180,10 CONTROL "Show info bar",IDC_SHOWINFOBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,45,180,10 CONTROL "Show avatars",IDC_AVATARSUPPORT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,56,180,10 - CONTROL "Use the contact's status icon as the window icon",IDC_STATUSWIN, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,67,292,10 - CONTROL "Show progress indicator",IDC_SHOWPROGRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,78,180,10 + CONTROL "Show progress indicator",IDC_SHOWPROGRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,67,180,10 CONTROL "Enable transparency",IDC_TRANSPARENCY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,95,140,10 LTEXT "active",IDC_TRANSPARENCYTEXT1,152,91,36,8 CONTROL "Slider1",IDC_ATRANSPARENCYVALUE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,194,91,70,12 diff --git a/plugins/Scriver/src/chat_window.cpp b/plugins/Scriver/src/chat_window.cpp index 7331033f84..ad31b1805e 100644 --- a/plugins/Scriver/src/chat_window.cpp +++ b/plugins/Scriver/src/chat_window.cpp @@ -533,16 +533,11 @@ void CChatRoomDlg::UpdateStatusBar() void CChatRoomDlg::UpdateTitle() { + MODULEINFO *mi = pci->MM_FindModule(m_si->pszModule); + TitleBarData tbd = {}; - if (g_dat.flags & SMF_STATUSICON) { - MODULEINFO *mi = pci->MM_FindModule(m_si->pszModule); - tbd.hIcon = (m_si->wStatus == ID_STATUS_ONLINE) ? mi->hOnlineIcon : mi->hOfflineIcon; - tbd.hIconBig = (m_si->wStatus == ID_STATUS_ONLINE) ? mi->hOnlineIconBig : mi->hOfflineIconBig; - } - else { - tbd.hIcon = GetCachedIcon("chat_window"); - tbd.hIconBig = g_dat.hIconChatBig; - } + tbd.hIcon = (m_si->wStatus == ID_STATUS_ONLINE) ? mi->hOnlineIcon : mi->hOfflineIcon; + tbd.hIconBig = (m_si->wStatus == ID_STATUS_ONLINE) ? mi->hOnlineIconBig : mi->hOfflineIconBig; tbd.hIconNot = (m_si->wState & (GC_EVENT_HIGHLIGHT | STATE_TALK)) ? GetCachedIcon("chat_overlay") : nullptr; wchar_t szTemp[512]; @@ -564,6 +559,7 @@ void CChatRoomDlg::UpdateTitle() tbd.iFlags = TBDF_TEXT | TBDF_ICON; tbd.pszText = szTemp; SendMessage(m_hwndParent, CM_UPDATETITLEBAR, (WPARAM)&tbd, (LPARAM)m_hwnd); + SendMessage(m_hwnd, DM_UPDATETABCONTROL, 0, 0); } diff --git a/plugins/Scriver/src/globals.cpp b/plugins/Scriver/src/globals.cpp index 058f0d5286..0886f048cc 100644 --- a/plugins/Scriver/src/globals.cpp +++ b/plugins/Scriver/src/globals.cpp @@ -366,8 +366,6 @@ void ReloadGlobals() g_dat.flags |= SMF_SENDONENTER; if (db_get_b(0, SRMM_MODULE, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER)) g_dat.flags |= SMF_SENDONDBLENTER; - if (db_get_b(0, SRMM_MODULE, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)) - g_dat.flags |= SMF_STATUSICON; if (db_get_b(0, SRMM_MODULE, SRMSGSET_INDENTTEXT, SRMSGDEFSET_INDENTTEXT)) g_dat.flags |= SMF_INDENTTEXT; diff --git a/plugins/Scriver/src/globals.h b/plugins/Scriver/src/globals.h index a396493a4a..652a077f86 100644 --- a/plugins/Scriver/src/globals.h +++ b/plugins/Scriver/src/globals.h @@ -33,7 +33,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define SMF_SENDONDBLENTER 0x00000200 #define SMF_SHOWPROGRESS 0x00000400 #define SMF_AVATAR 0x00000800 -#define SMF_STATUSICON 0x00002000 #define SMF_RTL 0x00004000 #define SMF_USEIEVIEW 0x00010000 #define SMF_SHOWICONS 0x00020000 diff --git a/plugins/Scriver/src/msgdialog.cpp b/plugins/Scriver/src/msgdialog.cpp index faddf76067..a9110a2e03 100644 --- a/plugins/Scriver/src/msgdialog.cpp +++ b/plugins/Scriver/src/msgdialog.cpp @@ -598,14 +598,14 @@ void CSrmmWindow::GetTitlebarIcon(TitleBarData *tbd) if (m_bShowTyping && (g_dat.flags2 & SMF2_SHOWTYPINGWIN)) tbd->hIconNot = tbd->hIcon = GetCachedIcon("scriver_TYPING"); else if (m_iShowUnread && (GetActiveWindow() != m_hwndParent || GetForegroundWindow() != m_hwndParent)) { - tbd->hIcon = (g_dat.flags & SMF_STATUSICON) ? m_hStatusIcon : g_dat.hMsgIcon; - tbd->hIconNot = (g_dat.flags & SMF_STATUSICON) ? g_dat.hMsgIcon : GetCachedIcon("scriver_OVERLAY"); + tbd->hIcon = m_hStatusIcon; + tbd->hIconNot = g_dat.hMsgIcon; } else { - tbd->hIcon = (g_dat.flags & SMF_STATUSICON) ? m_hStatusIcon : g_dat.hMsgIcon; + tbd->hIcon = m_hStatusIcon; tbd->hIconNot = nullptr; } - tbd->hIconBig = (g_dat.flags & SMF_STATUSICON) ? m_hStatusIconBig : g_dat.hMsgIconBig; + tbd->hIconBig = m_hStatusIconBig; } bool CSrmmWindow::IsTypingNotificationSupported() @@ -784,10 +784,8 @@ void CSrmmWindow::UpdateTitle() ptrW tmplt(db_get_wsa(0, SRMM_MODULE, SRMSGSET_WINDOWTITLE)); if (tmplt != nullptr) wszTitle = tmplt; - else if (g_dat.flags & SMF_STATUSICON) - wszTitle = L"%name% - "; else - wszTitle = L"%name% (%status%) : "; + wszTitle = L"%name% - "; if (m_hContact && m_szProto) { wszTitle.Replace(L"%name%", Clist_GetContactDisplayName(m_hContact)); diff --git a/plugins/Scriver/src/msgoptions.cpp b/plugins/Scriver/src/msgoptions.cpp index ecaac38ec9..0ddefba75d 100644 --- a/plugins/Scriver/src/msgoptions.cpp +++ b/plugins/Scriver/src/msgoptions.cpp @@ -398,7 +398,6 @@ static INT_PTR CALLBACK DlgProcLayoutOptions(HWND hwndDlg, UINT msg, WPARAM wPar EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSPARENCYTEXT1), bChecked); EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSPARENCYTEXT2), bChecked); - CheckDlgButton(hwndDlg, IDC_STATUSWIN, db_get_b(0, SRMM_MODULE, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_SHOWPROGRESS, db_get_b(0, SRMM_MODULE, SRMSGSET_SHOWPROGRESS, SRMSGDEFSET_SHOWPROGRESS) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_AVATARSUPPORT, g_dat.flags & SMF_AVATAR); return TRUE; @@ -449,7 +448,6 @@ static INT_PTR CALLBACK DlgProcLayoutOptions(HWND hwndDlg, UINT msg, WPARAM wPar db_set_dw(0, SRMM_MODULE, SRMSGSET_ACTIVEALPHA, SendDlgItemMessage(hwndDlg, IDC_ATRANSPARENCYVALUE, TBM_GETPOS, 0, 0)); db_set_dw(0, SRMM_MODULE, SRMSGSET_INACTIVEALPHA, SendDlgItemMessage(hwndDlg, IDC_ITRANSPARENCYVALUE, TBM_GETPOS, 0, 0)); - db_set_b(0, SRMM_MODULE, SRMSGSET_STATUSICON, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_STATUSWIN)); db_set_b(0, SRMM_MODULE, SRMSGSET_SHOWPROGRESS, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SHOWPROGRESS)); db_set_b(0, SRMM_MODULE, SRMSGSET_AVATARENABLE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)); @@ -487,8 +485,6 @@ static INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LP CheckDlgButton(hwndDlg, IDC_CASCADE, db_get_b(0, SRMM_MODULE, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_SENDONENTER, db_get_b(0, SRMM_MODULE, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_SENDONDBLENTER, db_get_b(0, SRMM_MODULE, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_STATUSWIN, db_get_b(0, SRMM_MODULE, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_HIDECONTAINERS, db_get_b(0, SRMM_MODULE, SRMSGSET_HIDECONTAINERS, SRMSGDEFSET_HIDECONTAINERS) ? BST_CHECKED : BST_UNCHECKED); EnableWindow(GetDlgItem(hwndDlg, IDC_STAYMINIMIZED), IsDlgButtonChecked(hwndDlg, IDC_AUTOPOPUP)); diff --git a/plugins/Scriver/src/msgs.h b/plugins/Scriver/src/msgs.h index bb209cb686..16c6b6e5d6 100644 --- a/plugins/Scriver/src/msgs.h +++ b/plugins/Scriver/src/msgs.h @@ -374,8 +374,6 @@ extern int fontOptionsListSize; #define SRMSGDEFSET_SENDONENTER 1 #define SRMSGSET_SENDONDBLENTER "SendOnDblEnter" #define SRMSGDEFSET_SENDONDBLENTER 0 -#define SRMSGSET_STATUSICON "UseStatusWinIcon" -#define SRMSGDEFSET_STATUSICON 0 #define SRMSGSET_SENDBUTTON "UseSendButton" #define SRMSGDEFSET_SENDBUTTON 0 #define SRMSGSET_CHARCOUNT "ShowCharCount" diff --git a/plugins/Scriver/src/resource.h b/plugins/Scriver/src/resource.h index 7966a71277..7b429acd80 100644 --- a/plugins/Scriver/src/resource.h +++ b/plugins/Scriver/src/resource.h @@ -125,7 +125,6 @@ #define IDC_ERRORTEXT 1596 #define IDC_MSGTEXT 1597 #define IDC_SHOWNOTIFY 1600 -#define IDC_STATUSWIN 1601 #define IDC_TYPEWIN 1602 #define IDC_TYPETRAY 1603 #define IDC_TABSATBOTTOM 1603 diff --git a/plugins/Scriver/src/version.h b/plugins/Scriver/src/version.h index d6cf92b2b3..fc56d643d5 100644 --- a/plugins/Scriver/src/version.h +++ b/plugins/Scriver/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 3 #define __MINOR_VERSION 0 #define __RELEASE_NUM 1 -#define __BUILD_NUM 7 +#define __BUILD_NUM 8 #include diff --git a/plugins/SimpleStatusMsg/src/main.cpp b/plugins/SimpleStatusMsg/src/main.cpp index 1e01eb7936..92575882db 100644 --- a/plugins/SimpleStatusMsg/src/main.cpp +++ b/plugins/SimpleStatusMsg/src/main.cpp @@ -1727,8 +1727,7 @@ static int OnModulesLoaded(WPARAM, LPARAM) if (db_get_b(NULL, "SimpleStatusMsg", "UpdateMsgOn", 1)) g_uUpdateMsgTimer = SetTimer(nullptr, 0, db_get_w(NULL, "SimpleStatusMsg", "UpdateMsgInt", 10) * 1000, UpdateMsgTimerProc); - if (ServiceExists(MS_CS_SETSTATUSEX)) - HookEvent(ME_CS_STATUSCHANGEEX, CSStatusChange); + HookEvent(ME_CS_STATUSCHANGEEX, CSStatusChange); if (accounts->statusCount == 0) return 0; diff --git a/plugins/SmileyAdd/src/options.cpp b/plugins/SmileyAdd/src/options.cpp index 897982ade5..de31cf1b8a 100644 --- a/plugins/SmileyAdd/src/options.cpp +++ b/plugins/SmileyAdd/src/options.cpp @@ -482,9 +482,9 @@ bool OptionsDialogType::BrowseForSmileyPacks(int item) wchar_t filter[512], *pfilter; mir_wstrcpy(filter, TranslateT("Smiley packs")); - mir_wstrcat(filter, L" (*.msl;*.asl)"); + mir_wstrcat(filter, L" (*.msl;*.asl;*.xep)"); pfilter = filter + mir_wstrlen(filter) + 1; - mir_wstrcpy(pfilter, L"*.msl;*.asl"); + mir_wstrcpy(pfilter, L"*.msl;*.asl;*.xep"); pfilter = pfilter + mir_wstrlen(pfilter) + 1; mir_wstrcpy(pfilter, TranslateT("All files")); mir_wstrcat(pfilter, L" (*.*)"); diff --git a/plugins/SmileyAdd/src/smileys.cpp b/plugins/SmileyAdd/src/smileys.cpp index 73a303a393..6c19d195f0 100644 --- a/plugins/SmileyAdd/src/smileys.cpp +++ b/plugins/SmileyAdd/src/smileys.cpp @@ -1,911 +1,1017 @@ -/* -Miranda NG SmileyAdd Plugin -Copyright (C) 2012-18 Miranda NG team (https://miranda-ng.org) -Copyright (C) 2005-11 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2003-04 Rein-Peter de Boer - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#include "stdafx.h" - -SmileyPackListType g_SmileyPacks; -SmileyCategoryListType g_SmileyCategories; - -static HWND hwndHidden = nullptr; - -static void CALLBACK timerProc(HWND, UINT, UINT_PTR param, DWORD) -{ - SmileyType *pType = (SmileyType*)param; - pType->MoveToNextFrame(); -} - -// these two functions must be called from the main thread -static void CALLBACK sttStartTimer(PVOID obj) -{ - if (hwndHidden == nullptr) - hwndHidden = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); - - SmileyType *pType = (SmileyType*)obj; - pType->SetFrameDelay(); -} - -static void CALLBACK sttStopTimer(PVOID obj) -{ - KillTimer(hwndHidden, (DWORD_PTR)obj); -} - -// -// SmileyType -// - -SmileyType::SmileyType(void) : - m_arSmileys(10, PtrKeySortT) -{ - m_SmileyIcon = nullptr; - m_xepimg = nullptr; - m_flags = 0; - m_index = 0; - m_size.cx = 0; - m_size.cy = 0; -} - -SmileyType::~SmileyType() -{ - if (m_xepimg) { - m_xepimg->Release(); - m_xepimg = nullptr; - } - - if (m_SmileyIcon != nullptr) { - DestroyIcon(m_SmileyIcon); - m_SmileyIcon = nullptr; - } -} - -void SmileyType::AddObject(ISmileyBase *pObject) -{ - if (m_arSmileys.getCount() == 0) { - if (m_xepimg == nullptr) - m_xepimg = AddCacheImage(m_filepath, m_index); - CallFunctionAsync(sttStartTimer, this); - } - - m_arSmileys.insert(pObject); -} - -void SmileyType::RemoveObject(ISmileyBase *pObject) -{ - int idx = m_arSmileys.getIndex(pObject); - if (idx == -1) - return; - - m_arSmileys.remove(idx); - if (m_arSmileys.getCount() == 0) - CallFunctionAsync(sttStopTimer, this); -} - -void SmileyType::SetFrameDelay() -{ - int iFrameDelay = (m_xepimg == nullptr) ? 0 : m_xepimg->GetFrameDelay(); - if (iFrameDelay <= 0) - KillTimer(hwndHidden, (DWORD_PTR)this); - else - SetTimer(hwndHidden, (DWORD_PTR)this, iFrameDelay*10, timerProc); -} - -void SmileyType::MoveToNextFrame() -{ - m_index = m_xepimg->SelectNextFrame(m_index); - - for (auto &it : m_arSmileys) - it->Draw(); - - SetFrameDelay(); // reset timer -} - -HICON SmileyType::GetIcon(void) -{ - if (m_SmileyIcon == nullptr) { - ImageBase *img = CreateCachedImage(); - if (!img) - return nullptr; - - img->SelectFrame(m_index); - m_SmileyIcon = img->GetIcon(); - img->Release(); - } - return m_SmileyIcon; -} - -HICON SmileyType::GetIconDup(void) -{ - ImageBase *img = CreateCachedImage(); - img->SelectFrame(m_index); - HICON hIcon = img->GetIcon(); - img->Release(); - return hIcon; -} - -bool SmileyType::LoadFromImage(IStream *pStream) -{ - if (m_xepimg) - m_xepimg->Release(); - - CMStringW name; - m_xepimg = new ImageType(0, name, pStream); - return true; -} - -bool SmileyType::LoadFromResource(const CMStringW &file, const int index) -{ - m_index = index; - m_filepath = file; - return true; -} - -void SmileyType::GetSize(SIZE &size) -{ - if (m_size.cy == 0) { - ImageBase *img = CreateCachedImage(); - if (img) { - img->GetSize(m_size); - img->Release(); - } - } - size = m_size; -} - -ImageBase* SmileyType::CreateCachedImage(void) -{ - if (m_xepimg) { - m_xepimg->AddRef(); - return m_xepimg; - } - return AddCacheImage(m_filepath, m_index); -} - -void SmileyType::SetImList(HIMAGELIST hImLst, long i) -{ - if (m_xepimg) m_xepimg->Release(); - m_xepimg = new ImageListItemType(0, hImLst, i); -} - -HBITMAP SmileyType::GetBitmap(COLORREF bkgClr, int sizeX, int sizeY) -{ - ImageBase *img = CreateCachedImage(); - if (!img) return nullptr; - img->SelectFrame(m_index); - HBITMAP hBmp = img->GetBitmap(bkgClr, sizeX, sizeY); - img->Release(); - - return hBmp; -} - -// -// SmileyPackType -// - -SmileyPackType::SmileyPackType() -{ - m_hSmList = nullptr; - errorFound = false; -} - -SmileyType* SmileyPackType::GetSmiley(unsigned index) -{ - return (index < (unsigned)m_SmileyList.getCount()) ? &m_SmileyList[index] : nullptr; -} - -static DWORD_PTR ConvertServiceParam(MCONTACT hContact, const wchar_t *param) -{ - if (param == nullptr) - return 0; - if (mir_wstrcmpi(L"hContact", param) == 0) - return hContact; - if (iswdigit(*param)) - return _wtoi(param); - - return (DWORD_PTR)param; -} - -void SmileyType::CallSmileyService(MCONTACT hContact) -{ - MRegexp16 srvsplit(L"(.*)\\|(.*)\\|(.*)"); - srvsplit.match(m_TriggerText); - - CMStringW name = srvsplit.getGroup(1); - CMStringW par1 = srvsplit.getGroup(2); - CMStringW par2 = srvsplit.getGroup(3); - - const char *proto = ""; - if (name[0] == '/') { - proto = (const char*)GetContactProto(hContact); - if (proto == nullptr) - return; - } - - char str[MAXMODULELABELLENGTH]; - mir_snprintf(str, "%s%s", proto, _T2A(name.c_str())); - CallService(str, - ConvertServiceParam(hContact, par1.c_str()), - ConvertServiceParam(hContact, par2.c_str())); -} - -SmileyPackType::~SmileyPackType() -{ - if (m_hSmList != nullptr) ImageList_Destroy(m_hSmList); -} - -static const wchar_t urlRegEx[] = L"(?:ftp|https|http|file|aim|webcal|irc|msnim|xmpp|gopher|mailto|news|nntp|telnet|wais|prospero)://?[\\w.?%:/$+;]*"; -static const wchar_t pathRegEx[] = L"[\\s\"][a-zA-Z]:[\\\\/][\\w.\\-\\\\/]*"; -static const wchar_t timeRegEx[] = L"\\d{1,2}:\\d{2}:\\d{2}|\\d{1,2}:\\d{2}"; - -void SmileyPackType::AddTriggersToSmileyLookup(void) -{ - CMStringW emptystr; - m_SmileyLookup.insert(new SmileyLookup(urlRegEx, true, -1, emptystr)); - m_SmileyLookup.insert(new SmileyLookup(pathRegEx, true, -1, emptystr)); - m_SmileyLookup.insert(new SmileyLookup(timeRegEx, true, -1, emptystr)); - - for (int dist = 0; dist < m_SmileyList.getCount(); dist++) { - auto &p = m_SmileyList[dist]; - if (p.IsRegEx()) { - SmileyLookup *dats = new SmileyLookup(p.GetTriggerText(), true, dist, GetFilename()); - if (dats->IsValid()) - m_SmileyLookup.insert(dats); - else - errorFound = true; - if (p.m_InsertText.IsEmpty()) - p.m_InsertText = p.m_ToolText; - } - else if (!p.IsService()) { - bool first = true; - const CMStringW &text = p.GetTriggerText(); - int iStart = 0; - while (true) { - CMStringW wszWord = text.Tokenize(L" \t", iStart); - if (iStart == -1) - break; - - ReplaceAllSpecials(wszWord, wszWord); - SmileyLookup *dats = new SmileyLookup(wszWord, false, dist, GetFilename()); - if (dats->IsValid()) { - m_SmileyLookup.insert(dats); - if (first) { - p.m_InsertText = wszWord; - first = false; - } - } - else delete dats; - } - } - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static MRegexp16 isCode(L"\\&\\#(\\d*)\\;"); - -static void replaceCodes(CMStringW &str) -{ - if (isCode.match(str) < 0) - return; - - str.Delete(isCode.getPos(), isCode.getLength()); - - uint32_t iCode = _wtoi(isCode.getGroup(1)); - wchar_t tmp[3] = { 0, 0, 0 }; - if (iCode < 0x10000) - tmp[0] = LOWORD(iCode), tmp[1] = HIWORD(iCode); - else { - iCode -= 0x10000; - tmp[0] = 0xD800 + (iCode >> 10); - tmp[1] = 0xDC00 + (iCode & 0x3FF); - } - str.Insert(isCode.getPos(), tmp); -} - -void SmileyPackType::ReplaceAllSpecials(const CMStringW &Input, CMStringW &Output) -{ - Output = Input; - Output.Replace(L"%%_%%", L" "); - Output.Replace(L"%%__%%", L" "); - Output.Replace(L"%%''%%", L"\""); - replaceCodes(Output); -} - -void SmileyPackType::Clear(void) -{ - m_SmileyList.destroy(); - m_SmileyLookup.destroy(); - if (m_hSmList != nullptr) { ImageList_Destroy(m_hSmList); m_hSmList = nullptr; } - m_Filename.Empty(); - m_Name.Empty(); - m_Date.Empty(); - m_Version.Empty(); - m_Author.Empty(); - m_VisibleCount = 0; - m_ButtonSmiley.Empty(); - errorFound = false; -} - -bool SmileyPackType::LoadSmileyFile(const CMStringW &filename, const CMStringW &packname, bool onlyInfo, bool noerr) -{ - Clear(); - - if (filename.IsEmpty()) { - m_Name = L"Nothing loaded"; - return false; - } - - CMStringW modpath; - pathToAbsolute(filename, modpath); - - // Load file - int fh = _wopen(modpath.c_str(), _O_BINARY | _O_RDONLY); - if (fh == -1) { - if (!noerr) { - static const wchar_t errmsg[] = LPGENW("Smiley pack %s for category \"%s\" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys."); - wchar_t msgtxt[1024]; - mir_snwprintf(msgtxt, TranslateW(errmsg), modpath.c_str(), packname.c_str()); - ReportError(msgtxt); - } - - m_Name = L"Nothing loaded"; - return false; - } - - m_Filename = filename; - - // Find file size - const long flen = _filelength(fh); - - // Allocate file buffer - char *buf = new char[flen + sizeof(wchar_t)]; - - // Read file in - int len = _read(fh, buf, flen); - *(wchar_t*)(buf + len) = 0; - - // Close file - _close(fh); - - CMStringW tbuf; - - if (len > 2 && *(wchar_t*)buf == 0xfeff) - tbuf = ((wchar_t*)buf + 1); - else if (len > 3 && buf[0] == '\xef' && buf[1] == '\xbb' && buf[2] == '\xbf') - tbuf = _A2T(buf + 3, CP_UTF8); - else - tbuf = _A2T(buf); - - delete[] buf; - - CMStringW pathstr, packstr; - { - MRegexp16 pathsplit(L"(.*\\\\)(.*)\\.|$"); - pathsplit.match(modpath); - - pathstr = pathsplit.getGroup(1); - packstr = pathsplit.getGroup(2); - } - - if (!onlyInfo) - selec.x = selec.y = win.x = win.y = 0; - - int iStart = 0; - MRegexp16 otherf(L"^\\s*(Name|Author|Date|Version|ButtonSmiley)\\s*=\\s*\"(.*)\""); - MRegexp16 size(L"^\\s*(Selection|Window)Size\\s*=\\s*(\\d+)\\s*,\\s*(\\d+)"); - MRegexp16 smiley( - L"^\\s*Smiley(\\*)?\\s*=" // Is Hidden - L"(?:\\s*\"(.*)\")" // Smiley file name - L"(?:[\\s,]+(\\-?\\d+))" // Icon resource id - L"(?:[\\s,]+(R|S)?\"(.*?)\")" // Trigger text - L"(?:[\\s,]+\"(.*?)\")?" // Tooltip or insert text - L"(?:[\\s,]+\"(.*?)\")?"); // Tooltip text - - SmileyVectorType hiddenSmileys; - unsigned smnum = 0; - - while (true) { - CMStringW line = tbuf.Tokenize(L"\r\n", iStart); - if (iStart == -1) - break; - - if (line.IsEmpty() || line[0] == ';') - continue; - - if (otherf.match(line) >= 0) { - CMStringW key(otherf.getGroup(1)), value(otherf.getGroup(2)); - if (key == L"Name") - m_Name = value; - else if (key == L"Author") - m_Author = value; - else if (key == L"Date") - m_Date = value; - else if (key == L"Version") - m_Version = value; - else if (key == L"ButtonSmiley") - m_ButtonSmiley = value; - continue; - } - - if (onlyInfo) - continue; - - if (size.match(line) >= 0) { - POINT tpt; - tpt.x = _wtol(size.getGroup(2)); - tpt.y = _wtol(size.getGroup(3)); - - if (size.getGroup(1) == L"Selection") - selec = tpt; - else if (size.getGroup(1) == L"Window") - win = tpt; - continue; - } - - if (smiley.match(line)) { - CMStringW resname = smiley.getGroup(2); - if (resname.Find(L"http://") != -1) { - if (GetSmileyFile(resname, packstr)) - continue; - } - else if (!resname.IsEmpty()) - resname.Insert(0, pathstr); - - SmileyType *dat = new SmileyType; - - const int iconIndex = _wtol(smiley.getGroup(3)); - - dat->SetHidden(!smiley.getGroup(1).IsEmpty()); - - CMStringW wszGrp4(smiley.getGroup(4)); - if (!wszGrp4.IsEmpty()) { - dat->SetRegEx(wszGrp4 == L"R"); - dat->SetService(wszGrp4 == L"S"); - } - - dat->m_TriggerText = smiley.getGroup(5); - - CMStringW wszGrp6(smiley.getGroup(6)), wszGrp7(smiley.getGroup(7)); - if (dat->IsRegEx()) { - if (!wszGrp6.IsEmpty()) - ReplaceAllSpecials(wszGrp6, dat->m_InsertText); - - if (!wszGrp7.IsEmpty()) - ReplaceAllSpecials(wszGrp7, dat->m_ToolText); - else - dat->m_ToolText = dat->m_InsertText; - } - else { - if (!wszGrp6.IsEmpty()) - ReplaceAllSpecials(wszGrp6, dat->m_ToolText); - else - ReplaceAllSpecials(dat->m_TriggerText, dat->m_ToolText); - } - - if (resname.IsEmpty()) { - dat->SetHidden(true); - dat->SetText(true); - noerr = true; - } - else noerr = dat->LoadFromResource(resname, iconIndex); - - if (dat->IsHidden()) - hiddenSmileys.insert(dat); - else - m_SmileyList.insert(dat); - - if (!noerr) { - static const wchar_t errmsg[] = LPGENW("Smiley #%u in file %s for smiley pack %s not found."); - wchar_t msgtxt[1024]; - mir_snwprintf(msgtxt, TranslateW(errmsg), smnum, resname.c_str(), modpath.c_str()); - Netlib_LogW(hNetlibUser, msgtxt); - errorFound = true; - } - smnum++; - } - } - - m_VisibleCount = m_SmileyList.getCount(); - m_SmileyList.splice(hiddenSmileys); - AddTriggersToSmileyLookup(); - - if (errorFound) - ReportError(TranslateT("There were problems loading smiley pack (it should be corrected).\nSee network log for details.")); - - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// SmileyPackListType - -bool SmileyPackListType::AddSmileyPack(CMStringW &filename, CMStringW &packname) -{ - bool res = true; - if (GetSmileyPack(filename) == nullptr) { //not exist yet, so add - SmileyPackType *smileyPack = new SmileyPackType; - - res = smileyPack->LoadSmileyFile(filename, packname, FALSE); - if (res) - m_SmileyPacks.insert(smileyPack); - else - delete smileyPack; - } - return res; -} - -SmileyPackType* SmileyPackListType::GetSmileyPack(CMStringW &filename) -{ - CMStringW modpath; - pathToAbsolute(filename, modpath); - - for (auto &it : m_SmileyPacks) { - CMStringW modpath1; - pathToAbsolute(it->GetFilename(), modpath1); - if (mir_wstrcmpi(modpath.c_str(), modpath1.c_str()) == 0) - return it; - } - return nullptr; -} - -void SmileyPackListType::ClearAndFreeAll() -{ - m_SmileyPacks.destroy(); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// SmileyCategoryType - -SmileyCategoryType::SmileyCategoryType(SmileyPackListType *pSPS, const CMStringW &name, - const CMStringW &displayName, const CMStringW &defaultFilename, SmcType typ) -{ - m_pSmileyPackStore = pSPS; - type = typ; - m_Name = name; - m_DisplayName = displayName; - visible = true; - - opt.ReadPackFileName(m_Filename, m_Name, defaultFilename); -} - - -void SmileyCategoryType::Load(void) -{ - bool bVisibleCat = opt.UsePhysProto ? !IsAcc() : !IsPhysProto(); - bool bVisible = opt.UseOneForAll ? !IsProto() : bVisibleCat; - if (bVisible && !m_Filename.IsEmpty()) { - bool loaded = m_pSmileyPackStore->AddSmileyPack(m_Filename, m_DisplayName); - if (!loaded) { - ClearFilename(); - SaveSettings(); - } - } -} - -SmileyPackType* SmileyCategoryType::GetSmileyPack(void) -{ - return m_pSmileyPackStore->GetSmileyPack(m_Filename); -} - -void SmileyCategoryType::SaveSettings(void) -{ - opt.WritePackFileName(m_Filename, m_Name); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// SmileyCategoryListType - -void SmileyCategoryListType::ClearAndLoadAll(void) -{ - m_pSmileyPackStore->ClearAndFreeAll(); - - for (auto &it : m_SmileyCategories) - it->Load(); -} - -SmileyCategoryType* SmileyCategoryListType::GetSmileyCategory(const CMStringW &name) -{ - for (auto &it : m_SmileyCategories) - if (name.CompareNoCase(it->GetName()) == 0) - return it; - - return nullptr; -} - -SmileyCategoryType* SmileyCategoryListType::GetSmileyCategory(unsigned index) -{ - return index < (unsigned)m_SmileyCategories.getCount() ? &m_SmileyCategories[index] : nullptr; -} - -SmileyPackType* SmileyCategoryListType::GetSmileyPack(CMStringW &categoryname) -{ - SmileyCategoryType *smc = GetSmileyCategory(categoryname); - return smc != nullptr ? smc->GetSmileyPack() : nullptr; -} - -void SmileyCategoryListType::SaveSettings(void) -{ - CMStringW catstr; - for (auto &it : m_SmileyCategories) { - it->SaveSettings(); - if (it->IsCustom()) { - if (!catstr.IsEmpty()) - catstr += '#'; - catstr += it->GetName(); - } - } - opt.WriteCustomCategories(catstr); -} - -void SmileyCategoryListType::AddAndLoad(const CMStringW &name, const CMStringW &displayName) -{ - if (GetSmileyCategory(name) != nullptr) - return; - - AddCategory(name, displayName, smcExt); - // Load only if other smileys have been loaded already - if (m_SmileyCategories.getCount() > 1) - m_SmileyCategories[m_SmileyCategories.getCount() - 1].Load(); -} - -void SmileyCategoryListType::AddCategory(const CMStringW &name, const CMStringW &displayName, SmcType typ, const CMStringW &defaultFilename) -{ - if (GetSmileyCategory(name) == nullptr) - m_SmileyCategories.insert(new SmileyCategoryType(m_pSmileyPackStore, name, displayName, defaultFilename, typ)); -} - -bool SmileyCategoryListType::DeleteCustomCategory(int index) -{ - if (index < m_SmileyCategories.getCount()) { - if (m_SmileyCategories[index].IsCustom()) { - m_SmileyCategories.remove(index); - return true; - } - } - return false; -} - -void SmileyCategoryListType::AddAccountAsCategory(PROTOACCOUNT *acc, const CMStringW &defaultFile) -{ - if (acc->IsEnabled() && acc->szProtoName && IsSmileyProto(acc->szModuleName)) { - CMStringW displayName(acc->tszAccountName ? acc->tszAccountName : _A2T(acc->szModuleName)); - CMStringW PhysProtoName, paths; - DBVARIANT dbv; - - if (db_get_ws(NULL, acc->szModuleName, "AM_BaseProto", &dbv) == 0) { - PhysProtoName = L"AllProto"; - PhysProtoName += dbv.ptszVal; - db_free(&dbv); - } - - if (!PhysProtoName.IsEmpty()) - paths = g_SmileyCategories.GetSmileyCategory(PhysProtoName) ? g_SmileyCategories.GetSmileyCategory(PhysProtoName)->GetFilename() : L""; - - if (paths.IsEmpty()) { - const char *packnam = acc->szProtoName; - if (mir_strcmp(packnam, "JABBER") == 0) - packnam = "JGMail"; - else if (strstr(packnam, "SIP") != nullptr) - packnam = "MSN"; - - char path[MAX_PATH]; - mir_snprintf(path, "Smileys\\nova\\%s.msl", packnam); - - paths = _A2T(path); - CMStringW patha; - pathToAbsolute(paths, patha); - - if (_waccess(patha.c_str(), 0) != 0) - paths = defaultFile; - } - - CMStringW tname(_A2T(acc->szModuleName)); - AddCategory(tname, displayName, acc->bIsVirtual ? smcVirtualProto : smcProto, paths); - } -} - -void SmileyCategoryListType::AddProtoAsCategory(char *acc, const CMStringW &defaultFile) -{ - if (acc == nullptr) - return; - - const char *packnam = acc; - if (mir_strcmp(packnam, "JABBER") == 0) - packnam = "JGMail"; - else if (strstr(packnam, "SIP") != nullptr) - packnam = "MSN"; - - char path[MAX_PATH]; - mir_snprintf(path, "Smileys\\nova\\%s.msl", packnam); - - CMStringW paths = _A2T(path), patha; - pathToAbsolute(paths, patha); - - if (_waccess(patha.c_str(), 0) != 0) - paths = defaultFile; - CMStringW dName(acc), displayName; - displayName.AppendFormat(TranslateT("%s global smiley pack"), dName.GetBuffer()); - CMStringW tname("AllProto"); - tname += _A2T(acc); - AddCategory(tname, displayName, smcPhysProto, paths); -} - -void SmileyCategoryListType::DeleteAccountAsCategory(PROTOACCOUNT *acc) -{ - CMStringW tname(_A2T(acc->szModuleName)); - - for (auto &hContact : Contacts()) { - char *proto = GetContactProto(hContact); - if (proto == nullptr) - continue; - - DBVARIANT dbv; - if (!db_get_ws(hContact, proto, "Transport", &dbv)) { - bool found = (tname.CompareNoCase(dbv.ptszVal) == 0); - db_free(&dbv); - if (found) - return; - } - } - - for (auto &it : m_SmileyCategories) { - if (tname.CompareNoCase(it->GetName()) == 0) { - m_SmileyCategories.removeItem(&it); - break; - } - } -} - -void SmileyCategoryListType::AddContactTransportAsCategory(MCONTACT hContact, const CMStringW &defaultFile) -{ - char *proto = GetContactProto(hContact); - if (proto == nullptr) - return; - - DBVARIANT dbv; - if (!db_get_ws(hContact, proto, "Transport", &dbv)) { - if (dbv.ptszVal[0] == '\0') { - db_free(&dbv); - return; - } - char *trsp = mir_strdup(_T2A(dbv.ptszVal)); - _strlwr(trsp); - - const char *packname = nullptr; - if (strstr(trsp, "msn") != nullptr) - packname = "msn"; - else if (strstr(trsp, "icq") != nullptr) - packname = "icq"; - else if (strstr(trsp, "yahoo") != nullptr) - packname = "yahoo"; - else if (strstr(trsp, "aim") != nullptr) - packname = "aim"; - else if (strstr(trsp, "lcs") != nullptr) - packname = "msn"; - - mir_free(trsp); - - CMStringW displayName = dbv.ptszVal; - if (packname != nullptr) { - char path[MAX_PATH]; - mir_snprintf(path, "Smileys\\nova\\%s.msl", packname); - - CMStringW paths = _A2T(path), patha; - pathToAbsolute(paths, patha); - - if (_waccess(patha.c_str(), 0) != 0) - paths = defaultFile; - - AddCategory(displayName, displayName, smcTransportProto, paths); - } - else AddCategory(displayName, displayName, smcTransportProto, defaultFile); - - db_free(&dbv); - } -} - -void SmileyCategoryListType::AddAllProtocolsAsCategory(void) -{ - CMStringW displayName = TranslateT("Standard"); - CMStringW tname = L"Standard"; - AddCategory(tname, displayName, smcStd); - - const CMStringW &defaultFile = GetSmileyCategory(tname)->GetFilename(); - - PROTOCOLDESCRIPTOR **proto; - int protoCount = 0; - Proto_EnumProtocols(&protoCount, &proto); - - for (int i = 0; i < protoCount; i++) { - PROTOCOLDESCRIPTOR *pd = proto[i]; - if (pd->type == PROTOTYPE_PROTOWITHACCS) - AddProtoAsCategory(pd->szName, defaultFile); - } - - for (auto &pa : Accounts()) - AddAccountAsCategory(pa, defaultFile); - - for (auto &hContact : Contacts()) - AddContactTransportAsCategory(hContact, defaultFile); - - CMStringW cats; - opt.ReadCustomCategories(cats); - - int cppv = 0; - for (;;) { - int cp = cats.Find('#', cppv); - if (cp == -1) - break; - - displayName = cats.Mid(cppv, cp - cppv); - AddCategory(displayName, displayName, smcCustom, defaultFile); - cppv = cp + 1; - } - - if (cppv != cats.GetLength()) { - displayName = cats.Mid(cppv); - AddCategory(displayName, displayName, smcCustom, defaultFile); - } -} - -static const CMStringW testString(L"Test String"); - -SmileyLookup::SmileyLookup(const CMStringW &str, const bool regexs, const int ind, const CMStringW &smpt) -{ - m_ind = ind; - if (regexs) { - m_pattern.compile(str); - m_valid = m_pattern.isValid(); - if (!m_valid) { - wchar_t msgtxt[1024]; - mir_snwprintf(msgtxt, TranslateT("Regular expression \"%s\" in smiley pack \"%s\" malformed."), str.c_str(), smpt.c_str()); - Netlib_LogW(hNetlibUser, msgtxt); - } - } - else { - m_text = str; - replaceCodes(m_text); - m_valid = !str.IsEmpty(); - } -} - -SmileyLookup::~SmileyLookup() -{ -} - -void SmileyLookup::Find(const CMStringW &str, SmileyLocVecType &smlcur, bool firstOnly) -{ - if (!m_valid) return; - - if (m_text.IsEmpty()) { - while (m_pattern.nextMatch(str) >= 0) { - CMStringW wszMatch(m_pattern.getMatch()); - smlcur.insert(new SmileyLocType(m_pattern.getPos(), wszMatch.GetLength())); - if (firstOnly && m_ind != -1) - return; - } - } - else { - const wchar_t *pos = str.c_str(); - while ((pos = wcsstr(pos, m_text.c_str())) != nullptr) { - smlcur.insert(new SmileyLocType(pos - str.c_str(), m_text.GetLength())); - pos += m_text.GetLength(); - if (firstOnly && m_ind != -1) - return; - } - } -} +/* +Miranda NG SmileyAdd Plugin +Copyright (C) 2012-18 Miranda NG team (https://miranda-ng.org) +Copyright (C) 2005-11 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2003-04 Rein-Peter de Boer + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "stdafx.h" + +SmileyPackListType g_SmileyPacks; +SmileyCategoryListType g_SmileyCategories; + +static HWND hwndHidden = nullptr; + +static void CALLBACK timerProc(HWND, UINT, UINT_PTR param, DWORD) +{ + SmileyType *pType = (SmileyType*)param; + pType->MoveToNextFrame(); +} + +// these two functions must be called from the main thread +static void CALLBACK sttStartTimer(PVOID obj) +{ + if (hwndHidden == nullptr) + hwndHidden = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); + + SmileyType *pType = (SmileyType*)obj; + pType->SetFrameDelay(); +} + +static void CALLBACK sttStopTimer(PVOID obj) +{ + KillTimer(hwndHidden, (DWORD_PTR)obj); +} + +// +// SmileyType +// + +SmileyType::SmileyType(void) : + m_arSmileys(10, PtrKeySortT) +{ + m_SmileyIcon = nullptr; + m_xepimg = nullptr; + m_flags = 0; + m_index = 0; + m_size.cx = 0; + m_size.cy = 0; +} + +SmileyType::~SmileyType() +{ + if (m_xepimg) { + m_xepimg->Release(); + m_xepimg = nullptr; + } + + if (m_SmileyIcon != nullptr) { + DestroyIcon(m_SmileyIcon); + m_SmileyIcon = nullptr; + } +} + +void SmileyType::AddObject(ISmileyBase *pObject) +{ + if (m_arSmileys.getCount() == 0) { + if (m_xepimg == nullptr) + m_xepimg = AddCacheImage(m_filepath, m_index); + CallFunctionAsync(sttStartTimer, this); + } + + m_arSmileys.insert(pObject); +} + +void SmileyType::RemoveObject(ISmileyBase *pObject) +{ + int idx = m_arSmileys.getIndex(pObject); + if (idx == -1) + return; + + m_arSmileys.remove(idx); + if (m_arSmileys.getCount() == 0) + CallFunctionAsync(sttStopTimer, this); +} + +void SmileyType::SetFrameDelay() +{ + int iFrameDelay = (m_xepimg == nullptr) ? 0 : m_xepimg->GetFrameDelay(); + if (iFrameDelay <= 0) + KillTimer(hwndHidden, (DWORD_PTR)this); + else + SetTimer(hwndHidden, (DWORD_PTR)this, iFrameDelay*10, timerProc); +} + +void SmileyType::MoveToNextFrame() +{ + m_index = m_xepimg->SelectNextFrame(m_index); + + for (auto &it : m_arSmileys) + it->Draw(); + + SetFrameDelay(); // reset timer +} + +HICON SmileyType::GetIcon(void) +{ + if (m_SmileyIcon == nullptr) { + ImageBase *img = CreateCachedImage(); + if (!img) + return nullptr; + + img->SelectFrame(m_index); + m_SmileyIcon = img->GetIcon(); + img->Release(); + } + return m_SmileyIcon; +} + +HICON SmileyType::GetIconDup(void) +{ + ImageBase *img = CreateCachedImage(); + img->SelectFrame(m_index); + HICON hIcon = img->GetIcon(); + img->Release(); + return hIcon; +} + +bool SmileyType::LoadFromImage(IStream *pStream) +{ + if (m_xepimg) + m_xepimg->Release(); + + CMStringW name; + m_xepimg = new ImageType(0, name, pStream); + return true; +} + +bool SmileyType::LoadFromResource(const CMStringW &file, const int index) +{ + m_index = index; + m_filepath = file; + return true; +} + +void SmileyType::GetSize(SIZE &size) +{ + if (m_size.cy == 0) { + ImageBase *img = CreateCachedImage(); + if (img) { + img->GetSize(m_size); + img->Release(); + } + } + size = m_size; +} + +ImageBase* SmileyType::CreateCachedImage(void) +{ + if (m_xepimg) { + m_xepimg->AddRef(); + return m_xepimg; + } + return AddCacheImage(m_filepath, m_index); +} + +void SmileyType::SetImList(HIMAGELIST hImLst, long i) +{ + if (m_xepimg) m_xepimg->Release(); + m_xepimg = new ImageListItemType(0, hImLst, i); +} + +HBITMAP SmileyType::GetBitmap(COLORREF bkgClr, int sizeX, int sizeY) +{ + ImageBase *img = CreateCachedImage(); + if (!img) return nullptr; + img->SelectFrame(m_index); + HBITMAP hBmp = img->GetBitmap(bkgClr, sizeX, sizeY); + img->Release(); + + return hBmp; +} + +// +// SmileyPackType +// + +SmileyPackType::SmileyPackType() +{ + m_hSmList = nullptr; + errorFound = false; +} + +SmileyType* SmileyPackType::GetSmiley(unsigned index) +{ + return (index < (unsigned)m_SmileyList.getCount()) ? &m_SmileyList[index] : nullptr; +} + +static DWORD_PTR ConvertServiceParam(MCONTACT hContact, const wchar_t *param) +{ + if (param == nullptr) + return 0; + if (mir_wstrcmpi(L"hContact", param) == 0) + return hContact; + if (iswdigit(*param)) + return _wtoi(param); + + return (DWORD_PTR)param; +} + +void SmileyType::CallSmileyService(MCONTACT hContact) +{ + MRegexp16 srvsplit(L"(.*)\\|(.*)\\|(.*)"); + srvsplit.match(m_TriggerText); + + CMStringW name = srvsplit.getGroup(1); + CMStringW par1 = srvsplit.getGroup(2); + CMStringW par2 = srvsplit.getGroup(3); + + const char *proto = ""; + if (name[0] == '/') { + proto = (const char*)GetContactProto(hContact); + if (proto == nullptr) + return; + } + + char str[MAXMODULELABELLENGTH]; + mir_snprintf(str, "%s%s", proto, _T2A(name.c_str())); + CallService(str, + ConvertServiceParam(hContact, par1.c_str()), + ConvertServiceParam(hContact, par2.c_str())); +} + +SmileyPackType::~SmileyPackType() +{ + if (m_hSmList != nullptr) ImageList_Destroy(m_hSmList); +} + +static const wchar_t urlRegEx[] = L"(?:ftp|https|http|file|aim|webcal|irc|msnim|xmpp|gopher|mailto|news|nntp|telnet|wais|prospero)://?[\\w.?%:/$+;]*"; +static const wchar_t pathRegEx[] = L"[\\s\"][a-zA-Z]:[\\\\/][\\w.\\-\\\\/]*"; +static const wchar_t timeRegEx[] = L"\\d{1,2}:\\d{2}:\\d{2}|\\d{1,2}:\\d{2}"; + +void SmileyPackType::AddTriggersToSmileyLookup(void) +{ + CMStringW emptystr; + m_SmileyLookup.insert(new SmileyLookup(urlRegEx, true, -1, emptystr)); + m_SmileyLookup.insert(new SmileyLookup(pathRegEx, true, -1, emptystr)); + m_SmileyLookup.insert(new SmileyLookup(timeRegEx, true, -1, emptystr)); + + for (int dist = 0; dist < m_SmileyList.getCount(); dist++) { + auto &p = m_SmileyList[dist]; + if (p.IsRegEx()) { + SmileyLookup *dats = new SmileyLookup(p.GetTriggerText(), true, dist, GetFilename()); + if (dats->IsValid()) + m_SmileyLookup.insert(dats); + else + errorFound = true; + if (p.m_InsertText.IsEmpty()) + p.m_InsertText = p.m_ToolText; + } + else if (!p.IsService()) { + bool first = true; + const CMStringW &text = p.GetTriggerText(); + int iStart = 0; + while (true) { + CMStringW wszWord = text.Tokenize(L" \t", iStart); + if (iStart == -1) + break; + + ReplaceAllSpecials(wszWord, wszWord); + SmileyLookup *dats = new SmileyLookup(wszWord, false, dist, GetFilename()); + if (dats->IsValid()) { + m_SmileyLookup.insert(dats); + if (first) { + p.m_InsertText = wszWord; + first = false; + } + } + else delete dats; + } + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static MRegexp16 isCode(L"\\&\\#(\\d*)\\;"); + +static void replaceCodes(CMStringW &str) +{ + if (isCode.match(str) < 0) + return; + + str.Delete(isCode.getPos(), isCode.getLength()); + + uint32_t iCode = _wtoi(isCode.getGroup(1)); + wchar_t tmp[3] = { 0, 0, 0 }; + if (iCode < 0x10000) + tmp[0] = LOWORD(iCode), tmp[1] = HIWORD(iCode); + else { + iCode -= 0x10000; + tmp[0] = 0xD800 + (iCode >> 10); + tmp[1] = 0xDC00 + (iCode & 0x3FF); + } + str.Insert(isCode.getPos(), tmp); +} + +void SmileyPackType::ReplaceAllSpecials(const CMStringW &Input, CMStringW &Output) +{ + Output = Input; + Output.Replace(L"%%_%%", L" "); + Output.Replace(L"%%__%%", L" "); + Output.Replace(L"%%''%%", L"\""); + replaceCodes(Output); +} + +void SmileyPackType::Clear(void) +{ + m_SmileyList.destroy(); + m_SmileyLookup.destroy(); + if (m_hSmList != nullptr) { ImageList_Destroy(m_hSmList); m_hSmList = nullptr; } + m_Filename.Empty(); + m_Name.Empty(); + m_Date.Empty(); + m_Version.Empty(); + m_Author.Empty(); + m_VisibleCount = 0; + m_ButtonSmiley.Empty(); + errorFound = false; +} + +bool SmileyPackType::LoadSmileyFile(const CMStringW &filename, const CMStringW &packname, bool onlyInfo, bool noerr) +{ + Clear(); + + if (filename.IsEmpty()) { + m_Name = L"Nothing loaded"; + return false; + } + + CMStringW modpath; + pathToAbsolute(filename, modpath); + + // Load file + int fh = _wopen(modpath.c_str(), _O_BINARY | _O_RDONLY); + if (fh == -1) { + if (!noerr) { + static const wchar_t errmsg[] = LPGENW("Smiley pack %s for category \"%s\" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys."); + wchar_t msgtxt[1024]; + mir_snwprintf(msgtxt, TranslateW(errmsg), modpath.c_str(), packname.c_str()); + ReportError(msgtxt); + } + + m_Name = L"Nothing loaded"; + return false; + } + + m_Filename = filename; + + // Find file size + const long flen = _filelength(fh); + + // Allocate file buffer + char *buf = new char[flen + sizeof(wchar_t)]; + + // Read file in + int len = _read(fh, buf, flen); + *(wchar_t*)(buf + len) = 0; + + // Close file + _close(fh); + + CMStringW tbuf; + if (len > 2 && *(wchar_t*)buf == 0xfeff) + tbuf = ((wchar_t*)buf + 1); + else if (len > 3 && buf[0] == '\xef' && buf[1] == '\xbb' && buf[2] == '\xbf') + tbuf = _A2T(buf + 3, CP_UTF8); + else + tbuf = _A2T(buf); + + delete[] buf; + + bool res; + if (filename.Find(L".xep") == -1) + res = LoadSmileyFileMSL(tbuf, onlyInfo, modpath); + else + res = LoadSmileyFileXEP(tbuf, onlyInfo); + + if (errorFound) + ReportError(TranslateT("There were problems loading smiley pack (it should be corrected).\nSee network log for details.")); + + return res; +} + +static IStream* DecodeBase64Data(const wchar_t *pString) +{ + size_t dataLen; + ptrA data((char*)mir_base64_decode(_T2A(pString), &dataLen)); + if (data == nullptr) + return nullptr; + + // Read image list + HGLOBAL hBuffer = GlobalAlloc(GMEM_MOVEABLE, dataLen); + if (!hBuffer) + return nullptr; + + void *dst = GlobalLock(hBuffer); + memcpy(dst, data, dataLen); + GlobalUnlock(hBuffer); + + IStream *pStream = nullptr; + CreateStreamOnHGlobal(hBuffer, TRUE, &pStream); + return pStream; +} + +static CMStringW FilterQuotes(const wchar_t *pStr) +{ + CMStringW res(pStr); + int iStart = res.Find('\"', 0); + if (iStart != -1) { + int iEnd = res.Find('\"', ++iStart); + if (iEnd != -1) + res = res.Mid(iStart, iEnd - iStart); + } + + return res; +} + +bool SmileyPackType::LoadSmileyFileXEP(CMStringW &tbuf, bool onlyInfo) +{ + HXML node, xmlRoot = xmlParseString(tbuf, nullptr, nullptr); + if (!xmlRoot) + return false; + + if (node = xmlGetChildByPath(xmlRoot, L"settings/DataBaseName", 0)) + m_Name = xmlGetText(node); + if (node = xmlGetChildByPath(xmlRoot, L"settings/PackageAuthor", 0)) + m_Author = xmlGetText(node); + + if (!onlyInfo) { + const wchar_t *pStr = xmlGetClear(xmlGetChildByPath(xmlRoot, L"lists/images", 0), 0, 0, 0); + if (pStr) { + IStream *pStream = DecodeBase64Data(pStr); + if (pStream) { + if (m_hSmList != nullptr) + ImageList_Destroy(m_hSmList); + m_hSmList = ImageList_Read(pStream); + pStream->Release(); + } + } + + HXML nRec, dataRoot = xmlGetChildByPath(xmlRoot, L"dataroot", 0); + for (int i = 0; (nRec = xmlGetNthChild(dataRoot, L"record", i)) != 0; i++) { + pStr = xmlGetAttrValue(nRec, L"ImageIndex"); + if (pStr == nullptr) + continue; + + SmileyType *dat = new SmileyType; + dat->SetRegEx(true); + dat->SetImList(m_hSmList, _wtoi(pStr)); + dat->m_ToolText = xmlGetText(nRec); + + if (node = xmlGetChildByPath(nRec, L"Expression", 0)) + dat->m_TriggerText = FilterQuotes(xmlGetText(node)); + if (node = xmlGetChildByPath(nRec, L"PasteText", 0)) + dat->m_InsertText = FilterQuotes(xmlGetText(node)); + + dat->SetHidden(dat->m_InsertText.IsEmpty()); + + if (node = xmlGetChildByPath(nRec, L"Image", 0)) { + IStream *pStream = DecodeBase64Data(xmlGetText(node)); + if (pStream) { + dat->LoadFromImage(pStream); + pStream->Release(); + } + } + + m_SmileyList.insert(dat); + } + } + + xmlDestroyNode(xmlRoot); + + m_VisibleCount = m_SmileyList.getCount(); + AddTriggersToSmileyLookup(); + + selec.x = selec.y = win.x = win.y = 0; + return true; +} + +bool SmileyPackType::LoadSmileyFileMSL(CMStringW &tbuf, bool onlyInfo, CMStringW &modpath) +{ + CMStringW pathstr, packstr; + { + MRegexp16 pathsplit(L"(.*\\\\)(.*)\\.|$"); + pathsplit.match(modpath); + + pathstr = pathsplit.getGroup(1); + packstr = pathsplit.getGroup(2); + } + + if (!onlyInfo) + selec.x = selec.y = win.x = win.y = 0; + + int iStart = 0; + MRegexp16 otherf(L"^\\s*(Name|Author|Date|Version|ButtonSmiley)\\s*=\\s*\"(.*)\""); + MRegexp16 size(L"^\\s*(Selection|Window)Size\\s*=\\s*(\\d+)\\s*,\\s*(\\d+)"); + MRegexp16 smiley( + L"^\\s*Smiley(\\*)?\\s*=" // Is Hidden + L"(?:\\s*\"(.*)\")" // Smiley file name + L"(?:[\\s,]+(\\-?\\d+))" // Icon resource id + L"(?:[\\s,]+(R|S)?\"(.*?)\")" // Trigger text + L"(?:[\\s,]+\"(.*?)\")?" // Tooltip or insert text + L"(?:[\\s,]+\"(.*?)\")?"); // Tooltip text + + SmileyVectorType hiddenSmileys; + unsigned smnum = 0; + + while (true) { + CMStringW line = tbuf.Tokenize(L"\r\n", iStart); + if (iStart == -1) + break; + + if (line.IsEmpty() || line[0] == ';') + continue; + + if (otherf.match(line) >= 0) { + CMStringW key(otherf.getGroup(1)), value(otherf.getGroup(2)); + if (key == L"Name") + m_Name = value; + else if (key == L"Author") + m_Author = value; + else if (key == L"Date") + m_Date = value; + else if (key == L"Version") + m_Version = value; + else if (key == L"ButtonSmiley") + m_ButtonSmiley = value; + continue; + } + + if (onlyInfo) + continue; + + if (size.match(line) >= 0) { + POINT tpt; + tpt.x = _wtol(size.getGroup(2)); + tpt.y = _wtol(size.getGroup(3)); + + if (size.getGroup(1) == L"Selection") + selec = tpt; + else if (size.getGroup(1) == L"Window") + win = tpt; + continue; + } + + if (smiley.match(line)) { + CMStringW resname = smiley.getGroup(2); + if (resname.Find(L"http://") != -1) { + if (GetSmileyFile(resname, packstr)) + continue; + } + else if (!resname.IsEmpty()) + resname.Insert(0, pathstr); + + SmileyType *dat = new SmileyType; + + const int iconIndex = _wtol(smiley.getGroup(3)); + + dat->SetHidden(!smiley.getGroup(1).IsEmpty()); + + CMStringW wszGrp4(smiley.getGroup(4)); + if (!wszGrp4.IsEmpty()) { + dat->SetRegEx(wszGrp4 == L"R"); + dat->SetService(wszGrp4 == L"S"); + } + + dat->m_TriggerText = smiley.getGroup(5); + + CMStringW wszGrp6(smiley.getGroup(6)), wszGrp7(smiley.getGroup(7)); + if (dat->IsRegEx()) { + if (!wszGrp6.IsEmpty()) + ReplaceAllSpecials(wszGrp6, dat->m_InsertText); + + if (!wszGrp7.IsEmpty()) + ReplaceAllSpecials(wszGrp7, dat->m_ToolText); + else + dat->m_ToolText = dat->m_InsertText; + } + else { + if (!wszGrp6.IsEmpty()) + ReplaceAllSpecials(wszGrp6, dat->m_ToolText); + else + ReplaceAllSpecials(dat->m_TriggerText, dat->m_ToolText); + } + + bool noerr; + if (resname.IsEmpty()) { + dat->SetHidden(true); + dat->SetText(true); + noerr = true; + } + else noerr = dat->LoadFromResource(resname, iconIndex); + + if (dat->IsHidden()) + hiddenSmileys.insert(dat); + else + m_SmileyList.insert(dat); + + if (!noerr) { + static const wchar_t errmsg[] = LPGENW("Smiley #%u in file %s for smiley pack %s not found."); + wchar_t msgtxt[1024]; + mir_snwprintf(msgtxt, TranslateW(errmsg), smnum, resname.c_str(), modpath.c_str()); + Netlib_LogW(hNetlibUser, msgtxt); + errorFound = true; + } + smnum++; + } + } + + m_VisibleCount = m_SmileyList.getCount(); + m_SmileyList.splice(hiddenSmileys); + AddTriggersToSmileyLookup(); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// SmileyPackListType + +bool SmileyPackListType::AddSmileyPack(CMStringW &filename, CMStringW &packname) +{ + bool res = true; + if (GetSmileyPack(filename) == nullptr) { //not exist yet, so add + SmileyPackType *smileyPack = new SmileyPackType; + + res = smileyPack->LoadSmileyFile(filename, packname, FALSE); + if (res) + m_SmileyPacks.insert(smileyPack); + else + delete smileyPack; + } + return res; +} + +SmileyPackType* SmileyPackListType::GetSmileyPack(CMStringW &filename) +{ + CMStringW modpath; + pathToAbsolute(filename, modpath); + + for (auto &it : m_SmileyPacks) { + CMStringW modpath1; + pathToAbsolute(it->GetFilename(), modpath1); + if (mir_wstrcmpi(modpath.c_str(), modpath1.c_str()) == 0) + return it; + } + return nullptr; +} + +void SmileyPackListType::ClearAndFreeAll() +{ + m_SmileyPacks.destroy(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// SmileyCategoryType + +SmileyCategoryType::SmileyCategoryType(SmileyPackListType *pSPS, const CMStringW &name, + const CMStringW &displayName, const CMStringW &defaultFilename, SmcType typ) +{ + m_pSmileyPackStore = pSPS; + type = typ; + m_Name = name; + m_DisplayName = displayName; + visible = true; + + opt.ReadPackFileName(m_Filename, m_Name, defaultFilename); +} + + +void SmileyCategoryType::Load(void) +{ + bool bVisibleCat = opt.UsePhysProto ? !IsAcc() : !IsPhysProto(); + bool bVisible = opt.UseOneForAll ? !IsProto() : bVisibleCat; + if (bVisible && !m_Filename.IsEmpty()) { + bool loaded = m_pSmileyPackStore->AddSmileyPack(m_Filename, m_DisplayName); + if (!loaded) { + ClearFilename(); + SaveSettings(); + } + } +} + +SmileyPackType* SmileyCategoryType::GetSmileyPack(void) +{ + return m_pSmileyPackStore->GetSmileyPack(m_Filename); +} + +void SmileyCategoryType::SaveSettings(void) +{ + opt.WritePackFileName(m_Filename, m_Name); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// SmileyCategoryListType + +void SmileyCategoryListType::ClearAndLoadAll(void) +{ + m_pSmileyPackStore->ClearAndFreeAll(); + + for (auto &it : m_SmileyCategories) + it->Load(); +} + +SmileyCategoryType* SmileyCategoryListType::GetSmileyCategory(const CMStringW &name) +{ + for (auto &it : m_SmileyCategories) + if (name.CompareNoCase(it->GetName()) == 0) + return it; + + return nullptr; +} + +SmileyCategoryType* SmileyCategoryListType::GetSmileyCategory(unsigned index) +{ + return index < (unsigned)m_SmileyCategories.getCount() ? &m_SmileyCategories[index] : nullptr; +} + +SmileyPackType* SmileyCategoryListType::GetSmileyPack(CMStringW &categoryname) +{ + SmileyCategoryType *smc = GetSmileyCategory(categoryname); + return smc != nullptr ? smc->GetSmileyPack() : nullptr; +} + +void SmileyCategoryListType::SaveSettings(void) +{ + CMStringW catstr; + for (auto &it : m_SmileyCategories) { + it->SaveSettings(); + if (it->IsCustom()) { + if (!catstr.IsEmpty()) + catstr += '#'; + catstr += it->GetName(); + } + } + opt.WriteCustomCategories(catstr); +} + +void SmileyCategoryListType::AddAndLoad(const CMStringW &name, const CMStringW &displayName) +{ + if (GetSmileyCategory(name) != nullptr) + return; + + AddCategory(name, displayName, smcExt); + // Load only if other smileys have been loaded already + if (m_SmileyCategories.getCount() > 1) + m_SmileyCategories[m_SmileyCategories.getCount() - 1].Load(); +} + +void SmileyCategoryListType::AddCategory(const CMStringW &name, const CMStringW &displayName, SmcType typ, const CMStringW &defaultFilename) +{ + if (GetSmileyCategory(name) == nullptr) + m_SmileyCategories.insert(new SmileyCategoryType(m_pSmileyPackStore, name, displayName, defaultFilename, typ)); +} + +bool SmileyCategoryListType::DeleteCustomCategory(int index) +{ + if (index < m_SmileyCategories.getCount()) { + if (m_SmileyCategories[index].IsCustom()) { + m_SmileyCategories.remove(index); + return true; + } + } + return false; +} + +void SmileyCategoryListType::AddAccountAsCategory(PROTOACCOUNT *acc, const CMStringW &defaultFile) +{ + if (acc->IsEnabled() && acc->szProtoName && IsSmileyProto(acc->szModuleName)) { + CMStringW displayName(acc->tszAccountName ? acc->tszAccountName : _A2T(acc->szModuleName)); + CMStringW PhysProtoName, paths; + DBVARIANT dbv; + + if (db_get_ws(NULL, acc->szModuleName, "AM_BaseProto", &dbv) == 0) { + PhysProtoName = L"AllProto"; + PhysProtoName += dbv.ptszVal; + db_free(&dbv); + } + + if (!PhysProtoName.IsEmpty()) + paths = g_SmileyCategories.GetSmileyCategory(PhysProtoName) ? g_SmileyCategories.GetSmileyCategory(PhysProtoName)->GetFilename() : L""; + + if (paths.IsEmpty()) { + const char *packnam = acc->szProtoName; + if (mir_strcmp(packnam, "JABBER") == 0) + packnam = "JGMail"; + else if (strstr(packnam, "SIP") != nullptr) + packnam = "MSN"; + + char path[MAX_PATH]; + mir_snprintf(path, "Smileys\\nova\\%s.msl", packnam); + + paths = _A2T(path); + CMStringW patha; + pathToAbsolute(paths, patha); + + if (_waccess(patha.c_str(), 0) != 0) + paths = defaultFile; + } + + CMStringW tname(_A2T(acc->szModuleName)); + AddCategory(tname, displayName, acc->bIsVirtual ? smcVirtualProto : smcProto, paths); + } +} + +void SmileyCategoryListType::AddProtoAsCategory(char *acc, const CMStringW &defaultFile) +{ + if (acc == nullptr) + return; + + const char *packnam = acc; + if (mir_strcmp(packnam, "JABBER") == 0) + packnam = "JGMail"; + else if (strstr(packnam, "SIP") != nullptr) + packnam = "MSN"; + + char path[MAX_PATH]; + mir_snprintf(path, "Smileys\\nova\\%s.msl", packnam); + + CMStringW paths = _A2T(path), patha; + pathToAbsolute(paths, patha); + + if (_waccess(patha.c_str(), 0) != 0) + paths = defaultFile; + CMStringW dName(acc), displayName; + displayName.AppendFormat(TranslateT("%s global smiley pack"), dName.GetBuffer()); + CMStringW tname("AllProto"); + tname += _A2T(acc); + AddCategory(tname, displayName, smcPhysProto, paths); +} + +void SmileyCategoryListType::DeleteAccountAsCategory(PROTOACCOUNT *acc) +{ + CMStringW tname(_A2T(acc->szModuleName)); + + for (auto &hContact : Contacts()) { + char *proto = GetContactProto(hContact); + if (proto == nullptr) + continue; + + DBVARIANT dbv; + if (!db_get_ws(hContact, proto, "Transport", &dbv)) { + bool found = (tname.CompareNoCase(dbv.ptszVal) == 0); + db_free(&dbv); + if (found) + return; + } + } + + for (auto &it : m_SmileyCategories) { + if (tname.CompareNoCase(it->GetName()) == 0) { + m_SmileyCategories.removeItem(&it); + break; + } + } +} + +void SmileyCategoryListType::AddContactTransportAsCategory(MCONTACT hContact, const CMStringW &defaultFile) +{ + char *proto = GetContactProto(hContact); + if (proto == nullptr) + return; + + DBVARIANT dbv; + if (!db_get_ws(hContact, proto, "Transport", &dbv)) { + if (dbv.ptszVal[0] == '\0') { + db_free(&dbv); + return; + } + char *trsp = mir_strdup(_T2A(dbv.ptszVal)); + _strlwr(trsp); + + const char *packname = nullptr; + if (strstr(trsp, "msn") != nullptr) + packname = "msn"; + else if (strstr(trsp, "icq") != nullptr) + packname = "icq"; + else if (strstr(trsp, "yahoo") != nullptr) + packname = "yahoo"; + else if (strstr(trsp, "aim") != nullptr) + packname = "aim"; + else if (strstr(trsp, "lcs") != nullptr) + packname = "msn"; + + mir_free(trsp); + + CMStringW displayName = dbv.ptszVal; + if (packname != nullptr) { + char path[MAX_PATH]; + mir_snprintf(path, "Smileys\\nova\\%s.msl", packname); + + CMStringW paths = _A2T(path), patha; + pathToAbsolute(paths, patha); + + if (_waccess(patha.c_str(), 0) != 0) + paths = defaultFile; + + AddCategory(displayName, displayName, smcTransportProto, paths); + } + else AddCategory(displayName, displayName, smcTransportProto, defaultFile); + + db_free(&dbv); + } +} + +void SmileyCategoryListType::AddAllProtocolsAsCategory(void) +{ + CMStringW displayName = TranslateT("Standard"); + CMStringW tname = L"Standard"; + AddCategory(tname, displayName, smcStd); + + const CMStringW &defaultFile = GetSmileyCategory(tname)->GetFilename(); + + PROTOCOLDESCRIPTOR **proto; + int protoCount = 0; + Proto_EnumProtocols(&protoCount, &proto); + + for (int i = 0; i < protoCount; i++) { + PROTOCOLDESCRIPTOR *pd = proto[i]; + if (pd->type == PROTOTYPE_PROTOWITHACCS) + AddProtoAsCategory(pd->szName, defaultFile); + } + + for (auto &pa : Accounts()) + AddAccountAsCategory(pa, defaultFile); + + for (auto &hContact : Contacts()) + AddContactTransportAsCategory(hContact, defaultFile); + + CMStringW cats; + opt.ReadCustomCategories(cats); + + int cppv = 0; + for (;;) { + int cp = cats.Find('#', cppv); + if (cp == -1) + break; + + displayName = cats.Mid(cppv, cp - cppv); + AddCategory(displayName, displayName, smcCustom, defaultFile); + cppv = cp + 1; + } + + if (cppv != cats.GetLength()) { + displayName = cats.Mid(cppv); + AddCategory(displayName, displayName, smcCustom, defaultFile); + } +} + +static const CMStringW testString(L"Test String"); + +SmileyLookup::SmileyLookup(const CMStringW &str, const bool regexs, const int ind, const CMStringW &smpt) +{ + m_ind = ind; + if (regexs) { + m_pattern.compile(str); + m_valid = m_pattern.isValid(); + if (!m_valid) { + wchar_t msgtxt[1024]; + mir_snwprintf(msgtxt, TranslateT("Regular expression \"%s\" in smiley pack \"%s\" malformed."), str.c_str(), smpt.c_str()); + Netlib_LogW(hNetlibUser, msgtxt); + } + } + else { + m_text = str; + replaceCodes(m_text); + m_valid = !str.IsEmpty(); + } +} + +SmileyLookup::~SmileyLookup() +{ +} + +void SmileyLookup::Find(const CMStringW &str, SmileyLocVecType &smlcur, bool firstOnly) +{ + if (!m_valid) return; + + if (m_text.IsEmpty()) { + while (m_pattern.nextMatch(str) >= 0) { + CMStringW wszMatch(m_pattern.getMatch()); + smlcur.insert(new SmileyLocType(m_pattern.getPos(), wszMatch.GetLength())); + if (firstOnly && m_ind != -1) + return; + } + } + else { + const wchar_t *pos = str.c_str(); + while ((pos = wcsstr(pos, m_text.c_str())) != nullptr) { + smlcur.insert(new SmileyLocType(pos - str.c_str(), m_text.GetLength())); + pos += m_text.GetLength(); + if (firstOnly && m_ind != -1) + return; + } + } +} diff --git a/plugins/SmileyAdd/src/smileys.h b/plugins/SmileyAdd/src/smileys.h index d75d40c418..d0d7a0ef3c 100644 --- a/plugins/SmileyAdd/src/smileys.h +++ b/plugins/SmileyAdd/src/smileys.h @@ -203,6 +203,9 @@ public: bool LoadSmileyFile(const CMStringW &filename, const CMStringW &packname, bool onlyInfo, bool noerr = false); + bool LoadSmileyFileMSL(CMStringW &body, bool bOnlyInfo, CMStringW &modPath); + bool LoadSmileyFileXEP(CMStringW &body, bool bOnlyInfo); + void Clear(void); }; diff --git a/plugins/SmileyAdd/src/stdafx.h b/plugins/SmileyAdd/src/stdafx.h index 3993c29660..db2cc70b63 100644 --- a/plugins/SmileyAdd/src/stdafx.h +++ b/plugins/SmileyAdd/src/stdafx.h @@ -68,6 +68,7 @@ along with this program. If not, see . #include #include #include +#include #include #include diff --git a/plugins/SmileyAdd/src/version.h b/plugins/SmileyAdd/src/version.h index 5c207eebfb..486043ea5f 100644 --- a/plugins/SmileyAdd/src/version.h +++ b/plugins/SmileyAdd/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 3 #define __RELEASE_NUM 0 -#define __BUILD_NUM 1 +#define __BUILD_NUM 2 #include diff --git a/plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.cpp b/plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.cpp index 5ca571ec9d..ae7c2bd791 100644 --- a/plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.cpp +++ b/plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.cpp @@ -324,7 +324,7 @@ static VOID CALLBACK AutoAwayTimer(HWND, UINT, UINT_PTR, DWORD) if (confirm) confirmDialog = ShowConfirmDialogEx(&ps, db_get_w(0, AAAMODULENAME, SETTING_CONFIRMDELAY, 5)); else if (statusChanged) - CallService(MS_CS_SETSTATUSEX, (WPARAM)&ps, 0); + SetStatusEx(ps); } } diff --git a/plugins/StatusManager/src/KeepStatus/keepstatus.cpp b/plugins/StatusManager/src/KeepStatus/keepstatus.cpp index cd24606687..403f8e8be2 100644 --- a/plugins/StatusManager/src/KeepStatus/keepstatus.cpp +++ b/plugins/StatusManager/src/KeepStatus/keepstatus.cpp @@ -198,7 +198,7 @@ static int SetCurrentStatus() } } ProcessPopup(KS_CONN_STATE_RETRY, (LPARAM)ps.getArray()); - return CallService(MS_CS_SETSTATUSEX, (WPARAM)&ps, 0); + return SetStatusEx(ps); } static int StatusChange(WPARAM wParam, LPARAM lParam) @@ -243,7 +243,7 @@ static int CSStatusChange(WPARAM wParam, LPARAM) return 0; } -static int CSStatusChangeEx(WPARAM wParam, LPARAM) +static int CSStatusChangeEx(WPARAM wParam, LPARAM pCount) { // the status was changed by commonstatus (new) if (wParam != 0) { @@ -251,7 +251,7 @@ static int CSStatusChangeEx(WPARAM wParam, LPARAM) if (protoSettings == nullptr) return -1; - for (int i = 0; i < protoList.getCount(); i++) { + for (int i = 0; i < pCount; i++) { auto psi = protoSettings[i]; if (psi->m_szName == nullptr) continue; diff --git a/plugins/StatusManager/src/StartupStatus/ss_profiles.cpp b/plugins/StatusManager/src/StartupStatus/ss_profiles.cpp index 2aba9ad8d8..46db3d1299 100644 --- a/plugins/StatusManager/src/StartupStatus/ss_profiles.cpp +++ b/plugins/StatusManager/src/StartupStatus/ss_profiles.cpp @@ -204,7 +204,7 @@ INT_PTR LoadAndSetProfile(WPARAM iProfileNo, LPARAM) char setting[64]; mir_snprintf(setting, "%d_%s", profile, SETTING_SHOWCONFIRMDIALOG); if (!db_get_b(0, SSMODULENAME, setting, 0)) - CallService(MS_CS_SETSTATUSEX, (WPARAM)&ps, 0); + SetStatusEx(ps); else ShowConfirmDialogEx(&ps, db_get_dw(0, SSMODULENAME, SETTING_DLGTIMEOUT, 5)); } diff --git a/plugins/StatusManager/src/StartupStatus/startupstatus.cpp b/plugins/StatusManager/src/StartupStatus/startupstatus.cpp index 6eb6bb820a..a4e67e1b31 100644 --- a/plugins/StatusManager/src/StartupStatus/startupstatus.cpp +++ b/plugins/StatusManager/src/StartupStatus/startupstatus.cpp @@ -215,7 +215,7 @@ static void CALLBACK SetStatusTimed(HWND, UINT, UINT_PTR, DWORD) if (it->ssDisabled) it->m_status = ID_STATUS_DISABLED; - CallService(MS_CS_SETSTATUSEX, (WPARAM)&ps, 0); + SetStatusEx(ps); } static int OnOkToExit(WPARAM, LPARAM) diff --git a/plugins/StatusManager/src/commonstatus.cpp b/plugins/StatusManager/src/commonstatus.cpp index 13e7108af6..7cf8928221 100644 --- a/plugins/StatusManager/src/commonstatus.cpp +++ b/plugins/StatusManager/src/commonstatus.cpp @@ -69,7 +69,6 @@ TProtoSettings::TProtoSettings(const TProtoSettings &p) char* StatusModeToDbSetting(int status, const char *suffix); DWORD StatusModeToProtoFlag(int status); -INT_PTR SetStatusEx(WPARAM wParam, LPARAM lParam); // some helpers from awaymsg.c ================================================================ @@ -144,9 +143,9 @@ wchar_t* GetDefaultStatusMessage(PROTOCOLSETTINGEX *ps, int newstatus) return tMsg; } -static int equalsGlobalStatus(PROTOCOLSETTINGEX **ps) +static int equalsGlobalStatus(TProtoSettings &ps) { - int j, pstatus = 0, gstatus = 0; + int pstatus = 0, gstatus = 0; for (auto &it : protoList) if (it->m_szMsg != nullptr && GetActualStatus(it) != ID_STATUS_OFFLINE) @@ -157,9 +156,9 @@ static int equalsGlobalStatus(PROTOCOLSETTINGEX **ps) continue; pstatus = 0; - for (j = 0; j < protoList.getCount(); j++) - if (!mir_strcmp(pa->szModuleName, ps[j]->m_szName)) - pstatus = GetActualStatus(ps[j]); + for (auto &it : ps) + if (!mir_strcmp(pa->szModuleName, it->m_szName)) + pstatus = GetActualStatus(it); if (pstatus == 0) pstatus = pa->iRealStatus; @@ -215,22 +214,17 @@ static void SetStatusMsg(PROTOCOLSETTINGEX *ps, int newstatus) mir_free(tszMsg); } -INT_PTR SetStatusEx(WPARAM wParam, LPARAM) +int SetStatusEx(TProtoSettings &ps) { - PROTOCOLSETTINGEX** protoSettings = *(PROTOCOLSETTINGEX***)wParam; - if (protoSettings == nullptr) - return -1; - - int globStatus = equalsGlobalStatus(protoSettings); + int globStatus = equalsGlobalStatus(ps); // issue with setting global status; // things get messy because SRAway hooks ME_CLIST_STATUSMODECHANGE, so the status messages of SRAway and // commonstatus will clash - NotifyEventHooks(hCSStatusChangedExEvent, (WPARAM)&protoSettings, protoList.getCount()); + NotifyEventHooks(hCSStatusChangedExEvent, (WPARAM)&ps, ps.getCount()); // set all status messages first - for (int i = 0; i < protoList.getCount(); i++) { - PROTOCOLSETTINGEX *p = protoSettings[i]; + for (auto &p : ps) { if (p->m_status == ID_STATUS_DISABLED) continue; @@ -239,7 +233,7 @@ INT_PTR SetStatusEx(WPARAM wParam, LPARAM) continue; } // some checks - int newstatus = GetActualStatus(protoSettings[i]); + int newstatus = GetActualStatus(p); if (newstatus == 0) { log_debugA("CommonStatus: incorrect status for %s (%d)", p->m_szName, p->m_status); continue; @@ -273,7 +267,7 @@ INT_PTR SetStatusEx(WPARAM wParam, LPARAM) // set status message first if (b_Caps1 && b_Caps3) - SetStatusMsg(protoSettings[i], newstatus); + SetStatusMsg(p, newstatus); // set the status if (newstatus != oldstatus /*&& !(b_Caps1 && b_Caps3 && ServiceExists(MS_NAS_SETSTATE))*/) { @@ -306,18 +300,6 @@ bool IsSuitableProto(PROTOACCOUNT *pa) return (pa == nullptr) ? false : pa->IsVisible(); } -static int CreateServices() -{ - if (ServiceExists(MS_CS_SETSTATUSEX)) - return -1; - - hCSStatusChangedExEvent = CreateHookableEvent(ME_CS_STATUSCHANGEEX); - - CreateServiceFunction(MS_CS_SETSTATUSEX, SetStatusEx); - CreateServiceFunction(MS_CS_GETPROTOCOUNT, GetProtocolCountService); - return 0; -} - static int onShutdown(WPARAM, LPARAM) { g_bMirandaLoaded = false; @@ -325,10 +307,25 @@ static int onShutdown(WPARAM, LPARAM) return 0; } +static INT_PTR SetStatusEx(WPARAM wParam, LPARAM pCount) +{ + PROTOCOLSETTINGEX **protoSettings = *(PROTOCOLSETTINGEX***)wParam; + if (protoSettings == nullptr) + return -1; + + TProtoSettings ps; + for (int i = 0; i < pCount; i++) + ps.insert((SMProto*)protoSettings[i]); + return SetStatusEx(ps); +} + int InitCommonStatus() { - if (!CreateServices()) - HookEvent(ME_SYSTEM_PRESHUTDOWN, onShutdown); + hCSStatusChangedExEvent = CreateHookableEvent(ME_CS_STATUSCHANGEEX); + CreateServiceFunction(MS_CS_SETSTATUSEX, SetStatusEx); + CreateServiceFunction(MS_CS_GETPROTOCOUNT, GetProtocolCountService); + + HookEvent(ME_SYSTEM_PRESHUTDOWN, onShutdown); return 0; } diff --git a/plugins/StatusManager/src/commonstatus.h b/plugins/StatusManager/src/commonstatus.h index ee9fa8b128..1577f6a5a7 100644 --- a/plugins/StatusManager/src/commonstatus.h +++ b/plugins/StatusManager/src/commonstatus.h @@ -138,4 +138,6 @@ extern TProtoSettings protoList; int CompareProtoSettings(const SMProto *p1, const SMProto *p2); HWND ShowConfirmDialogEx(TProtoSettings *params, int _timeout); +int SetStatusEx(TProtoSettings &ps); + #endif //COMMONSTATUSHEADER diff --git a/plugins/StatusManager/src/confirmdialog.cpp b/plugins/StatusManager/src/confirmdialog.cpp index a833408839..63c13658e0 100644 --- a/plugins/StatusManager/src/confirmdialog.cpp +++ b/plugins/StatusManager/src/confirmdialog.cpp @@ -27,27 +27,7 @@ static HWND win; static int timeOut; -struct TConfirmSetting : public PROTOCOLSETTINGEX -{ - TConfirmSetting(const PROTOCOLSETTINGEX &x) - { - memcpy(this, &x, sizeof(PROTOCOLSETTINGEX)); - if (m_szMsg) - m_szMsg = mir_wstrdup(m_szMsg); - } - - ~TConfirmSetting() - { - mir_free(m_szMsg); - } -}; - -static int CompareSettings(const TConfirmSetting* p1, const TConfirmSetting* p2) -{ - return mir_strcmp(p1->m_szName, p2->m_szName); -} - -static OBJLIST *confirmSettings; +static TProtoSettings *confirmSettings; static INT_PTR CALLBACK StatusMessageDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -385,7 +365,7 @@ static INT_PTR CALLBACK ConfirmDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LP break; case UM_CLOSECONFIRMDLG: - CallService(MS_CS_SETSTATUSEX, (WPARAM)confirmSettings, 0); + SetStatusEx(*confirmSettings); DestroyWindow(hwndDlg); break; @@ -400,11 +380,11 @@ static INT_PTR CALLBACK ConfirmDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LP HWND ShowConfirmDialogEx(TProtoSettings *params, int _timeout) { delete confirmSettings; - confirmSettings = new OBJLIST(10, CompareSettings); + confirmSettings = new TProtoSettings(); for (auto &it : *params) if (it->m_status != ID_STATUS_DISABLED) - confirmSettings->insert(new TConfirmSetting(*it)); + confirmSettings->insert(new SMProto(*it)); timeOut = _timeout; if (timeOut < 0) diff --git a/plugins/StatusManager/src/version.h b/plugins/StatusManager/src/version.h index 45db33e0dc..b16d6f952c 100644 --- a/plugins/StatusManager/src/version.h +++ b/plugins/StatusManager/src/version.h @@ -1,8 +1,8 @@ // plugin version part #define __MAJOR_VERSION 1 -#define __MINOR_VERSION 1 +#define __MINOR_VERSION 2 #define __RELEASE_NUM 0 -#define __BUILD_NUM 4 +#define __BUILD_NUM 1 // other stuff for Version resource #include diff --git a/plugins/TabSRMM/src/resource.h b/plugins/TabSRMM/src/resource.h index c4472425c5..b0ecaae43e 100644 --- a/plugins/TabSRMM/src/resource.h +++ b/plugins/TabSRMM/src/resource.h @@ -193,7 +193,6 @@ #define IDC_TOGGLETOOLBAR 1144 #define IDC_ERRORTEXT 1145 #define IDC_SHOWNOTIFY 1146 -#define IDC_STATUSWIN 1147 #define IDC_TYPEFLASHWIN 1148 #define IDC_CHARCOUNT 1149 #define IDC_TYPENOWIN 1150 diff --git a/src/core/stdmsg/res/resource.rc b/src/core/stdmsg/res/resource.rc index dbdc5bcf2b..9acdd24f88 100644 --- a/src/core/stdmsg/res/resource.rc +++ b/src/core/stdmsg/res/resource.rc @@ -33,36 +33,39 @@ EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN LTEXT "Automatically popup window when:",IDC_STATIC,7,7,141,13 - CONTROL "Tree1",IDC_POPLIST,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | TVS_NOHSCROLL | TVS_NONEVENHEIGHT | WS_BORDER | WS_HSCROLL | WS_TABSTOP,199,6,98,42 + CONTROL "Tree1",IDC_POPLIST,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | TVS_NOHSCROLL | TVS_NONEVENHEIGHT | WS_BORDER | WS_TABSTOP,199,6,98,42 CONTROL "In background",IDC_DONOTSTEALFOCUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,21,130,10 + + LTEXT "Maximum number of flashes",IDC_STATIC,7,35,141,8 + EDITTEXT IDC_NFLASHES,148,33,25,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "Close the message window on send",IDC_AUTOCLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,50,289,10 CONTROL "Minimize the message window on send",IDC_AUTOMIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,62,289,10 - CONTROL "Use the contact's status icon as the window icon",IDC_STATUSWIN, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,74,289,10 CONTROL "Save the window size and location individually for each contact",IDC_SAVEPERCONTACT, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,86,289,10 CONTROL "Cascade new windows",IDC_CASCADE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,98,289,10 - CONTROL "Show 'Send' button",IDC_SHOWSENDBTN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,166,135,10 - CONTROL "Show toolbar buttons on top row",IDC_SHOWBUTTONLINE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,192,137,10 - CONTROL "Send message on double 'Enter'",IDC_SENDONDBLENTER, - "Button", BS_AUTORADIOBUTTON | WS_TABSTOP,148,166,149,10 - CONTROL "Send message on 'Enter'",IDC_SENDONENTER,"Button", BS_AUTORADIOBUTTON | WS_TABSTOP,148,179,152,10 - CONTROL "Show character count",IDC_CHARCOUNT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,148,192,149,10 - LTEXT "Show warning when message has not been received after",IDC_STATIC,8,208,211,8 - EDITTEXT IDC_SECONDS,223,206,25,12,ES_AUTOHSCROLL - LTEXT "seconds",IDC_STATIC,253,208,44,8 CONTROL "Support CTRL+Up/Down in message area to show previously sent messages",IDC_CTRLSUPPORT, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,110,289,10 CONTROL "Delete temporary contacts when closing message window",IDC_DELTEMP, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,122,287,10 CONTROL "Enable avatar support in the message window",IDC_AVATARSUPPORT, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,135,289,10 + CONTROL "Limit avatar height to",IDC_LIMITAVATARH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,149,126,10 EDITTEXT IDC_AVATARHEIGHT,148,148,28,13,ES_AUTOHSCROLL LTEXT "pixels",IDC_STATIC,181,150,35,8 - LTEXT "Maximum number of flashes",IDC_STATIC,7,35,141,8 - EDITTEXT IDC_NFLASHES,148,33,25,12,ES_AUTOHSCROLL | ES_NUMBER + + CONTROL "Show 'Send' button",IDC_SHOWSENDBTN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,166,135,10 + CONTROL "Show character count",IDC_CHARCOUNT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,179,135,10 + CONTROL "Show toolbar buttons on top row",IDC_SHOWBUTTONLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,192,137,10 + + CONTROL "Send message on double 'Enter'",IDC_SENDONDBLENTER,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,148,166,149,10 + CONTROL "Send message on 'Enter'",IDC_SENDONENTER,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,148,179,152,10 + CONTROL "Send message on 'Ctrl-Enter'",IDC_SENDONCTRLENTER, "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,148,192,152,10 + + LTEXT "Show warning when message has not been received after",IDC_STATIC,8,208,211,8 + EDITTEXT IDC_SECONDS,223,206,25,12,ES_AUTOHSCROLL + LTEXT "seconds",IDC_STATIC,253,208,44,8 END IDD_MSGSENDERROR DIALOGEX 0, 0, 187, 110 @@ -242,7 +245,7 @@ BEGIN CONTROL "Custom2",IDC_BKG,"ColourPicker",WS_TABSTOP,201,93,50,14,WS_EX_NOACTIVATE | 0x10000000L EDITTEXT IDC_TIMEOUT,132,134,38,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER CONTROL "Spin1",IDC_SPIN1,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,169,135,11,14 - GROUPBOX "Popups for the Chat plugin",IDC_STATIC,0,0,277,174 + GROUPBOX "Popups for the StdMsg plugin",IDC_STATIC,0,0,277,174 LTEXT "Timeout (s)",IDC_STATIC,33,138,92,8 LTEXT "Text",IDC_STATIC,141,83,49,8 LTEXT "Background",IDC_STATIC,201,83,67,8 diff --git a/src/core/stdmsg/src/chat_manager.cpp b/src/core/stdmsg/src/chat_manager.cpp index a4e4697f3e..d55671f558 100644 --- a/src/core/stdmsg/src/chat_manager.cpp +++ b/src/core/stdmsg/src/chat_manager.cpp @@ -60,33 +60,26 @@ CHAT_MANAGER *pci; HMENU g_hMenu = nullptr; BOOL SmileyAddInstalled = FALSE, PopupInstalled = FALSE; -HIMAGELIST hIconsList; GlobalLogSettings g_Settings; static void OnDestroyModule(MODULEINFO *mi) { - if (mi->hOnlineIcon) DestroyIcon(mi->hOnlineIcon); - if (mi->hOnlineTalkIcon) DestroyIcon(mi->hOnlineTalkIcon); - if (mi->hOfflineIcon) DestroyIcon(mi->hOfflineIcon); - if (mi->hOfflineTalkIcon) DestroyIcon(mi->hOfflineTalkIcon); + if (mi->hOnlineIcon) + DestroyIcon(mi->hOnlineIcon); + if (mi->hOfflineIcon) + DestroyIcon(mi->hOfflineIcon); } static void OnCreateModule(MODULEINFO *mi) { OnDestroyModule(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->OnlineIconIndex = pcli->pfnIconFromStatusMode(mi->pszModule, ID_STATUS_ONLINE, 0); + mi->hOnlineIcon = ImageList_GetIcon(Clist_GetImageList(), mi->OnlineIconIndex, ILD_TRANSPARENT); - 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); - - g_iMessageIconIndex = ImageList_AddIcon(hIconsList, Skin_LoadIcon(SKINICON_EVENT_MESSAGE)); + mi->OfflineIconIndex = pcli->pfnIconFromStatusMode(mi->pszModule, ID_STATUS_OFFLINE, 0); + mi->hOfflineIcon = ImageList_GetIcon(Clist_GetImageList(), mi->OfflineIconIndex, ILD_TRANSPARENT); } static void OnReplaceSession(SESSION_INFO *si) @@ -257,11 +250,6 @@ void Load_ChatModule() g_hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU)); - hIconsList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 0, 100); - ImageList_AddIcon(hIconsList, Skin_LoadIcon(SKINICON_EVENT_MESSAGE)); - ImageList_AddIcon(hIconsList, LoadIconEx("overlay", FALSE)); - ImageList_SetOverlayImage(hIconsList, 1, 1); - HookEvent(ME_SYSTEM_MODULELOAD, OnCheckPlugins); } diff --git a/src/core/stdmsg/src/chat_options.cpp b/src/core/stdmsg/src/chat_options.cpp index 96bdb59659..2764e3c528 100644 --- a/src/core/stdmsg/src/chat_options.cpp +++ b/src/core/stdmsg/src/chat_options.cpp @@ -31,8 +31,6 @@ struct branch_t }; static branch_t branch1[] = { - { LPGENW("Send message by pressing the 'Enter' key"), "SendOnEnter", 0, true }, - { LPGENW("Send message by pressing the 'Enter' key twice"), "SendOnDblEnter", 0, false }, { LPGENW("Flash window when someone speaks"), "FlashWindow", 0, false }, { LPGENW("Flash window when a word is highlighted"), "FlashWindowHighlight", 0, true }, { LPGENW("Show list of users in the chat room"), "ShowNicklist", 0, true }, diff --git a/src/core/stdmsg/src/chat_window.cpp b/src/core/stdmsg/src/chat_window.cpp index 4767d84312..a015311e85 100644 --- a/src/core/stdmsg/src/chat_window.cpp +++ b/src/core/stdmsg/src/chat_window.cpp @@ -58,7 +58,7 @@ void CChatRoomDlg::OnInitDialog() if (g_Settings.bTabsEnable) SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, GetWindowLongPtr(m_hwnd, GWL_EXSTYLE) | WS_EX_APPWINDOW); else - onActivate(); + OnActivate(); m_log.SendMsg(EM_AUTOURLDETECT, 1, 0); @@ -86,7 +86,7 @@ void CChatRoomDlg::OnDestroy() CSuper::OnDestroy(); } -void CChatRoomDlg::onActivate() +void CChatRoomDlg::OnActivate() { WINDOWPLACEMENT wp = {}; wp.length = sizeof(wp); @@ -286,13 +286,8 @@ void CChatRoomDlg::UpdateOptions() hIcon = (m_si->wStatus == ID_STATUS_ONLINE) ? mi->hOnlineIcon : mi->hOfflineIcon; } - if (g_Settings.bTabsEnable) - g_pTabDialog->FixTabIcons(nullptr); - SendMessage(m_pOwner->m_hwndStatus, SB_SETICON, 0, (LPARAM)hIcon); - Window_SetIcon_IcoLib(m_pOwner->GetHwnd(), GetIconHandle("window")); - m_log.SendMsg(EM_SETBKGNDCOLOR, 0, g_Settings.crLogBackground); CHARFORMAT2 cf; @@ -341,10 +336,6 @@ void CChatRoomDlg::UpdateStatusBar() } SendMessage(m_pOwner->m_hwndStatus, SB_SETICON, 0, (LPARAM)hIcon); - - if (g_Settings.bTabsEnable) - g_pTabDialog->FixTabIcons(nullptr); - SendMessage(m_pOwner->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)ptszDispName); SendMessage(m_pOwner->m_hwndStatus, SB_SETTEXT, 1, (LPARAM)(m_si->ptszStatusbarText ? m_si->ptszStatusbarText : L"")); SendMessage(m_pOwner->m_hwndStatus, SB_SETTIPTEXT, 1, (LPARAM)(m_si->ptszStatusbarText ? m_si->ptszStatusbarText : L"")); @@ -635,11 +626,11 @@ LRESULT CChatRoomDlg::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) return TRUE; if (wParam == '\n' || wParam == '\r') { - if ((isCtrl != 0) ^ (0 != db_get_b(0, CHAT_MODULE, "SendOnEnter", 1))) { + if ((isCtrl && g_dat.bSendOnCtrlEnter) || (!isCtrl && g_dat.bSendOnEnter)) { m_btnOk.OnClick(&m_btnOk); return 0; } - if (db_get_b(0, CHAT_MODULE, "SendOnDblEnter", 0)) { + if (g_dat.bSendOnDblEnter) { if (m_iLastEnterTime + 2 < time(0)) m_iLastEnterTime = time(0); else { @@ -667,10 +658,10 @@ LRESULT CChatRoomDlg::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) bool isAlt = (GetKeyState(VK_MENU) & 0x8000) != 0; if (wParam == VK_RETURN) { szTabSave[0] = '\0'; - if ((isCtrl != 0) ^ (0 != db_get_b(0, CHAT_MODULE, "SendOnEnter", 1))) + if ((isCtrl && g_dat.bSendOnCtrlEnter) || (!isCtrl && g_dat.bSendOnEnter)) return 0; - if (db_get_b(0, CHAT_MODULE, "SendOnDblEnter", 0)) + if (g_dat.bSendOnDblEnter) if (m_iLastEnterTime + 2 >= time(0)) return 0; @@ -1110,17 +1101,8 @@ INT_PTR CChatRoomDlg::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) if (g_Settings.bTabsEnable) { m_si->wState &= ~GC_EVENT_HIGHLIGHT; m_si->wState &= ~STATE_TALK; - g_pTabDialog->FixTabIcons(nullptr); } - break; } - if (LOWORD(wParam) == WA_ACTIVE) - onActivate(); - break; - - case WM_MOUSEACTIVATE: - onActivate(); - SetFocus(m_message.GetHwnd()); break; case WM_NOTIFY: diff --git a/src/core/stdmsg/src/globals.cpp b/src/core/stdmsg/src/globals.cpp index 01aa85af7b..353bd8bf17 100644 --- a/src/core/stdmsg/src/globals.cpp +++ b/src/core/stdmsg/src/globals.cpp @@ -47,7 +47,6 @@ static int OnShutdown(WPARAM, LPARAM) si->pDlg->Close(); UninitTabs(); - ImageList_Destroy(hIconsList); return 0; } @@ -126,9 +125,9 @@ GlobalMessageData::GlobalMessageData() : bCtrlSupport(SRMMMOD, "SupportCtrlUpDn", true), bShowReadChar(SRMMMOD, "ShowCharCount", false), bSendOnDblEnter(SRMMMOD, "SendOnDblEnter", false), + bSendOnCtrlEnter(SRMMMOD, "SendOnCtrlEnter", false), bDeleteTempCont(SRMMMOD, "DeleteTempCont", false), bSavePerContact(SRMMMOD, "SavePerContact", false), - bUseStatusWinIcon(SRMMMOD, "UseStatusWinIcon", false), bDoNotStealFocus(SRMMMOD, "DoNotStealFocus", false), bLimitAvatarHeight(SRMMMOD, "AvatarLimitHeight", true), diff --git a/src/core/stdmsg/src/globals.h b/src/core/stdmsg/src/globals.h index fef2a2a44f..a0ad036b01 100644 --- a/src/core/stdmsg/src/globals.h +++ b/src/core/stdmsg/src/globals.h @@ -41,6 +41,7 @@ struct GlobalMessageData CMOption bShowReadChar; CMOption bSendOnEnter; CMOption bSendOnDblEnter; + CMOption bSendOnCtrlEnter; CMOption bAutoClose; CMOption bAutoMin; CMOption bTypingNew; @@ -48,7 +49,6 @@ struct GlobalMessageData CMOption bCtrlSupport; CMOption bShowFormat; CMOption bSavePerContact; - CMOption bUseStatusWinIcon; CMOption bDoNotStealFocus; CMOption bCascade; CMOption bDeleteTempCont; diff --git a/src/core/stdmsg/src/msgdialog.cpp b/src/core/stdmsg/src/msgdialog.cpp index 0a5ef46008..a65857539a 100644 --- a/src/core/stdmsg/src/msgdialog.cpp +++ b/src/core/stdmsg/src/msgdialog.cpp @@ -308,6 +308,17 @@ void CSrmmWindow::OnDestroy() db_delete_contact(m_hContact); } +void CSrmmWindow::OnActivate() +{ + SetupStatusBar(); + SetFocus(m_message.GetHwnd()); + UpdateTitle(); + UpdateLastMessage(); + if (KillTimer(m_hwnd, TIMERID_FLASHWND)) + FlashWindow(m_pOwner->GetHwnd(), FALSE); + SendMessage(m_hwnd, DM_UPDATEWINICON, 0, 0); +} + ///////////////////////////////////////////////////////////////////////////////////////// void CSrmmWindow::onClick_Ok(CCtrlButton *pButton) @@ -353,12 +364,12 @@ void CSrmmWindow::OnOptionsApplied(bool bUpdateAvatar) continue; bool bShow = false; - if (m_hContact) { + if (m_hContact && g_dat.bShowButtons) { if (cbd->m_dwButtonCID == IDC_ADD) { bShow = 0 != db_get_b(m_hContact, "CList", "NotOnList", 0); cbd->m_bHidden = !bShow; } - else bShow = g_dat.bShowButtons; + else bShow = true; } ShowWindow(hwndButton, (bShow) ? SW_SHOW : SW_HIDE); } @@ -585,19 +596,22 @@ void CSrmmWindow::UpdateIcon(WPARAM wParam) if (!m_hContact || !m_szProto) return; + bool bIsStatus = false; DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *)wParam; - if (!cws || (!mir_strcmp(cws->szModule, m_szProto) && !mir_strcmp(cws->szSetting, "Status"))) { - if (m_szProto) { - HICON hIcon = Skin_LoadProtoIcon(m_szProto, m_wStatus); - if (hIcon) { - if (m_hStatusIcon) - IcoLib_ReleaseIcon(m_hStatusIcon); - m_hStatusIcon = hIcon; - SendDlgItemMessage(m_hwnd, IDC_USERMENU, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - } + if (cws && !mir_strcmp(cws->szModule, m_szProto) && !mir_strcmp(cws->szSetting, "Status")) { + bIsStatus = true; + m_wStatus = cws->value.wVal; + } + + if (!cws || bIsStatus) { + HICON hIcon = Skin_LoadProtoIcon(m_szProto, m_wStatus); + if (hIcon) { + if (m_hStatusIcon) + IcoLib_ReleaseIcon(m_hStatusIcon); + m_hStatusIcon = hIcon; } - if (g_dat.bUseStatusWinIcon) - SendMessage(m_hwnd, DM_UPDATEWINICON, 0, 0); + + SendMessage(m_hwnd, DM_UPDATEWINICON, 0, 0); } } @@ -634,23 +648,15 @@ void CSrmmWindow::UpdateTitle() m_wStatus = db_get_w(m_hContact, m_szProto, "Status", ID_STATUS_OFFLINE); wchar_t *contactName = Clist_GetContactDisplayName(m_hContact); - if (g_dat.bUseStatusWinIcon) - mir_snwprintf(newtitle, L"%s - %s", contactName, TranslateT("Message session")); - else { - wchar_t *szStatus = Clist_GetStatusModeDescription(m_szProto == nullptr ? ID_STATUS_OFFLINE : db_get_w(m_hContact, m_szProto, "Status", ID_STATUS_OFFLINE), 0); - mir_snwprintf(newtitle, L"%s (%s): %s", contactName, szStatus, TranslateT("Message session")); - } - + mir_snwprintf(newtitle, L"%s - %s", contactName, TranslateT("Message session")); m_wOldStatus = m_wStatus; } else mir_wstrncpy(newtitle, TranslateT("Message session"), _countof(newtitle)); wchar_t oldtitle[256]; GetWindowText(m_pOwner->GetHwnd(), oldtitle, _countof(oldtitle)); - if (mir_wstrcmp(newtitle, oldtitle)) { //swt() flickers even if the title hasn't actually changed + if (mir_wstrcmp(newtitle, oldtitle)) //swt() flickers even if the title hasn't actually changed SetWindowText(m_pOwner->GetHwnd(), newtitle); - Resize(); - } } ///////////////////////////////////////////////////////////////////////////////////////// @@ -737,7 +743,11 @@ LRESULT CSrmmWindow::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) isAlt = (GetKeyState(VK_MENU) & 0x8000) != 0; if (wParam == VK_RETURN) { - if (!isShift && isCtrl != g_dat.bSendOnEnter) { + if (!isShift && !isCtrl && g_dat.bSendOnEnter) { + onClick_Ok(&m_btnOk); + return 0; + } + if (!isShift && isCtrl && g_dat.bSendOnCtrlEnter) { onClick_Ok(&m_btnOk); return 0; } @@ -1032,15 +1042,7 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) break; case DM_UPDATEWINICON: - if (g_dat.bUseStatusWinIcon) { - Window_FreeIcon_IcoLib(m_pOwner->GetHwnd()); - - if (m_szProto) { - Window_SetProtoIcon_IcoLib(m_pOwner->GetHwnd(), m_szProto, Contact_GetStatus(m_hContact)); - break; - } - } - Window_SetSkinIcon_IcoLib(m_pOwner->GetHwnd(), SKINICON_EVENT_MESSAGE); + m_pOwner->FixTabIcons(this); break; case DM_USERNAMETOCLIP: @@ -1080,22 +1082,6 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) } break; - case WM_ACTIVATE: - if (LOWORD(wParam) != WA_ACTIVE) - break; - - __fallthrough; - - case WM_MOUSEACTIVATE: - SetFocus(m_message.GetHwnd()); - UpdateTitle(); - UpdateLastMessage(); - if (KillTimer(m_hwnd, TIMERID_FLASHWND)) - FlashWindow(m_pOwner->GetHwnd(), FALSE); - if (g_dat.bUseStatusWinIcon) - SendMessage(m_hwnd, DM_UPDATEWINICON, 0, 0); - break; - case WM_CBD_LOADICONS: Srmm_UpdateToolbarIcons(m_hwnd); break; diff --git a/src/core/stdmsg/src/msgoptions.cpp b/src/core/stdmsg/src/msgoptions.cpp index 5168b2933c..6c62b74d07 100644 --- a/src/core/stdmsg/src/msgoptions.cpp +++ b/src/core/stdmsg/src/msgoptions.cpp @@ -154,9 +154,9 @@ class COptionMainDlg : public CPluginDlgBase { CCtrlEdit edtNFlash, edtAvatarH, edtSecs; CCtrlCheck chkAutoMin, chkAutoClose, chkSavePerContact, chkDoNotStealFocus; - CCtrlCheck chkDelTemp, chkCascade, chkCharCount, chkStatusWin, chkCtrlSupport; + CCtrlCheck chkDelTemp, chkCascade, chkCharCount, chkCtrlSupport; CCtrlCheck chkAvatar, chkLimitAvatar; - CCtrlCheck chkSendOnEnter, chkSendOnDblEnter, chkShowSend, chkShowButtons; + CCtrlCheck chkSendOnEnter, chkSendOnDblEnter, chkSendOnCtrlEnter, chkShowSend, chkShowButtons; CCtrlTreeView tree; @@ -204,13 +204,13 @@ public: chkCascade(this, IDC_CASCADE), chkShowSend(this, IDC_SHOWSENDBTN), chkAutoClose(this, IDC_AUTOCLOSE), - chkStatusWin(this, IDC_STATUSWIN), chkCharCount(this, IDC_CHARCOUNT), chkLimitAvatar(this, IDC_LIMITAVATARH), chkShowButtons(this, IDC_SHOWBUTTONLINE), chkCtrlSupport(this, IDC_CTRLSUPPORT), chkSendOnEnter(this, IDC_SENDONENTER), chkSendOnDblEnter(this, IDC_SENDONDBLENTER), + chkSendOnCtrlEnter(this, IDC_SENDONCTRLENTER), chkSavePerContact(this, IDC_SAVEPERCONTACT), chkDoNotStealFocus(this, IDC_DONOTSTEALFOCUS) { @@ -234,11 +234,11 @@ public: CreateLink(chkAutoClose, g_dat.bAutoClose); CreateLink(chkShowSend, g_dat.bSendButton); CreateLink(chkCharCount, g_dat.bShowReadChar); - CreateLink(chkStatusWin, g_dat.bUseStatusWinIcon); CreateLink(chkShowButtons, g_dat.bShowButtons); CreateLink(chkCtrlSupport, g_dat.bCtrlSupport); CreateLink(chkSendOnEnter, g_dat.bSendOnEnter); CreateLink(chkSendOnDblEnter, g_dat.bSendOnDblEnter); + CreateLink(chkSendOnCtrlEnter, g_dat.bSendOnCtrlEnter); CreateLink(chkSavePerContact, g_dat.bSavePerContact); CreateLink(chkDoNotStealFocus, g_dat.bDoNotStealFocus); } diff --git a/src/core/stdmsg/src/msgs.cpp b/src/core/stdmsg/src/msgs.cpp index 1b8a5f9727..a95501bf69 100644 --- a/src/core/stdmsg/src/msgs.cpp +++ b/src/core/stdmsg/src/msgs.cpp @@ -41,6 +41,23 @@ void CMsgDialog::CloseTab() else SendMessage(m_hwndParent, WM_CLOSE, 0, 0); } +INT_PTR CMsgDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_ACTIVATE: + if (LOWORD(wParam) == WA_ACTIVE) + OnActivate(); + break; + + case WM_MOUSEACTIVATE: + OnActivate(); + SetFocus(m_message.GetHwnd()); + break; + } + + return CSuper::DlgProc(uMsg, wParam, lParam); +} + ///////////////////////////////////////////////////////////////////////////////////////// int OnCheckPlugins(WPARAM, LPARAM); @@ -409,27 +426,20 @@ void SetButtonsPos(HWND hwndDlg, bool bIsChat) GetClientRect(hwndDlg, &rc); int iLeftX = 2, iRightX = rc.right - 2; - bool bShow = (bIsChat) ? true : g_dat.bShowButtons; - CustomButtonData *cbd; for (int i = 0; cbd = Srmm_GetNthButton(i); i++) { HWND hwndButton = GetDlgItem(hwndDlg, cbd->m_dwButtonCID); if (hwndButton == nullptr || cbd->m_bHidden) continue; - if (bShow) { - ShowWindow(hwndButton, SW_SHOW); - - if (cbd->m_bRSided) { - iRightX -= g_dat.iGap + cbd->m_iButtonWidth; - hdwp = DeferWindowPos(hdwp, hwndButton, nullptr, iRightX, yPos, 0, 0, SWP_NOZORDER | SWP_NOSIZE); - } - else { - hdwp = DeferWindowPos(hdwp, hwndButton, nullptr, iLeftX, yPos, 0, 0, SWP_NOZORDER | SWP_NOSIZE); - iLeftX += g_dat.iGap + cbd->m_iButtonWidth; - } + if (cbd->m_bRSided) { + iRightX -= g_dat.iGap + cbd->m_iButtonWidth; + hdwp = DeferWindowPos(hdwp, hwndButton, nullptr, iRightX, yPos, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } + else { + hdwp = DeferWindowPos(hdwp, hwndButton, nullptr, iLeftX, yPos, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + iLeftX += g_dat.iGap + cbd->m_iButtonWidth; } - else ShowWindow(hwndButton, SW_HIDE); } EndDeferWindowPos(hdwp); diff --git a/src/core/stdmsg/src/msgs.h b/src/core/stdmsg/src/msgs.h index 75c64c69cb..3d5e443517 100644 --- a/src/core/stdmsg/src/msgs.h +++ b/src/core/stdmsg/src/msgs.h @@ -53,8 +53,12 @@ protected: CMsgDialog(int idDialog, SESSION_INFO *si = nullptr); + virtual void OnActivate() PURE; + + INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override; + public: - virtual void CloseTab() override; + void CloseTab() override; __forceinline SESSION_INFO* getChat() const { return m_si; } }; @@ -63,8 +67,8 @@ class CSrmmWindow : public CMsgDialog { typedef CMsgDialog CSuper; - virtual LRESULT WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) override; - virtual LRESULT WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) override; + LRESULT WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) override; + LRESULT WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) override; CCtrlBase m_avatar; CSplitter m_splitter; @@ -114,16 +118,17 @@ public: public: CSrmmWindow(CTabbedWindow*, MCONTACT hContact); - virtual void OnInitDialog() override; - virtual void OnDestroy() override; + void OnInitDialog() override; + void OnDestroy() override; + void OnActivate() override; - virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override; - virtual int Resizer(UTILRESIZECONTROL *urc) override; + INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override; + int Resizer(UTILRESIZECONTROL *urc) override; - virtual void LoadSettings() override {} - virtual void ScrollToBottom() override; - virtual void SetStatusText(const wchar_t*, HICON) override; - virtual void UpdateTitle() override; + void LoadSettings() override {} + void ScrollToBottom() override; + void SetStatusText(const wchar_t*, HICON) override; + void UpdateTitle() override; void OnSplitterMoved(CSplitter*); @@ -152,9 +157,9 @@ class CChatRoomDlg : public CMsgDialog static INT_PTR CALLBACK FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); - virtual LRESULT WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) override; - virtual LRESULT WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) override; - virtual LRESULT WndProc_Nicklist(UINT msg, WPARAM wParam, LPARAM lParam) override; + LRESULT WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) override; + LRESULT WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) override; + LRESULT WndProc_Nicklist(UINT msg, WPARAM wParam, LPARAM lParam) override; wchar_t szTabSave[20]; @@ -164,26 +169,25 @@ class CChatRoomDlg : public CMsgDialog int m_iSplitterX, m_iSplitterY; - void onActivate(void); - public: CChatRoomDlg(CTabbedWindow*, SESSION_INFO*); - virtual void OnInitDialog() override; - virtual void OnDestroy() override; - - virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override; - virtual int Resizer(UTILRESIZECONTROL *urc) override; - - virtual void LoadSettings() override; - virtual void RedrawLog() override; - virtual void StreamInEvents(LOGINFO *lin, bool bRedraw) override; - virtual void ScrollToBottom() override; - virtual void ShowFilterMenu() override; - virtual void UpdateNickList() override; - virtual void UpdateOptions() override; - virtual void UpdateStatusBar() override; - virtual void UpdateTitle() override; + void OnInitDialog() override; + void OnDestroy() override; + void OnActivate() override; + + INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override; + int Resizer(UTILRESIZECONTROL *urc) override; + + void LoadSettings() override; + void RedrawLog() override; + void StreamInEvents(LOGINFO *lin, bool bRedraw) override; + void ScrollToBottom() override; + void ShowFilterMenu() override; + void UpdateNickList() override; + void UpdateOptions() override; + void UpdateStatusBar() override; + void UpdateTitle() override; void onClick_Ok(CCtrlButton*); diff --git a/src/core/stdmsg/src/resource.h b/src/core/stdmsg/src/resource.h index fda43c6d1e..92b72236fb 100644 --- a/src/core/stdmsg/src/resource.h +++ b/src/core/stdmsg/src/resource.h @@ -1,4 +1,4 @@ -//{{NO_DEPENDENCIES}} +//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by resource.rc // @@ -60,7 +60,6 @@ #define IDI_INCOMING 276 #define IDI_OUTGOING 277 #define IDI_EXCL 282 - #define IDC_SPLITTERX 1003 #define IDC_AUTOCLOSE 1004 #define IDC_AUTOMIN 1005 @@ -88,6 +87,7 @@ #define IDC_SENDONDBLENTER 1044 #define IDC_LOADTIMEN 1045 #define IDC_LOADTIMESPIN 1046 +#define IDC_SENDONCTRLENTER 1046 #define IDC_LOADTIME 1047 #define IDC_STMINSOLD 1048 #define IDC_SPIN1 1049 @@ -130,14 +130,12 @@ #define IDC_HIGHLIGHT 1089 #define IDC_TEXTO 1090 #define IDC_LOGGING 1091 - +#define IDC_STMSGLOGGROUP 1442 #define IDC_DETAILS 1469 #define IDC_USERMENU 1471 -#define IDC_STMSGLOGGROUP 1442 #define IDC_ERRORTEXT 1596 #define IDC_MSGTEXT 1597 #define IDC_SHOWNOTIFY 1600 -#define IDC_STATUSWIN 1601 #define IDC_TYPEWIN 1602 #define IDC_CHARCOUNT 1603 #define IDC_TYPETRAY 1603 @@ -158,7 +156,6 @@ #define IDC_CLOSETABS 1621 #define IDC_RESTORETABS 1622 #define IDC_TABSBOTTOM 1623 - #define IDM_CUT 40000 #define IDM_COPY 40001 #define IDM_PASTE 40002 @@ -169,17 +166,16 @@ #define IDM_COPYALL 40011 #define IDM_SELECTALL 40012 #define IDM_CLEAR 40013 - #define ID_MESS 40021 #define ID_COPYALL 40026 #define ID_CLEARLOG 40029 +#define ID_MESSAGE_PASTE 40030 #define ID_MESSAGE_UNDO 40033 #define ID_MESSAGE_COPY 40034 #define ID_MESSAGE_CUT 40035 #define ID_MESSAGE_CLEAR 40037 #define ID_MESSAGE_SELECTALL 40038 #define ID_MESSAGE_REDO 40039 -#define ID_MESSAGE_PASTE 40030 #define ID_CLOSE 40042 #define ID_CLOSEOTHER 40043 #define ID_LOCKPOSITION 40044 @@ -190,7 +186,7 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 290 +#define _APS_NEXT_RESOURCE_VALUE 291 #define _APS_NEXT_COMMAND_VALUE 40019 #define _APS_NEXT_CONTROL_VALUE 1620 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/src/core/stdmsg/src/stdafx.h b/src/core/stdmsg/src/stdafx.h index 28f6e257fd..c9f458a840 100644 --- a/src/core/stdmsg/src/stdafx.h +++ b/src/core/stdmsg/src/stdafx.h @@ -88,11 +88,8 @@ extern HINSTANCE g_hInst; struct MODULEINFO : public GCModuleInfoBase { - HICON hOnlineIcon, hOnlineTalkIcon; - HICON hOfflineIcon, hOfflineTalkIcon; - - int OnlineIconIndex; - int OfflineIconIndex; + HICON hOnlineIcon, hOfflineIcon; + int OnlineIconIndex, OfflineIconIndex; }; struct SESSION_INFO : public GCSessionInfoBase {}; @@ -112,11 +109,9 @@ struct GlobalLogSettings : public GlobalLogSettingsBase extern GlobalLogSettings g_Settings; extern HMENU g_hMenu; -extern HIMAGELIST hIconsList; extern HINSTANCE g_hInst; extern BOOL SmileyAddInstalled, PopupInstalled; -extern int g_iMessageIconIndex; // main.cpp void LoadIcons(void); diff --git a/src/core/stdmsg/src/tabs.cpp b/src/core/stdmsg/src/tabs.cpp index c244f0dd24..ba2e2670c5 100644 --- a/src/core/stdmsg/src/tabs.cpp +++ b/src/core/stdmsg/src/tabs.cpp @@ -42,7 +42,6 @@ void TB_SaveSession(SESSION_INFO *si) } CTabbedWindow *g_pTabDialog = nullptr; -int g_iMessageIconIndex; ///////////////////////////////////////////////////////////////////////////////////////// @@ -85,7 +84,7 @@ static LRESULT CALLBACK TabSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR MODULEINFO *mi = pci->MM_FindModule(si->pszModule); bDragging = true; iBeginIndex = idx; - ImageList_BeginDrag(hIconsList, bOnline ? mi->OnlineIconIndex : mi->OfflineIconIndex, 8, 8); + ImageList_BeginDrag(Clist_GetImageList(), bOnline ? mi->OnlineIconIndex : mi->OfflineIconIndex, 8, 8); ImageList_DragEnter(hwnd, tci.pt.x, tci.pt.y); SetCapture(hwnd); } @@ -192,7 +191,7 @@ void CTabbedWindow::OnInitDialog() SetWindowLongPtr(m_tab.GetHwnd(), GWL_STYLE, mask); TabCtrl_SetMinTabWidth(m_tab.GetHwnd(), 80); - TabCtrl_SetImageList(m_tab.GetHwnd(), hIconsList); + TabCtrl_SetImageList(m_tab.GetHwnd(), Clist_GetImageList()); // restore previous tabs if (g_Settings.bTabRestore) { @@ -273,9 +272,8 @@ void CTabbedWindow::AddPage(SESSION_INFO *si, int insertAt) CChatRoomDlg *pDlg = new CChatRoomDlg(this, si); pDlg->SetParent(m_hwnd); m_tab.AddPage(szTemp, nullptr, pDlg); - FixTabIcons(pDlg); - m_tab.ActivatePage(m_tab.GetCount() - 1); + FixTabIcons(pDlg); } else if (insertAt == -1) m_tab.ActivatePage(indexfound); @@ -283,31 +281,32 @@ void CTabbedWindow::AddPage(SESSION_INFO *si, int insertAt) void CTabbedWindow::FixTabIcons(CSrmmBaseDialog *pDlg) { - if (pDlg != nullptr) { - int idx = m_tab.GetDlgIndex(pDlg); - if (idx == -1) - return; + if (pDlg == nullptr) + return; - int image = 0; - if (SESSION_INFO *si = ((CChatRoomDlg*)pDlg)->m_si) { - if (!(si->wState & GC_EVENT_HIGHLIGHT)) { - MODULEINFO *mi = pci->MM_FindModule(si->pszModule); - image = (si->wStatus == ID_STATUS_ONLINE) ? mi->OnlineIconIndex : mi->OfflineIconIndex; - if (si->wState & STATE_TALK) - image++; - } - } - else image = g_iMessageIconIndex; + int idx = m_tab.GetDlgIndex(pDlg); + if (idx == -1) + return; - TCITEM tci = {}; - tci.mask = TCIF_IMAGE; - TabCtrl_GetItem(m_tab.GetHwnd(), idx, &tci); - if (tci.iImage != image) { - tci.iImage = image; - TabCtrl_SetItem(m_tab.GetHwnd(), idx, &tci); + int image = 0; + if (SESSION_INFO *si = ((CChatRoomDlg*)pDlg)->m_si) { + if (!(si->wState & GC_EVENT_HIGHLIGHT)) { + MODULEINFO *mi = pci->MM_FindModule(si->pszModule); + image = (si->wStatus == ID_STATUS_ONLINE) ? mi->OnlineIconIndex : mi->OfflineIconIndex; } } - else RedrawWindow(m_tab.GetHwnd(), nullptr, nullptr, RDW_INVALIDATE); + else image = pcli->pfnIconFromStatusMode(GetContactProto(pDlg->m_hContact), Contact_GetStatus(pDlg->m_hContact), pDlg->m_hContact); + + TCITEM tci = {}; + tci.mask = TCIF_IMAGE; + TabCtrl_GetItem(m_tab.GetHwnd(), idx, &tci); + if (tci.iImage != image) { + tci.iImage = image; + TabCtrl_SetItem(m_tab.GetHwnd(), idx, &tci); + } + + if (pDlg == m_tab.GetActivePage()) + SendMessage(m_hwnd, WM_SETICON, 0, (LPARAM)ImageList_GetIcon(Clist_GetImageList(), image, 0)); } void CTabbedWindow::SaveWindowPosition(bool bUpdateSession) diff --git a/src/mir_app/src/clisttray.cpp b/src/mir_app/src/clisttray.cpp index 658a11fd70..95a48da22d 100644 --- a/src/mir_app/src/clisttray.cpp +++ b/src/mir_app/src/clisttray.cpp @@ -27,8 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define TOOLTIP_TOLERANCE 5 -extern HIMAGELIST hCListImages; - static UINT WM_TASKBARCREATED; static UINT WM_TASKBARBUTTONCREATED; static UINT_PTR RefreshTimerId = 0; /////by FYR -- cgit v1.2.3