1// 2// This file is part of the aMule Project. 3// 4// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org ) 5// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net ) 6// 7// Any parts of this program derived from the xMule, lMule or eMule project, 8// or contributed by third-party developers are copyrighted by their 9// respective authors. 10// 11// This program is free software; you can redistribute it and/or modify 12// it under the terms of the GNU General Public License as published by 13// the Free Software Foundation; either version 2 of the License, or 14// (at your option) any later version. 15// 16// This program is distributed in the hope that it will be useful, 17// but WITHOUT ANY WARRANTY; without even the implied warranty of 18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19// GNU General Public License for more details. 20// 21// You should have received a copy of the GNU General Public License 22// along with this program; if not, write to the Free Software 23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 24// 25 26#include <wx/tokenzr.h> 27#include <wx/imaglist.h> 28#include <wx/datetime.h> 29 30#include "pixmaps/chat.ico.xpm" 31#include "ChatSelector.h" // Interface declarations 32#include "Preferences.h" // Needed for CPreferences 33#include "amule.h" // Needed for theApp 34#include "ClientRef.h" // Needed for CClientRef 35#include "OtherFunctions.h" 36#include "muuli_wdr.h" // Needed for amuleSpecial 37#include "UserEvents.h" 38#include "Constants.h" // Needed for MS_NONE 39 40//#warning Needed while not ported 41#include "ClientList.h" 42#include <common/Format.h> // Needed for CFormat 43 44 45// Default colors, 46#define COLOR_BLACK wxTextAttr( wxColor( 0, 0, 0 ) ) 47#define COLOR_BLUE wxTextAttr( wxColor( 0, 0, 255 ) ) 48#define COLOR_GREEN wxTextAttr( wxColor( 0, 102, 0 ) ) 49#define COLOR_RED wxTextAttr( wxColor( 255, 0, 0 ) ) 50 51CChatSession::CChatSession(wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name) 52: CMuleTextCtrl( parent, id, value, pos, size, style | wxTE_READONLY | wxTE_RICH | wxTE_MULTILINE, validator, name ) 53{ 54 m_client_id = 0; 55 m_active = false; 56 SetBackgroundColour(*wxWHITE); 57} 58 59 60CChatSession::~CChatSession() 61{ 62 //#warning EC NEEDED 63 #ifndef CLIENT_GUI 64 theApp->clientlist->SetChatState(m_client_id,MS_NONE); 65 #endif 66} 67 68 69void CChatSession::AddText(const wxString& text, const wxTextAttr& style, bool newline) 70{ 71 // Split multi-line messages into individual lines 72 wxStringTokenizer tokens( text, wxT("\n") ); 73 74 while ( tokens.HasMoreTokens() ) { 75 // Check if we should add a time-stamp 76 if ( GetNumberOfLines() > 1 ) { 77 // Check if the last line ended with a newline 78 wxString line = GetLineText( GetNumberOfLines() - 1 ); 79 if ( line.IsEmpty() ) { 80 SetDefaultStyle( COLOR_BLACK ); 81 82 AppendText( wxT(" [") + wxDateTime::Now().FormatISOTime() + wxT("] ") ); 83 } 84 } 85 86 SetDefaultStyle(style); 87 88 AppendText( tokens.GetNextToken() ); 89 90 // Only add newlines after the last line if it is desired 91 if ( tokens.HasMoreTokens() || newline ) { 92 AppendText( wxT("\n") ); 93 } 94 } 95} 96 97 98 99 100CChatSelector::CChatSelector(wxWindow* parent, wxWindowID id, const wxPoint& pos, wxSize siz, long style) 101: CMuleNotebook(parent, id, pos, siz, style) 102{ 103 wxImageList* imagelist = new wxImageList(16,16); 104 105 // Chat icon -- default state 106 imagelist->Add(wxBitmap(chat_ico_xpm)); 107 // Close icon -- on mouseover 108 imagelist->Add(amuleSpecial(4)); 109 110 AssignImageList(imagelist); 111} 112 113CChatSession* CChatSelector::StartSession(uint64 client_id, const wxString& client_name, bool show) 114{ 115 // Check to see if we've already opened a session for this user 116 if ( GetPageByClientID( client_id ) ) { 117 if ( show ) { 118 SetSelection( GetTabByClientID( client_id ) ); 119 } 120 121 return NULL; 122 } 123 124 CChatSession* chatsession = new CChatSession(this); 125 126 chatsession->m_client_id = client_id; 127 128 wxString text; 129 text = wxT(" *** ") + (CFormat(_("Chat-Session Started: %s (%s:%u) - %s %s")) 130 % client_name 131 % Uint32toStringIP(IP_FROM_GUI_ID(client_id)) 132 % PORT_FROM_GUI_ID(client_id) 133 % wxDateTime::Now().FormatISODate() 134 % wxDateTime::Now().FormatISOTime()); 135 136 chatsession->AddText( text, COLOR_RED ); 137 AddPage(chatsession, client_name, show, 0); 138 139 CUserEvents::ProcessEvent(CUserEvents::NewChatSession, &client_name); 140 141 return chatsession; 142} 143 144 145CChatSession* CChatSelector::GetPageByClientID(uint64 client_id) 146{ 147 for ( unsigned int i = 0; i < (unsigned int ) GetPageCount(); i++ ) { 148 CChatSession* page = (CChatSession*)GetPage( i ); 149 150 if( page->m_client_id == client_id ) { 151 return page; 152 } 153 } 154 155 return NULL; 156} 157 158 159int CChatSelector::GetTabByClientID(uint64 client_id) 160{ 161 for ( unsigned int i = 0; i < (unsigned int) GetPageCount(); i++ ) { 162 CChatSession* page = (CChatSession*)GetPage( i ); 163 164 if( page->m_client_id == client_id ) { 165 return i; 166 } 167 } 168 169 return -1; 170} 171 172 173bool CChatSelector::ProcessMessage(uint64 sender_id, const wxString& message) 174{ 175 CChatSession* session = GetPageByClientID(sender_id); 176 177 // Try to get the name (core sent it?) 178 int separator = message.Find(wxT("|")); 179 wxString client_name; 180 wxString client_message; 181 if (separator != -1) { 182 client_name = message.Left(separator); 183 client_message = message.Mid(separator+1); 184 } else { 185 // No need to define client_name. If needed, will be build on tab creation. 186 client_message = message; 187 } 188 189 bool newtab = !session; 190 191 if ( !session ) { 192 // This must be a mesage from a client that is not already chatting 193 if (client_name.IsEmpty()) { 194 // Core did not send us the name. 195 // This must NOT happen. 196 // Build a client name based on the ID 197 uint32 ip = IP_FROM_GUI_ID(sender_id); 198 client_name = CFormat(wxT("IP: %s Port: %u")) % Uint32toStringIP(ip) % PORT_FROM_GUI_ID(sender_id); 199 } 200 201 session = StartSession( sender_id, client_name, true ); 202 } 203 204 // Other client connected after disconnection or a new session 205 if ( !session->m_active ) { 206 session->m_active = true; 207 208 session->AddText( _("*** Connected to Client ***"), COLOR_RED ); 209 } 210 211 // Page text is client name 212 session->AddText( GetPageText(GetTabByClientID(sender_id)), COLOR_BLUE, false ); 213 session->AddText( wxT(": ") + client_message, COLOR_BLACK ); 214 215 return newtab; 216} 217 218bool CChatSelector::SendMessage( const wxString& message, const wxString& client_name, uint64 to_id ) 219{ 220 // Dont let the user send empty messages 221 // This is also a user-fix for people who mash the enter-key ... 222 if ( message.IsEmpty() ) { 223 return false; 224 } 225 226 if (to_id) { 227 // Checks if there's a page with this client, and selects it or creates it 228 StartSession(to_id, client_name, true); 229 } 230 231 int usedtab = GetSelection(); 232 // Workaround for a problem with wxNotebook, where an invalid selection is returned 233 if (usedtab >= (int)GetPageCount()) { 234 usedtab = GetPageCount() - 1; 235 } 236 if (usedtab == -1) { 237 return false; 238 } 239 240 CChatSession* ci = (CChatSession*)GetPage( usedtab ); 241 242 ci->m_active = true; 243 244 //#warning EC needed here. 245 246 #ifndef CLIENT_GUI 247 if (theApp->clientlist->SendChatMessage(ci->m_client_id, message)) { 248 ci->AddText( thePrefs::GetUserNick(), COLOR_GREEN, false ); 249 ci->AddText( wxT(": ") + message, COLOR_BLACK ); 250 } else { 251 ci->AddText( _("*** Connecting to Client ***"), COLOR_RED ); 252 } 253 #endif 254 255 return true; 256} 257 258//#warning Creteil? I know you are here Creteil... follow the white rabbit. 259/* Madcat - knock knock ... 260 ,-.,-. 261 \ \\ \ 262 \ \\_\ 263 / \ 264 __| a a| 265 /` `'. = y)= 266 / `"`} 267 _| \ } 268 { \ ), // 269 '-', /__\ ( ( 270 jgs (______)\_)_) 271*/ 272 273 274void CChatSelector::ConnectionResult(bool success, const wxString& message, uint64 id) 275{ 276 CChatSession* ci = GetPageByClientID(id); 277 if ( !ci ) { 278 return; 279 } 280 281 if ( !success ) { 282 ci->AddText( _("*** Failed to Connect to client / Connection lost ***"), COLOR_RED ); 283 284 ci->m_active = false; 285 } else { 286 // Kry - Woops, fix for the everlasting void message sending. 287 if ( !message.IsEmpty() ) { 288 ci->AddText( _("*** Connected to Client ***"), COLOR_RED ); 289 ci->AddText( thePrefs::GetUserNick(), COLOR_GREEN, false ); 290 ci->AddText( wxT(": ") + message, COLOR_BLACK ); 291 } 292 } 293} 294 295 296void CChatSelector::EndSession(uint64 client_id) 297{ 298 int usedtab; 299 if (client_id) { 300 usedtab = GetTabByClientID(client_id); 301 } else { 302 usedtab = GetSelection(); 303 } 304 305 if (usedtab == -1) { 306 return; 307 } 308 309 DeletePage(usedtab); 310} 311 312 313// Refresh the tab assosiated with a client 314void CChatSelector::RefreshFriend(uint64 toupdate_id, const wxString& new_name) 315{ 316 wxASSERT( toupdate_id ); 317 318 int tab = GetTabByClientID(toupdate_id); 319 320 if (tab != -1) { 321 // This client has a tab. 322 SetPageText(tab,new_name); 323 } else { 324 // This client has no tab (friend disconnecting, etc) 325 // Nothing to be done here. 326 } 327} 328 329 330void CChatSelector::ShowCaptchaResult(uint64 id, bool ok) 331{ 332 CChatSession* ci = GetPageByClientID(id); 333 if (ci) { 334 ci->AddText(ok 335 ? _("*** You have passed the captcha check and the user has received your message. ***") 336 : _("*** Your response to the captcha was wrong and your message has been ignored. You can request a new captcha by sending a new message. ***"), 337 COLOR_RED ); 338 } 339} 340 341 342#ifdef CLIENT_GUI 343bool CChatSelector::GetCurrentClient(CClientRef&) const 344{ 345 return false; 346} 347#else 348bool CChatSelector::GetCurrentClient(CClientRef& clientref) const 349{ 350 // Get the chat session associated with the active tab 351 CChatSession* ci = (CChatSession*)GetPage(GetSelection()); 352 353 // Get the client that the session is open to 354 if (ci) { 355 clientref.Link(theApp->clientlist->FindClientByIP(IP_FROM_GUI_ID(ci->m_client_id), PORT_FROM_GUI_ID(ci->m_client_id)) CLIENT_DEBUGSTRING("CChatSelector::GetCurrentClient")); 356 return true; 357 } else { 358 return false; 359 } 360} 361#endif 362 363// File_checked_for_headers 364