Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

Emoticons.cpp

Go to the documentation of this file.
00001 //
00002 // Emoticons.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "Emoticons.h"
00026 #include "ImageServices.h"
00027 #include "ImageFile.h"
00028 #include "XML.h"
00029 
00030 #include "RichDocument.h"
00031 #include "RichElement.h"
00032 
00033 #ifdef _DEBUG
00034 #undef THIS_FILE
00035 static char THIS_FILE[]=__FILE__;
00036 #define new DEBUG_NEW
00037 #endif
00038 
00039 CEmoticons Emoticons;
00040 
00041 
00043 // CEmoticons construction
00044 
00045 CEmoticons::CEmoticons()
00046 {
00047         m_pTokens = NULL;
00048 }
00049 
00050 CEmoticons::~CEmoticons()
00051 {
00052         Clear();
00053 }
00054 
00056 // CEmoticons find next token and index
00057 
00058 LPCTSTR CEmoticons::FindNext(LPCTSTR pszText, int* pnIndex)
00059 {
00060         LPCTSTR pszBest = NULL;
00061         int nIndex = 0, nBest;
00062 
00063         if ( m_pTokens == NULL ) return NULL;
00064 
00065         for ( LPCTSTR pszToken = m_pTokens ; *pszToken ; nIndex++ )
00066         {
00067                 LPCTSTR pszFind = _tcsstr( pszText, pszToken );
00068 
00069                 if ( pszFind != NULL && ( pszBest == NULL || pszFind < pszBest ||
00070                    ( pszFind == pszBest && _tcslen( GetText( nBest ) ) < _tcslen( pszToken ) ) ) )
00071                 {
00072                         pszBest = pszFind;
00073                         nBest = nIndex;
00074                 }
00075 
00076                 pszToken += _tcslen( pszToken ) + 1;
00077         }
00078 
00079         if ( pszBest && pnIndex ) *pnIndex = nBest;
00080 
00081         return pszBest;
00082 }
00083 
00085 // CEmoticons lookup index from text
00086 
00087 int CEmoticons::Lookup(LPCTSTR pszText, int nLen) const
00088 {
00089         TCHAR cSave = 0;
00090         int nIndex = 0;
00091 
00092         if ( m_pTokens == NULL ) return -1;
00093 
00094         if ( nLen >= 0 )
00095         {
00096                 cSave = pszText[ nLen ];
00097                 ((LPTSTR)pszText)[ nLen ] = 0;
00098         }
00099 
00100     LPCTSTR pszToken = m_pTokens;
00101         for ( ; *pszToken ; nIndex++ )
00102         {
00103                 if ( _tcscmp( pszToken, pszText ) == 0 )
00104                 {
00105                         break;
00106                 }
00107 
00108                 pszToken += _tcslen( pszToken ) + 1;
00109         }
00110 
00111         if ( nLen >= 0 ) ((LPTSTR)pszText)[ nLen ] = cSave;
00112 
00113         return ( *pszToken != 0 ) ? nIndex : -1;
00114 }
00115 
00117 // CEmoticons get the text for an index
00118 
00119 LPCTSTR CEmoticons::GetText(int nIndex) const
00120 {
00121         if ( m_pTokens == NULL ) return NULL;
00122 
00123         for ( LPCTSTR pszToken = m_pTokens ; *pszToken ; )
00124         {
00125                 if ( nIndex-- <= 0 ) return pszToken;
00126 
00127                 pszToken += _tcslen( pszToken ) + 1;
00128         }
00129 
00130         return NULL;
00131 }
00132 
00134 // CEmoticons draw
00135 
00136 void CEmoticons::Draw(CDC* pDC, int nIndex, int nX, int nY, COLORREF crBack)
00137 {
00138         if ( m_pTokens == NULL ) return;
00139         ImageList_DrawEx( m_pImage.m_hImageList, nIndex, pDC->GetSafeHdc(),
00140                 nX, nY, 16, 16, crBack, CLR_DEFAULT, ILD_NORMAL );
00141         // if ( crBack != CLR_NONE ) pDC->ExcludeClipRect( nX, nY, nX + 16, nY + 16 );
00142 }
00143 
00145 // CEmoticons menu
00146 
00147 CMenu* CEmoticons::CreateMenu()
00148 {
00149         CMenu* pMenu = new CMenu();
00150         pMenu->CreatePopupMenu();
00151 
00152         int nCount = 0;
00153 
00154         for ( int nPos = 0 ; nPos < m_pButtons.GetSize() ; nPos++ )
00155         {
00156                 int nIndex = m_pButtons.GetAt( nPos );
00157 
00158                 if ( nCount > 0 && ( nCount % 12 ) == 0 )
00159                 {
00160                         pMenu->AppendMenu( MF_OWNERDRAW|MF_MENUBREAK, nIndex + 1, (LPCTSTR)NULL );
00161                 }
00162                 else
00163                 {
00164                         pMenu->AppendMenu( MF_OWNERDRAW, nIndex + 1, (LPCTSTR)NULL );
00165                 }
00166 
00167                 nCount++;
00168         }
00169 
00170         return pMenu;
00171 }
00172 
00174 // CEmoticons load
00175 
00176 BOOL CEmoticons::Load()
00177 {
00178         Clear();
00179         m_pImage.Create( 16, 16, ILC_COLOR32|ILC_MASK, 1, 8 );
00180 
00181         CString strFile = Settings.General.Path + _T("\\Data\\Emoticons.xml");
00182 
00183         BOOL bSuccess = LoadTrillian( strFile );
00184         if ( ! bSuccess ) return FALSE;
00185 
00186         BuildTokens();
00187 
00188         return TRUE;
00189 }
00190 
00192 // CEmoticons clear
00193 
00194 void CEmoticons::Clear()
00195 {
00196         if ( m_pImage.m_hImageList != NULL ) m_pImage.DeleteImageList();
00197 
00198         if ( m_pTokens != NULL ) delete [] m_pTokens;
00199         m_pTokens = NULL;
00200 
00201         m_pIndex.RemoveAll();
00202         m_pButtons.RemoveAll();
00203 }
00204 
00206 // CEmoticons add an emoticon
00207 
00208 int CEmoticons::AddEmoticon(LPCTSTR pszText, CImageFile* pImage, CRect* pRect, COLORREF crBack, BOOL bButton)
00209 {
00210         ASSERT( pImage->m_bLoaded && pImage->m_nComponents == 3 );
00211 
00212         if ( pRect->left < 0 || pRect->left + 16 > pImage->m_nWidth ) return -1;
00213         if ( pRect->top < 0 || pRect->top > pImage->m_nHeight + 16 ) return -1;
00214         if ( pRect->right != pRect->left + 16 ) return -1;
00215         if ( pRect->bottom != pRect->top + 16 ) return -1;
00216 
00217         DWORD nPitch = pImage->m_nWidth * pImage->m_nComponents;
00218         while ( nPitch & 3 ) nPitch++;
00219 
00220         BYTE* pSource = pImage->m_pImage;
00221         pSource += pRect->top * nPitch + pRect->left * pImage->m_nComponents;
00222 
00223         HDC hDC = GetDC( 0 );
00224         CBitmap bmImage;
00225 
00226         bmImage.CreateCompatibleBitmap( CDC::FromHandle( hDC ), 16, 16 );
00227 
00228         BITMAPINFOHEADER pInfo;
00229         pInfo.biSize            = sizeof(BITMAPINFOHEADER);
00230         pInfo.biWidth           = 16;
00231         pInfo.biHeight          = 16;
00232         pInfo.biPlanes          = 1;
00233         pInfo.biBitCount        = 24;
00234         pInfo.biCompression     = BI_RGB;
00235         pInfo.biSizeImage       = 16 * 16 * 3;
00236 
00237         for ( int nY = 15 ; nY >= 0 ; nY-- )
00238         {
00239                 SetDIBits( hDC, bmImage, nY, 1, pSource, (BITMAPINFO*)&pInfo, DIB_RGB_COLORS );
00240                 pSource += nPitch;
00241         }
00242 
00243         ReleaseDC( 0, hDC );
00244         int nIndex = m_pImage.Add( &bmImage, crBack );
00245         bmImage.DeleteObject();
00246 
00247         m_pIndex.Add( pszText );
00248         if ( bButton ) m_pButtons.Add( nIndex );
00249 
00250         return nIndex;
00251 }
00252 
00254 // CEmoticons build tokens
00255 
00256 void CEmoticons::BuildTokens()
00257 {
00258         int nLength = 2;
00259 
00260         for ( int nIndex = 0 ; nIndex < m_pIndex.GetSize() ; nIndex++ )
00261         {
00262                 nLength += m_pIndex.GetAt( nIndex ).GetLength() + 1;
00263         }
00264 
00265         ASSERT( m_pTokens == NULL );
00266         LPTSTR pszOut = m_pTokens = new TCHAR[ nLength ];
00267 
00268         for ( int nIndex = 0 ; nIndex < m_pIndex.GetSize() ; nIndex++ )
00269         {
00270                 _tcscpy( pszOut, m_pIndex.GetAt( nIndex ) );
00271                 pszOut += m_pIndex.GetAt( nIndex ).GetLength() + 1;
00272         }
00273 
00274         *pszOut++ = 0;
00275 }
00276 
00278 // CEmoticons load Trillian XML
00279 
00280 BOOL CEmoticons::LoadTrillian(LPCTSTR pszFile)
00281 {
00282         CString strPath, strValue;
00283 
00284         CXMLElement* pXML = CXMLElement::FromFile( pszFile, TRUE );
00285         if ( pXML == NULL ) return FALSE;
00286 
00287         strPath = pszFile;
00288         int nSlash = strPath.ReverseFind( '\\' );
00289         if ( nSlash >= 0 ) strPath = strPath.Left( nSlash + 1 );
00290 
00291         CXMLElement* pBitmap = pXML->GetElementByName( _T("bitmap") );
00292 
00293         if ( pBitmap == NULL )
00294         {
00295                 delete pXML;
00296                 return FALSE;
00297         }
00298 
00299         strValue = pBitmap->GetAttributeValue( _T("file") );
00300 
00301         nSlash = strValue.ReverseFind( '/' );
00302         if ( nSlash >= 0 ) strValue = strValue.Mid( nSlash + 1 );
00303         strValue = strPath + strValue;
00304 
00305         CImageServices pServices;
00306         CImageFile pImage( &pServices );
00307 
00308         if (    ! pImage.LoadFromFile( strValue ) ||
00309                         ! pImage.EnsureRGB( GetSysColor( COLOR_WINDOW ) ) ||
00310                         ! pImage.SwapRGB() )
00311         {
00312                 delete pXML;
00313                 return FALSE;
00314         }
00315 
00316         COLORREF crBack = RGB( pImage.m_pImage[2], pImage.m_pImage[1], pImage.m_pImage[0] );
00317 
00318         for ( POSITION pos = pXML->GetElementIterator() ; pos ; )
00319         {
00320                 CXMLElement* pEmoticon = pXML->GetNextElement( pos );
00321                 if ( ! pEmoticon->IsNamed( _T("emoticon") ) ) continue;
00322 
00323                 CXMLElement* pSource = pEmoticon->GetElementByName( _T("source") );
00324                 CString strText = pEmoticon->GetAttributeValue( _T("text") );
00325                 CRect rc( 0, 0, 0, 0 );
00326 
00327                 strValue = pSource->GetAttributeValue( _T("left"), _T("0") );
00328                 _stscanf( strValue, _T("%i"), &rc.left );
00329                 strValue = pSource->GetAttributeValue( _T("top"), _T("0") );
00330                 _stscanf( strValue, _T("%i"), &rc.top );
00331                 strValue = pSource->GetAttributeValue( _T("right"), _T("0") );
00332                 _stscanf( strValue, _T("%i"), &rc.right );
00333                 strValue = pSource->GetAttributeValue( _T("bottom"), _T("0") );
00334                 _stscanf( strValue, _T("%i"), &rc.bottom );
00335 
00336                 BOOL bButton = pEmoticon->GetAttributeValue( _T("button") ).CompareNoCase( _T("yes") ) == 0;
00337 
00338                 AddEmoticon( strText, &pImage, &rc, crBack, bButton );
00339         }
00340 
00341         delete pXML;
00342 
00343         return TRUE;
00344 }
00345 
00347 // CEmoticons rich text formatting
00348 
00349 void CEmoticons::FormatText(CRichDocument* pDocument, LPCTSTR pszBody, BOOL bNewlines)
00350 {
00351         static LPCTSTR pszURLs[] = { _T("\r\n"), _T("http://"), _T("magnet:?"), _T("gnutella:"), _T("gnet:"), _T("ftp://"), _T("raza:"), _T("shareaza:"), _T("ed2k://"), _T("sig2dat:"), _T("www."), NULL };
00352         BOOL bBold = FALSE, bItalic = FALSE, bUnderline = FALSE;
00353         COLORREF cr = 0;
00354         CString str;
00355 
00356         while ( *pszBody )
00357         {
00358                 LPCTSTR pszToken = _tcschr( pszBody, '[' );
00359 
00360                 for ( int nURL = 0 ; pszURLs[ nURL ] != NULL ; nURL++ )
00361                 {
00362                         LPCTSTR pszFind = _tcsistr( pszBody, pszURLs[ nURL ] );
00363                         if ( pszFind != NULL && ( pszToken == NULL || pszFind < pszToken ) ) pszToken = pszFind;
00364                 }
00365 
00366                 int nEmoticon = -1;
00367                 LPCTSTR pszEmoticon = FindNext( pszBody, &nEmoticon );
00368 
00369                 if ( pszEmoticon != NULL && ( pszToken == NULL || pszEmoticon < pszToken ) )
00370                 {
00371                         pszToken = pszEmoticon;
00372                 }
00373 
00374                 if ( pszToken != pszBody )
00375                 {
00376                         if ( pszToken != NULL )
00377                         {
00378                                 TCHAR cSave = *pszToken;
00379                                 *(LPTSTR)pszToken = 0;
00380                                 str = pszBody;
00381                                 *(LPTSTR)pszToken = cSave;
00382                         }
00383                         else
00384                         {
00385                                 str = pszBody;
00386                         }
00387 
00388                         pDocument->Add( retText, str, NULL,
00389                                 ( bBold ? retfBold : 0 ) |
00390                                 ( bItalic ? retfItalic : 0 ) |
00391                                 ( bUnderline ? retfUnderline : 0 ) |
00392                                 ( cr ? retfColour : 0 ) )->m_cColour = cr;
00393                 }
00394 
00395                 if ( pszToken == NULL ) break;
00396 
00397                 pszBody = pszToken;
00398                 if ( *pszBody == 0 ) break;
00399 
00400                 if ( pszEmoticon == pszBody )
00401                 {
00402                         str.Format( _T("%lu"), nEmoticon );
00403                         pDocument->Add( retEmoticon, str );
00404                         pszBody += _tcslen( GetText( nEmoticon ) );
00405                         continue;
00406                 }
00407                 else if ( pszBody[0] == '\r' && pszBody[1] == '\n' )
00408                 {
00409                         if ( bNewlines )
00410                         {
00411                                 pDocument->Add( retNewline, _T("4") );
00412                         }
00413 
00414                         pszBody += 2;
00415                         continue;
00416                 }
00417                 else if ( *pszBody != '[' )
00418                 {
00419                         for ( ; *pszToken ; pszToken++ )
00420                         {
00421                                 if ( ! _istalnum( *pszToken ) &&
00422                                         _tcschr( _T(":@/?=&%._-+;~#"), *pszToken ) == NULL )
00423                                 {
00424                                         break;
00425                                 }
00426                         }
00427 
00428                         TCHAR cSave = *pszToken;
00429                         *(LPTSTR)pszToken = 0;
00430                         str = pszBody;
00431                         *(LPTSTR)pszToken = cSave;
00432 
00433                         if ( _tcsnicmp( str, _T("www."), 4 ) == 0 ) str = _T("http://") + str;
00434 
00435                         pDocument->Add( retLink, str, str,
00436                                 ( bBold ? retfBold : 0 ) |
00437                                 ( bItalic ? retfItalic : 0 ) |
00438                                 ( bUnderline ? retfUnderline : 0 ) );
00439 
00440                         pszBody = pszToken;
00441                 }
00442                 else if ( _tcsnicmp( pszBody, _T("[b]"), 3 ) == 0 )
00443                 {
00444                         bBold = TRUE;
00445                 }
00446                 else if ( _tcsnicmp( pszBody, _T("[/b]"), 4 ) == 0 )
00447                 {
00448                         bBold = FALSE;
00449                 }
00450                 else if ( _tcsnicmp( pszBody, _T("[i]"), 3 ) == 0 )
00451                 {
00452                         bItalic = TRUE;
00453                 }
00454                 else if ( _tcsnicmp( pszBody, _T("[/i]"), 4 ) == 0 )
00455                 {
00456                         bItalic = FALSE;
00457                 }
00458                 else if ( _tcsnicmp( pszBody, _T("[u]"), 3 ) == 0 )
00459                 {
00460                         bUnderline = TRUE;
00461                 }
00462                 else if ( _tcsnicmp( pszBody, _T("[/u]"), 4 ) == 0 )
00463                 {
00464                         bUnderline = FALSE;
00465                 }
00466                 else if ( _tcsnicmp( pszBody, _T("[/c]"), 4 ) == 0 )
00467                 {
00468                         cr = 0;
00469                 }
00470                 else if ( _tcsnicmp( pszBody, _T("[c:#"), 4 ) == 0 && _tcslen( pszBody ) >= 4 + 6 + 1 )
00471                 {
00472                         _tcsncpy( str.GetBuffer( 6 ), pszBody + 4, 6 );
00473                         str.ReleaseBuffer( 6 );
00474                         int nRed, nGreen, nBlue;
00475                         _stscanf( str.Mid( 0, 2 ), _T("%x"), &nRed );
00476                         _stscanf( str.Mid( 2, 2 ), _T("%x"), &nGreen );
00477                         _stscanf( str.Mid( 4, 2 ), _T("%x"), &nBlue );
00478                         cr = RGB( nRed, nGreen, nBlue );
00479                 }
00480 
00481                 if ( *pszBody == '[' )
00482                 {
00483                         pszToken = _tcschr( pszBody, ']' );
00484                         if ( pszToken != NULL ) pszBody = pszToken + 1;
00485                         else pszBody ++;
00486                 }
00487         }
00488 }

Generated on Thu Dec 15 10:39:42 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2