📄 tutorial.cpp
字号:
// -------- tutorial.cpp
#include "stdafx.h"
#include <ddeml.h>
#include "Quincy.h"
#include "QuincyDoc.h"
#include "TextDocument.h"
#include "WatchDialog.h"
#include "debugger.h"
#include "TutDlg.h"
#ifdef TYCPP
// ----- setup a tutorial based on the contents of a tutorial profile (.tut) file in .INI format
void CQuincyApp::ReadTutorial()
{
OnStop();
m_bReadTutorial = false;
POSITION pos = GetFirstDocTemplatePosition();
while (pos != 0) {
CDocTemplate* pTemplate = GetNextDocTemplate(pos);
POSITION dpos = pTemplate->GetFirstDocPosition();
while (dpos != 0) {
CDocument* pDoc = pTemplate->GetNextDoc(dpos);
if (pDoc->IsModified()) {
CString strTitle("Save changes to ");
strTitle += pDoc->GetTitle();
strTitle += "?";
int rtn;
if ((rtn = AfxMessageBox(strTitle, MB_YESNOCANCEL)) == IDYES) {
CString strPath = pDoc->GetPathName();
pDoc->OnSaveDocument(strPath);
}
else if (rtn == IDCANCEL)
return;
}
}
}
CloseAllDocuments(false);
theApp.CloseErrorLog();
struct _stat sbuf;
int rtn = _stat(m_strTutorial.GetBuffer(0), &sbuf);
if (rtn == -1)
AfxMessageBox("Tutorial files are corrupted", MB_ICONSTOP);
else {
// ---- compute if Quincy is reading an old .tut file with different code for command line prompt
struct tm* ptime = gmtime(& sbuf.st_mtime);
bool isoldtutorial = ptime->tm_year < 102;
CString strTutorial;
CString strProfile;
char path[MAX_PATH];
strTutorial = m_strTutorial;
GetPrivateProfileString("Documents", "Directory", "", path, MAX_PATH, strTutorial);
CString strSourcePath(path);
if (strSourcePath.IsEmpty()) {
// ------ change to the subdirectory of the .tut file
// (that's where the source code files should be)
int offset = strTutorial.ReverseFind('\\');
if (offset > 0)
strSourcePath = strTutorial.Left(offset+1);
}
if (!strSourcePath.IsEmpty())
_chdir(strSourcePath);
// ------ load the document files
int i;
int nDocct = GetPrivateProfileInt("Documents", "Docct", 0, strTutorial);
for (i = 0; i < nDocct; i++) {
strProfile.Format("Doc%02d", i + 1);
GetPrivateProfileString("Documents", strProfile, "", path, MAX_PATH, strTutorial);
if (*path) {
CString strOpenPath = strSourcePath + path;
if (OpenDocumentFile(strOpenPath))
if (nDocct == 1)
MaximizeDocument(path);
}
}
// ------ load the watches
if (m_bWatchCreated)
m_pdlgWatch->ClearWatches();
int nWatchct = GetPrivateProfileInt("Watches", "Watchct", 0, strTutorial);
if (nWatchct > 0) {
CreateWatchWindow();
m_pdlgWatch->ShowWindow(SW_SHOW);
}
else if (m_bWatchCreated)
m_pdlgWatch->ShowWindow(SW_HIDE);
for (i = 0; i < nWatchct; i++) {
strProfile.Format("Watch%02d", i + 1);
char watch[120];
GetPrivateProfileString("Watches", strProfile, "", watch, 120, strTutorial);
m_pdlgWatch->AddWatch(watch);
}
ClearBreakpoints();
// ----- load the breakpoints
int nBreakpointct = GetPrivateProfileInt("Breakpoints", "Breakpointct", 0, strTutorial);
for (i = 0; i < nBreakpointct; i++) {
strProfile.Format("Breakpoint%02d", i + 1);
char breakpoint[120];
GetPrivateProfileString("Breakpoints", strProfile, "", breakpoint, 120, strTutorial);
char* npLineno = strchr(breakpoint, '/');
if (npLineno != 0) {
*npLineno = '\0';
int nLineno = atoi(npLineno+1);
if (nLineno > 0)
theApp.AddBreakpoint(breakpoint, nLineno);
}
}
// ---- load the runtime options
m_bDebugging = GetPrivateProfileInt("Options", "Debugging", 1, strTutorial);
m_bExceptions = GetPrivateProfileInt("Options", "Exceptions", 0, strTutorial);
m_bRTTI = GetPrivateProfileInt("Options", "RTTI", 0, strTutorial);
m_bStrict = GetPrivateProfileInt("Options", "Strict", 0, strTutorial);
char line[257];
line[256] = '\0';
GetPrivateProfileString("Options", "Command Line", "", line, 256, strTutorial);
m_strCommandLine = line;
m_CommandLinePromptOption = GetPrivateProfileInt("Options", "Command Line Prompt", 0, strTutorial);
if (isoldtutorial) {
// convert old tutorial prompt option values to new
if (m_CommandLinePromptOption == 0)
m_CommandLinePromptOption = 1;
else if (m_strCommandLine.IsEmpty())
m_CommandLinePromptOption = 0;
else
m_CommandLinePromptOption = 2;
}
GetPrivateProfileString("Options", "Define", "", line, 256, strTutorial);
LoadArray(m_Defines, line);
m_pMainWnd->SetForegroundWindow();
// --- test for dependencies
int nDepct = GetPrivateProfileInt("Dependencies", "Depct", 0, strTutorial);
CString msg(
"This project depends on the "
"following file(s), which have "
"not been built:\n"
);
CString postmsg("\n\nYou can build the file(s) from here:\n");
bool dependents = false;
for (i = 0; i < nDepct; i++) {
strProfile.Format("Dep%02d", i + 1);
GetPrivateProfileString("Dependencies", strProfile, "", path, MAX_PATH, strTutorial);
if (*path) {
if (_access(path, 0) != 0) {
// a dependent file does not exist
dependents = true;
CString fl(path);
int ndx = fl.ReverseFind('\\');
if (ndx != -1)
fl = fl.Right(fl.GetLength() - ndx - 1);
msg += '\n';
msg += fl;
strProfile.Format("Tut%02d", i + 1);
char txt[100];
GetPrivateProfileString("Dependencies", strProfile, "", txt, 100, strTutorial);
CString ctxt("\n");
ctxt += txt;
postmsg += ctxt;
}
}
}
if (dependents)
AfxMessageBox(msg + postmsg);
}
}
// ----- the Win32 API forgot to include this function
static void WritePrivateProfileInt(LPCTSTR lpapp, LPCTSTR lpkey, int nVal, LPCTSTR lpFileName)
{
CString strVal;
strVal.Format("%d", nVal);
WritePrivateProfileString(lpapp, lpkey, strVal, lpFileName);
}
void CQuincyApp::WriteTutorial(const CString& strTutorial)
{
m_strTutorial = strTutorial;
CString strProfile;
CString strDocument;
// ------- write the documents
int nDocct = 0;
POSITION tpos = GetFirstDocTemplatePosition();
while (tpos != 0) {
CDocTemplate* pTem = GetNextDocTemplate(tpos);
ASSERT(pTem != 0);
POSITION dpos = pTem->GetFirstDocPosition();
while (dpos != 0) {
CTextDocument* pDoc = static_cast<CTextDocument*>(pTem->GetNextDoc(dpos));
ASSERT(pDoc != 0);
strDocument = pDoc->GetPathName();
strProfile.Format("Doc%02d", ++nDocct);
WritePrivateProfileString("Documents", strProfile, GetFileName(strDocument), strTutorial);
}
}
WritePrivateProfileInt("Documents", "Docct", nDocct, strTutorial);
int i;
// ------- write the watches
int nWatchct = m_bWatchCreated ? m_pdlgWatch->GetWatchCount() : 0;
WritePrivateProfileInt("Watches", "Watchct", nWatchct, strTutorial);
for (i = 0; i < nWatchct; i++) {
strProfile.Format("Watch%02d", i + 1);
CString strWatch;
m_pdlgWatch->GetWatchValue(i, strWatch);
WritePrivateProfileString("Watches", strProfile, strWatch, strTutorial);
}
// ------- write the breakpoints
WritePrivateProfileInt("Breakpoints", "Breakpointct", theApp.BreakpointCount(), strTutorial);
const std::set<Breakpoint>& bp = theApp.GetProgrammedBreakpoints();
std::set<Breakpoint>::const_iterator iter;
i = 0;
for (iter = bp.begin(); iter != bp.end(); iter++, i++) {
strProfile.Format("Breakpoint%02d", i + 1);
CString strBreakpoint;
strBreakpoint.Format("%s/%d", (*iter).m_strFile, (*iter).m_nLineNo);
WritePrivateProfileString("Breakpoints", strProfile, strBreakpoint, strTutorial);
}
// ----- write the runtime options
WritePrivateProfileInt("Options", "Debugging", m_bDebugging, strTutorial);
WritePrivateProfileInt("Options", "Exceptions", m_bExceptions, strTutorial);
WritePrivateProfileInt("Options", "RTTI", m_bRTTI, strTutorial);
WritePrivateProfileInt("Options", "Strict", m_bStrict, strTutorial);
WritePrivateProfileInt("Options", "Command Line Prompt", m_CommandLinePromptOption, strTutorial);
WritePrivateProfileString("Options", "Command Line", m_strCommandLine, strTutorial);
CString strArray;
GetArray(strArray, m_Defines);
WritePrivateProfileString("Options", "Define", strArray, strTutorial);
}
void CQuincyApp::OnWritetutorial()
{
// ------ try using original tutorial name (if one was loaded)
CString strTutorial(m_strTutorial);
if (strTutorial.IsEmpty()) {
// ------ try to develop a file name from project file
GetProjectDocument(&strTutorial);
if (strTutorial.IsEmpty()) {
// ------ try to develop a file name from first available source code file
POSITION tpos = GetFirstDocTemplatePosition();
while (tpos != 0) {
CDocTemplate* pTem = GetNextDocTemplate(tpos);
ASSERT(pTem != 0);
POSITION dpos = pTem->GetFirstDocPosition();
if (dpos != 0) {
CTextDocument* pDoc = static_cast<CTextDocument*>(pTem->GetNextDoc(dpos));
ASSERT(pDoc != 0);
strTutorial = pDoc->GetPathName();
break;
}
}
}
}
if (!strTutorial.IsEmpty()) {
int nIndex = strTutorial.ReverseFind('.');
if (nIndex != -1)
strTutorial = strTutorial.Left(nIndex) + ".tut";
}
CFileDialog dlgTut(false, "tut", strTutorial, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
"Tutorial Files (*.tut)|*.tut|All Files (*.*)|*.*||");
if (dlgTut.DoModal() == IDOK)
WriteTutorial(dlgTut.GetPathName());
}
bool CQuincyApp::IsTutorial(const CString& strFileName)
{
return strFileName.Right(4).CompareNoCase(".tut") == 0;
}
void CQuincyApp::OnTycpp()
{
CreateTutorialDialog();
m_pCTutDlg->ShowWindow(SW_SHOW);
m_pCTutDlg->SetFocus();
if (!m_strTutorial.IsEmpty())
m_pCTutDlg->OpenExercise(m_strTutorial);
}
void CQuincyApp::CreateTutorialDialog()
{
ASSERT(m_pCTutDlg != 0);
if (m_bTutCreated != true) {
m_pCTutDlg->Create(IDD_TUTORIAL);
m_bTutCreated = true;
}
}
void CQuincyApp::LoadTutorials()
{
m_strTutorialPath = GetProfileString("Directories", "Tutorial");
if (m_strTutorialPath.IsEmpty())
m_strTutorialPath = m_strQuincyBinPath.Left(m_strQuincyBinPath.GetLength() - 3) + "Programs";
CString strTocPath = m_strTutorialPath + "\\TYCPP.TOC";
m_bIsTutorial = _access(strTocPath, 0) == 0;
if (m_bIsTutorial)
m_pCTutDlg = new CTutDlg(strTocPath);
}
void CQuincyApp::OpenTutorial(const CString& strTut)
{
if (strTut.Left(7) == "Program") {
// --- extract the chapter number from the exercise title
char cch[3];
cch[0] = strTut[8];
cch[1] = strTut[9];
cch[2] = '\0';
int chapno = atoi(cch);
// --- extract the exercise number from the title
int ndx = 9;
if (strTut[ndx] != '.')
ndx++;
cch[0] = strTut[++ndx];
cch[1] = strTut[++ndx];
int exno = atoi(cch);
CString strTutorial;
strTutorial.Format("%s%02d\\PR%02d%03d.tut", m_strTutorialPath + "\\Chap",
chapno, chapno, exno);
m_bReadTutorial = true;
m_strTutorial = strTutorial;
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -