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

📄 textview.cpp

📁 一个完全使用MFC框架开发的C++编译器的代码。功能十分强大可以编译大型程序。
💻 CPP
字号:
// TextView.cpp : implementation file
//

#include "stdafx.h"
#include "Quincy.h"
#include "debugger.h"
#include "TextView.h"
#include "QuincyView.h"
#include "TextDocument.h"
#include "Compiler.h"

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

/////////////////////////////////////////////////////////////////////////////
// CTextView

static const int margin = 1;				// margin for breakpoint and program counter carets
static const char breakpointchar = '>';		// breakpoint margin displaycharacter

IMPLEMENT_DYNCREATE(CTextView, CEditorView)

CTextView::CTextView()
{
}

CTextView::~CTextView()
{
}

BEGIN_MESSAGE_MAP(CTextView, CEditorView)
	//{{AFX_MSG_MAP(CTextView)
	ON_COMMAND(ID_BUILD, OnBuild)
	ON_COMMAND(ID_BUILDALL, OnBuildall)
	ON_COMMAND(ID_COMPILE, OnCompile)
	ON_COMMAND(ID_EXECUTE, OnRun)
	ON_COMMAND(ID_DEBUG_BREAKPOINT, OnDebugBreakpoint)
	ON_COMMAND(ID_DEBUG_STEP, OnDebugStep)
	ON_COMMAND(ID_DEBUG_STEPTOCURSOR, OnDebugSteptocursor)
	ON_UPDATE_COMMAND_UI(ID_BUILD, OnUpdateBuild)
	ON_UPDATE_COMMAND_UI(ID_BUILDALL, OnUpdateBuildAll)
	ON_UPDATE_COMMAND_UI(ID_COMPILE, OnUpdateCompile)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_ALL, OnUpdateFileSaveAll)
	ON_COMMAND(ID_DEBUG_STEPOUTOFFUNCTION, OnDebugStepoutoffunction)
	ON_WM_CHAR()
	ON_WM_TIMER()
	ON_WM_LBUTTONDBLCLK()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTextView diagnostics

#ifdef _DEBUG
void CTextView::AssertValid() const
{
	CEditorView::AssertValid();
}

void CTextView::Dump(CDumpContext& dc) const
{
	CEditorView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CTextView message handlers


void CTextView::OnBuildall() 
{
	// ----- if a project document is open, send build command to its view
	CQuincyView* pView = theApp.GetProjectView();
	if (pView != 0)
		pView->SendMessage(WM_COMMAND, ID_BUILDALL, 0);
}

void CTextView::OnBuild() 
{
	// ----- if a project document is open, send build command to its view
	CQuincyView* pView = theApp.GetProjectView();
	if (pView != 0)
		pView->SendMessage(WM_COMMAND, ID_BUILD, 0);
	else
		DoCompile(true, false);
}

bool CTextView::DoCompile(bool bDoLink, bool bDoExecute, bool bDoStep) 
{
	CDocument* pDoc = GetDocument();
	ASSERT(pDoc != 0);

	CString& rstrPath = const_cast<CString&>(pDoc->GetPathName());
	if (pDoc->IsModified())
		pDoc->OnSaveDocument(rstrPath);

	theApp.SaveAllDocuments(true);

	// ----- make a copy of the file spec without the extension;
	bool isCpp = rstrPath.Right(4).CompareNoCase(".cpp") == 0;
	CString strSpec = rstrPath.Left(rstrPath.GetLength()-(isCpp ? 4 : 2));

	CString strExeSpec = strSpec + ".exe";

	// ---- queue the source and object files for compile/link
	theApp.GetCompiler().ClearArrays();
	theApp.GetCompiler().AddSourceFile(rstrPath);
	if (bDoLink)
		theApp.GetCompiler().AddObjectFile(theApp.GetCompiler().MakeObjectFileName(strSpec));
	theApp.GetCompiler().ClearErrorLog();
	theApp.GetCompiler().BuildTarget(strExeSpec, 
		(bDoExecute ? (bDoStep ? Compiler::step : Compiler::run) : Compiler::none));

	return true;
}

void CTextView::OnCompile()
{
	DoCompile(false, false);
}

void CTextView::OnDebugStep() 
{
	// ----- if a project document is open, send step command to its view
	CQuincyView* pView = theApp.GetProjectView();
	if (pView != 0)
		pView->PostMessage(WM_COMMAND, ID_DEBUG_STEP, 0);
	else if (!theApp.StepProgram())
		if (!BuildIfNeeded(true))
			theApp.DebugProgram(m_strExe, true);
}

void CTextView::OnDebugStepoutoffunction() 
{
	theApp.StepOut();
}

void CTextView::OnRun() 
{
	// ----- if a project document is open, send execute command to its view
	CQuincyView* pView = theApp.GetProjectView();
	if (pView != 0)
		pView->DoRun();
	else if (!theApp.ExecuteRunningProgram())
		if (!BuildIfNeeded(false))
			theApp.StartProgram(m_strExe);
}

// --- returns true if build is started meaning delay the execution
//     also returns true if no exe and user opts not to build, meaning no execution
//     otherwise returns false meaning execution may proceed
bool CTextView::BuildIfNeeded(bool bStep)
{
	CDocument* pDoc = GetDocument();
	ASSERT(pDoc != 0);
	CString& rstrPath = const_cast<CString&>(pDoc->GetPathName());
	// ----- make a copy of the file spec with the .EXE extension;
	bool isCpp = rstrPath.Right(4).CompareNoCase(".cpp") == 0;
	m_strExe = rstrPath.Left(rstrPath.GetLength()-(isCpp ? 4 : 2)) + ".exe";
	int rtn;
	if (_access(m_strExe, 0) != 0)	{
		CString strMsg = theApp.GetFileName(m_strExe) + " does not exist. Build?";
		if (AfxMessageBox(strMsg, MB_YESNO | MB_ICONQUESTION) == IDYES)
			DoCompile(true, true, bStep);
		return true;
	}
	if (pDoc->IsModified())	{
		CString strMsg = theApp.GetFileName(rstrPath) + " has been modified. Build?";
		if ((rtn = AfxMessageBox(strMsg, MB_YESNOCANCEL | MB_ICONQUESTION)) == IDYES)	{
			DoCompile(true, true, bStep);
			return true;
		}
		else if (rtn == IDCANCEL)
			return true;
	}
	else if (theApp.CompareFileTimes(rstrPath, m_strExe) > 0)	{
		CString strMsg = theApp.GetFileName(m_strExe) + " out of date. Rebuild?";
		if ((rtn = AfxMessageBox(strMsg, MB_YESNOCANCEL | MB_ICONQUESTION)) == IDYES)	{
			DoCompile(true, true, bStep);
			return true;
		}
	}
	return false;
}

// ----- return the document file specification
CString CTextView::SourceCodeFileName()
{
	CTextDocument* pDoc = (CTextDocument*)GetDocument();
	return pDoc == 0 ? CString() : pDoc->GetPathName();
}
// ----- called to set or clear a breakpoint in this source code file
void CTextView::OnDebugBreakpoint() 
{
	// ---- get the name of the source code file
	CString strFile = GetDocument()->GetPathName();
	// ----- get the current line number from the source code file
	int nLineno = CurrentLineNumber();		// current line number
	theApp.ToggleBreakpoint(strFile, nLineno);
	DrawMargins();
}
// --- write a 16 X 15 bitmap into the editor's left margin
//     nLine is the window's vertical pixel position
void CTextView::WriteMarginBitmap(int nRow, CBitmap& bm)
{
	CDC* pCDC = GetDC();

	CDC dcMem;
	dcMem.CreateCompatibleDC(pCDC);
	CBitmap* pOld = static_cast<CBitmap*>(dcMem.SelectObject(&bm));
	dcMem.SetMapMode(pCDC->GetMapMode());
	pCDC->BitBlt(0, nRow, 16, 15, &dcMem, 0, 0, SRCCOPY);
	dcMem.SelectObject(pOld);
}

// ---- compute the window's zero-based client area pixel position number
//      from the one-based text line number
inline int CTextView::RelativeRow(int nLineno)
{
	ASSERT(nLineno > 0);
	int lno = nLineno - TopLine();	// zero-based line number
	int top = TopRow() % m_fontheight;
	int y = lno * m_fontheight - top;
	return y;
}

void CTextView::OnDraw(CDC* pDC) 
{
	CEditorView::OnDraw(pDC);
	DrawMargins();
}

void CTextView::DrawMargins()
{
	PadMargin();
	// ---- get the name of the source code file
	CString strFile = theApp.GetFileName(SourceCodeFileName());
	if (strFile.IsEmpty())
		return;
	// ----- compute top and bottom lines of the client window
	int nLine = TopLine(); // one-based line number
	RECT rc;
	GetClientRect(&rc);
	int nBottomLine = nLine + rc.bottom / m_fontheight; // one-based line number

	// --- set flag if this file is the current debugged source code file
	bool bSrc = false;
	Debugger* pDebugger = theApp.GetDebugger(false);
	if (pDebugger != 0)	{
		const CString* pCurrentSrcFile = pDebugger->CurrentSrcFile();
		CString str = theApp.GetFileName(*pCurrentSrcFile);
		if (pCurrentSrcFile != 0)	{
			bSrc = strFile.CompareNoCase(str) == 0;
		}
	}
	// ---- iterate the lines, displaying 
	//      breakpoint margin carets and the program counter cursor bar
	do	{
		bool bPC = (bSrc && nLine == theApp.GetDebugger()->CurrentLineNo()) != false;
		if (theApp.IsBreakpoint(strFile, nLine))	{
			if (bPC)
				SetPCBreakpointDisplay(nLine);
			else
				SetBreakpointDisplay(nLine, true);
		}
		else if (bPC)
			SetProgramCounterDisplay(nLine, true);
	} while (nLine++ < nBottomLine);
}

// ---- set or clear a breakpoint bitmap in the margin
// ------ nLineno is the one-based file line number
void CTextView::SetBreakpointDisplay(int nLineno, bool bOnOff)
{
	int nRelativeRow = RelativeRow(nLineno);
	CBitmap bm;
	bm.LoadBitmap(bOnOff ? IDB_BITMAP4 : IDB_BITMAP3);
	WriteMarginBitmap(nRelativeRow, bm);
	bm.DeleteObject();
}
// ---- set a breakpoint and pc bitmap in the margin
// ------ nLineno is the one-based file line number
void CTextView::SetPCBreakpointDisplay(int nLineno)
{
	int nRelativeRow = RelativeRow(nLineno);
	CBitmap bm;
	bm.LoadBitmap(IDB_BITMAP5);
	WriteMarginBitmap(nRelativeRow, bm);
	bm.DeleteObject();
}
// ---- set or clear the program counter cursor in the margin
// ------ nLineno is the zero-based file line number
void CTextView::SetProgramCounterDisplay(int nLineno, bool bOnOff)
{
	int nRelativeRow = RelativeRow(nLineno);
	CBitmap bm;
	bm.LoadBitmap(bOnOff ? IDB_BITMAP2 : IDB_BITMAP3);
	WriteMarginBitmap(nRelativeRow, bm);
	bm.DeleteObject();
}

void CTextView::OnDebugSteptocursor() 
{
	if (!theApp.TestProgramChanged())	{
		int nLineNo = CurrentLineNumber();
		CString strFile = SourceCodeFileName();
		if (!theApp.StepTo(strFile, nLineNo))
			OnRun();
	}
}

void CTextView::OnUpdateBuild(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(CanBuild() && (theApp.IsProjectFileLoaded() || IsSourceFile()));
}

void CTextView::OnUpdateBuildAll(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(CanBuild() && theApp.IsProjectFileLoaded());
}

void CTextView::OnUpdateCompile(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(CanBuild() && IsSourceFile());
}

bool CTextView::CanBuild()
{
	Debugger* pDebugger = theApp.GetDebugger(false);
	return !theApp.CompileRunning() && pDebugger == 0 && theApp.CanCompile();
}
bool CTextView::IsSourceFile()
{
	CTextDocument* pDoc = (CTextDocument*)GetDocument();
	ASSERT(pDoc != 0);
	return pDoc->IsSourceFile();
}

void CTextView::OnUpdateFileSaveAll(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(true);
}

void CTextView::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	if (point.x < m_margin)
		OnDebugBreakpoint();
	else
		CEditorView::OnLButtonDblClk(nFlags, point);
}

⌨️ 快捷键说明

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