📄 explain.cpp
字号:
getftime(fileno(stream), &ft);
fclose(stream);
// 如果需要,分别对月,日,小时,分钟,秒分别进行前部加“0”处理
HeadZero(ft.ft_month, Month);
HeadZero(ft.ft_day, Day);
HeadZero(ft.ft_hour, Hour);
HeadZero(ft.ft_min, Minute);
HeadZero(ft.ft_tsec * 2, Sec);
// 设置输出文件名格式
sprintf(Name, "%-12s", ffblk.ff_name);
// 设置底部信息栏信息格式
sprintf(Mess, "Date : %4u-%s-%s %c Time : %s:%s:%s %c Size : %ld",
ft.ft_year+1980, Month, Day, 179, Hour, Minute, Sec, 179, ffblk.ff_fsize);
// 将当前文件加入列表
lstOpenFile.Add(Name, Mess);
// 搜索下一个源文件
Done = findnext(&ffblk);
}
// 对列表按文件名升序进行排序
lstOpenFile.Sort();
// 用户选中的文件序号
int Sign;
// 存储选中文件的文件名
char Name[MaxLenOfFileName] = "";
do
{
// 隐藏光标
_setcursortype(_NOCURSOR);
// 打印列表
lstOpenFile.Show();
// 当代用户选择,并返回选择序号
Sign = lstOpenFile.Work();
if (Sign > 0)
{
// 用户选择了一个已存在的文件
// 取出文件名
strcpy(Name, lstOpenFile.ItemName(Sign));
// 删除尾部空格
ClearTailBlank(Name);
}
else if (Sign == 0)
{
// 用户选择新建一个文件
// 打开窗口等待用户输入文件名
winGetFileName.Show();
winGetFileName.GetInput(Name, 10, 46, MaxLenOfFileName);
winGetFileName.Hide();
}
} while (Name[0] == '\0' && Sign != Cancel);
// 隐藏打开文件列表
lstOpenFile.Hide();
int i = 0;
if (Sign != Cancel && Name != '\0')
{
// 可以打开文件或建立新的文件
if (!strchr(Name, '.'))
{
// 若没有扩展名则自动添加扩展名
strcat(Name, ".BAS");
}
FILE *fi;
if ((fi = fopen(Name, "r")) != NULL)
{
// 文件已存在
// 以新文件设置参数
NewFile(Name);
while (!feof(fi))
{
// 文件未读完
if (i > TotRoomLine)
{
// 需要申请新的文本行空间
// 申请新的文本行空间
NewLine();
if (Error)
{
// 无剩余内存可申请
// 重置错误代码
Error = NoError;
// 重置编辑窗口标题为默认文件
winEdit.SetTitle(DefaultFileName);
winEdit.RefreshTitle();
return;
}
}
// 读入文件的一行
char Chr;
int Len = -1;
Chr = fgetc(fi);
while (Chr != '\n' && Len < MaxY - 2 && !feof(fi))
{
if (Chr == '\t')
{
for (int j = 0; j < TabSize && Len < MaxY - 1; j++)
{
Len++;
}
}
else
{
Len++;
Text[i]->Line[Len] = Chr;
}
Chr = fgetc(fi);
}
StandardizeLine(i);
// 该行未着色
Text[i]->Sign[0] = ' ';
// 该行无标记
Text[i]->Mark = false;
// 该行无断点
Text[i]->Break = false;
// 准备下一行
i++;
}
// 关闭文件
fclose(fi);
// 设置最后一行序号
EndLine = i - 1;
// 设置编辑窗口文本高度
winEdit.SetTotHigh(EndLine);
// 打印编辑窗口当前屏文本
PrintText(winEdit.Top() + 1);
}
else if (fopen(Name, "w") == NULL)
{
// 无此文件
// 打开文件错误
ShowError(ErrorOpening);
}
else
{
// 是新文件
// 打开新文件
NewFile(Name);
}
}
SetCursor();
}
int SaveFile
(
const char Name[MaxLenOfFileName] // 文件名
)
{
// 存盘
if (strcmp(Name, DefaultFileName) == 0)
{
// 当前使用默认文件名,需要输入文件名
return SaveAsFile();
}
FILE *fo;
if ((fo = fopen(Name, "w")) != NULL)
{
char Line[MaxY];
for (int i = 0; i <= EndLine; i++)
{
// 清除尾部空格
strcpy(Line, Text[i]->Line);
ClearTailBlank(Line);
// 将本行写入磁盘
fprintf(fo, "%s", Line);
if (i < EndLine)
{
// 不是最后一行
// 打印回车
fprintf(fo, "\n");
}
}
// 关闭文件
fclose(fo);
// 设置修改标志
ShowSaved(true);
}
else
{
// 存盘错误
ShowError(ErrorSaving, -1, "");
}
return Yes;
}
int SaveAsFile()
{
// 存储文件名
char Name[MaxY];
// 显示查询文件名窗口
winGetFileName.Show();
bool FileNameOK = false;
do
{
// 等待用户输入文件名
winGetFileName.GetInput(Name, 10, 46, MaxLenOfFileName);
FileNameOK = IsFileName(Name);
if (!FileNameOK)
{
Sound();
}
} while (Name[0] != '\0' && (strcmp(Name, DefaultFileName) == 0 || !FileNameOK));
// 隐藏查询文件名窗口
winGetFileName.Hide();
if (Name[0] != '\0')
{
if (strlen(Name) > 8)
{
Name[8] = '\0';
}
if (!strchr(Name, '.'))
{
// 没有扩展名
// 添加默认扩展名
strcat(Name, ".BAS");
}
strupr(Name);
FILE *fi;
if ((fi = fopen(Name, "r")) != NULL)
{
// 文件已经存在
// 关闭文件
fclose(fi);
// 询问用户是否覆盖
winAsk.Clear();
winAsk.Add(" Overwrite the file(Y/N)?");
int Return = Ask();
switch(Return)
{
case Yes:
break;
case No:
case Cancel:
return Return;
}
}
// 存盘
SaveFile(Name);
if (Error)
{
Error = NoError;
return No;
}
// 设置编辑窗口标题
winEdit.SetTitle(Name);
// 刷新标题
winEdit.RefreshTitle();
return Yes;
}
return No;
}
void PrintFile()
{
// 输出文件到打印机
if (fprintf(stdprn, "======= %s =======\n", winEdit.Caption()) != EOF)
{
// 打印机工作正常
// 临时存储文本行
char Line[MaxY];
for (int i = 0; i <= EndLine; i++)
{
// 复制文本行
strcpy(Line, Text[i]->Line);
// 删除尾部空格
ClearTailBlank(Line);
// 输出到打印机
fprintf(stdprn, "%s\n", Line);
}
}
else
{
// 打印机无法正常工作
// 输出错误
ShowError(ErrorPrint);
Error = NoError;
}
}
void Quit()
{
// 退出系统
window(1, 1, 80, 25);
// 设置颜色并清屏
SetColor(WHITE,BLACK);
clrscr();
// 打印退出信息
printf("Leaving from Cool Basic ...\n");
// 程序中止
exit(0);
}
void Standardize()
{
// 对整个程序进行标准化
for (int LineNo = 0; LineNo <= EndLine; LineNo++)
{
// 标准化一行
StandardizeLine(LineNo);
}
}
void StandardizeLine
(
const int LineNo // 要处理的行号
)
{
// 标准化一行
//暂存要标准化的字符串,便于扫描
char Source[MaxY] = "";
//标准化后的字符串
char Return[2 * MaxY] = "";
//暂存分隔的单词
char Word[MaxY] = "";
//暂存Word的大写字符串
char WordUpcase[MaxY] = "";
// 复制待处理的文本行到Source
strcpy(Source, Text[LineNo]->Line);
// 清除Source末尾的空格,便于处理
ClearTailBlank(Source);
// 复制Source前面的空格到Return,保持缩进
int i = 0;
while(Source[i] == ' ')
{
strcat(Return, " ");
i++;
}
// 清除Source前部空格
ClearHeadBlank(Source);
// 取长度
int Len = strlen(Source);
// 置加锁标志,在涉及字符串处理中使用
int Lock = false;
for (i = 0; i <= Len; i++)
{
if (Source[i] == '"')
{
// 是字符串的开始或结尾
// 加锁标志取反
Lock = true + false - Lock;
}
if (Lock)
{
// 处于字符串中
if (Word[0] != '\0')
{
// 单词非空
// 做一份单词的全大写副本
strcpy(WordUpcase, Word);
strupr(WordUpcase);
// 处理单词缓冲
DealWord(Word, WordUpcase, Return, Lock);
}
if (Source[i] == '"')
{
// 本位是字符串开始处的引号
if (Return[0] != '\0' && Return[strlen(Return) - 1] != ' ')
{
// 返回字符串非空,且返回字符串最后一位非空格
// 返回字符串加空格
strcat(Return, " ");
}
// 返回字符串添加本位的引号
strcat(Return, "\"");
}
else
{
// 本位在字符串内部
// 将本位原样复制到返回字符串中
strcat(Return, " ");
Return[strlen(Return) - 1] = Source[i];
}
// 处理下一位
continue;
}
else if (Source[i] == '"')
{
// 本位是字符串结尾处的引号
// 将本位的引号复制到返回字符串中
strcat(Return, "\"");
// 处理下一位
continue;
}
if (Source[i] == ' ' || i == Len)
{
// 本位是空格,或已到源字符串末尾
if (Word[0] != '\0')
{
// 单词非空
// 做一份单词的全大写副本
strcpy(WordUpcase, Word);
strupr(WordUpcase);
if (strcmp(WordUpcase, "REM") == 0)
{
// 单词为REM
// 将REM加入返回字符串
strcat(Return, "REM");
// 将后面的内容原样复制到返回字符串中
for (int j = i; j <= Len; j++)
{
strcat(Return, " ");
Return[strlen(Return) - 1] = Source[j];
}
// 处理完毕,退出循环
break;
}
else
{
// 单词非REM,处理单词
DealWord(Word, WordUpcase, Return, Lock);
}
}
}
else if (!Lock && IsSymbol(Source[i]))
{
// 非字符串,且本位是符号
// 为了美观,必要的时候在符号的两边添加空格
// 先处理单词
if (Word[0] != '\0')
{
// 单词非空
// 做一份单词的全大写副本
strcpy(WordUpcase, Word);
strupr(WordUpcase);
// 处理单词
DealWord(Word, WordUpcase, Return, Lock);
}
// 存储最后两位的字符串,用于下面在加前部空格时做双字节符号判断
char Symbol2[3] = "00";
if (i >= 1)
{
// 可以取源字符串的后两位
Symbol2[0] = Source[i - 1];
Symbol2[1] = Source[i];
}
// 开始加前部空格
if (!strchr(",;()", Source[i]) &&
strcmp(Symbol2, "<=") != 0 &&
strcmp(Symbol2, ">=") != 0 &&
strcmp(Symbol2, "<>") != 0 &&
strcmp(Symbol2, "(+") != 0 &&
strcmp(Symbol2, "(-") != 0 &&
Return[0] != '\0' &&
Return[strlen(Return) - 1] != ' ')
{
// 以下情况下,符号前面不加空格:
// 1、逗号,分号,左括号,右括号
// 2、前一位和本位连起来是下面这些情况:“<=”,“>=”,“<>”,“(+”,“(-”
// 3、返回字符串末尾已经是空格
strcat(Return, " ");
}
// 将本位的符号添加到返回字符串中
strcat(Return, " ");
Return[strlen(Return) - 1] = Source[i];
strcpy(Symbol2, "00");
Symbol2[0] = Source[i];
if (i + 1 < strlen(Source))
{
Symbol2[1] = Source[i + 1];
}
// 开始添加尾部空格
if (Source[i] != '(' &&
Source[i] != ')' &&
strcmp(Symbol2, "<=") != 0 &&
strcmp(Symbol2, ">=") != 0 &&
strcmp(Symbol2, "<>") != 0)
{
// 以下情况,符号后面不加空格:
// 1、左括号,右括号
// 2、本位和下一位连起来是下面这些情况:“<=”,“>=”,“<>”
strcat(Return, " ");
}
}
else
{
// 本位是字母和数字
// 添加如单词
strcat(Word, " ");
Word[strlen(Word) - 1] = Source[i];
}
}
Len = strlen(Return);
if (Len > MaxY - 1)
{
Return[MaxY - 1] = '\0';
}
// 在末尾填充空格使其和编辑窗口等宽
while(Len < MaxY - 1)
{
Len++;
strcat(Return, " ");
}
// 用标准化后的字符串覆盖原文本
strcpy(Text[LineNo]->Line, Return);
Text[LineNo]->Sign[0] = ' ';
}
void DealWord
(
char *Word, // 单词
const char WordUpcase[MaxY], // 单词的全大写副本
char *Return, // 返回字符串
const int Lock // 加锁标志
)
{
// 处理单词
// StandardizeLine专用
// 关键字序号,非关键字则为-1
int KeyWordValue = -1;
if (isalpha(Word[0]))
{
// 第一位是字母,是关键字的必要条件
for (int i = 0; i < TotKeyWord; i++)
{
if (strcmp(KeyWord[i], WordUpcase) == 0)
{
// 关键字匹配成功,记下序号,退出
KeyWordValue = i;
break;
}
}
}
// 返回字符串的长度
int Len = strlen(Return);
if (Len > 0 && Return[Len - 1] != '(' && Return[Len - 1] != ' ' && !Lock)
{
// 以下情况,单词前不加空格:
// 1、返回字符串最后一位是左括号
// 2、返回字符串最后一位是空格
strcat(Return, " ");
}
if (KeyWordValue >= 0)
{
// 是关键字,将大写的副本加入返回字符串
strcat(Return, WordUpcase);
if (strcmp(WordUpcase, "RND") != 0 &&
strcmp(WordUpcase, "INT") != 0 &&
strcmp(WordUpcase, "SQR") != 0)
{
strcat(Return, " ");
}
}
else
{
// 不是关键字,将原文加入返回字符串
strcat(Return, Word);
}
// 单词清空
Word[0] = '\0';
}
void RunProgram()
{
// 运行程序
// 检查整个程序的语法
CheckSyntax();
if (Error)
{
return;
}
if (RunLineNo < 0)
{
// 从编辑状态开始运行程序
// 清除全部变量空间
ClearAll();
window(1, 1, 80, 25);
// 清屏
CallCls();
CreateTable();
if (Error)
{
Error = NoError;
return;
}
// 准备运行的行号
RunLineNo = NextLine(0);
}
else
{
// 从调试状态继续执行
// 保存当前准备执行的行号
PreRunLineNo = RunLineNo;
// 重新打印调试状态下准备执行的行,使其呈正常语句的颜色
RunLineNo = -1;
if (x0 <= PreRunLineNo && PreRunLineNo < x0 + winEdit.High())
{
// 准备执行的行在编辑窗口的本屏范围内
// 重新打印该行
PrintLine(PreRunLineNo);
SetCursor();
}
RunLineNo = PreRunLineNo;
// 存储编辑窗口画面
gettext(1, 1, 80, 25, TextMirror);
// 恢复输出窗口画面
puttext(1, 1, 80, 25, OutMirror);
// 置光标于当前输出的位置
gotoxy(OutX, OutY);
}
do
{
// 执行当前语句,并返回下一个要执行的语句行号
RunLineNo = NextLine(RunLine(RunLineNo));
} while (!Finished && !Error && !Text[RunLineNo]->Break);
if (!Error)
{
// 执行中没有错误,存储输出窗口画面
gettext(1, 1, 80, 25, OutMirror);
}
}
void DebugLine(const int LineNo)
{
if (LineNo >= 0)
{
// 打印当前调试时的语句行
gotoxy(winEdit.Left() + 1, LineNo + winEdit.Top() + 1 - x0);
SetColor(BLACK, WHITE);
cprintf("%-78s", Text[LineNo]->Line);
}
}
void StepInto()
{
// 单步执行语句,不进入SUB
if (NextLine(0) == -1)
{
// 程序执行完毕,退出
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -