00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "CtrlChatFrame.h"
00026 #include "RichElement.h"
00027 #include "EDClients.h"
00028 #include "EDPacket.h"
00029 #include "ChatWindows.h"
00030 #include "ChatCore.h"
00031 #include "ChatSession.h"
00032 #include "CoolInterface.h"
00033 #include "Emoticons.h"
00034 #include "WndChat.h"
00035
00036 #ifdef _DEBUG
00037 #define new DEBUG_NEW
00038 #undef THIS_FILE
00039 static char THIS_FILE[] = __FILE__;
00040 #endif
00041
00042 IMPLEMENT_DYNAMIC(CChatFrame, CWnd)
00043
00044 BEGIN_MESSAGE_MAP(CChatFrame, CWnd)
00045
00046 ON_WM_CREATE()
00047 ON_WM_DESTROY()
00048 ON_UPDATE_COMMAND_UI(ID_CHAT_BOLD, OnUpdateChatBold)
00049 ON_COMMAND(ID_CHAT_BOLD, OnChatBold)
00050 ON_UPDATE_COMMAND_UI(ID_CHAT_ITALIC, OnUpdateChatItalic)
00051 ON_COMMAND(ID_CHAT_ITALIC, OnChatItalic)
00052 ON_UPDATE_COMMAND_UI(ID_CHAT_UNDERLINE, OnUpdateChatUnderline)
00053 ON_COMMAND(ID_CHAT_UNDERLINE, OnChatUnderline)
00054 ON_COMMAND(ID_CHAT_COLOUR, OnChatColour)
00055 ON_UPDATE_COMMAND_UI(ID_CHAT_CONNECT, OnUpdateChatConnect)
00056 ON_COMMAND(ID_CHAT_CONNECT, OnChatConnect)
00057 ON_UPDATE_COMMAND_UI(ID_CHAT_DISCONNECT, OnUpdateChatDisconnect)
00058 ON_COMMAND(ID_CHAT_DISCONNECT, OnChatDisconnect)
00059 ON_COMMAND(ID_CHAT_CLEAR, OnChatClear)
00060 ON_COMMAND(ID_CHAT_EMOTICONS, OnChatEmoticons)
00061 ON_WM_MEASUREITEM()
00062 ON_WM_DRAWITEM()
00063 ON_WM_TIMER()
00064 ON_WM_SETFOCUS()
00065 ON_NOTIFY(RVN_CLICK, IDC_CHAT_TEXT, OnClickView)
00066 ON_UPDATE_COMMAND_UI(ID_CHAT_TIMESTAMP, OnUpdateChatTimestamp)
00067 ON_COMMAND(ID_CHAT_TIMESTAMP, OnChatTimestamp)
00068
00069 END_MESSAGE_MAP()
00070
00071 #define EDIT_HISTORY 256
00072 #define NEWLINE_FORMAT _T("2")
00073
00074
00076
00077
00078 CChatFrame::CChatFrame()
00079 {
00080 m_pSession = NULL;
00081 m_pIconMenu = NULL;
00082 m_pChildWnd = NULL;
00083 m_pDesktopWnd = NULL;
00084 }
00085
00086 CChatFrame::~CChatFrame()
00087 {
00088 ASSERT( m_pSession == NULL );
00089 }
00090
00092
00093
00094 int CChatFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
00095 {
00096 if ( CWnd::OnCreate( lpCreateStruct ) == -1 ) return -1;
00097
00098 CRect rc;
00099 GetClientRect( &rc );
00100
00101 m_wndView.Create( WS_CHILD|WS_VISIBLE, rc, this, IDC_CHAT_TEXT );
00102 m_wndView.SetDocument( &m_pContent );
00103 m_wndView.SetSelectable( TRUE );
00104 m_wndView.SetFollowBottom( TRUE );
00105
00106 m_pContent.m_szMargin = CSize( 8, 4 );
00107
00108 m_wndToolBar.Create( this, WS_CHILD|WS_VISIBLE );
00109 m_wndToolBar.SetBarStyle( m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_BORDER_TOP | CBRS_BORDER_BOTTOM );
00110
00111 m_wndEdit.Create( WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_AUTOVSCROLL, rc, this, IDC_CHAT_EDIT );
00112 m_wndEdit.SetFont( &theApp.m_gdiFont );
00113
00114 m_nHistory = 0;
00115
00116 SetDesktopMode( FALSE );
00117
00118 ChatWindows.Add( this );
00119
00120 return 0;
00121 }
00122
00123 void CChatFrame::OnDestroy()
00124 {
00125 CSingleLock pLock( &ChatCore.m_pSection, TRUE );
00126
00127 if ( m_pSession != NULL )
00128 {
00129 m_pSession->OnCloseWindow();
00130 m_pSession = NULL;
00131 }
00132
00133 ChatWindows.Remove( this );
00134
00135 pLock.Unlock();
00136
00137 CWnd::OnDestroy();
00138 }
00139
00140 void CChatFrame::OnSkinChange()
00141 {
00142 }
00143
00145
00146
00147 void CChatFrame::SetDesktopMode(BOOL bDesktop)
00148 {
00149 if ( bDesktop && m_pDesktopWnd != NULL ) return;
00150 if ( ! bDesktop && m_pChildWnd != NULL ) return;
00151
00152 ShowWindow( SW_HIDE );
00153 SetParent( NULL );
00154
00155 if ( m_pDesktopWnd != NULL )
00156 {
00157
00158 m_pDesktopWnd->DestroyWindow();
00159 m_pDesktopWnd = NULL;
00160 }
00161
00162 if ( m_pChildWnd != NULL )
00163 {
00164 m_pChildWnd->m_pFrame = NULL;
00165 m_pChildWnd->DestroyWindow();
00166 m_pChildWnd = NULL;
00167 }
00168
00169 if ( bDesktop )
00170 {
00171
00172 }
00173 else
00174 {
00175 m_pChildWnd = new CChatWnd( this );
00176 }
00177 }
00178
00179 void CChatFrame::SetAlert(BOOL bAlert)
00180 {
00181 PostMessage( WM_TIMER, 1 );
00182 }
00183
00185
00186
00187 BOOL CChatFrame::PreTranslateMessage(MSG* pMsg)
00188 {
00189 if ( pMsg->message == WM_KEYDOWN )
00190 {
00191 if ( ! m_pSession ) return TRUE;
00192
00193 if ( pMsg->wParam == VK_RETURN )
00194 {
00195 m_wndEdit.GetWindowText( m_sCurrent );
00196 if ( m_sCurrent.IsEmpty() ) return TRUE;
00197
00198 m_sCurrent = m_sCurrent.SpanExcluding( _T("\r\n") );
00199 OnLocalText( m_sCurrent );
00200
00201 m_pHistory.Add( m_sCurrent );
00202 if ( m_pHistory.GetSize() > EDIT_HISTORY ) m_pHistory.RemoveAt( 0 );
00203 m_nHistory = m_pHistory.GetSize();
00204
00205 m_sCurrent.Empty();
00206 m_wndEdit.SetWindowText( m_sCurrent );
00207 return TRUE;
00208 }
00209 else if ( pMsg->wParam == VK_ESCAPE )
00210 {
00211 m_wndEdit.SetWindowText( _T("") );
00212 m_nHistory = m_pHistory.GetSize();
00213 m_sCurrent.Empty();
00214 return TRUE;
00215 }
00216 else if ( pMsg->wParam == VK_UP )
00217 {
00218 MoveHistory( -1 );
00219 return TRUE;
00220 }
00221 else if ( pMsg->wParam == VK_DOWN )
00222 {
00223 MoveHistory( 1 );
00224 return TRUE;
00225 }
00226 else if ( pMsg->wParam == VK_PRIOR )
00227 {
00228 m_wndView.PostMessage( WM_VSCROLL, MAKELONG( SB_PAGEUP, 0 ), NULL );
00229 return TRUE;
00230 }
00231 else if ( pMsg->wParam == VK_NEXT )
00232 {
00233 m_wndView.PostMessage( WM_VSCROLL, MAKELONG( SB_PAGEDOWN, 0 ), NULL );
00234 return TRUE;
00235 }
00236 else if ( pMsg->wParam == VK_HOME && ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) )
00237 {
00238 m_wndView.PostMessage( WM_VSCROLL, MAKELONG( SB_TOP, 0 ), NULL );
00239 return TRUE;
00240 }
00241 else if ( pMsg->wParam == VK_END && ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) )
00242 {
00243 m_wndView.PostMessage( WM_VSCROLL, MAKELONG( SB_BOTTOM, 0 ), NULL );
00244 return TRUE;
00245 }
00246 else if ( pMsg->wParam == 'B' && ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) )
00247 {
00248 OnChatBold();
00249 return TRUE;
00250 }
00251 else if ( pMsg->wParam == 'I' && ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) )
00252 {
00253 OnChatItalic();
00254 return TRUE;
00255 }
00256 else if ( pMsg->wParam == 'U' && ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) )
00257 {
00258 OnChatUnderline();
00259 return TRUE;
00260 }
00261 else if ( pMsg->wParam == 'K' && ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) )
00262 {
00263 OnChatColour();
00264 return TRUE;
00265 }
00266 }
00267
00268 return CWnd::PreTranslateMessage( pMsg );
00269 }
00270
00271 void CChatFrame::MoveHistory(int nDelta)
00272 {
00273 if ( m_nHistory == m_pHistory.GetSize() )
00274 {
00275 m_wndEdit.GetWindowText( m_sCurrent );
00276 }
00277
00278 m_nHistory += nDelta;
00279 m_nHistory = max( 0, min( m_pHistory.GetSize(), m_nHistory ) );
00280
00281 if ( m_nHistory == m_pHistory.GetSize() )
00282 {
00283 m_wndEdit.SetWindowText( m_sCurrent );
00284 }
00285 else
00286 {
00287 m_wndEdit.SetWindowText( m_pHistory.GetAt( m_nHistory ) );
00288 }
00289
00290 int nLen = m_wndEdit.GetWindowTextLength();
00291 m_wndEdit.SetSel( nLen, nLen );
00292 }
00293
00294 BOOL CChatFrame::IsInRange(LPCTSTR pszToken)
00295 {
00296 CString strRange, strToken;
00297 int nStart, nEnd;
00298
00299 m_wndEdit.GetSel( nStart, nEnd );
00300 if ( nStart != nEnd ) return FALSE;
00301
00302 m_wndEdit.GetWindowText( strRange );
00303 if ( nStart <= 0 ) return FALSE;
00304 if ( nStart < strRange.GetLength() ) strRange = strRange.Left( nStart );
00305
00306 CharLower( strRange.GetBuffer() );
00307 strRange.ReleaseBuffer();
00308 strRange.MakeReverse();
00309 strToken.Format( _T("]%s["), pszToken );
00310 nStart = strRange.Find( strToken );
00311 strToken.Format( _T("]%s/["), pszToken );
00312 nEnd = strRange.Find( strToken );
00313
00314 if ( nStart < 0 ) return FALSE;
00315 if ( nEnd < 0 ) return TRUE;
00316
00317 return ( nEnd > nStart );
00318 }
00319
00320 void CChatFrame::InsertText(LPCTSTR pszToken)
00321 {
00322 int nStart, nEnd;
00323 m_wndEdit.GetSel( nStart, nEnd );
00324
00325 if ( nStart == nEnd )
00326 {
00327 m_wndEdit.ReplaceSel( pszToken );
00328 }
00329 else
00330 {
00331 CString strIn, strOut;
00332 m_wndEdit.GetWindowText( strIn );
00333 if ( nEnd < nStart ) m_wndEdit.GetSel( nEnd, nStart );
00334 strOut.Format( _T("%s%s[/%c]"), pszToken,
00335 (LPCTSTR)strIn.Mid( nStart, nEnd - nStart ), pszToken[1] );
00336 m_wndEdit.ReplaceSel( strOut );
00337 }
00338
00339 m_wndEdit.SetFocus();
00340 }
00341
00343
00344
00345 void CChatFrame::AddText(LPCTSTR pszText)
00346 {
00347 m_pContent.Add( retText, pszText );
00348 m_pContent.Add( retNewline, NEWLINE_FORMAT );
00349 m_wndView.InvalidateIfModified();
00350 }
00351
00352 void CChatFrame::AddText(BOOL bSelf, BOOL bAction, LPCTSTR pszNick, LPCTSTR pszBody)
00353 {
00354 CString str;
00355
00356 if ( Settings.Community.Timestamp )
00357 {
00358 CTime tNow = CTime::GetCurrentTime();
00359
00360 str.Format( _T("[%.2i:%.2i] "),
00361 tNow.GetHour(), tNow.GetMinute() );
00362 m_pContent.Add( retText, str, NULL, retfColour )->m_cColour = RGB( 128, 128, 128 );
00363 }
00364
00365 str.Format( bAction ? _T("* %s ") : _T("%s: "), pszNick );
00366 m_pContent.Add( retText, str, NULL, retfBold | retfColour )->m_cColour
00367 = ( bSelf ? RGB( 255, 0, 0 ) : RGB( 0, 0, 255 ) );
00368
00369 Emoticons.FormatText( &m_pContent, pszBody );
00370
00371 m_pContent.Add( retNewline, NEWLINE_FORMAT );
00372 m_wndView.InvalidateIfModified();
00373 }
00374
00376
00377
00378 void CChatFrame::OnStatusMessage(int nFlags, LPCTSTR pszText)
00379 {
00380 m_pContent.Add( retText, pszText, NULL, retfColour )->m_cColour
00381 = nFlags == 1 ? RGB( 255, 0, 0 ) : RGB( 128, 128, 128 );
00382 m_pContent.Add( retNewline, NEWLINE_FORMAT );
00383 m_wndView.InvalidateIfModified();
00384 }
00385
00386 void CChatFrame::OnLocalText(LPCTSTR pszText)
00387 {
00388 if ( pszText == NULL || *pszText == 0 || ! m_pSession ) return;
00389
00390 if ( *pszText == '/' )
00391 {
00392 CString strCommand = CString( pszText ).SpanExcluding( _T(" \t") );
00393 CharLower( strCommand.GetBuffer() );
00394 strCommand.ReleaseBuffer();
00395
00396 if ( strCommand == _T("/me") )
00397 {
00398 OnLocalMessage( TRUE, pszText + 4 );
00399 }
00400 else
00401 {
00402 OnLocalCommand( strCommand, pszText + strCommand.GetLength() + 1 );
00403 }
00404 }
00405 else
00406 {
00407 OnLocalMessage( FALSE, pszText );
00408 }
00409 }
00410
00411 void CChatFrame::OnLocalMessage(BOOL bAction, LPCTSTR pszText)
00412 {
00413 }
00414
00415 void CChatFrame::OnLocalCommand(LPCTSTR pszCommand, LPCTSTR pszMessage)
00416 {
00417 if ( _tcscmp( pszCommand, _T("/clear") ) == 0 )
00418 {
00419 PostMessage( WM_COMMAND, ID_CHAT_CLEAR );
00420 }
00421 else if ( _tcscmp( pszCommand, _T("/connect") ) == 0 )
00422 {
00423 PostMessage( WM_COMMAND, ID_CHAT_CONNECT );
00424 }
00425 else if ( _tcscmp( pszCommand, _T("/disconnect") ) == 0 )
00426 {
00427 PostMessage( WM_COMMAND, ID_CHAT_DISCONNECT );
00428 }
00429 else if ( _tcscmp( pszCommand, _T("/close") ) == 0 )
00430 {
00431 GetParent()->PostMessage( WM_CLOSE );
00432 }
00433 else if ( _tcscmp( pszCommand, _T("/exit") ) == 0 )
00434 {
00435 GetParent()->PostMessage( WM_CLOSE );
00436 }
00437 }
00438
00440
00441
00442 void CChatFrame::OnUpdateChatBold(CCmdUI* pCmdUI)
00443 {
00444 pCmdUI->SetCheck( IsInRange( _T("b") ) );
00445 }
00446
00447 void CChatFrame::OnChatBold()
00448 {
00449 if ( ! m_pSession ) return;
00450
00451 if ( IsInRange( _T("b") ) )
00452 InsertText( _T("[/b]") );
00453 else
00454 InsertText( _T("[b]") );
00455 }
00456
00457 void CChatFrame::OnUpdateChatItalic(CCmdUI* pCmdUI)
00458 {
00459 pCmdUI->SetCheck( IsInRange( _T("i") ) );
00460 }
00461
00462 void CChatFrame::OnChatItalic()
00463 {
00464 if ( ! m_pSession ) return;
00465
00466 if ( IsInRange( _T("i") ) )
00467 InsertText( _T("[/i]") );
00468 else
00469 InsertText( _T("[i]") );
00470 }
00471
00472 void CChatFrame::OnUpdateChatUnderline(CCmdUI* pCmdUI)
00473 {
00474 pCmdUI->SetCheck( IsInRange( _T("u") ) );
00475 }
00476
00477 void CChatFrame::OnChatUnderline()
00478 {
00479 if ( ! m_pSession ) return;
00480
00481 if ( IsInRange( _T("u") ) )
00482 InsertText( _T("[/u]") );
00483 else
00484 InsertText( _T("[u]") );
00485 }
00486
00487 void CChatFrame::OnChatColour()
00488 {
00489 if ( ! m_pSession ) return;
00490
00491 CColorDialog dlg( 0, CC_ANYCOLOR | CC_FULLOPEN );
00492 if ( dlg.DoModal() != IDOK ) return;
00493
00494 COLORREF cr = dlg.GetColor();
00495 CString str;
00496
00497 str.Format( _T("[c:#%.2x%.2x%.2x]"), GetRValue( cr ), GetGValue( cr ), GetBValue( cr ) );
00498 InsertText( str );
00499 }
00500
00501 void CChatFrame::OnChatEmoticons()
00502 {
00503 if ( ! m_pSession ) return;
00504
00505 m_pIconMenu = Emoticons.CreateMenu();
00506
00507 UINT nID = m_wndToolBar.ThrowMenu( ID_CHAT_EMOTICONS, m_pIconMenu, this, TRUE );
00508
00509 delete m_pIconMenu;
00510 m_pIconMenu = NULL;
00511
00512 if ( nID == 0 ) return;
00513
00514 LPCTSTR pszToken = Emoticons.GetText( nID - 1 );
00515 if ( pszToken != NULL ) InsertText( pszToken );
00516 }
00517
00518 void CChatFrame::OnChatClear()
00519 {
00520 m_pContent.Clear();
00521 m_wndView.InvalidateIfModified();
00522 }
00523
00524 void CChatFrame::OnUpdateChatTimestamp(CCmdUI* pCmdUI)
00525 {
00526 pCmdUI->SetCheck( Settings.Community.Timestamp );
00527 }
00528
00529 void CChatFrame::OnChatTimestamp()
00530 {
00531 Settings.Community.Timestamp = ! Settings.Community.Timestamp;
00532 }
00533
00534 void CChatFrame::OnUpdateChatConnect(CCmdUI* pCmdUI)
00535 {
00536 BOOL bState = ( ( m_pSession != NULL ) &&
00537 ( m_pSession->GetConnectedState() == TS_FALSE ) &&
00538 ( m_pSession->m_nProtocol != PROTOCOL_ED2K ) );
00539 if ( CCoolBarItem* pItem = CCoolBarItem::FromCmdUI( pCmdUI ) ) pItem->Show( bState );
00540 pCmdUI->Enable( bState );
00541 }
00542
00543 void CChatFrame::OnChatConnect()
00544 {
00545 if ( m_pSession != NULL && m_pSession->GetConnectedState() == TS_FALSE )
00546 {
00547 CWnd* pParent = GetParent();
00548 if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
00549 pParent->BringWindowToTop();
00550 pParent->SetForegroundWindow();
00551 m_pSession->Connect();
00552 }
00553 }
00554
00555 void CChatFrame::OnUpdateChatDisconnect(CCmdUI* pCmdUI)
00556 {
00557 BOOL bState = ( m_pSession != NULL ) &&
00558 ( m_pSession->GetConnectedState() != TS_FALSE ) &&
00559 ( m_pSession->m_nProtocol != PROTOCOL_ED2K );
00560 if ( CCoolBarItem* pItem = CCoolBarItem::FromCmdUI( pCmdUI ) ) pItem->Show( bState );
00561 pCmdUI->Enable( bState );
00562 }
00563
00564 void CChatFrame::OnChatDisconnect()
00565 {
00566 if ( m_pSession != NULL ) m_pSession->Close();
00567 }
00568
00570
00571
00572 void CChatFrame::OnTimer(UINT nIDEvent)
00573 {
00574 if ( nIDEvent == 1 )
00575 {
00576 if ( m_pChildWnd != NULL ) m_pChildWnd->SetAlert();
00577
00578 }
00579 else if ( nIDEvent == 4 )
00580 {
00581 if ( GetForegroundWindow() != GetTopLevelParent() )
00582 {
00583 CWnd* pParentWnd = GetTopLevelParent();
00584
00585 if ( HINSTANCE hUser = LoadLibrary( _T("User32") ) )
00586 {
00587 BOOL (WINAPI *pfnFlashWindowEx)(PFLASHWINFO pfwi);
00588
00589 if ( (FARPROC&)pfnFlashWindowEx = GetProcAddress( hUser, "FlashWindowEx" ) )
00590 {
00591 FLASHWINFO pFWX;
00592
00593 pFWX.cbSize = sizeof(pFWX);
00594 pFWX.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG;
00595 pFWX.uCount = 3;
00596 pFWX.dwTimeout = 0;
00597 pFWX.hwnd = pParentWnd->GetSafeHwnd();
00598
00599 (*pfnFlashWindowEx)( &pFWX );
00600 }
00601
00602 FreeLibrary( hUser );
00603 }
00604 }
00605 }
00606 }
00607
00608 void CChatFrame::OnSetFocus(CWnd* pOldWnd)
00609 {
00610 CWnd::OnSetFocus( pOldWnd );
00611 m_wndEdit.SetFocus();
00612 }
00613
00614 void CChatFrame::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
00615 {
00616 lpMeasureItemStruct->itemWidth = 20;
00617 lpMeasureItemStruct->itemHeight = 22;
00618 }
00619
00620 void CChatFrame::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
00621 {
00622 CDC* pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
00623 CRect rc( &lpDrawItemStruct->rcItem );
00624
00625 Emoticons.Draw( pDC, lpDrawItemStruct->itemID - 1, rc.left + 8, rc.top + 3 );
00626
00627 if ( lpDrawItemStruct->itemState & ODS_SELECTED )
00628 {
00629 pDC->Draw3dRect( &rc, CoolInterface.m_crHighlight, CoolInterface.m_crHighlight );
00630 rc.DeflateRect( 1, 1 );
00631 pDC->Draw3dRect( &rc, CoolInterface.m_crHighlight, CoolInterface.m_crHighlight );
00632 }
00633 else
00634 {
00635 pDC->Draw3dRect( &rc, CoolInterface.m_crWindow, CoolInterface.m_crWindow );
00636 rc.DeflateRect( 1, 1 );
00637 pDC->Draw3dRect( &rc, CoolInterface.m_crWindow, CoolInterface.m_crWindow );
00638 }
00639 }
00640
00641 void CChatFrame::OnClickView(RVN_ELEMENTEVENT* pNotify, LRESULT *pResult)
00642 {
00643 if ( CRichElement* pElement = pNotify->pElement )
00644 {
00645 theApp.InternalURI( pElement->m_sLink );
00646 }
00647 }