⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 richviewctrl.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	m_pFragments.RemoveAll();
	m_nLength = 0;
	
	if ( m_bSelecting )
	{
		m_bSelecting = FALSE;
		ReleaseCapture();
	}
	
	m_pSelStart.nFragment		= m_pSelStart.nOffset		= 0;
	m_pSelEnd.nFragment			= m_pSelEnd.nOffset			= 0;
	m_pSelAbsStart.nFragment	= m_pSelAbsStart.nOffset	= 0;
	m_pSelAbsEnd.nFragment		= m_pSelAbsEnd.nOffset		= 0;
}

void CRichViewCtrl::Layout(CDC* pDC, CRect* pRect)
{
	ASSERT( m_pDocument != NULL );
	
	CSingleLock pLock( &m_pDocument->m_pSection, TRUE );
	
	ClearFragments();
	
	pRect->DeflateRect( m_pDocument->m_szMargin.cx, m_pDocument->m_szMargin.cy );
	
	CPoint pt( pRect->left, pRect->top );
	
	int nLeftPoint		= pRect->left;
	int nWidth			= pRect->Width();
	int nLineHeight		= 0;
	int nAlign			= reaLeft;
	
	CRichFragment* pFrag = NULL;
	CPtrList pLine;
	
	for ( POSITION pos = m_pDocument->GetIterator() ; pos ; )
	{
		CRichElement* pElement = m_pDocument->GetNext( pos );
		
		if ( pElement->m_nFlags & retfHidden ) continue;
		
		pElement->PrePaint( pDC, FALSE );
		
		if ( pElement->m_nType == retNewline )
		{
			WrapLineHelper( pLine, pt, nLineHeight, nWidth, nAlign );
			
			int nGap = 0, nIndent = 0;
			
			if ( _stscanf( pElement->m_sText, _T("%lu.%lu"), &nGap, &nIndent ) == 2 )
			{
				nLeftPoint	= pRect->left + nIndent;
				nWidth		= pRect->right - nIndent;
			}
			
			pt.x = nLeftPoint;
			pt.y += nGap;
			
			continue;
		}
		else if ( pElement->m_nType == retAlign )
		{
			WrapLineHelper( pLine, pt, nLineHeight, nWidth, nAlign );
			
			if ( pElement->m_sText.CompareNoCase( _T("center") ) == 0 )
			{
				nAlign = reaCenter;
			}
			else if ( pElement->m_sText.CompareNoCase( _T("right") ) == 0 )
			{
				nAlign = reaRight;
			}
			else
			{
				nAlign = reaLeft;
			}
			
			continue;
		}
		else if ( pElement->m_nType == retGap || pElement->m_nType < retText )
		{
			pFrag = new CRichFragment( pElement, &pt );
			m_pFragments.Add( pFrag );
			
			if ( pt.x + pFrag->m_sz.cx > nWidth )
			{
				WrapLineHelper( pLine, pt, nLineHeight, nWidth, nAlign );
				pFrag->m_pt = pt;
			}
			
			pt.x += pFrag->m_sz.cx;
			
			if ( pElement->m_nType != retGap )
			{
				nLineHeight = max( nLineHeight, pFrag->m_sz.cy );
				pLine.AddTail( pFrag );
			}
			
			continue;
		}
		
		LPTSTR  pszText	= (LPTSTR)(LPCTSTR)pElement->m_sText;
		LPCTSTR pszWord	= pszText;
		LPCTSTR pszLast	= NULL;
		
		int nWordStart	= 0;
		int nSpace		= pDC->GetTextExtent( _T(" ") ).cx;
		
		pFrag = NULL;
		
		for ( int nChar = 0 ; nChar <= pElement->m_sText.GetLength() ; nChar++, pszText++ )
		{
			if ( *pszText != ' ' && *pszText != '\t' && *pszText != 0 ) continue;
			
			if ( nChar > nWordStart || *pszText == 0 )
			{
				TCHAR cSave = *pszText;
				*pszText = 0;
				
				CSize szWord = pDC->GetTextExtent( pszWord );
				
				if ( pFrag != NULL )
				{
					CSize szLast = pDC->GetTextExtent( pszLast );
					
					if ( pFrag->m_pt.x + szLast.cx <= nWidth )
					{
						pt.x -= pFrag->m_sz.cx;
						pFrag->Add( nChar - pFrag->m_nOffset, &szLast );
						pt.x += pFrag->m_sz.cx;
						nWordStart = -1;
					}
				}
				
				if ( nChar == nWordStart && *pszText == 0 ) break;
				
				if ( nWordStart >= 0 )
				{
					if ( pt.x + szWord.cx + ( pFrag ? nSpace : 0 ) > nWidth )
					{
						WrapLineHelper( pLine, pt, nLineHeight, nWidth, nAlign );
					}
					else if ( pFrag != NULL ) pt.x += nSpace;
					
					pFrag = new CRichFragment( pElement, nWordStart, nChar - nWordStart, &pt, &szWord );
					pszLast = pszWord;
					
					pt.x += pFrag->m_sz.cx;
					nLineHeight = max( nLineHeight, pFrag->m_sz.cy );
					
					m_pFragments.Add( pFrag );
					pLine.AddTail( pFrag );
				}
				
				*pszText = cSave;
			}
			
			if ( pFrag != NULL )
			{
				nWordStart	= nChar + 1;
				pszWord		= pszText + 1;
			}
		}
	}
	
	WrapLineHelper( pLine, pt, nLineHeight, nWidth, nAlign );
	
	pRect->InflateRect( m_pDocument->m_szMargin.cx, m_pDocument->m_szMargin.cy );
	
	m_nLength = pt.y - pRect->top + m_pDocument->m_szMargin.cy;
	
	SCROLLINFO pInfo;
	
	pInfo.cbSize	= sizeof(pInfo);
	pInfo.fMask		= SIF_POS | SIF_RANGE | SIF_PAGE;
	
	GetScrollInfo( SB_VERT, &pInfo, pInfo.fMask );
	
	if ( m_bFollowBottom && pInfo.nPos >= pInfo.nMax - (int)pInfo.nPage - 1 )
		pInfo.nPos = m_nLength;
	
	pInfo.fMask		= SIF_ALL & ~SIF_TRACKPOS;
	pInfo.nMin		= 0;
	pInfo.nMax		= m_nLength - 1;
	pInfo.nPage		= ( pRect->bottom == -1 ) ? m_nLength : pRect->Height();
	pInfo.nPos		= min( pInfo.nPos, max( 0, pInfo.nMax - (int)pInfo.nPage ) );
	
	SetScrollInfo( SB_VERT, &pInfo, TRUE );
	
	m_nCookie = m_pDocument->m_nCookie;
	OnLayoutComplete();
}

void CRichViewCtrl::WrapLineHelper(CPtrList& pLine, CPoint& pt, int& nLineHeight, int nWidth, int nAlign)
{
	if ( pLine.GetCount() == 0 ) return;
	
	int nLeft = ((CRichFragment*)pLine.GetHead())->m_pt.x;
	int nHorz = 0;

	if ( nAlign == reaCenter )
	{
		nHorz = nWidth / 2 - ( pt.x - nLeft ) / 2;
	}
	else if ( nAlign == reaRight )
	{
		nHorz = nWidth - pt.x;
	}

	for ( POSITION posAlign = pLine.GetHeadPosition() ; posAlign ; )
	{
		CRichFragment* pAlign = (CRichFragment*)pLine.GetNext( posAlign );

		if ( pAlign->m_pElement->m_nFlags & retfMiddle )
		{
			pAlign->m_pt.y += ( nLineHeight / 2 - pAlign->m_sz.cy / 2 );
		}
		else
		{
			pAlign->m_pt.y += ( nLineHeight - pAlign->m_sz.cy );
		}

		pAlign->m_pt.x += nHorz;
	}

	pt.x = nLeft;
	pt.y += nLineHeight;

	pLine.RemoveAll();
	nLineHeight = 0;
}

/////////////////////////////////////////////////////////////////////////////
// CRichViewCtrl coordinate mapping

CRichFragment* CRichViewCtrl::PointToFrag(CPoint& pt)
{
	if ( m_pDocument == NULL || m_pDocument->m_nCookie != m_nCookie ) return NULL;
	
	pt.y += GetScrollPos( SB_VERT );
	
	for ( int nFragment = m_pFragments.GetSize() - 1 ; nFragment >= 0 ; nFragment-- )
	{
		CRichFragment* pFragment = (CRichFragment*)m_pFragments.GetAt( nFragment );
		
		if ( pt.x >= pFragment->m_pt.x && pt.y >= pFragment->m_pt.y &&
			 pt.x < pFragment->m_pt.x + pFragment->m_sz.cx &&
			 pt.y < pFragment->m_pt.y + pFragment->m_sz.cy )
		{
			pt.y -= GetScrollPos( SB_VERT );
			return pFragment;
		}
	}
	
	pt.y -= GetScrollPos( SB_VERT );
	
	return NULL;
}

RICHPOSITION CRichViewCtrl::PointToPosition(CPoint& pt)
{
	RICHPOSITION pos = { -1, 0 };
	
	if ( m_pDocument == NULL || m_pDocument->m_nCookie != m_nCookie ) return pos;

	pt.y += GetScrollPos( SB_VERT );
	
	for ( int nFragment = 0 ; nFragment < m_pFragments.GetSize() ; nFragment++ )
	{
		CRichFragment* pFragment = (CRichFragment*)m_pFragments.GetAt( nFragment );
		
		if ( pt.x >= pFragment->m_pt.x && pt.y >= pFragment->m_pt.y &&
			 pt.x < pFragment->m_pt.x + pFragment->m_sz.cx &&
			 pt.y < pFragment->m_pt.y + pFragment->m_sz.cy )
		{
			pos.nFragment = nFragment;
			
			if ( pFragment->m_nLength > 0 )
			{
				CClientDC dc( this );
				CFont* pOld = dc.GetCurrentFont();
				pFragment->m_pElement->PrePaint( &dc, FALSE );
				
				LPCTSTR pszText = pFragment->m_pElement->m_sText;
				pszText += pFragment->m_nOffset;
				int nX = pt.x - pFragment->m_pt.x;
				
				for ( pos.nOffset = 0 ; pos.nOffset < pFragment->m_nLength ; pszText ++ )
				{
					int nWidth = dc.GetTextExtent( pszText, 1 ).cx;
					if ( nX < ( nWidth >> 1 ) ) break;
					pos.nOffset++;
					if ( nX < nWidth ) break;
					nX -= nWidth;
				}
				
				dc.SelectObject( pOld );
			}
			
			break;
		}		
	}	
	
	pt.y -= GetScrollPos( SB_VERT );
	
	return pos;
}

CPoint CRichViewCtrl::PositionToPoint(RICHPOSITION& pos)
{
	CPoint pt( 0, - GetScrollPos( SB_VERT ) );
	
	if ( m_pDocument == NULL || m_pDocument->m_nCookie != m_nCookie ) return pt;
	if ( pos.nFragment < 0 || m_pFragments.GetSize() == 0 ) return pt;
	
	BOOL bOverload = pos.nFragment >= m_pFragments.GetSize();
	
	CRichFragment* pFragment = (CRichFragment*)m_pFragments.GetAt(
								bOverload ? m_pFragments.GetSize() - 1 : pos.nFragment );
	
	pt.x = pFragment->m_pt.x;
	pt.y += pFragment->m_pt.y;
	
	if ( bOverload )
	{
		pt.x += pFragment->m_sz.cx;
	}
	else if ( pos.nOffset > 0 )
	{
		if ( pos.nOffset < pFragment->m_nLength )
		{
			CClientDC dc( this );
			CFont* pOld = dc.GetCurrentFont();
			pFragment->m_pElement->PrePaint( &dc, FALSE );
			LPCTSTR pszText = pFragment->m_pElement->m_sText;
			pszText += pFragment->m_nOffset;
			pt.x += dc.GetTextExtent( pszText, pos.nOffset ).cx;
			dc.SelectObject( pOld );
		}
		else
		{
			pt.x += pFragment->m_sz.cx;
		}
	}
	
	return pt;
}

/////////////////////////////////////////////////////////////////////////////
// CRichViewCtrl selection helpers

void CRichViewCtrl::UpdateSelection()
{
	if ( m_pSelStart.nFragment < m_pSelEnd.nFragment || ( m_pSelStart.nFragment == m_pSelEnd.nFragment && m_pSelStart.nOffset <= m_pSelEnd.nOffset ) )
	{
		if (	m_pSelAbsStart.nFragment	!= m_pSelStart.nFragment ||
				m_pSelAbsStart.nOffset		!= m_pSelStart.nOffset ||
				m_pSelAbsEnd.nFragment		!= m_pSelEnd.nFragment ||
				m_pSelAbsEnd.nOffset		!= m_pSelEnd.nOffset )
		{
			m_pSelAbsStart	= m_pSelStart;
			m_pSelAbsEnd	= m_pSelEnd;
			Invalidate();
		}
	}
	else
	{
		if (	m_pSelAbsStart.nFragment	!= m_pSelEnd.nFragment ||
				m_pSelAbsStart.nOffset		!= m_pSelEnd.nOffset ||
				m_pSelAbsEnd.nFragment		!= m_pSelStart.nFragment ||
				m_pSelAbsEnd.nOffset		!= m_pSelStart.nOffset )
		{
			m_pSelAbsStart	= m_pSelEnd;
			m_pSelAbsEnd	= m_pSelStart;
			Invalidate();
		}
	}
}

void CRichViewCtrl::CopySelection()
{
	CString str;
	
	for ( int nFragment = m_pSelAbsStart.nFragment ; nFragment <= m_pSelAbsEnd.nFragment ; nFragment++ )
	{
		CRichFragment* pFragment = (CRichFragment*)m_pFragments.GetAt( nFragment );
		
		if ( pFragment->m_nLength == 0 )
		{
			if ( nFragment == m_pSelAbsEnd.nFragment ) break;
			
			if ( pFragment->m_pElement->m_nType == retEmoticon )
			{
				int nToken = 0;
				_stscanf( pFragment->m_pElement->m_sText, _T("%i"), &nToken );
				if ( LPCTSTR pszToken = Emoticons.GetText( nToken ) )
					str += pszToken;
			}
			else if ( pFragment->m_pElement->m_nType < retText )
			{
				str += ' ';
			}
		}
		else
		{
			int nCharStart = 0, nCharEnd = pFragment->m_nLength;
			
			if ( m_pSelAbsStart.nFragment == nFragment )
			{
				nCharStart = m_pSelAbsStart.nOffset;
			}
			
			if ( m_pSelAbsEnd.nFragment == nFragment )
			{
				nCharEnd = m_pSelAbsEnd.nOffset;
			}
			
			if ( nCharEnd > nCharStart )
			{
				str +=  pFragment->m_pElement->m_sText.Mid(
						pFragment->m_nOffset + nCharStart,
						nCharEnd - nCharStart );
			}
		}
		
		if ( nFragment < m_pSelAbsEnd.nFragment )
		{
			CRichFragment* pNextFrag = (CRichFragment*)m_pFragments.GetAt( nFragment + 1 );
			
			if ( pFragment->m_pElement != pNextFrag->m_pElement )
			{
				POSITION pos = m_pDocument->Find( pFragment->m_pElement );
				
				while ( pos )
				{
					CRichElement* pCopy = m_pDocument->GetNext( pos );
					if ( pCopy == pNextFrag->m_pElement ) break;
					if ( pCopy->m_nType == retNewline ) str += _T("\r\n");
				}
			}
		}
	}
	
	if ( str.GetLength() && AfxGetMainWnd()->OpenClipboard() )
	{
		USES_CONVERSION;
		EmptyClipboard();
		
		if ( theApp.m_bNT )
		{
			LPCWSTR pszWide = T2CW( (LPCTSTR)str );
			HANDLE hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, ( wcslen(pszWide) + 1 ) * sizeof(WCHAR) );
			LPVOID pMem = GlobalLock( hMem );
			CopyMemory( pMem, pszWide, ( wcslen(pszWide) + 1 ) * sizeof(WCHAR) );
			GlobalUnlock( hMem );
			SetClipboardData( CF_UNICODETEXT, hMem );
		}
		else
		{
			LPCSTR pszASCII = T2CA( (LPCTSTR)str );
			HANDLE hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, strlen(pszASCII) + 1 );
			LPVOID pMem = GlobalLock( hMem );
			CopyMemory( pMem, pszASCII, strlen(pszASCII) + 1 );
			GlobalUnlock( hMem );
			SetClipboardData( CF_TEXT, hMem );
		}
		
		CloseClipboard();
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -