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 "RichDocument.h"
00025 #include "RichElement.h"
00026 #include "XML.h"
00027
00028 #ifdef _DEBUG
00029 #undef THIS_FILE
00030 static char THIS_FILE[]=__FILE__;
00031 #define new DEBUG_NEW
00032 #endif
00033
00034
00036
00037
00038 CRichDocument::CRichDocument() : m_szMargin( 8, 8 )
00039 {
00040 m_nCookie = 0;
00041 m_crBackground = RGB( 255, 255, 255 );
00042 m_crText = RGB( 0, 0, 0 );
00043 m_crLink = RGB( 0, 0, 255 );
00044 m_crHover = RGB( 255, 0, 0 );
00045 m_crHeading = RGB( 0x80, 0, 0 );
00046 }
00047
00048 CRichDocument::~CRichDocument()
00049 {
00050 Clear();
00051 }
00052
00054
00055
00056 POSITION CRichDocument::GetIterator() const
00057 {
00058 return m_pElements.GetHeadPosition();
00059 }
00060
00061 CRichElement* CRichDocument::GetNext(POSITION& pos) const
00062 {
00063 return (CRichElement*)m_pElements.GetNext( pos );
00064 }
00065
00066 CRichElement* CRichDocument::GetPrev(POSITION& pos) const
00067 {
00068 return (CRichElement*)m_pElements.GetPrev( pos );
00069 }
00070
00071 int CRichDocument::GetCount() const
00072 {
00073 return m_pElements.GetCount();
00074 }
00075
00076 POSITION CRichDocument::Find(CRichElement* pElement) const
00077 {
00078 return m_pElements.Find( pElement );
00079 }
00080
00082
00083
00084 CRichElement* CRichDocument::Add(CRichElement* pElement, POSITION posBefore)
00085 {
00086 CSingleLock pLock( &m_pSection, TRUE );
00087
00088 if ( posBefore )
00089 m_pElements.InsertBefore( posBefore, pElement );
00090 else
00091 m_pElements.AddTail( pElement );
00092
00093 pElement->m_pDocument = this;
00094 m_nCookie++;
00095
00096 return pElement;
00097 }
00098
00099 CRichElement* CRichDocument::Add(int nType, LPCTSTR pszText, LPCTSTR pszLink, DWORD nFlags, int nGroup, POSITION posBefore)
00100 {
00101 CRichElement* pElement = new CRichElement( nType, pszText, pszLink, nFlags, nGroup );
00102 return Add( pElement, posBefore );
00103 }
00104
00105 void CRichDocument::Remove(CRichElement* pElement)
00106 {
00107 CSingleLock pLock( &m_pSection, TRUE );
00108
00109 if ( POSITION pos = m_pElements.Find( pElement ) )
00110 {
00111 m_pElements.RemoveAt( pos );
00112 pElement->m_pDocument = NULL;
00113 m_nCookie++;
00114 }
00115 }
00116
00117 void CRichDocument::ShowGroup(int nGroup, BOOL bShow)
00118 {
00119 CSingleLock pLock( &m_pSection, TRUE );
00120
00121 for ( POSITION pos = GetIterator() ; pos ; )
00122 {
00123 CRichElement* pElement = GetNext( pos );
00124 if ( pElement->m_nGroup == nGroup ) pElement->Show( bShow );
00125 }
00126 }
00127
00128 void CRichDocument::ShowGroupRange(int nMin, int nMax, BOOL bShow)
00129 {
00130 CSingleLock pLock( &m_pSection, TRUE );
00131
00132 for ( POSITION pos = GetIterator() ; pos ; )
00133 {
00134 CRichElement* pElement = GetNext( pos );
00135 if ( pElement->m_nGroup >= nMin && pElement->m_nGroup <= nMax )
00136 pElement->Show( bShow );
00137 }
00138 }
00139
00140 void CRichDocument::SetModified()
00141 {
00142 m_nCookie++;
00143 }
00144
00145 void CRichDocument::Clear()
00146 {
00147 CSingleLock pLock( &m_pSection, TRUE );
00148
00149 for ( POSITION pos = GetIterator() ; pos ; )
00150 {
00151 delete GetNext( pos );
00152 }
00153
00154 m_pElements.RemoveAll();
00155 m_nCookie++;
00156 }
00157
00159
00160
00161 void CRichDocument::CreateFonts(LPCTSTR pszFaceName, int nSize)
00162 {
00163 CSingleLock pLock( &m_pSection, TRUE );
00164
00165 if ( m_fntNormal.m_hObject ) m_fntNormal.DeleteObject();
00166
00167 m_fntNormal.CreateFont( -nSize, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
00168 DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
00169 DEFAULT_PITCH|FF_DONTCARE, pszFaceName );
00170
00171 if ( m_fntBold.m_hObject ) m_fntBold.DeleteObject();
00172
00173 m_fntBold.CreateFont( -nSize, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
00174 DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
00175 DEFAULT_PITCH|FF_DONTCARE, pszFaceName );
00176
00177 if ( m_fntItalic.m_hObject ) m_fntItalic.DeleteObject();
00178
00179 m_fntItalic.CreateFont( -nSize, 0, 0, 0, FW_NORMAL, TRUE, FALSE, FALSE,
00180 DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
00181 DEFAULT_PITCH|FF_DONTCARE, pszFaceName );
00182
00183 if ( m_fntUnder.m_hObject ) m_fntUnder.DeleteObject();
00184
00185 m_fntUnder.CreateFont( -nSize, 0, 0, 0, FW_NORMAL, FALSE, TRUE, FALSE,
00186 DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
00187 DEFAULT_PITCH|FF_DONTCARE, pszFaceName );
00188
00189 if ( m_fntBoldUnder.m_hObject ) m_fntBoldUnder.DeleteObject();
00190
00191 m_fntBoldUnder.CreateFont( -nSize, 0, 0, 0, FW_BOLD, FALSE, TRUE, FALSE,
00192 DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
00193 DEFAULT_PITCH|FF_DONTCARE, pszFaceName );
00194
00195 if ( m_fntHeading.m_hObject ) m_fntHeading.DeleteObject();
00196
00197 m_fntHeading.CreateFont( -( nSize + 6 ), 0, 0, 0, FW_EXTRABOLD, FALSE, FALSE, FALSE,
00198 DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
00199 DEFAULT_PITCH|FF_DONTCARE, pszFaceName );
00200 }
00201
00203
00204
00205 BOOL CRichDocument::LoadXML(CXMLElement* pBase, CMapStringToPtr* pMap, int nGroup)
00206 {
00207 CSingleLock pLock( &m_pSection, TRUE );
00208
00209 if ( pBase == NULL ) return FALSE;
00210
00211 CString strTemp;
00212
00213 if ( pBase->IsNamed( _T("document") ) )
00214 {
00215 strTemp = pBase->GetAttributeValue( _T("fontFace") );
00216 if ( strTemp.GetLength() ) CreateFonts( strTemp );
00217
00218 LoadXMLColour( pBase, _T("crBackground"), &m_crBackground );
00219 LoadXMLColour( pBase, _T("crText"), &m_crText );
00220 LoadXMLColour( pBase, _T("crLink"), &m_crLink );
00221 LoadXMLColour( pBase, _T("crHover"), &m_crHover );
00222 LoadXMLColour( pBase, _T("crHeading"), &m_crHeading );
00223
00224 strTemp = pBase->GetAttributeValue( _T("leftMargin") );
00225 if ( strTemp.GetLength() ) _stscanf( strTemp, _T("%i"), &m_szMargin.cx );
00226 strTemp = pBase->GetAttributeValue( _T("topMargin") );
00227 if ( strTemp.GetLength() ) _stscanf( strTemp, _T("%i"), &m_szMargin.cy );
00228 }
00229
00230 for ( POSITION pos = pBase->GetElementIterator() ; pos ; )
00231 {
00232 CXMLElement* pXML = pBase->GetNextElement( pos );
00233 CRichElement* pElement = NULL;
00234
00235 if ( pXML->IsNamed( _T("text") ) )
00236 {
00237 pElement = new CRichElement( retText );
00238 }
00239 else if ( pXML->IsNamed( _T("link") ) )
00240 {
00241 pElement = new CRichElement( retLink );
00242 }
00243 else if ( pXML->IsNamed( _T("heading") ) )
00244 {
00245 pElement = new CRichElement( retHeading );
00246 }
00247 else if ( pXML->IsNamed( _T("newline") ) )
00248 {
00249 pElement = new CRichElement( retNewline );
00250
00251 strTemp = pXML->GetAttributeValue( _T("gap") );
00252
00253 if ( strTemp.GetLength() )
00254 {
00255 pElement->m_sText = strTemp;
00256 strTemp = pXML->GetAttributeValue( _T("indent") );
00257 if ( strTemp.GetLength() ) pElement->m_sText += '.' + strTemp;
00258 }
00259 else
00260 {
00261 strTemp = pXML->GetAttributeValue( _T("indent") );
00262 if ( strTemp.GetLength() ) pElement->m_sText = _T("0.") + strTemp;
00263 }
00264 }
00265 else if ( pXML->IsNamed( _T("gap") ) )
00266 {
00267 pElement = new CRichElement( retGap );
00268
00269 strTemp = pXML->GetAttributeValue( _T("size") );
00270 if ( strTemp ) pElement->m_sText = strTemp;
00271 }
00272 else if ( pXML->IsNamed( _T("bitmap") ) )
00273 {
00274 pElement = new CRichElement( retBitmap );
00275 }
00276 else if ( pXML->IsNamed( _T("icon") ) )
00277 {
00278 pElement = new CRichElement( retIcon );
00279 }
00280 else if ( pXML->IsNamed( _T("anchor") ) )
00281 {
00282 pElement = new CRichElement( retAnchor );
00283 }
00284 else if ( pXML->IsNamed( _T("para") ) )
00285 {
00286 Add( pElement = new CRichElement( retAlign,
00287 pXML->GetAttributeValue( _T("align") ) ) );
00288
00289 if ( pXML->GetElementCount() )
00290 {
00291 if ( ! LoadXML( pXML, pMap, nGroup ) ) return FALSE;
00292 if ( pElement->m_sText.CompareNoCase( _T("left") ) )
00293 {
00294 Add( new CRichElement( retAlign, _T("left") ) );
00295 }
00296 }
00297
00298 continue;
00299 }
00300 else if ( pXML->IsNamed( _T("group") ) )
00301 {
00302 int nSubGroup = 0;
00303 if ( _stscanf( pXML->GetAttributeValue( _T("id") ), _T("%i"), &nSubGroup ) != 1 )
00304 return FALSE;
00305 if ( ! LoadXML( pXML, pMap, nSubGroup ) ) return FALSE;
00306 continue;
00307 }
00308 else if ( pXML->IsNamed( _T("styles") ) )
00309 {
00310 if ( ! LoadXMLStyles( pXML ) ) return FALSE;
00311 }
00312 else
00313 {
00314 return FALSE;
00315 }
00316
00317 if ( pElement == NULL ) continue;
00318
00319 strTemp = pXML->GetValue();
00320 if ( strTemp.GetLength() ) pElement->m_sText = strTemp;
00321
00322 pElement->m_nGroup = nGroup;
00323 strTemp = pXML->GetAttributeValue( _T("group") );
00324 if ( strTemp.GetLength() ) _stscanf( strTemp, _T("%i"), &pElement->m_nGroup );
00325
00326 strTemp = pXML->GetAttributeValue( _T("format") );
00327 CharLower( strTemp.GetBuffer() );
00328 strTemp.ReleaseBuffer();
00329 if ( strTemp.Find( 'b' ) >= 0 ) pElement->m_nFlags |= retfBold;
00330 if ( strTemp.Find( 'i' ) >= 0 ) pElement->m_nFlags |= retfItalic;
00331 if ( strTemp.Find( 'u' ) >= 0 ) pElement->m_nFlags |= retfUnderline;
00332
00333 strTemp = pXML->GetAttributeValue( _T("align") );
00334 CharLower( strTemp.GetBuffer() );
00335 strTemp.ReleaseBuffer();
00336 if ( strTemp == _T("middle") ) pElement->m_nFlags |= retfMiddle;
00337
00338 strTemp = pXML->GetAttributeValue( _T("colour") );
00339 if ( strTemp.GetLength() == 6 )
00340 {
00341 pElement->m_nFlags |= retfColour;
00342 LoadXMLColour( pXML, _T("colour"), &pElement->m_cColour );
00343 }
00344
00345 if ( pElement->m_nType == retIcon )
00346 {
00347 strTemp = pXML->GetAttributeValue( _T("command") );
00348 if ( strTemp.GetLength() )
00349 {
00350 pElement->m_nType = retCmdIcon;
00351 pElement->m_sText = strTemp;
00352 }
00353 }
00354
00355 if ( pElement->m_nType == retIcon || pElement->m_nType == retBitmap || pElement->m_nType == retAnchor )
00356 {
00357 strTemp = pXML->GetAttributeValue( _T("res") );
00358 if ( strTemp.GetLength() ) pElement->m_sText = strTemp;
00359 strTemp = pXML->GetAttributeValue( _T("path") );
00360 if ( strTemp.GetLength() ) pElement->m_sText = strTemp;
00361
00362 strTemp = pXML->GetAttributeValue( _T("width") );
00363 if ( strTemp.GetLength() )
00364 {
00365 if ( pElement->m_sText.GetLength() ) pElement->m_sText += '.';
00366 pElement->m_sText += strTemp;
00367 strTemp = pXML->GetAttributeValue( _T("height") );
00368 if ( strTemp.GetLength() ) pElement->m_sText += '.' + strTemp;
00369 }
00370 }
00371
00372 pElement->m_sLink = pXML->GetAttributeValue( _T("target") );
00373
00374 if ( pMap )
00375 {
00376 strTemp = pXML->GetAttributeValue( _T("id") );
00377 if ( strTemp.GetLength() ) pMap->SetAt( strTemp, pElement );
00378 }
00379
00380 Add( pElement );
00381 }
00382
00383 return TRUE;
00384 }
00385
00386 BOOL CRichDocument::LoadXMLStyles(CXMLElement* pParent)
00387 {
00388 for ( POSITION pos = pParent->GetElementIterator() ; pos ; )
00389 {
00390 CXMLElement* pXML = pParent->GetNextElement( pos );
00391 if ( ! pXML->IsNamed( _T("style") ) ) continue;
00392
00393 CString strName = pXML->GetAttributeValue( _T("name") );
00394 CharLower( strName.GetBuffer() );
00395 strName.ReleaseBuffer();
00396
00397 CString strFontFace = theApp.m_sDefaultFont;
00398 int nFontSize = theApp.m_nDefaultFontSize + 1;
00399 int nFontWeight = FW_BOLD;
00400
00401 if ( CXMLElement* pFont = pXML->GetElementByName( _T("font") ) )
00402 {
00403 strFontFace = pFont->GetAttributeValue( _T("face") );
00404 CString strTemp = pFont->GetAttributeValue( _T("size") );
00405 _stscanf( strTemp, _T("%i"), &nFontSize );
00406 strTemp = pFont->GetAttributeValue( _T("weight") );
00407 _stscanf( strTemp, _T("%i"), &nFontWeight );
00408 }
00409
00410 CXMLElement* pColours = pXML->GetElementByName( _T("colours") );
00411 if ( pColours == NULL ) pColours = pXML;
00412
00413 if ( strName == _T("default") || strName.IsEmpty() )
00414 {
00415 LoadXMLColour( pColours, _T("text"), &m_crText );
00416 LoadXMLColour( pColours, _T("link"), &m_crLink );
00417 LoadXMLColour( pColours, _T("hover"), &m_crHover );
00418 CreateFonts( strFontFace, nFontSize );
00419 }
00420 else if ( strName == _T("heading") )
00421 {
00422 LoadXMLColour( pColours, _T("text"), &m_crHeading );
00423
00424 if ( m_fntHeading.m_hObject ) m_fntHeading.DeleteObject();
00425 m_fntHeading.CreateFont( -nFontSize, 0, 0, 0, nFontWeight, FALSE, FALSE, FALSE,
00426 DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
00427 DEFAULT_PITCH|FF_DONTCARE, strFontFace );
00428 }
00429 }
00430
00431 return TRUE;
00432 }
00433
00434 BOOL CRichDocument::LoadXMLColour(CXMLElement* pXML, LPCTSTR pszName, COLORREF* pColour)
00435 {
00436 CString str = pXML->GetAttributeValue( pszName );
00437 if ( str.GetLength() != 6 ) return FALSE;
00438
00439 int nRed, nGreen, nBlue;
00440
00441 if ( _stscanf( str.Mid( 0, 2 ), _T("%x"), &nRed ) != 1 ) return FALSE;
00442 if ( _stscanf( str.Mid( 2, 2 ), _T("%x"), &nGreen ) != 1 ) return FALSE;
00443 if ( _stscanf( str.Mid( 4, 2 ), _T("%x"), &nBlue ) != 1 ) return FALSE;
00444
00445 *pColour = RGB( nRed, nGreen, nBlue );
00446
00447 return TRUE;
00448 }