📄 bcgpeditctrl.cpp
字号:
SetCaret (m_nCurrOffset, FALSE);
if (m_nTotalLines - m_nHiddenLines < m_rectText.Height () / m_nLineHeight &&
m_nTopVisibleOffset > 0)
{
OnScroll (SB_VERT, SB_THUMBPOSITION, 0);
}
else
{
SetScrollPos (SB_VERT, m_nScrollOffsetVert, FALSE);
}
SetScrollPos (SB_HORZ, m_nScrollOffsetHorz, FALSE);
}
//*****************************************************************************
int CBCGPEditCtrl::HitTest (CPoint& pt, BOOL bNormalize, BOOL bIgnoreTextBounds)
{
if (!m_rectText.PtInRect (pt) && !bIgnoreTextBounds)
{
return -1;
}
int x = -1;
int y = m_rectText.top; // - m_nScrollOffsetVert * m_nLineHeight;
int nOffset = 0;
CClientDC dc (this);
CFont* pOldFont = SelectFont (&dc);
// --------------
// Calculate row:
// --------------
int nRow = max (0, (pt.y + m_nScrollOffsetVert * m_nLineHeight) / m_nLineHeight);
int nColumn = 0;
int iRowOffset = m_nTopVisibleOffset;
int nStrartFrom = m_nScrollOffsetVert;
if (pt.y < 0)
{
iRowOffset = GetRowStart (nRow, TRUE);
nStrartFrom = nRow;
}
for (int i = nStrartFrom; i <= nRow; i++)
{
int iNextRow = m_strBuffer.Find (_T('\n'), iRowOffset);
while (iNextRow != -1 && FindCollapsedBlock (iNextRow) != NULL) // skip hidden text
{
iNextRow = m_strBuffer.Find (_T('\n'), iNextRow + 1);
}
if (i == nRow)
{
// -----------------
// Calculate column:
// -----------------
CString strRow;
if (iNextRow < 0)
{
strRow = m_strBuffer.Mid (iRowOffset);
}
else
{
strRow = m_strBuffer.Mid (iRowOffset, iNextRow - iRowOffset);
}
int nXRight = m_rectText.left + GetStringExtent (&dc, strRow, strRow.GetLength ()).cx;
if (pt.x >= nXRight)
{
x = nXRight;
nOffset = (iNextRow < 0) ? m_strBuffer.GetLength () : iNextRow;
nColumn = iNextRow - iRowOffset;
}
else
{
int cxPrev = m_rectText.left;
int nScrollOffsetPix = m_nScrollOffsetHorz * m_nMaxCharWidth; //GetHorzRowExtent (&dc, iRowOffset);
int nOffsetInRowPix = 0;
nOffset = -1;
int nStartOffsetToCheck = 0;
int nExtent = 0; //GetStringExtent (&dc, (LPCTSTR) strRow, nStartOffsetToCheck).cx;
for (int iIdx = nStartOffsetToCheck; iIdx < strRow.GetLength (); iIdx++)
{
TCHAR chNext = strRow [iIdx];
int nSymExtraLen = 0;
int nCharWidth = 0;
CBCGPOutlineBaseNode* pHiddenText = FindCollapsedBlock (iRowOffset + iIdx);
if (pHiddenText != NULL)
{
OnCalcOutlineSymbol (&dc, CPoint (m_rectText.left + nExtent, y), pHiddenText);
nCharWidth = pHiddenText->m_rectTool.Width ();
nSymExtraLen = pHiddenText->m_nEnd - pHiddenText->m_nStart;
}
else if (m_bEnableSymSupport)
{
BCGP_EDIT_SYM_DEF symDef;
if (LookUpSymbol (strRow, iIdx, strRow.GetLength (), chNext, symDef, nSymExtraLen))
{
IMAGEINFO imgInfo;
m_pSymbolsImgList->GetImageInfo (symDef.m_nIndex, &imgInfo);
nCharWidth = imgInfo.rcImage.right - imgInfo.rcImage.left;
}
}
if (nCharWidth == 0 && !m_mapCharWidth.Lookup (chNext, nCharWidth))
{
nCharWidth = GetStringExtent (&dc, CString (chNext), 1).cx;
m_mapCharWidth.SetAt (chNext, nCharWidth);
}
if (pHiddenText != NULL)
{
}
else if (chNext == _T ('\t'))
{
int nRestOfTab = m_nTabSize - nColumn % m_nTabSize;
nColumn += nRestOfTab;
nCharWidth = nRestOfTab * nCharWidth / m_nTabSize;
}
else
{
nColumn++;
}
nExtent += nCharWidth;
int cx = m_rectText.left + nExtent;
int nAddition = (iIdx == strRow.GetLength () - 1) ? 0 : nCharWidth / 2;
if (cx >= pt.x + nScrollOffsetPix + nAddition)
{
x = cxPrev;
nOffset = iRowOffset + iIdx;
nOffsetInRowPix = cx - m_rectText.left;
break;
}
else if (iIdx == (strRow.GetLength () - 1))
{
x = cx;
nOffset = iRowOffset + strRow.GetLength();
break;
}
cxPrev = cx;
iIdx += nSymExtraLen;
}
if (nOffset == -1)
{
nOffset = iRowOffset + iIdx;
}
nColumn++;
}
break;
}
iRowOffset = iNextRow + 1;
y += m_nLineHeight;
if (iNextRow == -1 && x == -1)
{
x = m_rectText.left;
y -= m_nLineHeight;
nOffset = m_strBuffer.GetLength ();
break;
}
}
dc.SelectObject (pOldFont);
if (bNormalize)
{
pt.x = x;
pt.y = y;
}
OnSetCaret ();
return nOffset;
}
//******************************************************************************
BOOL CBCGPEditCtrl::SetCaret (int nOffset, BOOL bScrollToCaret, BOOL bRedrawOnScroll)
{
CPoint pt;
CPoint ptRowColumn;
if (!OffsetToPoint (nOffset, pt, &ptRowColumn))
{
return FALSE;
}
m_nCurrOffset = nOffset;
m_ptCaret = pt;
BOOL bScrollRequired = FALSE;
BOOL bCaretSet = FALSE;
if (bScrollToCaret)
{
int nDeltaX = 0;
if (m_ptCaret.x < m_rectText.left + m_nMaxCharWidth)
{
nDeltaX = ((m_ptCaret.x - m_rectText.left) / m_nMaxCharWidth) - m_nScrollLeftOffset;
}
else if (m_ptCaret.x >= m_rectText.right - m_nMaxCharWidth)
{
int nScrollOffset = m_rectText.Width () / m_nMaxCharWidth * m_nScrollRightOffset / 100;
if (nScrollOffset < 1)
{
nScrollOffset = 1;
}
nDeltaX = ((m_ptCaret.x - m_rectText.right) / m_nMaxCharWidth) + nScrollOffset;
}
if (nDeltaX != 0)
{
int nScrollValue = m_nScrollOffsetHorz + nDeltaX;
if (nDeltaX < 0)
{
int nRowEndOffset = 0;
int nNumColumnsInRow = GetNumOfColumnsInRowByOffset (nOffset, nRowEndOffset, TRUE);
if (nScrollValue > nNumColumnsInRow - m_nScrollLeftOffset)
{
nScrollValue = max (0, nNumColumnsInRow - m_nScrollLeftOffset);
}
}
bScrollRequired = OnScroll (SB_HORZ, SB_THUMBPOSITION, nScrollValue);
OffsetToPoint (nOffset, pt, &ptRowColumn);
m_nCurrOffset = nOffset;
m_ptCaret = pt;
SetCaretPos (m_ptCaret);
OnSetCaret ();
bCaretSet = TRUE;
}
int nDeltaY = 0;
if (m_ptCaret.y < m_rectText.top + m_nLineHeight)
{
nDeltaY = ((m_ptCaret.y - m_rectText.top) / m_nLineHeight);
}
else if (m_ptCaret.y >= m_rectText.bottom - m_nLineHeight * 2)
{
nDeltaY = ((m_ptCaret.y - m_rectText.bottom + m_nLineHeight * 2) / m_nLineHeight);
}
if (nDeltaY != 0)
{
bScrollRequired = OnScroll (SB_VERT, SB_THUMBPOSITION, m_nScrollOffsetVert + nDeltaY);
OffsetToPoint (nOffset, pt, &ptRowColumn);
m_nCurrOffset = nOffset;
m_ptCaret = pt;
SetCaretPos (m_ptCaret);
OnSetCaret ();
bCaretSet = TRUE;
}
}
m_nCurRow = RowFromOffset (m_nCurrOffset);//ptRowColumn.y;
m_nCurColumn = GetColumnFromOffset (m_nCurrOffset, FALSE);
if (!bCaretSet && bScrollToCaret)
{
SetCaretPos (m_ptCaret);
OnSetCaret ();
}
if (bRedrawOnScroll && bScrollRequired)
{
RedrawWindow ();
}
return TRUE;
}
//***************************************************************************************
int CBCGPEditCtrl::GetColumnFromOffset (int nOffset, BOOL bSkipHidden) const
{
int nRowStart = GetRowStartByOffset (nOffset, bSkipHidden);
if (m_bKeepTabs)
{
int nColumn = 0;
int nNumChars = nOffset - nRowStart;
LPCTSTR lpcszRowStart = ((LPCTSTR) m_strBuffer) + nRowStart;
for (int i = 0; i < nNumChars; i++)
{
CBCGPOutlineBaseNode* pHiddenText = NULL;
pHiddenText = bSkipHidden ? FindCollapsedBlock (nRowStart + i) : NULL;
if (pHiddenText == NULL)
{
TCHAR chNext = lpcszRowStart [i];
if (chNext == _T ('\t'))
{
int nRestOfTab = m_nTabSize - nColumn % m_nTabSize;
nColumn += nRestOfTab;
}
else
{
nColumn++;
}
}
else
{
nColumn += pHiddenText->m_strReplace.GetLength ();
i += pHiddenText->m_nEnd - (nRowStart + i); // skip the rest of the hidden text
}
}
return nColumn;
}
else if (bSkipHidden)
{
int nColumn = 0;
for (int i = nRowStart; i < nOffset; )
{
CBCGPOutlineBaseNode* pHiddenText = FindCollapsedBlockInRange (i, nOffset, TRUE);
if (pHiddenText != NULL)
{
ASSERT_VALID (pHiddenText);
nColumn += pHiddenText->m_nStart - i;
if (nOffset == pHiddenText->m_nStart)
{
break;
}
nColumn += pHiddenText->m_strReplace.GetLength ();
i += max (pHiddenText->m_nEnd - i + 1, 1); // skip the rest of the hidden text
}
else
{
nColumn += nOffset - i;
break;
}
}
return nColumn;
}
return nOffset - nRowStart;
}
//******************************************************************************
void CBCGPEditCtrl::OnChangeFont (CDC* pDC)
{
CClientDC dc (this);
if (pDC == NULL)
{
pDC = &dc;
}
CFont* pOldFont = SelectFont (pDC);
TEXTMETRIC tm;
pDC->GetTextMetrics (&tm);
if (m_pSymbolsImgList != NULL)
{
IMAGEINFO imgInfo;
memset (&imgInfo, 0, sizeof (IMAGEINFO));
if (m_pSymbolsImgList->GetImageInfo (0, &imgInfo))
{
int nImgHeight = imgInfo.rcImage.bottom - imgInfo.rcImage.top;
if (nImgHeight > m_nLineHeight)
{
m_nLineVertSpacing += nImgHeight - m_nLineHeight;
}
}
}
m_nLineHeight = tm.tmHeight + m_nLineVertSpacing;
m_nMaxCharWidth = tm.tmMaxCharWidth;
m_nAveCharWidth = tm.tmAveCharWidth;
pDC->SelectObject (pOldFont);
m_mapCharWidth.RemoveAll ();
//------------------
// Initialize caret:
//------------------
::DestroyCaret ();
CSize sizeCaret = GetCaretSize ();
::CreateCaret (GetSafeHwnd (), NULL, sizeCaret.cx, sizeCaret.cy);
UpdateScrollBars ();
if (!m_bReadOnly)
{
SetCaret (m_nCurrOffset);
ShowCaret ();
}
}
//******************************************************************************
BOOL CBCGPEditCtrl::OffsetToPoint (int nOffset, CPoint& pt, LPPOINT ptRowColumn, LPINT pnScrollOffset)
{
ASSERT_VALID (this);
nOffset = min (max (nOffset, 0), m_strBuffer.GetLength ());
CClientDC dc (this);
CFont* pOldFont = SelectFont (&dc);
int nRow = -1;
int iRowOffset = 0;
int nLowBound = 0;
if (nOffset >= m_nTopVisibleOffset)
{
nLowBound = m_nTopVisibleOffset;
}
// --------------
// Calculate row:
// --------------
CBCGPOutlineBaseNode* pHiddenText = NULL;
if (nOffset - 1 >= nLowBound)
{
pHiddenText = FindCollapsedBlockInRange (nLowBound, nOffset - 1, FALSE);
}
for (int i = nOffset - 1; i >= nLowBound; )
{
if (pHiddenText != NULL && pHiddenText->m_nEnd >= i)
{
// skip hidden text
i -= max (i - pHiddenText->m_nStart + 1, 1);
if (i >= nLowBound)
{
pHiddenText = FindCollapsedBlockInRange (nLowBound, i, FALSE);
}
}
else
{
if (m_strBuffer [i] == _T('\n'))
{
if (nRow == -1)
{
nRow = 1;
}
else
{
nRow ++;
}
}
i--;
}
}
if (nRow == -1)
{
nRow = 0;
}
if (nOffset >= m_nTopVisibleOffset)
{
nRow += m_nScrollOffsetVert;
}
// -----------------
// Calculate column:
// -----------------
iRowOffset = GetRowStartByOffset (nOffset, TRUE);
int nScrolledExtent = m_nScrollOffsetHorz * m_nMaxCharWidth;
int nStringExtent = 0;
for (i = iRowOffset; i < nOffset; )
{
CBCGPOutlineBaseNode* pHiddenText = FindCollapsedBlockInRange (i, nOffset, TRUE);
if (pHiddenText != NULL)
{
ASSERT_VALID (pHiddenText);
nStringExtent += GetStringExtent (&dc, (LPCTSTR) m_strBuffer + i, pHiddenText->m_nStart - i).cx;
if (nOffset == pHiddenText->m_nStart)
{
break;
}
OnCalcOutlineSymbol (&dc, pHiddenText->m_rectTool.TopLeft (), pHiddenText);
nStringExtent += pHiddenText->m_rectTool.Width ();
i += max (pHiddenText->m_nEnd - i + 1, 1);
}
else
{
nStringExtent += GetStringExtent (&dc, (LPCTSTR) m_strBuffer + i, nOffset - i).cx;
break;
}
}
pt.x = m_rectText.left + nStringExtent - nScrolledExtent - 1;
pt.x = max (pt.x, m_rectText.left);
if (pnScrollOffset != NULL)
{
*pnScrollOffset = 0;
if (pt.x < m_rectText.left)
{
for (int i = nOffset - iRowOffset;
i < m_strBuffer.GetLength () && m_strBuffer [i] != _T('\n'); i++)
{
(*pnScrollOffset)++;
}
}
else if (pt.x >= m_rectText.right)
{
}
}
pt.y = m_rectText.top + (nRow - m_nScrollOffsetVert) * m_nLineHeight;
dc.SelectObject (pOldFont);
if (ptRowColumn != NULL)
{
ptRowColumn->x = GetColumnFromOffset (nOffset, TRUE);
ptRowColumn->y = nRow;
}
return TRUE;
}
//**************************************************************************************
BOOL CBCGPEditCtrl::Left (BOOL bRedrawOnScroll)
{
if (m_nCurrOffset == 0)
{
OnFailedOperation (g_dwOpLeft);
return FALSE;
}
int nCharCount = 1;
CBCGPOutlineBaseNode* pHiddenText = FindCollapsedBlock (m_nCurrOffset - 1);
if (pHiddenText != NULL)
{
nCharCount += pHiddenText->m_nEnd - pHiddenText->m_nStart;
}
else if (m_bEnableSymSupport && m_nCurrOffset > 0)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -