/* 用 tcc -mc bj 编译 */
#include stdio.h
#include dir.h
#include dos.h
#include ctype.h
#include alloc.h
#define BLCK_COLOR 0x1E /* 字块色彩 */
#define TEXT_COLOR 0x02 /* 文本字符色彩 */
#define PROM_COLOR 0x5F /* 提示及提问行色彩 */
#define CHAR_COLOR 0x03 /* 行末示意符色彩 */
#define HH 24 /* 屏幕最大行坐标 */
#define H1 (HH-1) /* 序号、文件名信息行行坐标 */
#define H2 (HH-2) /* 标尺行行坐标 */
#define H3 (HH-3) /* 编辑文本显示最下行行坐标 */
#define ZS 76 /* 每行显示文本的字数 */
#define BP (ZS/2) /* 每次移屏字节数 */
#define FH (ZS+3) /* 行末示意符列坐标 */
#define QB 400 /* 编辑数组可容纳的总行数 */
#define Q1 (QB/2) /* 编辑数组中间值 */
#define Q2 (QB*3/5) /* 第一次读入编辑数组的行数 */
#define Q3 (QB*2/5) /* 每次读写临时文件的行数 */
#define SZ 1000 /* 临时文件每次读写地址数组最大下标 */
#define HC 255 /* 编辑数组每行最大字节数控制值 */
#define KK 32000 /* 字块允许的最大字节数 */
#define PG ((HH-16)*6) /* 显示文件目录时,每页可显示目录数 */
long xx=0; /* 当前行在文本中的绝对行号 */
int yy=0; /* 当前列的文本列号,也是编辑数组列号 */
int ss_max=0; /* 编辑数组实用最大行号 */
int x=0,y=0; /* 当前行在显示屏幕上的行、列坐标 */
int ss_x=0; /* 当前行在编辑数组中的行号 */
int m=0; /* 左右移屏屏号,首屏为 0 */
int fp_end=0; /* 老文件是否读完的标志变量 */
int old=1; /* 区别新、老文件的标志变量 */
int ins=0; /* 是否为插入状态的标志变量 */
int vid=0; /* 区别图形和字符显示方式的标志变量 */
int tab=0; /* 中文表格线开关变量 */
int blck=0; /* 是否已定义字块的标志变量 */
int enq=HC-4; /* 排版行宽,初值设为 HC-4 */
long ksx=-1; /* 块首行号,未定义块时置 -1 */
int ksy=-1; /* 块首列号,未定义块时置 -1 */
long kwx=-1; /* 块尾行号,未定义块时置 -1 */
int kwy=-1; /* 块尾列号,未定义块时置 -1 */
long txx,tyy; /* 字块操作时保存原 xx,yy 坐标的变量 */
int chg=0; /* 文件是否已修改过的标志变量 */
int first=0; /* 字块中首行长度字节数 */
int oa=0,ob=0; /* 数组 wra[ ] 和 wrb[ ] 的标号变量 */
long wra[SZ],wrb[SZ]; /* 记录临时文件读写地址的数组 */
long fp_rd; /* fp_rd 为 fp 已读出行的最大行号 */
long ttl_x=0xFFFFFFFL; /* 文末行行号,先设一大数,fp 全部读完后,
用已读出行最大行号 fp_rd 代替 */
long ser=0; /* 当前光标处的字序数 */
long vw=0; /* 临时存盘时,保存正文文件读指针的变量 */
long vv=0; /* 读块时,存放读入块的字节数 */
unsigned char z1,z2,a1,a2; /* 为判断标点符号设置的变量 */
unsigned char *ss[QB]; /* 编辑缓冲区数组(简称编辑数组) */
char *mfile,*bfile; /* 分别存放源文件名和后备文件名 */
char *file1,*file2; /* 分别存放临时文件 1、2 的文件名 */
char far *mem, far *mmm; /* 长城字符方式显存基本区和扩展区地址指针 */
char *ddd,*dd; /* ddd 为读入块的指针变量,dd 为保存ddd串首的指针 */
char *hsz; /* 提问时输入字符串的指针变量 */
char *fnd; /* 存放要搜索的字符串 */
char two; /* 存放全角制表符第二字节的字符变量 */
char qq; /* 全角制表符第二字节的标志变量 */
char da[]={0x0D,0x0A,0}; /* 只有硬回车换行符的字符串 */
char ra[]={0x8D,0x0A,0}; /* 只有软回车换行符的字符串 */
struct ffblk pt[1]; /* 读文件目录用的结构 */
union REGS r; /* 中断调用函数用的联合 */
union inkey { /* 存放按键值的联合 */
unsigned char ch[2]; /* ch[0] 为高位字节, ch[1] 为低位字节 */
int ii;
} cc;
FILE *fp,*fopen(); /* fp 为老文件 mfile 的文件指针 */
FILE *fp1,*fp2; /* 临时文件 1、2 的文件指针 */
FILE *fp3; /* 读入的外部文件和字块写盘的文件指针 */
main(int argc,char *argv[]) /* 主控函数 */
{
int i;
clss(0,HH); /* 清全部屏幕 */
mod(); /* 测显示模式 */
for(i=0;iQB;i++) { /* 为给编辑数组分配内存建的循环 */
ss[i]=malloc(HC); /* 逐行分配内存空间 */
*ss[i]=0; /* 数组行清为空串 */
}
mfile=malloc(16); /* 为编辑文件名字符串分配内存空间 */
*mfile=0; /* 字符串清为空串 */
if(argc1) mfile=argv[1]; /* 如进入 BJ 时带命令行参数,放入 mfile */
filename(); /* 输入文件名,建临时文件名,老文件读入 */
hsz=malloc(HC); /* 为指针变量 hsz 分配内存空间 */
fnd=malloc(HC); /* 为搜索字符串变量分配内存空间 */
disp_t(); /* 显示编辑屏幕 */
Ins(); /* 置初始状态为插入状态 */
while(1) { /* 编辑主循环 */
xh(); /* 在信息行显示当前行、列、序号 */
coord(); /* 在标尺行显示标尺 */
goto_xy(x,y); /* 定屏幕文本光标位置 */
cc.ii=bioskey(0); /* 将按键值读入一联合中 */
clear_prompt(); /* 清提示区 */
if(cc.ch[0]) { /* 如果低位字节不为 0 */
switch(cc.ch[0]) { /* 判断低位字节 */
case 13: Enter(); /* 如为回车键,输入回车键操作 */
break; /* 跳出开关语句 */
case 8: Del(); /* 如为退格键,删字操作 */
break; /* 跳出开关语句 */
case 14: Ctrl_N(); /* Ctrl+N 在当前行前插入一空行 */
break; /* 跳出开关语句 */
case 25: Ctrl_Y(1); /* Ctrl+Y 删除当前行 */
break; /* 跳出开关语句 */
case 20: Ctrl_T(1); /* Ctrl+T 删至行尾 */
break; /* 跳出开关语句 */
case 5: Ctrl_E(1); /* Ctrl+E 删至行首 */
break; /* 跳出开关语句 */
case 6: Ctrl_F(1); /* Ctrl+F 移至块首 */
break; /* 跳出开关语句 */
case 22: Ctrl_V(); /* Ctrl+V 字块移动 */
break; /* 跳出开关语句 */
case 11: Ctrl_K(); /* Ctrl+K 字块拷贝 */
break; /* 跳出开关语句 */
case 23: Ctrl_W(); /* Ctrl+W 字块存盘 */
break; /* 跳出开关语句 */
case 4: Ctrl_D(); /* Ctrl+D 删除字块 */
break; /* 跳出开关语句 */
case 16: Ctrl_P(); /* Ctrl+P 打印当前编辑的文本文件 */
break; /* 跳出开关语句 */
case 18: Ctrl_R(); /* Ctrl+R 外部文件插入当前位置 */
break; /* 跳出开关语句 */
case 27: Esc(); /* Esc 键 不存盘退出 */
break; /* 跳出开关语句 */
case 3: bk(); /* Ctrl+C 退回 DOS 系统 */
default: Chr(); /* 如为字符键,输入字符 */
}
}
else { /* 如果低位字节为 0 */
switch(cc.ch[1]) { /* 判断高位字节 */
case 81: PgDn(); /* PgDn 键,向下翻屏 */
break; /* 跳出开关语句 */
case 73: PgUp(); /* PgUp 键,向上翻屏 */
break; /* 跳出开关语句 */
case 59: F1(1); /* F1 存盘并退出 */
break; /* 跳出开关语句 */
case 84: Shift_F1(); /* Shift+F1,存盘,不退出 */
break; /* 跳出开关语句 */
case 60: F2(); /* F2 移到指定行 */
break; /* 跳出开关语句 */
case 61: F3(); /* F3 输入格式文件排版行宽 */
break; /* 跳出开关语句 */
case 62: F4(); /* F4 段排版 */
break; /* 跳出开关语句 */
case 87: Shift_F4(); /* Shift+F4 从当前光标行排版至文末 */
break; /* 跳出开关语句 */
case 63: F5(); /* F5 搜索字符串 */
break; /* 跳出开关语句 */
case 88: Shift_F5(); /* Shift+F5 继续搜索 */
break; /* 跳出开关语句 */
case 64: F6(); /* F6 字符串的替代 */
break; /* 跳出开关语句 */
case 65: F7(); /* F7 定义块首 */
break; /* 跳出开关语句 */
case 66: F8(); /* F8 定义块尾 */
break; /* 跳出开关语句 */
case 90: /* Shift+F7 */
case 91: Shift_F7(); /* Shift+F8 取消块定义 */
break; /* 跳出开关语句 */
case 67: F9(); /* F9 光标移到文首 */
break; /* 跳出开关语句 */
case 92: Shift_F9(); /* Shift+F9 光标移到文末 */
break; /* 跳出开关语句 */
case 68: F10(); /* F10 表格线功能开关 */
break; /* 跳出开关语句 */
case 77: Right(); /* → 键 右移光标 */
break; /* 跳出开关语句 */
case 75: Left(); /* ← 键 左移光标 */
break; /* 跳出开关语句 */
case 72: Up(); /* ↑ 键 上移一行 */
break; /* 跳出开关语句 */
case 80: Down(); /* ↓ 键 下移一行 */
break; /* 跳出开关语句 */
case 82: Ins(); /* Ins 插入状态转换 */
break; /* 跳出开关语句 */
case 83: Del(); /* Del 同退格键 */
break; /* 跳出开关语句 */
case 71: Home(); /* Home 光标移到行首 */
break; /* 跳出开关语句 */
case 79: End(); /* End 光标移到行末 */
break; /* 跳出开关语句 */
}
}
}
}
mark() /* 软件标志 */
{
int i;
for(i=1;i8;i++) { /* 显示一块彩色 */
write_space(i,2,23,0x10); /* 蓝底色 */
if(i!=1) write_string(i,25," ",0x30); /* 右部浅蓝色影子 */
}
for(i=4;i27;i++) write_char(8,i,32,0x30); /* 下部浅蓝色影子 */
write_string(3,6,"BJ全屏幕编辑工具",0x1E); /* 显示软件名称 */
write_string(4,10,"Ver1.0",0x1E); /* 显示版本号 */
write_string(5,9,"沈 建 威",0x1E); /* 显示设计者姓名 */
}
filename() /* 输入要编辑的文件名 */
{
int i,k,tatol,page=1; /* tatol 目录总页数, page 目录显示页号 */
if(!*mfile) { /* 如未带命令行参数,mfile 为空串 */
mark(); /* 显示软件标志 */
write_string(11,20,"请输入要编辑的文件名:",0x0A);
tatol=make_dir(); /* 建目录数组,总页数放入 tatol */
while(1) { /* 为目录翻屏设置的循环 */
disp_dir(page); /* 显示目录清单 */
write_space(11,42,20,0x0A); /* 用 20 个空格清文件名输入区屏幕 */
if((k=key_string(11,42,mfile,0x0A))0) break;/* 输入文件名,成功跳出循环*/
if(k==-1 || k==0) bk(); /* 如为空串或按 ESC 退出至 DOS 下 */
if(k==-4 && page1) page--; /* 如按 PgUP,如不在首页,显示上页目录 */
if(k==-5 && pagetatol) page++; /* 按 PgDn,如不在最后页,显示下页目录*/
}
}
clss(0,HH); /* 清全部屏幕 */
for(i=0;iQB;i++) *ss[i]=0; /* 清编辑数组 */
if((fp=fopen(mfile,"rb"))==NULL) { /* 用只读方式打开文件,如失败为新文件 */
old=0; /* old=0 为新文件 */
fp_rd=0; /* 已从 fp 中读入行最大行号置为 0 */
write_string(H1,40,"新",0x05); /* 在信息行提示新文件 */
}
else fp_rd=read_from(0,Q2,fp)-1; /* 如为老文件,读 Q2 行到编辑数组 */
write_string(H1,42,"文件名:",0x05); /* 在信息行提示 */
write_string(H1,50,mfile,0x07); /* 在信息行显示文件名 */
if(fp_rdQ2-1) { /* 如读入不足 Q2 行, fp 已读完 */
ttl_x=fp_rd; /* 定文末总行号 */
fp_end=1; /* fp 已读完标志置 1 */
}
ss_max=fp_rd; /* 定编辑数组实用最大行号 */
f_name(); /* 建辅助文件名 */
}
int make_dir() /* 找当前目录中合适的文件名记入数组 */
{
int i=0;
if(findfirst("*.*",pt,0)==0 && compare()) /* 寻找第一个文件名并比较 */
strcpy(ss[i++],pt[0].ff_name); /* 如不是要忽略的文件,将它赋给数组 */
while(findnext(pt)==0) { /* 为继续找文件设的循环 */
if(compare()) /* 比较找到的文件名 */
strcpy(ss[i++],pt[0].ff_name); /* 如比较为真,记入数组 */
}
return (i-1)/PG+1; /* 返回可供显示页数 */
}
int compare() /* 如扩展名为 EXE 等可忽略的文件名,返回 0,否则返回 1 */
{
if(strstr(pt[0].ff_name,".EXE") || strstr(pt[0].ff_name,".COM")
|| strstr(pt[0].ff_name,".OV") || strstr(pt[0].ff_name,".OBJ")
|| strstr(pt[0].ff_name,".LIB") || strstr(pt[0].ff_name,".BAK")
|| strstr(pt[0].ff_name,".FOX") || strstr(pt[0].ff_name,".DBF")
|| strstr(pt[0].ff_name,".IDX"))
return 0;
return 1;
}
disp_dir(int a) /* 显示目录,a 为页号 */
{
int i=16,j=1,k; /* i 为行坐标,j 为列坐标 */
for(k=0;k80;k++)
write_char(14,k,'_',TEXT_COLOR); /* 在屏幕第 14 行画一横线,区分目录区 */
clss(15,HH); /* 清目录显示区 */
k=(a-1)*PG; /* 根据页号确定数组显示的起始项 */
while(ka*PG) { /* 为显示一页建的循环 */
write_string(i,j,ss[k++],0x0E); /* 显示一个文件名 */
j+=13; /* 右移 13 列 */
if(j67) { /* 如列号大于 67 */
++i; /* 下移一行 */
j=1; /* 列号置 1 */
}
}
}
f_name() /* 建临时文件和后备文件名 */
{
int i;
bfile=malloc(16); /* 为后备文件名字符串分配内存空间 */
file1=malloc(16); /* 为临时文件名字符串分配内存空间 */
file2=malloc(16); /* 为临时文件名字符串分配内存空间 */
for(i=0;*(mfile+i)!='.' && *(mfile+i);i++) *(bfile+i)=*(mfile+i);
/* 截取文件名.前的部分,放入 bfile */
*(bfile+i)=0; /* bfile 字符串以 ' ' 结尾 */
strcpy(file1,bfile); /* bfile 中字符串拷入 file1 */
strcpy(file2,bfile); /* bfile 中字符串拷入 file2 */
strcat(bfile,".BAK"); /* bfile 加后缀.BAK */
strcat(file1,".$1$"); /* 临时文件 1 加后缀.$1$ */
strcat(file2,".$2$"); /* 临时文件 2 加后缀.$2$ */
fp1=fopen(file1,"wb+"); /* 打开临时文件 1 */
fp2=fopen(file2,"wb+"); /* 打开临时文件 2 */
}
bk() /* 退出运行,至 DOS 下 */
{
fcloseall(); /* 关闭所有打开的文件 */
remove(file1); /* 删除临时文件 1 */
remove(file2); /* 删除临时文件 2 */
clss(0,HH); /* 清屏 */
goto_xy(0,0); /* 光标置屏幕左上角 */
exit(0); /* 退出运行 */
}
write_prompt(char a) /* 在屏幕提示区显示提示,a 为提示项数组下标 */
{
char *prom[]= { /* 存放提示的数组 */
"请稍候.....",
"请先定义块!",
"块太大!",
"行宽超过250!",
"必须输入数字!",
"只允许输入 Y 或 N!",
"文件未找到!",
"排版超宽!",
"未设定排版宽度!"
};
int g;
g=80-strlen(prom[a]); /* 显示起始列 */
if(a) putchar(7); /* 除第一项提示外,其余各项响铃警告 */
write_string(HH,g,prom[a],PROM_COLOR); /* 在提示区显示提示 */
}
write_ques(char a) /* 在屏幕提问区显示提问,a 为提问项数组下标 */
{
char *ques[]= { /* 存放提问的数组 */
"是否放弃并退出编辑?(Y/N) ",
"请输入字块存盘的文件名: ",
"已有同名文件,是否复盖?(Y/N) ",
"请输入要插入的文件名: ",
"请输入排版行宽: ",
"请输入要找的字符串: ",
"请输入要移到的行号: ",
"寻找: 换成: 换否? ",
"请输入每页打印的行数: ",
"打印机未准备好,请准备好打印机,按任一键继续。",
"请调好打印纸,按任一键开始打印。",
"正在打印.....",
"请输入页号打印列号: ",
"请输入起始页号: "
};
clear_ques(); /* 清提问区 */
write_string(HH,0,ques[a],PROM_COLOR); /* 在提问区显示提问 */
}
clear_prompt() /* 清提示区 */
{
write_space(HH,60,20,TEXT_COLOR); /* 用空格复盖提示区 */
}
clear_ques() /* 清提问区 */
{
write_space(HH,0,60,TEXT_COLOR); /* 用空格复盖提问区 */
}
int read_from(int a,int b,FILE *f) /* 从文件 f 读入 b 行放入数组的第 a 行起 */
{
int i,j;
write_prompt(0); /* 提示请稍候... */
for(i=a;ia+b;i++) { /* 为逐行读出设的循环 */
if(fgets(ss[i],HC,f)==NULL) { /* 从 f 读出一行,如已超出文末 */
j=0; /* j 置初值 */
while(ss[i-1][j]) { /* 检查文末行各字节 */
if(ss[i-1][j]==0x1A) { /* 文件结束符用 ' ' 替代 */
ss[i-1][j]=0;
break;
}
j++; /* 下移一字节 */
}
break; /* 跳出 for 循环 */
}
}
clear_prompt(); /* 清提示区 */
return i-a; /* 返回读出行数 */
}
write_to(int a,int b,FILE *f) /* 把编辑数组第 a 行起的 b 行写入文件 f */
{
int i;
write_prompt(0); /* 提示请稍候... */
for(i=a;ia+b;i++) fputs(ss[i],f); /* 逐行将字符串写入文件 f */
clear_prompt(); /* 清提示区 */
}