/* Plugin of Miranda IM for communicating with users of the AIM protocol. Copyright (c) 2008-2009 Boris Krasnovskiy 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; either version 2 of the License, or (at your option) any later version. 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" static const COLORREF crCols[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; void CAimProto::chat_register(void) { GCREGISTER gcr = { sizeof(gcr) }; gcr.dwFlags = GC_TYPNOTIF | GC_CHANMGR; gcr.nColors = 16; gcr.pColors = (COLORREF*)crCols; gcr.ptszDispName = m_tszUserName; gcr.pszModule = m_szModuleName; CallServiceSync(MS_GC_REGISTER, 0, (LPARAM)&gcr); HookProtoEvent(ME_GC_EVENT, &CAimProto::OnGCEvent); HookProtoEvent(ME_GC_BUILDMENU, &CAimProto::OnGCMenuHook); } void CAimProto::chat_start(const char* id, unsigned short exchange) { wchar_t *idt = mir_a2u(id); GCSESSION gcw = { sizeof(gcw) }; gcw.iType = GCW_CHATROOM; gcw.pszModule = m_szModuleName; gcw.ptszName = idt; gcw.ptszID = idt; CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw); GCDEST gcd = { m_szModuleName, idt, GC_EVENT_ADDGROUP }; GCEVENT gce = { sizeof(gce), &gcd }; gce.ptszStatus = TranslateT("Me"); CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); gcd.iType = GC_EVENT_ADDGROUP; gce.ptszStatus = TranslateT("Others"); CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); gcd.iType = GC_EVENT_CONTROL; CallServiceSync(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce); CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce); CallServiceSync(MS_GC_EVENT, WINDOW_VISIBLE, (LPARAM)&gce); setWord(find_chat_contact(id), "Exchange", exchange); mir_free(idt); } void CAimProto::chat_event(const char* id, const char* sn, int evt, const wchar_t* msg) { wchar_t *idt = mir_a2u(id); wchar_t *snt = mir_a2u(sn); MCONTACT hContact = contact_from_sn(sn); wchar_t *nick = hContact ? (wchar_t*)pcli->pfnGetContactDisplayName( WPARAM(hContact), 0) : snt; GCDEST gcd = { m_szModuleName, idt, evt }; GCEVENT gce = { sizeof(gce), &gcd }; gce.dwFlags = GCEF_ADDTOLOG; gce.pDest = &gcd; gce.ptszNick = nick; gce.ptszUID = snt; gce.bIsMe = _stricmp(sn, m_username) == 0; gce.ptszStatus = gce.bIsMe ? TranslateT("Me") : TranslateT("Others"); gce.ptszText = msg; gce.time = time(NULL); CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); mir_free(snt); mir_free(idt); } void CAimProto::chat_leave(const char* id) { wchar_t *idt = mir_a2u(id); GCDEST gcd = { m_szModuleName, idt, GC_EVENT_CONTROL }; GCEVENT gce = { sizeof(gce), &gcd }; gce.pDest = &gcd; CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce); CallServiceSync(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce); mir_free(idt); } int CAimProto::OnGCEvent(WPARAM, LPARAM lParam) { GCHOOK *gch = (GCHOOK*)lParam; if (!gch) return 1; if (mir_strcmp(gch->pDest->pszModule, m_szModuleName)) return 0; char *id = mir_u2a(gch->pDest->ptszID); chat_list_item* item = find_chat_by_id(id); if (item == NULL) return 0; switch (gch->pDest->iType) { case GC_SESSION_TERMINATE: aim_sendflap(item->hconn, 0x04, 0, NULL, item->seqno); Netlib_Shutdown(item->hconn); break; case GC_USER_MESSAGE: if (gch->ptszText && mir_wstrlen(gch->ptszText)) aim_chat_send_message(item->hconn, item->seqno, T2Utf(gch->ptszText)); break; case GC_USER_CHANMGR: DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHATROOM_INVITE), NULL, invite_to_chat_dialog, LPARAM(new invite_chat_param(item->id, this))); break; case GC_USER_PRIVMESS: { char* sn = mir_u2a(gch->ptszUID); MCONTACT hContact = contact_from_sn(sn); mir_free(sn); CallService(MS_MSG_SENDMESSAGE, hContact, 0); } break; case GC_USER_LOGMENU: switch (gch->dwData) { case 10: DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHATROOM_INVITE), NULL, invite_to_chat_dialog, LPARAM(new invite_chat_param(item->id, this))); break; case 20: chat_leave(id); break; } break; case GC_USER_NICKLISTMENU: { char *sn = mir_u2a(gch->ptszUID); MCONTACT hContact = contact_from_sn(sn); mir_free(sn); switch (gch->dwData) { case 10: CallService(MS_USERINFO_SHOWDIALOG, hContact, 0); break; case 20: CallService(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0); break; case 110: chat_leave(id); break; } } break; case GC_USER_TYPNOTIFY: break; } mir_free(id); return 0; } int CAimProto::OnGCMenuHook(WPARAM, LPARAM lParam) { GCMENUITEMS *gcmi = (GCMENUITEMS*)lParam; if (gcmi == NULL || _stricmp(gcmi->pszModule, m_szModuleName)) return 0; if (gcmi->Type == MENU_ON_LOG) { static const struct gc_item Items[] = { { TranslateT("&Invite user..."), 10, MENU_ITEM, FALSE }, { TranslateT("&Leave chat session"), 20, MENU_ITEM, FALSE } }; gcmi->nItems = _countof(Items); gcmi->Item = (gc_item*)Items; } else if (gcmi->Type == MENU_ON_NICKLIST) { char* sn = mir_u2a(gcmi->pszUID); if (!mir_strcmp(m_username, sn)) { static const struct gc_item Items[] = { { TranslateT("User &details"), 10, MENU_ITEM, FALSE }, { TranslateT("User &history"), 20, MENU_ITEM, FALSE }, { L"", 100, MENU_SEPARATOR, FALSE }, { TranslateT("&Leave chat session"), 110, MENU_ITEM, FALSE } }; gcmi->nItems = _countof(Items); gcmi->Item = (gc_item*)Items; } else { static const struct gc_item Items[] = { { TranslateT("User &details"), 10, MENU_ITEM, FALSE }, { TranslateT("User &history"), 20, MENU_ITEM, FALSE } }; gcmi->nItems = _countof(Items); gcmi->Item = (gc_item*)Items; } mir_free(sn); } return 0; } void __cdecl CAimProto::chatnav_request_thread(void* param) { chatnav_param *par = (chatnav_param*)param; if (wait_conn(m_hChatNavConn, m_hChatNavEvent, 0x0d)) { if (par->isroom) aim_chatnav_create(m_hChatNavConn, m_chatnav_seqno, par->id, par->exchange); else aim_chatnav_room_info(m_hChatNavConn, m_chatnav_seqno, par->id, par->exchange, par->instance); } delete par; } chat_list_item* CAimProto::find_chat_by_cid(unsigned short cid) { for (int i = 0; i < m_chat_rooms.getCount(); ++i) if (m_chat_rooms[i].cid == cid) return &m_chat_rooms[i]; return NULL; } chat_list_item* CAimProto::find_chat_by_id(char* id) { for (int i = 0; i < m_chat_rooms.getCount(); ++i) if (mir_strcmp(m_chat_rooms[i].id, id) == 0) return &m_chat_rooms[i]; return NULL; } chat_list_item* CAimProto::find_chat_by_conn(HANDLE conn) { for (int i = 0; i < m_chat_rooms.getCount(); ++i) if (m_chat_rooms[i].hconn == conn) return &m_chat_rooms[i]; return NULL; } void CAimProto::remove_chat_by_ptr(chat_list_item *item) { for (int i = 0; i < m_chat_rooms.getCount(); ++i) { if (&m_chat_rooms[i] == item) { m_chat_rooms.remove(i); break; } } } void CAimProto::shutdown_chat_conn(void) { for (int i = 0; i < m_chat_rooms.getCount(); ++i) { chat_list_item &item = m_chat_rooms[i]; if (item.hconn) { aim_sendflap(item.hconn, 0x04, 0, NULL, item.seqno); Netlib_Shutdown(item.hconn); } } } void CAimProto::close_chat_conn(void) { for (int i = 0; i < m_chat_rooms.getCount(); ++i) { chat_list_item &item = m_chat_rooms[i]; if (item.hconn) { Netlib_CloseHandle(item.hconn); item.hconn = NULL; } } }