From 3e00af6e0b04bca9e5398f250c7dd4280da608cc Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sat, 28 Jan 2023 19:58:25 +0300 Subject: IRC: fix for event broadcasting --- include/m_chat.h | 12 +- include/m_chat_int.h | 5 - libs/win32/mir_app.lib | Bin 235740 -> 235986 bytes libs/win64/mir_app.lib | Bin 232642 -> 232892 bytes plugins/Scriver/src/msgdialog.cpp | 2 - plugins/TabSRMM/src/msgdlgother.cpp | 1 - protocols/IRCG/src/commandmonitor.cpp | 4 +- protocols/IRCG/src/ircproto.cpp | 140 ++++++++++----------- protocols/IRCG/src/stdafx.h | 2 +- protocols/IRCG/src/tools.cpp | 25 ++-- src/core/stdmsg/src/msgdialog.cpp | 1 - src/mir_app/src/chat_manager.cpp | 21 ---- src/mir_app/src/chat_svc.cpp | 228 +++++++++++++++++----------------- src/mir_app/src/mir_app.def | 1 + src/mir_app/src/mir_app64.def | 1 + 15 files changed, 209 insertions(+), 234 deletions(-) diff --git a/include/m_chat.h b/include/m_chat.h index 096811cf3c..5cb316087a 100644 --- a/include/m_chat.h +++ b/include/m_chat.h @@ -354,12 +354,17 @@ MIR_APP_DLL(struct SESSION_INFO*) Chat_NewSession( #define GCEF_SILENT 0x0002 // never add to log #define GCEF_NOTNOTIFY 0x0004 #define GCEF_UTF8 0x0008 +#define GCEF_BROADCAST 0x0010 // means that pszModule is used struct SESSION_INFO; struct GCEVENT { - SESSION_INFO *si; // session to deal with + union { + SESSION_INFO *si; // session to deal with + const char *pszModule; // module name to broadcast + }; + int iType; // Use GC_EVENT_* as defined above. Only one event per service call. MAllCStrings pszText; // @@ -414,11 +419,12 @@ MIR_APP_DLL(int) Chat_SetStatusEx(SESSION_INFO *si, int flags, const wchar_t *ws #define WINDOW_HIDDEN 3 // close the room window. Session is not terminated. #define WINDOW_CLEARLOG 6 // clear the log of the room window -// if wszId == NULL, this message is broadcasted to all windows of specified szModule MIR_APP_DLL(int) Chat_Control(SESSION_INFO *si, int command); +MIR_APP_DLL(int) Chat_Terminate(SESSION_INFO *si, bool bRemoveContact = false); +// these functions broadcast a command to all windows of specified szModule +MIR_APP_DLL(int) Chat_Control(const char *szModule, int command); MIR_APP_DLL(int) Chat_Terminate(const char *szModule, bool bRemoveContact = false); -MIR_APP_DLL(int) Chat_Terminate(SESSION_INFO *si, bool bRemoveContact = false); ///////////////////////////////////////////////////////////////////////////////////////// // Use this function to get information on different aspects of the sessions that are registered with Chat. diff --git a/include/m_chat_int.h b/include/m_chat_int.h index b7be21801a..d72bff1b0f 100644 --- a/include/m_chat_int.h +++ b/include/m_chat_int.h @@ -273,9 +273,6 @@ struct CHAT_MANAGER { CHAT_MANAGER(); - void (*SetActiveSession)(SESSION_INFO *si); - SESSION_INFO* (*GetActiveSession)(void); - SESSION_INFO* (*SM_CreateSession)(void); SESSION_INFO* (*SM_FindSession)(const wchar_t *pszID, const char *pszModule); HICON (*SM_GetStatusIcon)(SESSION_INFO *si, USERINFO * ui); @@ -328,8 +325,6 @@ struct CHAT_MANAGER void (*CreateNick)(const SESSION_INFO *si, const LOGINFO *lin, CMStringW &dest); int logPixelSY, logPixelSX; - char *szActiveWndModule; - wchar_t *szActiveWndID; HICON hStatusIcons[STATUSICONCOUNT]; HBRUSH hListBkgBrush, hListSelectedBkgBrush; HANDLE hevWinPopup, hevPreCreate; diff --git a/libs/win32/mir_app.lib b/libs/win32/mir_app.lib index f613afbd72..2fdd599d80 100644 Binary files a/libs/win32/mir_app.lib and b/libs/win32/mir_app.lib differ diff --git a/libs/win64/mir_app.lib b/libs/win64/mir_app.lib index 34a3a10687..f416cbf44a 100644 Binary files a/libs/win64/mir_app.lib and b/libs/win64/mir_app.lib differ diff --git a/plugins/Scriver/src/msgdialog.cpp b/plugins/Scriver/src/msgdialog.cpp index abf97224a9..3618b9a1aa 100644 --- a/plugins/Scriver/src/msgdialog.cpp +++ b/plugins/Scriver/src/msgdialog.cpp @@ -1087,8 +1087,6 @@ INT_PTR CMsgDialog::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) if (isChat()) { SetFocus(m_message.GetHwnd()); - g_chatApi.SetActiveSession(m_si); - if (db_get_w(m_hContact, m_si->pszModule, "ApparentMode", 0) != 0) db_set_w(m_hContact, m_si->pszModule, "ApparentMode", 0); if (g_clistApi.pfnGetEvent(m_hContact, 0)) diff --git a/plugins/TabSRMM/src/msgdlgother.cpp b/plugins/TabSRMM/src/msgdlgother.cpp index 94f019b140..f2045b77df 100644 --- a/plugins/TabSRMM/src/msgdlgother.cpp +++ b/plugins/TabSRMM/src/msgdlgother.cpp @@ -2756,7 +2756,6 @@ void CMsgDialog::UpdateWindowState(UINT msg) } if (m_si) { - g_chatApi.SetActiveSession(m_si); m_hTabIcon = m_hTabStatusIcon; if (db_get_w(m_si->hContact, m_si->pszModule, "ApparentMode", 0) != 0) diff --git a/protocols/IRCG/src/commandmonitor.cpp b/protocols/IRCG/src/commandmonitor.cpp index eb846b07af..5e0705dfe8 100644 --- a/protocols/IRCG/src/commandmonitor.cpp +++ b/protocols/IRCG/src/commandmonitor.cpp @@ -371,7 +371,7 @@ bool CIrcProto::OnIrc_QUIT(const CIrcMessage *pmsg) CONTACT user = { pmsg->prefix.sNick, pmsg->prefix.sUser, pmsg->prefix.sHost, false, false, false }; CList_SetOffline(&user); if (pmsg->prefix.sNick == m_info.sNick) - setAllContactStatuses(SESSION_OFFLINE, false); + ::Chat_Control(m_szModuleName, SESSION_OFFLINE); } else ShowMessage(pmsg); @@ -2277,7 +2277,7 @@ void CIrcProto::OnIrcDisconnected() sDisconn += TranslateT("*Disconnected*"); DoEvent(GC_EVENT_INFORMATION, SERVERWINDOW, nullptr, sDisconn, nullptr, nullptr, NULL, true, false); - setAllContactStatuses(SESSION_OFFLINE, false); + ::Chat_Control(m_szModuleName, SESSION_OFFLINE); if (!Miranda_IsTerminated()) CList_SetAllOffline(m_disconnectDCCChats); diff --git a/protocols/IRCG/src/ircproto.cpp b/protocols/IRCG/src/ircproto.cpp index 5c7d9fb3ef..205dab708d 100644 --- a/protocols/IRCG/src/ircproto.cpp +++ b/protocols/IRCG/src/ircproto.cpp @@ -76,76 +76,76 @@ CIrcProto::CIrcProto(const char* szModuleName, const wchar_t* tszUserName) : HookProtoEvent(ME_GC_EVENT, &CIrcProto::GCEventHook); HookProtoEvent(ME_GC_BUILDMENU, &CIrcProto::GCMenuHook); - IRC_MAP_ENTRY("PING", PING) - IRC_MAP_ENTRY("JOIN", JOIN) - IRC_MAP_ENTRY("QUIT", QUIT) - IRC_MAP_ENTRY("KICK", KICK) - IRC_MAP_ENTRY("MODE", MODE) - IRC_MAP_ENTRY("NICK", NICK) - IRC_MAP_ENTRY("PART", PART) - IRC_MAP_ENTRY("PRIVMSG", PRIVMSG) - IRC_MAP_ENTRY("TOPIC", TOPIC) - IRC_MAP_ENTRY("NOTICE", NOTICE) - IRC_MAP_ENTRY("PING", PINGPONG) - IRC_MAP_ENTRY("PONG", PINGPONG) - IRC_MAP_ENTRY("CAP", CAP) - IRC_MAP_ENTRY("AUTHENTICATE", AUTHENTICATE) - IRC_MAP_ENTRY("INVITE", INVITE) - IRC_MAP_ENTRY("ERROR", ERROR) - IRC_MAP_ENTRY("001", WELCOME) - IRC_MAP_ENTRY("002", YOURHOST) - IRC_MAP_ENTRY("005", SUPPORT) - IRC_MAP_ENTRY("223", WHOIS_OTHER) //CodePage info - IRC_MAP_ENTRY("254", NOOFCHANNELS) - IRC_MAP_ENTRY("263", TRYAGAIN) - IRC_MAP_ENTRY("264", WHOIS_OTHER) //Encryption info (SSL connect) - IRC_MAP_ENTRY("301", WHOIS_AWAY) - IRC_MAP_ENTRY("302", USERHOST_REPLY) - IRC_MAP_ENTRY("305", BACKFROMAWAY) - IRC_MAP_ENTRY("306", SETAWAY) - IRC_MAP_ENTRY("307", WHOIS_AUTH) - IRC_MAP_ENTRY("310", WHOIS_OTHER) - IRC_MAP_ENTRY("311", WHOIS_NAME) - IRC_MAP_ENTRY("312", WHOIS_SERVER) - IRC_MAP_ENTRY("313", WHOIS_OTHER) - IRC_MAP_ENTRY("315", WHO_END) - IRC_MAP_ENTRY("317", WHOIS_IDLE) - IRC_MAP_ENTRY("318", WHOIS_END) - IRC_MAP_ENTRY("319", WHOIS_CHANNELS) - IRC_MAP_ENTRY("320", WHOIS_AUTH) - IRC_MAP_ENTRY("321", LISTSTART) - IRC_MAP_ENTRY("322", LIST) - IRC_MAP_ENTRY("323", LISTEND) - IRC_MAP_ENTRY("324", MODEQUERY) - IRC_MAP_ENTRY("330", WHOIS_AUTH) - IRC_MAP_ENTRY("332", INITIALTOPIC) - IRC_MAP_ENTRY("333", INITIALTOPICNAME) - IRC_MAP_ENTRY("352", WHO_REPLY) - IRC_MAP_ENTRY("353", NAMES) - IRC_MAP_ENTRY("366", ENDNAMES) - IRC_MAP_ENTRY("367", BANLIST) - IRC_MAP_ENTRY("368", BANLISTEND) - IRC_MAP_ENTRY("346", BANLIST) - IRC_MAP_ENTRY("347", BANLISTEND) - IRC_MAP_ENTRY("348", BANLIST) - IRC_MAP_ENTRY("349", BANLISTEND) - IRC_MAP_ENTRY("371", WHOIS_OTHER) - IRC_MAP_ENTRY("376", ENDMOTD) - IRC_MAP_ENTRY("401", WHOIS_NO_USER) - IRC_MAP_ENTRY("403", JOINERROR) - IRC_MAP_ENTRY("416", WHOTOOLONG) - IRC_MAP_ENTRY("421", UNKNOWN) - IRC_MAP_ENTRY("422", ENDMOTD) - IRC_MAP_ENTRY("433", NICK_ERR) - IRC_MAP_ENTRY("471", JOINERROR) - IRC_MAP_ENTRY("473", JOINERROR) - IRC_MAP_ENTRY("474", JOINERROR) - IRC_MAP_ENTRY("475", JOINERROR) - IRC_MAP_ENTRY("671", WHOIS_OTHER) //Encryption info (SSL connect) - IRC_MAP_ENTRY("903", AUTH_OK) - IRC_MAP_ENTRY("904", AUTH_FAIL) - IRC_MAP_ENTRY("905", AUTH_FAIL) - IRC_MAP_ENTRY("906", AUTH_FAIL) + IRC_MAP_ENTRY("PING", OnIrc_PING) + IRC_MAP_ENTRY("JOIN", OnIrc_JOIN) + IRC_MAP_ENTRY("QUIT", OnIrc_QUIT) + IRC_MAP_ENTRY("KICK", OnIrc_KICK) + IRC_MAP_ENTRY("MODE", OnIrc_MODE) + IRC_MAP_ENTRY("NICK", OnIrc_NICK) + IRC_MAP_ENTRY("PART", OnIrc_PART) + IRC_MAP_ENTRY("PRIVMSG", OnIrc_PRIVMSG) + IRC_MAP_ENTRY("TOPIC", OnIrc_TOPIC) + IRC_MAP_ENTRY("NOTICE", OnIrc_NOTICE) + IRC_MAP_ENTRY("PING", OnIrc_PINGPONG) + IRC_MAP_ENTRY("PONG", OnIrc_PINGPONG) + IRC_MAP_ENTRY("CAP", OnIrc_CAP) + IRC_MAP_ENTRY("AUTHENTICATE", OnIrc_AUTHENTICATE) + IRC_MAP_ENTRY("INVITE", OnIrc_INVITE) + IRC_MAP_ENTRY("ERROR", OnIrc_ERROR) + IRC_MAP_ENTRY("001", OnIrc_WELCOME) + IRC_MAP_ENTRY("002", OnIrc_YOURHOST) + IRC_MAP_ENTRY("005", OnIrc_SUPPORT) + IRC_MAP_ENTRY("223", OnIrc_WHOIS_OTHER) //CodePage info + IRC_MAP_ENTRY("254", OnIrc_NOOFCHANNELS) + IRC_MAP_ENTRY("263", OnIrc_TRYAGAIN) + IRC_MAP_ENTRY("264", OnIrc_WHOIS_OTHER) //Encryption info (SSL connect) + IRC_MAP_ENTRY("301", OnIrc_WHOIS_AWAY) + IRC_MAP_ENTRY("302", OnIrc_USERHOST_REPLY) + IRC_MAP_ENTRY("305", OnIrc_BACKFROMAWAY) + IRC_MAP_ENTRY("306", OnIrc_SETAWAY) + IRC_MAP_ENTRY("307", OnIrc_WHOIS_AUTH) + IRC_MAP_ENTRY("310", OnIrc_WHOIS_OTHER) + IRC_MAP_ENTRY("311", OnIrc_WHOIS_NAME) + IRC_MAP_ENTRY("312", OnIrc_WHOIS_SERVER) + IRC_MAP_ENTRY("313", OnIrc_WHOIS_OTHER) + IRC_MAP_ENTRY("315", OnIrc_WHO_END) + IRC_MAP_ENTRY("317", OnIrc_WHOIS_IDLE) + IRC_MAP_ENTRY("318", OnIrc_WHOIS_END) + IRC_MAP_ENTRY("319", OnIrc_WHOIS_CHANNELS) + IRC_MAP_ENTRY("320", OnIrc_WHOIS_AUTH) + IRC_MAP_ENTRY("321", OnIrc_LISTSTART) + IRC_MAP_ENTRY("322", OnIrc_LIST) + IRC_MAP_ENTRY("323", OnIrc_LISTEND) + IRC_MAP_ENTRY("324", OnIrc_MODEQUERY) + IRC_MAP_ENTRY("330", OnIrc_WHOIS_AUTH) + IRC_MAP_ENTRY("332", OnIrc_INITIALTOPIC) + IRC_MAP_ENTRY("333", OnIrc_INITIALTOPICNAME) + IRC_MAP_ENTRY("352", OnIrc_WHO_REPLY) + IRC_MAP_ENTRY("353", OnIrc_NAMES) + IRC_MAP_ENTRY("366", OnIrc_ENDNAMES) + IRC_MAP_ENTRY("367", OnIrc_BANLIST) + IRC_MAP_ENTRY("368", OnIrc_BANLISTEND) + IRC_MAP_ENTRY("346", OnIrc_BANLIST) + IRC_MAP_ENTRY("347", OnIrc_BANLISTEND) + IRC_MAP_ENTRY("348", OnIrc_BANLIST) + IRC_MAP_ENTRY("349", OnIrc_BANLISTEND) + IRC_MAP_ENTRY("371", OnIrc_WHOIS_OTHER) + IRC_MAP_ENTRY("376", OnIrc_ENDMOTD) + IRC_MAP_ENTRY("401", OnIrc_WHOIS_NO_USER) + IRC_MAP_ENTRY("403", OnIrc_JOINERROR) + IRC_MAP_ENTRY("416", OnIrc_WHOTOOLONG) + IRC_MAP_ENTRY("421", OnIrc_UNKNOWN) + IRC_MAP_ENTRY("422", OnIrc_ENDMOTD) + IRC_MAP_ENTRY("433", OnIrc_NICK_ERR) + IRC_MAP_ENTRY("471", OnIrc_JOINERROR) + IRC_MAP_ENTRY("473", OnIrc_JOINERROR) + IRC_MAP_ENTRY("474", OnIrc_JOINERROR) + IRC_MAP_ENTRY("475", OnIrc_JOINERROR) + IRC_MAP_ENTRY("671", OnIrc_WHOIS_OTHER) //Encryption info (SSL connect) + IRC_MAP_ENTRY("903", OnIrc_AUTH_OK) + IRC_MAP_ENTRY("904", OnIrc_AUTH_FAIL) + IRC_MAP_ENTRY("905", OnIrc_AUTH_FAIL) + IRC_MAP_ENTRY("906", OnIrc_AUTH_FAIL) } CIrcProto::~CIrcProto() diff --git a/protocols/IRCG/src/stdafx.h b/protocols/IRCG/src/stdafx.h index 26b290438b..d690634e4f 100644 --- a/protocols/IRCG/src/stdafx.h +++ b/protocols/IRCG/src/stdafx.h @@ -183,7 +183,7 @@ using namespace irc; // map actual member functions to their associated IRC command. // put any number of this macro in the class's constructor. #define IRC_MAP_ENTRY(name, member) \ - m_handlers.insert( new CIrcHandler( L##name, &CIrcProto::OnIrc_##member )); + m_handlers.insert( new CIrcHandler( L##name, &CIrcProto::##member )); ///////////////////////////////////////////////////////////////////////////////////////// // Functions diff --git a/protocols/IRCG/src/tools.cpp b/protocols/IRCG/src/tools.cpp index 4748f34534..89dff93034 100644 --- a/protocols/IRCG/src/tools.cpp +++ b/protocols/IRCG/src/tools.cpp @@ -378,26 +378,31 @@ INT_PTR CIrcProto::DoEvent(int iEvent, const wchar_t *pszWindow, const wchar_t * const wchar_t *pszText, const wchar_t *pszStatus, const wchar_t *pszUserInfo, DWORD_PTR dwItemData, bool bAddToLog, bool bIsMe, time_t timestamp) { - CMStringW sID; - CMStringW sText; - if (iEvent == GC_EVENT_INFORMATION && bIsMe && !bEcho) return false; + CMStringW sText; if (pszText) sText = DoColorCodes(pszText, FALSE, TRUE); - GCEVENT gce = { 0, iEvent }; - if (pszWindow) { - sID = pszWindow; - gce.si = Chat_Find(sID.c_str(), m_szModuleName); + GCEVENT gce = {}; + if (pszWindow) + gce.si = Chat_Find(pszWindow, m_szModuleName); + else { + gce.pszModule = m_szModuleName; + gce.dwFlags |= GCEF_BROADCAST; } - else gce.si = nullptr; + if (bAddToLog) + gce.dwFlags |= GCEF_ADDTOLOG; + + gce.iType = iEvent; gce.pszStatus.w = pszStatus; - gce.dwFlags = (bAddToLog) ? GCEF_ADDTOLOG : 0; gce.pszNick.w = pszNick; gce.pszUID.w = pszNick; + gce.dwItemData = dwItemData; + gce.bIsMe = bIsMe; + if (iEvent == GC_EVENT_TOPIC) gce.pszUserInfo.w = pszUserInfo; else @@ -406,12 +411,10 @@ INT_PTR CIrcProto::DoEvent(int iEvent, const wchar_t *pszWindow, const wchar_t * if (!sText.IsEmpty()) gce.pszText.w = sText.c_str(); - gce.dwItemData = dwItemData; if (timestamp == 1) gce.time = time(0); else gce.time = timestamp; - gce.bIsMe = bIsMe; return Chat_Event(&gce); } diff --git a/src/core/stdmsg/src/msgdialog.cpp b/src/core/stdmsg/src/msgdialog.cpp index 359b308022..67401eea28 100644 --- a/src/core/stdmsg/src/msgdialog.cpp +++ b/src/core/stdmsg/src/msgdialog.cpp @@ -267,7 +267,6 @@ void CMsgDialog::OnActivate() StopFlash(); if (isChat()) { - g_chatApi.SetActiveSession(m_si); UpdateStatusBar(); if (db_get_w(m_hContact, m_si->pszModule, "ApparentMode", 0) != 0) diff --git a/src/mir_app/src/chat_manager.cpp b/src/mir_app/src/chat_manager.cpp index 608e1bedac..014c092322 100644 --- a/src/mir_app/src/chat_manager.cpp +++ b/src/mir_app/src/chat_manager.cpp @@ -55,25 +55,6 @@ static int compareModules(const MODULEINFO *p1, const MODULEINFO *p2) static LIST g_arModules(5, compareModules); -///////////////////////////////////////////////////////////////////////////////////////// - -static void SetActiveSession(SESSION_INFO *si) -{ - if (si) { - replaceStrW(g_chatApi.szActiveWndID, si->ptszID); - replaceStr(g_chatApi.szActiveWndModule, si->pszModule); - } -} - -static SESSION_INFO* GetActiveSession(void) -{ - SESSION_INFO *si = Chat_Find(g_chatApi.szActiveWndID, g_chatApi.szActiveWndModule); - if (si) - return si; - - return g_arSessions[0]; -} - ///////////////////////////////////////////////////////////////////////////////////////// // Log manager functions // Necessary to keep track of events in a window log @@ -893,8 +874,6 @@ static void CreateNick(const SESSION_INFO *, const LOGINFO *lin, CMStringW &wszN static void ResetApi() { - g_chatApi.SetActiveSession = ::SetActiveSession; - g_chatApi.GetActiveSession = ::GetActiveSession; g_chatApi.SM_CreateSession = ::SM_CreateSession; g_chatApi.SM_GetStatusIcon = ::SM_GetStatusIcon; g_chatApi.SM_GetCount = ::SM_GetCount; diff --git a/src/mir_app/src/chat_svc.cpp b/src/mir_app/src/chat_svc.cpp index d4462ec3d2..7dd1c64498 100644 --- a/src/mir_app/src/chat_svc.cpp +++ b/src/mir_app/src/chat_svc.cpp @@ -268,6 +268,7 @@ MIR_APP_DLL(SESSION_INFO*) Chat_NewSession( struct ChatConrolParam { + const char *pszModule; SESSION_INFO *si; int command; }; @@ -283,25 +284,17 @@ static void SetInitDone(SESSION_INFO *si) p->iIconIndex = si->iStatusCount - p->iIconIndex - 1; } -static INT_PTR __stdcall stubRoomControl(void *param) +static int RoomControlHandler(int iCommand, SESSION_INFO *si) { - ChatConrolParam *p = (ChatConrolParam*)param; - - mir_cslock lck(csChat); - SESSION_INFO *si = g_arSessions.find(p->si); - if (si == nullptr) - return GC_EVENT_ERROR; - - switch (p->command) { + switch (iCommand) { case WINDOW_HIDDEN: SetInitDone(si); - g_chatApi.SetActiveSession(si); break; case WINDOW_VISIBLE: case SESSION_INITDONE: SetInitDone(si); - if (p->command != SESSION_INITDONE || !Chat::bPopupOnJoin) + if (iCommand != SESSION_INITDONE || !Chat::bPopupOnJoin) g_chatApi.ShowRoom(si); break; @@ -335,9 +328,41 @@ static INT_PTR __stdcall stubRoomControl(void *param) return 0; } +static INT_PTR __stdcall stubRoomControl(void *param) +{ + ChatConrolParam *p = (ChatConrolParam*)param; + + mir_cslock lck(csChat); + if (p->si) { + SESSION_INFO *si = g_arSessions.find(p->si); + if (si == nullptr) + return GC_EVENT_ERROR; + + return RoomControlHandler(p->command, si); + } + + for (auto &si : g_arSessions) + if (si->bInitDone && !mir_strcmpi(si->pszModule, p->pszModule)) + RoomControlHandler(p->command, si); + + return 0; +} + +MIR_APP_DLL(int) Chat_Control(const char *pszModule, int iCommand) +{ + if (!pszModule) + return GC_EVENT_ERROR; + + ChatConrolParam param = { pszModule, 0, iCommand }; + return CallFunctionSync(stubRoomControl, ¶m); +} + MIR_APP_DLL(int) Chat_Control(SESSION_INFO *si, int iCommand) { - ChatConrolParam param = { si, iCommand }; + if (!si) + return GC_EVENT_ERROR; + + ChatConrolParam param = { 0, si, iCommand }; return CallFunctionSync(stubRoomControl, ¶m); } @@ -404,64 +429,22 @@ static void AddUser(GCEVENT *gce) g_chatApi.OnNewUser(si, ui); } -static BOOL AddEventToAllMatchingUID(GCEVENT *gce) -{ - int bManyFix = 0; - - for (auto &si : g_arSessions) { - if (!si->bInitDone || mir_strcmpi(si->pszModule, gce->si->pszModule)) - continue; - - if (!g_chatApi.UM_FindUser(si, gce->pszUID.w)) - continue; - - if (g_chatApi.OnEventBroadcast) - g_chatApi.OnEventBroadcast(si, gce); - - if (si->pDlg && si->bInitDone) { - if (SM_AddEvent(si, gce, FALSE)) - si->pDlg->AddLog(); - else - RedrawLog2(si); - } - - if (!(gce->dwFlags & GCEF_NOTNOTIFY)) - g_chatApi.DoSoundsFlashPopupTrayStuff(si, gce, FALSE, bManyFix); - - bManyFix++; - if ((gce->dwFlags & GCEF_ADDTOLOG) && g_Settings->bLoggingEnabled) - LogToFile(si, gce); - } - - return 0; -} - -static INT_PTR CALLBACK sttEventStub(void *_param) +static BOOL HandleChatEvent(GCEVENT &gce, int bManyFix) { - ptrW wszId, wszUid, wszNick, wszText, wszStatus, wszUserInfo; - - GCEVENT gce = *(GCEVENT*)_param; - if (gce.dwFlags & GCEF_UTF8) { - gce.pszUID.w = (wszUid = mir_utf8decodeW(gce.pszUID.a)); - gce.pszNick.w = (wszNick = mir_utf8decodeW(gce.pszNick.a)); - gce.pszText.w = (wszText = mir_utf8decodeW(gce.pszText.a)); - gce.pszStatus.w = (wszStatus = mir_utf8decodeW(gce.pszStatus.a)); - gce.pszUserInfo.w = (wszUserInfo = mir_utf8decodeW(gce.pszUserInfo.a)); - gce.dwFlags &= ~GCEF_UTF8; - } - - if (NotifyEventHooks(hHookEvent, 0, LPARAM(&gce))) - return 1; + // no channel - nothing to do + SESSION_INFO *si = gce.si; + if (si == nullptr) + return GC_EVENT_ERROR; bool bIsHighlighted = false, bRemoveFlag = false; // Do different things according to type of event switch (gce.iType) { case GC_EVENT_SETCONTACTSTATUS: - return SM_SetContactStatus(gce.si, gce.pszUID.w, (uint16_t)gce.dwItemData); + return SM_SetContactStatus(si, gce.pszUID.w, (uint16_t)gce.dwItemData); case GC_EVENT_TOPIC: - if (SESSION_INFO *si = gce.si) { + { wchar_t *pwszNew = RemoveFormatting(gce.pszText.w); if (!mir_wstrcmp(si->ptszTopic, pwszNew)) // nothing changed? exiting return 0; @@ -485,24 +468,24 @@ static INT_PTR CALLBACK sttEventStub(void *_param) break; case GC_EVENT_ADDSTATUS: - SM_GiveStatus(gce.si, gce.pszUID.w, gce.pszStatus.w); + SM_GiveStatus(si, gce.pszUID.w, gce.pszStatus.w); bIsHighlighted = g_chatApi.IsHighlighted(nullptr, &gce); break; case GC_EVENT_REMOVESTATUS: - SM_TakeStatus(gce.si, gce.pszUID.w, gce.pszStatus.w); + SM_TakeStatus(si, gce.pszUID.w, gce.pszStatus.w); bIsHighlighted = g_chatApi.IsHighlighted(nullptr, &gce); break; case GC_EVENT_MESSAGE: case GC_EVENT_ACTION: - if (!gce.bIsMe && gce.si && gce.pszText.w) { - bIsHighlighted = g_chatApi.IsHighlighted(gce.si, &gce); + if (!gce.bIsMe && si && gce.pszText.w) { + bIsHighlighted = g_chatApi.IsHighlighted(si, &gce); } break; case GC_EVENT_NICK: - SM_ChangeNick(gce.si, &gce); + SM_ChangeNick(si, &gce); bIsHighlighted = g_chatApi.IsHighlighted(nullptr, &gce); break; @@ -522,65 +505,79 @@ static INT_PTR CALLBACK sttEventStub(void *_param) break; } - // Decide which window (log) should have the event - SESSION_INFO *si = nullptr; - if (gce.si) { - si = gce.si; - } - else if (gce.iType == GC_EVENT_NOTICE || gce.iType == GC_EVENT_INFORMATION) { - si = g_chatApi.GetActiveSession(); - if (!si) - return 0; - } - else { - // Send the event to all windows with a user pszUID. Used for broadcasting QUIT etc - AddEventToAllMatchingUID(&gce); - if (!bRemoveFlag) - return 0; - } - // add to log - if (si) { - if (gce.dwFlags & GCEF_SILENT) - return 0; - - // fix for IRC's old style mode notifications. Should not affect any other protocol - if ((gce.iType == GC_EVENT_ADDSTATUS || gce.iType == GC_EVENT_REMOVESTATUS) && !(gce.dwFlags & GCEF_ADDTOLOG)) - return 0; - - if (gce.iType == GC_EVENT_JOIN && gce.time == 0) - return 0; + if (gce.dwFlags & GCEF_SILENT) + return 0; - if (si && (si->bInitDone || gce.iType == GC_EVENT_TOPIC || (gce.iType == GC_EVENT_JOIN && gce.bIsMe))) { - if (gce.pszNick.w == nullptr && gce.pszUID.w != nullptr) { - USERINFO *ui = g_chatApi.UM_FindUser(si, gce.pszUID.w); - if (ui != nullptr) - gce.pszNick.w = ui->pszNick; - } + // fix for IRC's old style mode notifications. Should not affect any other protocol + if ((gce.iType == GC_EVENT_ADDSTATUS || gce.iType == GC_EVENT_REMOVESTATUS) && !(gce.dwFlags & GCEF_ADDTOLOG)) + return 0; - int isOk = SM_AddEvent(si, &gce, bIsHighlighted); - if (si->pDlg) { - if (isOk) - si->pDlg->AddLog(); - else - RedrawLog2(si); - } + if (gce.iType == GC_EVENT_JOIN && gce.time == 0) + return 0; - if (!(gce.dwFlags & GCEF_NOTNOTIFY)) - g_chatApi.DoSoundsFlashPopupTrayStuff(si, &gce, bIsHighlighted, 0); + if (si && (si->bInitDone || gce.iType == GC_EVENT_TOPIC || (gce.iType == GC_EVENT_JOIN && gce.bIsMe))) { + if (gce.pszNick.w == nullptr && gce.pszUID.w != nullptr) { + USERINFO *ui = g_chatApi.UM_FindUser(si, gce.pszUID.w); + if (ui != nullptr) + gce.pszNick.w = ui->pszNick; + } - if ((gce.dwFlags & GCEF_ADDTOLOG) && g_Settings->bLoggingEnabled) - LogToFile(si, &gce); + int isOk = SM_AddEvent(si, &gce, bIsHighlighted); + if (si->pDlg) { + if (isOk) + si->pDlg->AddLog(); + else + RedrawLog2(si); } - if (!bRemoveFlag) - return 0; + if (!(gce.dwFlags & GCEF_NOTNOTIFY)) + g_chatApi.DoSoundsFlashPopupTrayStuff(si, &gce, bIsHighlighted, bManyFix); + + if ((gce.dwFlags & GCEF_ADDTOLOG) && g_Settings->bLoggingEnabled) + LogToFile(si, &gce); } if (bRemoveFlag) - return SM_RemoveUser(gce.si, gce.pszUID.w) == 0; + return SM_RemoveUser(si, gce.pszUID.w) == 0; - return GC_EVENT_ERROR; + return 0; +} + +static INT_PTR CALLBACK sttEventStub(void *_param) +{ + ptrW wszId, wszUid, wszNick, wszText, wszStatus, wszUserInfo; + + GCEVENT gce = *(GCEVENT*)_param; + if (gce.dwFlags & GCEF_UTF8) { + gce.pszUID.w = (wszUid = mir_utf8decodeW(gce.pszUID.a)); + gce.pszNick.w = (wszNick = mir_utf8decodeW(gce.pszNick.a)); + gce.pszText.w = (wszText = mir_utf8decodeW(gce.pszText.a)); + gce.pszStatus.w = (wszStatus = mir_utf8decodeW(gce.pszStatus.a)); + gce.pszUserInfo.w = (wszUserInfo = mir_utf8decodeW(gce.pszUserInfo.a)); + gce.dwFlags &= ~GCEF_UTF8; + } + + if (NotifyEventHooks(hHookEvent, 0, LPARAM(&gce))) + return 1; + + if (gce.dwFlags & GCEF_BROADCAST) { + gce.dwFlags &= ~GCEF_BROADCAST; + + const char *pszModule = gce.pszModule; + int bManyFix = 0; + + for (auto &si : g_arSessions) { + if (!si->bInitDone || mir_strcmpi(si->pszModule, pszModule)) + continue; + + gce.si = si; + HandleChatEvent(gce, bManyFix++); + } + return 0; + } + + return HandleChatEvent(gce, 0); } MIR_APP_DLL(int) Chat_Event(GCEVENT *gce) @@ -951,9 +948,6 @@ void UnloadChatModule(void) if (!bInited) return; - mir_free(g_chatApi.szActiveWndID); - mir_free(g_chatApi.szActiveWndModule); - FreeMsgLogBitmaps(); OptionsUnInit(); diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def index bae7600aec..8150a19b26 100644 --- a/src/mir_app/src/mir_app.def +++ b/src/mir_app/src/mir_app.def @@ -816,3 +816,4 @@ Srmm_CreateHotkey @886 NONAME ?Chat_SetUserInfo@@YGHPAUSESSION_INFO@@PAX@Z @931 NONAME ?Chat_Terminate@@YGHPAUSESSION_INFO@@_N@Z @932 NONAME ?Chat_Terminate@@YGHPBD_N@Z @933 NONAME +?Chat_Control@@YGHPBDH@Z @934 NONAME diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def index 20cdf0907d..520d097e19 100644 --- a/src/mir_app/src/mir_app64.def +++ b/src/mir_app/src/mir_app64.def @@ -816,3 +816,4 @@ Srmm_CreateHotkey @886 NONAME ?Chat_SetUserInfo@@YAHPEAUSESSION_INFO@@PEAX@Z @931 NONAME ?Chat_Terminate@@YAHPEAUSESSION_INFO@@_N@Z @932 NONAME ?Chat_Terminate@@YAHPEBD_N@Z @933 NONAME +?Chat_Control@@YAHPEBDH@Z @934 NONAME -- cgit v1.2.3