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 "CtrlText.h"
00025
00026 #ifdef _DEBUG
00027 #define new DEBUG_NEW
00028 #undef THIS_FILE
00029 static char THIS_FILE[] = __FILE__;
00030 #endif
00031
00032 BEGIN_MESSAGE_MAP(CTextCtrl, CWnd)
00033
00034 ON_WM_VSCROLL()
00035 ON_WM_ERASEBKGND()
00036 ON_WM_PAINT()
00037 ON_WM_CREATE()
00038 ON_WM_SIZE()
00039 ON_WM_LBUTTONDOWN()
00040 ON_WM_MOUSEWHEEL()
00041
00042 END_MESSAGE_MAP()
00043
00044 #define LINE_BUFFER_LIMIT 1024
00045 #define LINE_BUFFER_BLOCK 64
00046
00047
00049
00050
00051 CTextCtrl::CTextCtrl()
00052 {
00053 m_crBackground = GetSysColor( COLOR_WINDOW );
00054 m_crText[0] = RGB( 0, 0, 0 );
00055 m_crText[1] = RGB( 0, 0, 127 );
00056 m_crText[2] = RGB( 255, 0, 0 );
00057 m_crText[3] = RGB( 192, 192, 192 );
00058 m_crText[4] = RGB( 0, 0, 255 );
00059
00060 m_pFont.CreateFont( -theApp.m_nDefaultFontSize, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
00061 DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
00062 DEFAULT_PITCH|FF_DONTCARE, theApp.m_sSystemLogFont );
00063 m_cCharacter = CSize( 0, 0 );
00064 }
00065
00066 CTextCtrl::~CTextCtrl()
00067 {
00068 Clear( FALSE );
00069 }
00070
00072
00073
00074 BOOL CTextCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
00075 {
00076 dwStyle |= WS_CHILD|WS_VSCROLL;
00077 return CWnd::Create( NULL, NULL, dwStyle, rect, pParentWnd, nID, NULL );
00078 }
00079
00080 void CTextCtrl::Add(int nType, LPCTSTR pszText)
00081 {
00082 CSingleLock pLock( &m_pSection, TRUE );
00083 CString strLine;
00084
00085 for ( ; *pszText ; pszText++ )
00086 {
00087 if ( *pszText == 13 )
00088 {
00089 if ( strLine.GetLength() ) AddLine( nType, strLine );
00090 strLine.Empty();
00091 }
00092 else if ( *pszText != 10 )
00093 {
00094 strLine += *pszText;
00095 }
00096 }
00097
00098 if ( strLine.GetLength() ) AddLine( nType, strLine );
00099 }
00100
00101 void CTextCtrl::AddLine(int nType, LPCTSTR pszLine)
00102 {
00103 CSingleLock pLock( &m_pSection, TRUE );
00104
00105 if ( m_pLines.GetSize() >= LINE_BUFFER_LIMIT )
00106 {
00107 for ( int nCount = 0 ; nCount < LINE_BUFFER_BLOCK ; nCount++ )
00108 {
00109 delete (CTextLine*)m_pLines.GetAt( 0 );
00110 m_pLines.RemoveAt( 0 );
00111 }
00112 m_bProcess = TRUE;
00113 }
00114
00115 m_pLines.Add( new CTextLine( nType, pszLine ) );
00116 Invalidate();
00117 }
00118
00119 void CTextCtrl::Clear(BOOL bInvalidate)
00120 {
00121 CSingleLock pLock( &m_pSection, TRUE );
00122
00123 for ( int nLine = 0 ; nLine < m_pLines.GetSize() ; nLine++ )
00124 {
00125 delete (CTextLine*)m_pLines.GetAt( nLine );
00126 }
00127 m_pLines.RemoveAll();
00128
00129 m_nPosition = m_nTotal = 0;
00130
00131 if ( bInvalidate )
00132 {
00133 UpdateScroll( TRUE );
00134 Invalidate();
00135 }
00136 }
00137
00138 void CTextCtrl::UpdateScroll(BOOL bFull)
00139 {
00140 SCROLLINFO si;
00141
00142 ZeroMemory( &si, sizeof(si) );
00143 si.cbSize = sizeof(si);
00144
00145 if ( bFull )
00146 {
00147 CRect rc;
00148 GetClientRect( &rc );
00149
00150 si.fMask = SIF_POS|SIF_PAGE|SIF_RANGE|SIF_DISABLENOSCROLL;
00151 si.nPos = m_nPosition;
00152 si.nPage = rc.Height() / m_cCharacter.cy;
00153 si.nMin = 0;
00154 si.nMax = m_nTotal + si.nPage - 1;
00155 }
00156 else
00157 {
00158 si.fMask = SIF_POS;
00159 si.nPos = m_nPosition;
00160 }
00161
00162 SetScrollInfo( SB_VERT, &si );
00163 }
00164
00165 CFont* CTextCtrl::GetFont()
00166 {
00167 return &m_pFont;
00168 }
00169
00171
00172
00173 int CTextCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
00174 {
00175 if ( CWnd::OnCreate( lpCreateStruct ) == -1 ) return -1;
00176
00177 m_nPosition = m_nTotal = 0;
00178 m_bProcess = TRUE;
00179
00180
00181 if( !SystemParametersInfo ( SPI_GETWHEELSCROLLLINES, 0, &m_nScrollWheelLines, 0) )
00182 m_nScrollWheelLines = 3;
00183
00184 return 0;
00185 }
00186
00187 void CTextCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
00188 {
00189 CSingleLock pLock( &m_pSection, TRUE );
00190 SCROLLINFO si;
00191
00192 ZeroMemory( &si, sizeof(si) );
00193 si.cbSize = sizeof(si);
00194 si.fMask = SIF_ALL;
00195
00196 GetScrollInfo( SB_VERT, &si );
00197
00198 switch ( nSBCode )
00199 {
00200 case SB_TOP:
00201 m_nPosition = 0;
00202 break;
00203 case SB_BOTTOM:
00204 m_nPosition = m_nTotal - 1;
00205 break;
00206 case SB_LINEUP:
00207 m_nPosition--;
00208 break;
00209 case SB_LINEDOWN:
00210 m_nPosition++;
00211 break;
00212 case SB_PAGEUP:
00213 m_nPosition -= ( si.nPage - 1 );
00214 break;
00215 case SB_PAGEDOWN:
00216 m_nPosition += ( si.nPage - 1 );
00217 break;
00218 case SB_THUMBPOSITION:
00219 case SB_THUMBTRACK:
00220 m_nPosition = si.nTrackPos;
00221 break;
00222 }
00223
00224 m_nPosition = max( 0, min( m_nTotal, m_nPosition ) );
00225
00226 UpdateScroll();
00227 Invalidate();
00228 }
00229
00230 BOOL CTextCtrl::OnEraseBkgnd(CDC* pDC)
00231 {
00232 return TRUE;
00233 }
00234
00235 void CTextCtrl::OnPaint()
00236 {
00237 CSingleLock pLock( &m_pSection, TRUE );
00238 CRect rcClient, rcLine;
00239 CPaintDC dc( this );
00240
00241 GetClientRect( &rcClient );
00242
00243 CFont* pOldFont = (CFont*)dc.SelectObject( &m_pFont );
00244
00245 if ( m_cCharacter.cx == 0 ) m_cCharacter = dc.GetTextExtent( _T("X") );
00246
00247 BOOL bBottom = ( m_nPosition >= m_nTotal );
00248 BOOL bModified = m_bProcess;
00249
00250 if ( m_bProcess ) m_nTotal = 0;
00251
00252 int nWidth = ( rcClient.right - 4 ) / m_cCharacter.cx;
00253
00254 for ( int nLine = 0 ; nLine < m_pLines.GetSize() ; nLine++ )
00255 {
00256 CTextLine* pLine = (CTextLine*)m_pLines.GetAt( nLine );
00257
00258 if ( m_bProcess || ! pLine->m_nLine )
00259 {
00260 m_nTotal += pLine->Process( nWidth );
00261 bModified = TRUE;
00262 }
00263 }
00264
00265 if ( bBottom ) m_nPosition = m_nTotal;
00266 if ( bModified ) UpdateScroll( TRUE );
00267 m_bProcess = FALSE;
00268
00269 dc.SetTextColor( m_crText[0] );
00270 dc.SetBkColor( m_crBackground );
00271 dc.SetBkMode( OPAQUE );
00272
00273 rcLine.CopyRect( &rcClient );
00274 rcLine.bottom += ( m_nTotal - m_nPosition ) * m_cCharacter.cy;
00275 rcLine.top = rcLine.bottom - m_cCharacter.cy;
00276
00277 for ( int nLine = m_pLines.GetSize() - 1 ; nLine >= 0 && rcLine.bottom > 0 ; nLine-- )
00278 {
00279 CTextLine* pLine = (CTextLine*)m_pLines.GetAt( nLine );
00280
00281 dc.SetTextColor( m_crText[ pLine->m_nType ] );
00282 pLine->Paint( &dc, &rcLine );
00283 }
00284
00285 if ( rcLine.bottom > 0 )
00286 {
00287 rcLine.top = 0;
00288 dc.FillSolidRect( &rcLine, m_crBackground );
00289 }
00290
00291 dc.SelectObject( pOldFont );
00292 }
00293
00294 void CTextCtrl::OnSize(UINT nType, int cx, int cy)
00295 {
00296 CWnd::OnSize( nType, cx, cy );
00297 m_bProcess = TRUE;
00298 }
00299
00300 void CTextCtrl::OnLButtonDown(UINT nFlags, CPoint point)
00301 {
00302 SetFocus();
00303 }
00304
00305 BOOL CTextCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
00306 {
00307 short nRows = ( zDelta / WHEEL_DELTA );
00308
00309 if ( WHEEL_PAGESCROLL == m_nScrollWheelLines )
00310 {
00311
00312 SCROLLINFO si;
00313
00314 ZeroMemory( &si, sizeof( si ) );
00315 si.cbSize = sizeof( si );
00316 si.fMask = SIF_ALL;
00317
00318 GetScrollInfo( SB_VERT, &si );
00319
00320 nRows *=( si.nPage - 1 );
00321 }
00322 else
00323 nRows *= m_nScrollWheelLines;
00324
00325 CSingleLock pLock( &m_pSection, TRUE );
00326
00327 m_nPosition-= nRows;
00328 m_nPosition = max( 0, min( m_nTotal, m_nPosition ) );
00329
00330 UpdateScroll();
00331 Invalidate();
00332
00333 return CWnd::OnMouseWheel(nFlags, zDelta, pt);
00334 }
00335
00337
00338
00339 CTextLine::CTextLine(int nType, LPCTSTR pszText)
00340 {
00341 m_sText = pszText;
00342 m_pLine = NULL;
00343 m_nLine = 0;
00344 m_nType = nType;
00345 }
00346
00347 CTextLine::~CTextLine()
00348 {
00349 if ( m_pLine ) delete [] m_pLine;
00350 }
00351
00353
00354
00355 int CTextLine::Process(int nWidth)
00356 {
00357 if ( m_pLine ) delete [] m_pLine;
00358 m_pLine = NULL;
00359 m_nLine = 0;
00360
00361 int nLength = 0;
00362 int nLast = 0;
00363
00364 for ( LPCTSTR pszText = m_sText ; ; pszText++, nLength++ )
00365 {
00366 if ( *pszText == 32 || *pszText == 0 )
00367 {
00368 if ( nLength <= nWidth )
00369 {
00370 nLast = nLength;
00371 }
00372 else if ( nLast )
00373 {
00374 AddLine( nLast );
00375 nLength = nLast = nLength - nLast;
00376 }
00377 else
00378 {
00379 break;
00380 }
00381 }
00382
00383 if ( *pszText == 0 ) break;
00384 }
00385
00386 if ( nLength || !m_nLine ) AddLine( nLength );
00387
00388 return m_nLine;
00389 }
00390
00391 void CTextLine::AddLine(int nLength)
00392 {
00393 int* pLine = new int[ m_nLine + 1 ];
00394 CopyMemory( pLine, m_pLine, m_nLine * sizeof(int) );
00395 if ( m_pLine ) delete [] m_pLine;
00396 m_pLine = pLine;
00397 m_pLine[ m_nLine++ ] = nLength;
00398 }
00399
00401
00402
00403 void CTextLine::Paint(CDC* pDC, CRect* pRect)
00404 {
00405 int nHeight = pRect->bottom - pRect->top;
00406
00407 pRect->top -= ( m_nLine - 1 ) * nHeight;
00408 pRect->bottom -= ( m_nLine - 1 ) * nHeight;
00409
00410 LPCTSTR pszLine = m_sText;
00411 int* pLength = m_pLine;
00412
00413 for ( int nLine = 0 ; nLine < m_nLine ; nLine++, pLength++ )
00414 {
00415 if ( pDC->RectVisible( pRect ) )
00416 {
00417 pDC->ExtTextOut( pRect->left + 2, pRect->top, ETO_CLIPPED|ETO_OPAQUE,
00418 pRect, pszLine, *pLength, NULL );
00419 }
00420 pszLine += *pLength;
00421
00422 pRect->top += nHeight;
00423 pRect->bottom += nHeight;
00424 }
00425
00426 pRect->top -= ( m_nLine + 1 ) * nHeight;
00427 pRect->bottom -= ( m_nLine + 1 ) * nHeight;
00428 }