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

📄 ccrystaltextbuffer.cpp

📁 一个完整的编辑器的代码(很值得参考
💻 CPP
📖 第 1 页 / 共 3 页
字号:
////////////////////////////////////////////////////////////////////////////
//  File:       ccrystaltextbuffer.cpp
//  Version:    1.0.0.0
//  Created:    29-Dec-1998
//
//  Author:     Stcherbatchenko Andrei
//  E-mail:     windfall@gmx.de
//
//  Implementation of the CCrystalTextBuffer class, a part of Crystal Edit -
//  syntax coloring text editor.
//
//  You are free to use or modify this code to the following restrictions:
//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
//  will be enough. If you can't (or don't want to), contact me personally.
//  - LEAVE THIS HEADER INTACT
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
//  17-Feb-99
//  +   FIX: unnecessary 'HANDLE' in CCrystalTextBuffer::SaveToFile
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
//  21-Feb-99
//      Paul Selormey, James R. Twine:
//  +   FEATURE: description for Undo/Redo actions
//  +   FEATURE: multiple MSVC-like bookmarks
//  +   FEATURE: 'Disable backspace at beginning of line' option
//  +   FEATURE: 'Disable drag-n-drop editing' option
//
//  +   FEATURE: changed layout of SUndoRecord. Now takes less memory
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
//  19-Jul-99
//      Ferdinand Prantl:
//  +   FEATURE: some other things I've forgotten ...
//
//  ... it's being edited very rapidly so sorry for non-commented
//        and maybe "ugly" code ...
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
//	??-Aug-99
//		Sven Wiegand (search for "//BEGIN SW" to find my changes):
//	+ FEATURE: Remembering the text-position of the latest change.
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
//	24-Oct-99
//		Sven Wiegand
//	+ FIX: Setting m_ptLastChange to the beginning of the selection in
//		     InternalDeleteText(), so that position is valid in any case.
//		     Editor won't crash any more i.e. by selecting whole buffer and
//		     deleting it and then executing ID_EDIT_GOTO_LAST_CHANGE-command.
////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <malloc.h>
#include "editcmd.h"
#include "ccrystaltextbuffer.h"
#include "ccrystaltextview.h"
#include "filesup.h"
#include "cs2cs.h"

#ifndef __AFXPRIV_H__
#pragma message("Include <afxpriv.h> in your stdafx.h to avoid this message")
#include <afxpriv.h>
#endif

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//  Line allocation granularity
#define     CHAR_ALIGN                  16
#define     ALIGN_BUF_SIZE(size)        ((size) / CHAR_ALIGN) * CHAR_ALIGN + CHAR_ALIGN;

#define     UNDO_BUF_SIZE               1024

const TCHAR crlf[] = _T ("\r\n");

#ifdef _DEBUG
#define _ADVANCED_BUGCHECK  1
#endif

int CCrystalTextBuffer::m_nDefaultEncoding = -1;

/////////////////////////////////////////////////////////////////////////////
// CCrystalTextBuffer::SUndoRecord

void CCrystalTextBuffer::SUndoRecord::
SetText (LPCTSTR pszText)
{
  m_pszText = NULL;
  if (pszText != NULL && pszText[0] != _T ('\0'))
    {
      int nLength = _tcslen (pszText);
      if (nLength > 1)
        {
          m_pszText = new TCHAR[(nLength + 1) * sizeof (TCHAR)];
          _tcscpy (m_pszText, pszText);
        }
      else
        {
          m_szText[0] = pszText[0];
        }
    }
}

void CCrystalTextBuffer::SUndoRecord::
FreeText ()
{
  if (HIWORD ((DWORD) m_pszText) != 0)
    delete m_pszText;
}


/////////////////////////////////////////////////////////////////////////////
// CCrystalTextBuffer::CUpdateContext

void CCrystalTextBuffer::CInsertContext::
RecalcPoint (CPoint & ptPoint)
{
  ASSERT (m_ptEnd.y > m_ptStart.y ||
          m_ptEnd.y == m_ptStart.y && m_ptEnd.x >= m_ptStart.x);
  if (ptPoint.y < m_ptStart.y)
    return;
  if (ptPoint.y > m_ptStart.y)
    {
      ptPoint.y += (m_ptEnd.y - m_ptStart.y);
      return;
    }
  if (ptPoint.x <= m_ptStart.x)
    return;
  ptPoint.y += (m_ptEnd.y - m_ptStart.y);
  ptPoint.x = m_ptEnd.x + (ptPoint.x - m_ptStart.x);
}

void CCrystalTextBuffer::CDeleteContext::
RecalcPoint (CPoint & ptPoint)
{
  ASSERT (m_ptEnd.y > m_ptStart.y ||
          m_ptEnd.y == m_ptStart.y && m_ptEnd.x >= m_ptStart.x);
  if (ptPoint.y < m_ptStart.y)
    return;
  if (ptPoint.y > m_ptEnd.y)
    {
      ptPoint.y -= (m_ptEnd.y - m_ptStart.y);
      return;
    }
  if (ptPoint.y == m_ptEnd.y && ptPoint.x >= m_ptEnd.x)
    {
      ptPoint.y = m_ptStart.y;
      ptPoint.x = m_ptStart.x + (ptPoint.x - m_ptEnd.x);
      return;
    }
  if (ptPoint.y == m_ptStart.y)
    {
      if (ptPoint.x > m_ptStart.x)
        ptPoint.x = m_ptStart.x;
      return;
    }
  ptPoint = m_ptStart;
}


/////////////////////////////////////////////////////////////////////////////
// CCrystalTextBuffer

IMPLEMENT_DYNCREATE (CCrystalTextBuffer, CCmdTarget)

CCrystalTextBuffer::CCrystalTextBuffer ()
{
  m_bInit = FALSE;
  m_bReadOnly = FALSE;
  m_bModified = FALSE;
  m_bCreateBackupFile = FALSE;
  m_nUndoPosition = 0;
	//BEGIN SW
	m_ptLastChange.x = m_ptLastChange.y = -1;
	//END SW
  m_nSourceEncoding = m_nDefaultEncoding;
}

CCrystalTextBuffer:: ~ CCrystalTextBuffer ()
{
  ASSERT (!m_bInit);            //  You must call FreeAll() before deleting the object
}


BEGIN_MESSAGE_MAP (CCrystalTextBuffer, CCmdTarget)
//{{AFX_MSG_MAP(CCrystalTextBuffer)
//}}AFX_MSG_MAP
END_MESSAGE_MAP ()


/////////////////////////////////////////////////////////////////////////////
// CCrystalTextBuffer message handlers

void CCrystalTextBuffer::InsertLine (LPCTSTR pszLine, int nLength /*= -1*/ , int nPosition /*= -1*/ )
{
  if (nLength == -1)
    {
      if (pszLine == NULL)
        nLength = 0;
      else
        nLength = _tcslen (pszLine);
    }

  SLineInfo li;
  li.m_nLength = nLength;
  li.m_nMax = ALIGN_BUF_SIZE (li.m_nLength);
  ASSERT (li.m_nMax >= li.m_nLength);
  if (li.m_nMax > 0)
    li.m_pcLine = new TCHAR[li.m_nMax];
  if (li.m_nLength > 0)
    memcpy (li.m_pcLine, pszLine, sizeof (TCHAR) * li.m_nLength);

  if (nPosition == -1)
    m_aLines.Add (li);
  else
    m_aLines.InsertAt (nPosition, li);

#ifdef _DEBUG
  int nLines = m_aLines.GetSize ();
  if (nLines % 5000 == 0)
    TRACE1 ("%d lines loaded!\n", nLines);
#endif
}

void CCrystalTextBuffer::
AppendLine (int nLineIndex, LPCTSTR pszChars, int nLength /*= -1*/ )
{
  if (nLength == -1)
    {
      if (pszChars == NULL)
        return;
      nLength = _tcslen (pszChars);
    }

  if (nLength == 0)
    return;

  register SLineInfo & li = m_aLines[nLineIndex];
  int nBufNeeded = li.m_nLength + nLength;
  if (nBufNeeded > li.m_nMax)
    {
      li.m_nMax = ALIGN_BUF_SIZE (nBufNeeded);
      ASSERT (li.m_nMax >= li.m_nLength + nLength);
      TCHAR *pcNewBuf = new TCHAR[li.m_nMax];
      if (li.m_nLength > 0)
        memcpy (pcNewBuf, li.m_pcLine, sizeof (TCHAR) * li.m_nLength);
      delete li.m_pcLine;
      li.m_pcLine = pcNewBuf;
    }
  memcpy (li.m_pcLine + li.m_nLength, pszChars, sizeof (TCHAR) * nLength);
  li.m_nLength += nLength;
  ASSERT (li.m_nLength <= li.m_nMax);
}

void CCrystalTextBuffer::
FreeAll ()
{
  //  Free text
  int nCount = m_aLines.GetSize ();
  for (int I = 0; I < nCount; I++)
    {
      if (m_aLines[I].m_nMax > 0)
        delete m_aLines[I].m_pcLine;
    }
  m_aLines.RemoveAll ();

  //  Free undo buffer
  int nBufSize = m_aUndoBuf.GetSize ();
  for (I = 0; I < nBufSize; I++)
    m_aUndoBuf[I].FreeText ();
  m_aUndoBuf.RemoveAll ();

  m_bInit = FALSE;
	//BEGIN SW
	m_ptLastChange.x = m_ptLastChange.y = -1;
	//END SW
}

BOOL CCrystalTextBuffer::
InitNew (int nCrlfStyle /*= CRLF_STYLE_DOS*/ )
{
  ASSERT (!m_bInit);
  ASSERT (m_aLines.GetSize () == 0);
  ASSERT (nCrlfStyle >= 0 && nCrlfStyle <= 2);
  InsertLine (_T (""));
  m_bInit = TRUE;
  m_bReadOnly = FALSE;
  m_nCRLFMode = nCrlfStyle;
  m_bModified = FALSE;
  m_nSyncPosition = m_nUndoPosition = 0;
  m_bUndoGroup = m_bUndoBeginGroup = FALSE;
  m_nUndoBufSize = UNDO_BUF_SIZE;
  ASSERT (m_aUndoBuf.GetSize () == 0);
  UpdateViews (NULL, NULL, UPDATE_RESET);
	//BEGIN SW
	m_ptLastChange.x = m_ptLastChange.y = -1;
	//END SW
  return TRUE;
}

BOOL CCrystalTextBuffer::
GetReadOnly ()
const
{
  ASSERT (m_bInit);        //  Text buffer not yet initialized.
  //  You must call InitNew() or LoadFromFile() first!

  return m_bReadOnly;
}

void CCrystalTextBuffer::SetReadOnly (BOOL bReadOnly /*= TRUE*/ )
{
  ASSERT (m_bInit);             //  Text buffer not yet initialized.
  //  You must call InitNew() or LoadFromFile() first!

  m_bReadOnly = bReadOnly;
}

static LPCTSTR crlfs[] =
  {
    _T ("\x0d\x0a"), //  DOS/Windows style
    _T ("\x0a"),     //  UNIX style
    _T ("\x0a")      //  Macintosh style
  };

BOOL CCrystalTextBuffer::
LoadFromFile (LPCTSTR pszFileName, int nCrlfStyle /*= CRLF_STYLE_AUTOMATIC*/ )
{
  ASSERT (!m_bInit);
  ASSERT (m_aLines.GetSize () == 0);

  HANDLE hFile = NULL;
  int nCurrentMax = 256;
  LPTSTR pcLineBuf = new TCHAR[nCurrentMax];

  BOOL bSuccess = FALSE;

  int nExt = GetExtPosition (pszFileName);
  if (pszFileName[nExt] == _T ('.'))
    nExt++;
  CCrystalTextView::TextDefinition *def = CCrystalTextView::GetTextType (pszFileName + nExt);
  if (def && def->encoding != -1)
    m_nSourceEncoding = def->encoding;

  __try
  {
    DWORD dwFileAttributes =::GetFileAttributes (pszFileName);
    if (dwFileAttributes == (DWORD) - 1)
      __leave;

      hFile =::CreateFile (pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
      if (hFile == INVALID_HANDLE_VALUE)
        __leave;

        int nCurrentLength = 0;

        const DWORD dwBufSize = 32768;
        LPTSTR pcBuf = (LPTSTR) _alloca (dwBufSize);
        DWORD dwCurSize;
        if (!::ReadFile (hFile, pcBuf, dwBufSize, &dwCurSize, NULL))
          __leave;

          if (nCrlfStyle == CRLF_STYLE_AUTOMATIC)
            {
              //  Try to determine current CRLF mode
              for (DWORD I = 0; I < dwCurSize; I++)
                {
                  if ((pcBuf[I] == _T('\x0d')) || (pcBuf[I] == _T('\x0a')))
                    break;
                }
              if (I == dwCurSize)
                {
                  //  By default (or in the case of empty file), set DOS style
                  nCrlfStyle = CRLF_STYLE_DOS;
                }
              else
                {
                  //  Otherwise, analyse the first occurance of line-feed character
                  if (pcBuf[I] == _T('\x0a'))
                    {
                      nCrlfStyle = CRLF_STYLE_UNIX;
                    }
                  else
                    {
                      if (I < dwCurSize - 1 && pcBuf[I + 1] == _T ('\x0a'))
                        nCrlfStyle = CRLF_STYLE_DOS;
                      else
                        nCrlfStyle = CRLF_STYLE_MAC;
                    }
                }
            }

    ASSERT (nCrlfStyle >= 0 && nCrlfStyle <= 2);
    m_nCRLFMode = nCrlfStyle;
    LPCTSTR crlf = crlfs[nCrlfStyle];

    m_aLines.SetSize (0, 4096);

    DWORD dwBufPtr = 0;
    int nCrlfPtr = 0;
    while (dwBufPtr < dwCurSize)
      {
        int c = pcBuf[dwBufPtr];
        dwBufPtr++;
        if (dwBufPtr == dwCurSize && dwCurSize == dwBufSize)
          {
            if (!::ReadFile (hFile, pcBuf, dwBufSize, &dwCurSize, NULL))
              __leave;
            dwBufPtr = 0;
          }

        pcLineBuf[nCurrentLength] = (TCHAR) c;
        nCurrentLength++;
        if (nCurrentLength == nCurrentMax)
          {
            //  Reallocate line buffer
            nCurrentMax += 256;
            LPTSTR pcNewBuf = new TCHAR[nCurrentMax];
            memcpy (pcNewBuf, pcLineBuf, nCurrentLength);
            delete pcLineBuf;
            pcLineBuf = pcNewBuf;
          }

        if ((TCHAR) c == crlf[nCrlfPtr])
          {
            nCrlfPtr++;
            if (crlf[nCrlfPtr] == 0)
              {
                pcLineBuf[nCurrentLength - nCrlfPtr] = 0;
                if (m_nSourceEncoding >= 0)
                  iconvert (pcLineBuf, m_nSourceEncoding, 1, m_nSourceEncoding == 15);
                InsertLine (pcLineBuf);
                nCurrentLength = 0;
                nCrlfPtr = 0;
              }
          }
        else
          nCrlfPtr = 0;
      }

    pcLineBuf[nCurrentLength] = 0;
    InsertLine (pcLineBuf);

    ASSERT (m_aLines.GetSize () > 0);   //  At least one empty line must present

    m_bInit = TRUE;
    m_bReadOnly = (dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0;
    m_bModified = FALSE;
    m_bUndoGroup = m_bUndoBeginGroup = FALSE;
    m_nUndoBufSize = UNDO_BUF_SIZE;
    m_nSyncPosition = m_nUndoPosition = 0;
    ASSERT (m_aUndoBuf.GetSize () == 0);
    bSuccess = TRUE;

    RetypeViews (pszFileName);
    UpdateViews (NULL, NULL, UPDATE_RESET);
  }
  __finally
  {
    if (pcLineBuf != NULL)
      delete pcLineBuf;
      if (hFile != NULL)
        ::CloseHandle (hFile);
      }
	//BEGIN SW
	m_ptLastChange.x = m_ptLastChange.y = -1;
	//END SW
  return bSuccess;
}

BOOL CCrystalTextBuffer::
SaveToFile (LPCTSTR pszFileName, int nCrlfStyle /*= CRLF_STYLE_AUTOMATIC*/ , BOOL bClearModifiedFlag /*= TRUE*/ )
{
  ASSERT (nCrlfStyle == CRLF_STYLE_AUTOMATIC || nCrlfStyle == CRLF_STYLE_DOS ||
          nCrlfStyle == CRLF_STYLE_UNIX || nCrlfStyle == CRLF_STYLE_MAC);
  ASSERT (m_bInit);
  HANDLE hTempFile = INVALID_HANDLE_VALUE;
  HANDLE hSearch = INVALID_HANDLE_VALUE;
  TCHAR szTempFileDir[_MAX_PATH + 1];
  TCHAR szTempFileName[_MAX_PATH + 1];
  TCHAR szBackupFileName[_MAX_PATH + 1];
  BOOL bSuccess = FALSE;
  __try
  {
    TCHAR drive[_MAX_PATH], dir[_MAX_PATH], name[_MAX_PATH], ext[_MAX_PATH];
#ifdef _UNICODE

⌨️ 快捷键说明

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