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

📄 ccrystaltextbuffer.cpp

📁 一个完整的编辑器的代码(很值得参考
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    }

  if (pszRestChars != NULL)
    delete pszRestChars;

  context.m_ptEnd.x = nEndChar;
  context.m_ptEnd.y = nEndLine;

  if (bNewLines)
    UpdateViews (pSource, &context, UPDATE_HORZRANGE | UPDATE_VERTRANGE, nLine);
  else
    UpdateViews (pSource, &context, UPDATE_SINGLELINE | UPDATE_HORZRANGE, nLine);

  if (!m_bModified)
    SetModified (TRUE);
	//BEGIN SW
	// remember current cursor position as last editing position
	m_ptLastChange = context.m_ptEnd;
	//END SW
  return TRUE;
}

BOOL CCrystalTextBuffer::
CanUndo ()
{
  ASSERT (m_nUndoPosition >= 0 && m_nUndoPosition <= m_aUndoBuf.GetSize ());
  return m_nUndoPosition > 0;
}

BOOL CCrystalTextBuffer::
CanRedo ()
{
  ASSERT (m_nUndoPosition >= 0 && m_nUndoPosition <= m_aUndoBuf.GetSize ());
  return m_nUndoPosition < m_aUndoBuf.GetSize ();
}

POSITION CCrystalTextBuffer::
GetUndoDescription (CString & desc, POSITION pos /*= NULL*/ )
{
  ASSERT (CanUndo ());          //  Please call CanUndo() first

  ASSERT ((m_aUndoBuf[0].m_dwFlags & UNDO_BEGINGROUP) != 0);

  int nPosition;
  if (pos == NULL)
    {
      //  Start from beginning
      nPosition = m_nUndoPosition;
    }
  else
    {
      nPosition = (int) pos;
      ASSERT (nPosition > 0 && nPosition < m_nUndoPosition);
      ASSERT ((m_aUndoBuf[nPosition].m_dwFlags & UNDO_BEGINGROUP) != 0);
    }

  //  Advance to next undo group
  nPosition--;
  while ((m_aUndoBuf[nPosition].m_dwFlags & UNDO_BEGINGROUP) == 0)
    nPosition--;

  //  Read description
  if (!GetActionDescription (m_aUndoBuf[nPosition].m_nAction, desc))
    desc.Empty ();              //  Use empty string as description

  //  Now, if we stop at zero position, this will be the last action,
  //  since we return (POSITION) nPosition
  return (POSITION) nPosition;
}

POSITION CCrystalTextBuffer::
GetRedoDescription (CString & desc, POSITION pos /*= NULL*/ )
{
  ASSERT (CanRedo ());          //  Please call CanRedo() before!

  ASSERT ((m_aUndoBuf[0].m_dwFlags & UNDO_BEGINGROUP) != 0);
  ASSERT ((m_aUndoBuf[m_nUndoPosition].m_dwFlags & UNDO_BEGINGROUP) != 0);

  int nPosition;
  if (pos == NULL)
    {
      //  Start from beginning
      nPosition = m_nUndoPosition;
    }
  else
    {
      nPosition = (int) pos;
      ASSERT (nPosition > m_nUndoPosition);
      ASSERT ((m_aUndoBuf[nPosition].m_dwFlags & UNDO_BEGINGROUP) != 0);
    }

  //  Read description
  if (!GetActionDescription (m_aUndoBuf[nPosition].m_nAction, desc))
    desc.Empty ();              //  Use empty string as description

  //  Advance to next undo group
  nPosition++;
  while (nPosition < m_aUndoBuf.GetSize () &&
        (m_aUndoBuf[nPosition].m_dwFlags & UNDO_BEGINGROUP) == 0)
    nPosition--;

  if (nPosition >= m_aUndoBuf.GetSize ())
    return NULL;                //  No more redo actions!

  return (POSITION) nPosition;
}

BOOL CCrystalTextBuffer::
Undo (CPoint & ptCursorPos)
{
  ASSERT (CanUndo ());
  ASSERT ((m_aUndoBuf[0].m_dwFlags & UNDO_BEGINGROUP) != 0);
  for (;;)
    {
      m_nUndoPosition--;
      const SUndoRecord & ur = m_aUndoBuf[m_nUndoPosition];
      if (ur.m_dwFlags & UNDO_INSERT)
        {
#ifdef _ADVANCED_BUGCHECK
          //  Try to ensure that we undoing correctly...
          //  Just compare the text as it was before Undo operation
          CString text;
          GetText (ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.m_ptEndPos.y, ur.m_ptEndPos.x, text);
          ASSERT (lstrcmp (text, ur.GetText ()) == 0);
#endif
          VERIFY (InternalDeleteText (NULL, ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.m_ptEndPos.y, ur.m_ptEndPos.x));
          ptCursorPos = ur.m_ptStartPos;
        }
      else
        {
          int nEndLine, nEndChar;
          VERIFY (InternalInsertText (NULL, ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.GetText (), nEndLine, nEndChar));
#ifdef _ADVANCED_BUGCHECK
          ASSERT (ur.m_ptEndPos.y == nEndLine);
          ASSERT (ur.m_ptEndPos.x == nEndChar);
#endif
          ptCursorPos = ur.m_ptEndPos;
        }
      if (ur.m_dwFlags & UNDO_BEGINGROUP)
        break;
    }
  if (m_bModified && m_nSyncPosition == m_nUndoPosition)
    SetModified (FALSE);
  if (!m_bModified && m_nSyncPosition != m_nUndoPosition)
    SetModified (TRUE);
  return TRUE;
}

BOOL CCrystalTextBuffer::
Redo (CPoint & ptCursorPos)
{
  ASSERT (CanRedo ());
  ASSERT ((m_aUndoBuf[0].m_dwFlags & UNDO_BEGINGROUP) != 0);
  ASSERT ((m_aUndoBuf[m_nUndoPosition].m_dwFlags & UNDO_BEGINGROUP) != 0);
  for (;;)
    {
      const SUndoRecord & ur = m_aUndoBuf[m_nUndoPosition];
      if (ur.m_dwFlags & UNDO_INSERT)
        {
          int nEndLine, nEndChar;
          VERIFY (InternalInsertText (NULL, ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.GetText (), nEndLine, nEndChar));
#ifdef _ADVANCED_BUGCHECK
          ASSERT (ur.m_ptEndPos.y == nEndLine);
          ASSERT (ur.m_ptEndPos.x == nEndChar);
#endif
          ptCursorPos = ur.m_ptEndPos;
        }
      else
        {
#ifdef _ADVANCED_BUGCHECK
          CString text;
          GetText (ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.m_ptEndPos.y, ur.m_ptEndPos.x, text);
          ASSERT (lstrcmp (text, ur.GetText ()) == 0);
#endif
          VERIFY (InternalDeleteText (NULL, ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.m_ptEndPos.y, ur.m_ptEndPos.x));
          ptCursorPos = ur.m_ptStartPos;
        }
      m_nUndoPosition++;
      if (m_nUndoPosition == m_aUndoBuf.GetSize ())
        break;
      if ((m_aUndoBuf[m_nUndoPosition].m_dwFlags & UNDO_BEGINGROUP) != 0)
        break;
    }
  if (m_bModified && m_nSyncPosition == m_nUndoPosition)
    SetModified (FALSE);
  if (!m_bModified && m_nSyncPosition != m_nUndoPosition)
    SetModified (TRUE);
  return TRUE;
}

//  [JRT] Support For Descriptions On Undo/Redo Actions
void CCrystalTextBuffer::
AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos, LPCTSTR pszText, int nActionType)
{
  //  Forgot to call BeginUndoGroup()?
  ASSERT (m_bUndoGroup);
  ASSERT (m_aUndoBuf.GetSize () == 0 || (m_aUndoBuf[0].m_dwFlags & UNDO_BEGINGROUP) != 0);

  //  Strip unnecessary undo records (edit after undo)
  int nBufSize = m_aUndoBuf.GetSize ();
  if (m_nUndoPosition < nBufSize)
    {
      for (int I = m_nUndoPosition; I < nBufSize; I++)
        m_aUndoBuf[I].FreeText ();
      m_aUndoBuf.SetSize (m_nUndoPosition);
    }

  //  If undo buffer size is close to critical, remove the oldest records
  ASSERT (m_aUndoBuf.GetSize () <= m_nUndoBufSize);
  nBufSize = m_aUndoBuf.GetSize ();
  if (nBufSize >= m_nUndoBufSize)
    {
      int nIndex = 0;
      for (;;)
        {
          m_aUndoBuf[nIndex].FreeText ();
          nIndex++;
          if (nIndex == nBufSize || (m_aUndoBuf[nIndex].m_dwFlags & UNDO_BEGINGROUP) != 0)
            break;
        }
      m_aUndoBuf.RemoveAt (0, nIndex);
    }
  ASSERT (m_aUndoBuf.GetSize () < m_nUndoBufSize);

  //  Add new record
  SUndoRecord ur;
  ur.m_dwFlags = bInsert ? UNDO_INSERT : 0;
  ur.m_nAction = nActionType;
  if (m_bUndoBeginGroup)
    {
      ur.m_dwFlags |= UNDO_BEGINGROUP;
      m_bUndoBeginGroup = FALSE;
    }
  ur.m_ptStartPos = ptStartPos;
  ur.m_ptEndPos = ptEndPos;
  ur.SetText (pszText);

  m_aUndoBuf.Add (ur);
  m_nUndoPosition = m_aUndoBuf.GetSize ();

  ASSERT (m_aUndoBuf.GetSize () <= m_nUndoBufSize);
}

BOOL CCrystalTextBuffer::
InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText,
            int &nEndLine, int &nEndChar, int nAction)
{
  if (!InternalInsertText (pSource, nLine, nPos, pszText, nEndLine, nEndChar))
    return FALSE;

  BOOL bGroupFlag = FALSE;
  if (!m_bUndoGroup)
    {
      BeginUndoGroup ();
      bGroupFlag = TRUE;
    }
  AddUndoRecord (TRUE, CPoint (nPos, nLine), CPoint (nEndChar, nEndLine), pszText, nAction);
  if (bGroupFlag)
    FlushUndoGroup (pSource);
  return TRUE;
}

BOOL CCrystalTextBuffer::
DeleteText (CCrystalTextView * pSource, int nStartLine, int nStartChar,
            int nEndLine, int nEndChar, int nAction)
{
  CString sTextToDelete;
  GetText (nStartLine, nStartChar, nEndLine, nEndChar, sTextToDelete);

  if (!InternalDeleteText (pSource, nStartLine, nStartChar, nEndLine, nEndChar))
    return FALSE;

  BOOL bGroupFlag = FALSE;
  if (!m_bUndoGroup)
    {
      BeginUndoGroup ();
      bGroupFlag = TRUE;
    }
  AddUndoRecord (FALSE, CPoint (nStartChar, nStartLine), CPoint (nEndChar, nEndLine), sTextToDelete, nAction);
  if (bGroupFlag)
    FlushUndoGroup (pSource);
  return TRUE;
}

BOOL CCrystalTextBuffer::
GetActionDescription (int nAction, CString & desc)
{
  HINSTANCE hOldResHandle = AfxGetResourceHandle ();
#ifdef CRYSEDIT_RES_HANDLE
  AfxSetResourceHandle (CRYSEDIT_RES_HANDLE);
#else
  if (CCrystalTextView::s_hResourceInst != NULL)
    AfxSetResourceHandle (CCrystalTextView::s_hResourceInst);
#endif
  BOOL bSuccess = FALSE;
  switch (nAction)
    {
    case CE_ACTION_PASTE:
      bSuccess = desc.LoadString (IDS_EDITOP_PASTE);
      break;
    case CE_ACTION_DELSEL:
      bSuccess = desc.LoadString (IDS_EDITOP_DELSELECTION);
      break;
    case CE_ACTION_CUT:
      bSuccess = desc.LoadString (IDS_EDITOP_CUT);
      break;
    case CE_ACTION_TYPING:
      bSuccess = desc.LoadString (IDS_EDITOP_TYPING);
      break;
    case CE_ACTION_BACKSPACE:
      bSuccess = desc.LoadString (IDS_EDITOP_BACKSPACE);
      break;
    case CE_ACTION_INDENT:
      bSuccess = desc.LoadString (IDS_EDITOP_INDENT);
      break;
    case CE_ACTION_DRAGDROP:
      bSuccess = desc.LoadString (IDS_EDITOP_DRAGDROP);
      break;
    case CE_ACTION_REPLACE:
      bSuccess = desc.LoadString (IDS_EDITOP_REPLACE);
      break;
    case CE_ACTION_DELETE:
      bSuccess = desc.LoadString (IDS_EDITOP_DELETE);
      break;
    case CE_ACTION_AUTOINDENT:
      bSuccess = desc.LoadString (IDS_EDITOP_AUTOINDENT);
      break;
    case CE_ACTION_AUTOCOMPLETE:
      bSuccess = desc.LoadString (IDS_EDITOP_AUTOCOMPLETE);
      break;
    case CE_ACTION_AUTOEXPAND:
      bSuccess = desc.LoadString (IDS_EDITOP_AUTOEXPAND);
      break;
    case CE_ACTION_LOWERCASE:
      bSuccess = desc.LoadString (IDS_EDITOP_LOWERCASE);
      break;
    case CE_ACTION_UPPERCASE:
      bSuccess = desc.LoadString (IDS_EDITOP_UPPERCASE);
      break;
    case CE_ACTION_SWAPCASE:
      bSuccess = desc.LoadString (IDS_EDITOP_SWAPCASE);
      break;
    case CE_ACTION_CAPITALIZE:
      bSuccess = desc.LoadString (IDS_EDITOP_CAPITALIZE);
      break;
    case CE_ACTION_SENTENCIZE:
      bSuccess = desc.LoadString (IDS_EDITOP_SENTENCIZE);
      break;
    case CE_ACTION_RECODE:
      bSuccess = desc.LoadString (IDS_EDITOP_RECODE);
      break;
    case CE_ACTION_SPELL:
      bSuccess = desc.LoadString (IDS_EDITOP_SPELL);
      break;
    default: /* case CE_ACTION_UNKNOWN: */
      bSuccess = desc.LoadString (IDS_EDITOP_UNKNOWN);
    }
  AfxSetResourceHandle (hOldResHandle);
  return bSuccess;
}

void CCrystalTextBuffer::
SetModified (BOOL bModified /*= TRUE*/ )
{
  m_bModified = bModified;
}

void CCrystalTextBuffer::
BeginUndoGroup (BOOL bMergeWithPrevious /*= FALSE*/ )
{
  ASSERT (!m_bUndoGroup);
  m_bUndoGroup = TRUE;
  m_bUndoBeginGroup = m_nUndoPosition == 0 || !bMergeWithPrevious;
}

void CCrystalTextBuffer::
FlushUndoGroup (CCrystalTextView * pSource)
{
  ASSERT (m_bUndoGroup);
  if (pSource != NULL)
    {
      ASSERT (m_nUndoPosition == m_aUndoBuf.GetSize ());
      if (m_nUndoPosition > 0)
        {
          m_bUndoBeginGroup = TRUE;
          pSource->OnEditOperation (m_aUndoBuf[m_nUndoPosition - 1].m_nAction, m_aUndoBuf[m_nUndoPosition - 1].GetText ());
        }
    }
  m_bUndoGroup = FALSE;
}

int CCrystalTextBuffer::
FindNextBookmarkLine (int nCurrentLine)
{
  BOOL bWrapIt = TRUE;
  DWORD dwFlags = GetLineFlags (nCurrentLine);
  if ((dwFlags & LF_BOOKMARKS) != 0)
    nCurrentLine++;

  int nSize = m_aLines.GetSize ();
  for (;;)
    {
      while (nCurrentLine < nSize)
        {
          if ((m_aLines[nCurrentLine].m_dwFlags & LF_BOOKMARKS) != 0)
            return nCurrentLine;
          // Keep going
          nCurrentLine++;
        }
      // End of text reached
      if (!bWrapIt)
        return -1;

      // Start from the beginning of text
      bWrapIt = FALSE;
      nCurrentLine = 0;
    }
  return -1;
}

int CCrystalTextBuffer::
FindPrevBookmarkLine (int nCurrentLine)
{
  BOOL bWrapIt = TRUE;
  DWORD dwFlags = GetLineFlags (nCurrentLine);
  if ((dwFlags & LF_BOOKMARKS) != 0)
    nCurrentLine--;

  int nSize = m_aLines.GetSize ();
  for (;;)
    {
      while (nCurrentLine >= 0)
        {
          if ((m_aLines[nCurrentLine].m_dwFlags & LF_BOOKMARKS) != 0)
            return nCurrentLine;
          // Keep moving up
          nCurrentLine--;
        }
      // Beginning of text reached
      if (!bWrapIt)
        return -1;

      // Start from the end of text
      bWrapIt = FALSE;
      nCurrentLine = nSize - 1;
    }
  return -1;
}

BOOL CCrystalTextBuffer::
IsMBSLead (int nLine, int nCol)
{
  ASSERT (m_bInit);             //  Text buffer not yet initialized.
  //  You must call InitNew() or LoadFromFile() first!

#ifdef _UNICODE
  LPCTSTR string = (LPCTSTR) GetLineChars (nLine);
  LPCTSTR current = string + nCol;
  return FALSE;
#else // _UNICODE
  const unsigned char *string = (const unsigned char *) GetLineChars (nLine);
  const unsigned char *current = string + nCol;
  if (_ismbslead (string, current) < 0)
    return TRUE;
  return FALSE;
#endif // _UNICODE
}

BOOL CCrystalTextBuffer::
IsMBSTrail (int nLine, int nCol)
{
  ASSERT (m_bInit);             //  Text buffer not yet initialized.
  //  You must call InitNew() or LoadFromFile() first!

#ifdef _UNICODE
  LPCTSTR string = (LPCTSTR) GetLineChars (nLine);
  LPCTSTR current = string + nCol;
  return FALSE;
#else // _UNICODE
  const unsigned char *string = (const unsigned char *) GetLineChars (nLine);
  const unsigned char *current = string + nCol;
  if (_ismbstrail (string, current) < 0)
    return TRUE;
  return FALSE;
#endif // _UNICODE
}

//BEGIN SW
CPoint CCrystalTextBuffer::GetLastChangePos() const
{
	return m_ptLastChange;
}
//END SW

⌨️ 快捷键说明

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