{
int i,j;
if(oa) { /* 如 fp1 中有记录 */
if(ss_max=Q1) wfp2(); /* 如数组大于Q1行,先将下部Q3 行存到 fp2 */
mov(0,Q3); /* 数组各行后移 Q3 行 */
fseek(fp1,wra[--oa],SEEK_SET); /* 移动 fp1 读写指针到读写起点 */
j=read_from(0,Q3,fp1); /* 从 fp1 读 Q3 行,写入数组 0 行起 */
ss_x+=j; /* 计算数组行号 */
ss_max+=j; /* 计算编辑数组实用最大行行号 */
}
}
wfp2() /* 写 Q3 行到临时文件 2 */
{
int i;
fseek(fp2,wrb[ob],SEEK_SET); /* 定 fp2 指针到本次读写位置 */
write_to(ss_max-Q3+1,Q3,fp2); /* 从数组ss_max-Q3+1行起,写 Q3 行到 fp2 */
if(xx-ss_x+ss_max==ttl_x) fputc(0,fp2); /* 文末行以 ' ' 定界 */
wrb[++ob]=ftell(fp2); /* 记录下一次写起始地址到指针数组wrb[ ] */
ss_max-=Q3; /* 数组实用最大行号相应减少 */
for(i=ss_max+1;iQB;i++)
*ss[i]=0; /* 编辑数组后部空行初始化 */
}
int mod() /* 测显示模式, 确定显存起始地址 */
{
int pp;
unsigned char vmode;
vmode=peek(0x40,0x49); /* 测显示方式 */
if(vmode3) { /* 如方式为 4 以上 */
vid=1; /* 置 vid=1,调用 BIOS 功能方式 */
return 1; /* 返回 1 */
}
else vid=0; /* 否则 vid=0,字符直接写屏方式 */
mem=(char far *)0xB8000000; /* 彩显基本区首址 */
pp=inp(0x3DA); /* 读出 3DA 端口值 */
pp/=0x10; /* 取高位字节 */
if(pp==1) /* 如高位字节为 1 */
mmm=(char far *)0xC0000000; /* 014 卡扩展区首址 */
else /* 如高位字节不为 1 */
mmm=(char far *)0xB0000000; /* CEGA、CVGA卡扩展区首址 */
}
write_string(int x,int y,char *p,int attrib) /* 在指定位置写字符串 p */
{ /* x 行坐标,y 列坐标,attlib 显示属性 */
if(vid) write_string1(x,y,p,attrib); /* 如为图形方式 */
else write_string2(x,y,p,attrib); /* 如为字符方式 */
}
write_string1(int x,int y,char *p,int attrib) /* 调用 BIOS 功能显示字符串 */
{
int i;
for(i=y;*p;i++) /* i 为屏幕显示的列坐标 */
write_char1(x,i,*p++,attrib);
}
write_string2(int x,int y,char *p,int attrib) /* 直接写屏方式显示字符串 */
{
int i;
unsigned int vh,vl;
char far *v,far *u;
u=mmm+(80*x+y)*2; /* 在扩展区绝对地址 */
v=mem+(80*x+y)*2; /* 在基本区绝对地址 */
while(*p) { /* 字符为真则循环 */
vh=*p++; /* 取出一字节 */
if(vh0xA1) { /* 如为半角字符 */
*v++=vh; /* 该字节写入基本区,基本区地址指针加1 */
*u++=0; /* 扩展区填 ' ',指针加 1 */
*v++=attrib; /* 基本区填入属性值,地址指针加 1 */
*u++=0; /* 扩展区填 ' ',指针加 1 */
}
else { /* 如为全角字符 */
vl=*p++; /* 再取出一字节 */
i=vh*0x100+vl-0xA0A0; /* 计算区位码 */
vh=i/0x100; /* 求区码 */
vl=i-vh*0x100; /* 求位码 */
if(vh0x0F) _DX=vh*94+vl+255; /* 1-9 区地址码 */
else _DX=(vh-6)*94+vl+255; /* 16 以上区地址码 */
*u++=_DH|0x40; /* 高位显示码写入扩展区,扩展区地址指针加 1 */
*v++=_DL; /* 低位显示码写入基本区基本区地址指针加 1 */
*u++=0; /* 扩展区填 ' ',指针加 1 */
*v++=attrib; /* 字符属性写入基本区,基本区指针加 1 */
*u++=0; /* 基本区和扩展区后两字节填 ' ' */
*v++=0;
*u++=0;
*v++=0;
}
}
}
write_char(int x,int y,char ch,int attrib) /* 写一半角字符 ch */
{ /* x 行坐标,y 列坐标,attlib 显示属性 */
if(vid) write_char1(x,y,ch,attrib); /* 如为图形方式 */
else write_char2(x,y,ch,attrib); /* 如为字符方式 */
}
write_char1(int x,int y,char ch,int attrib) /* 调用 BIOS 功能写一半角字符 */
{
goto_xy(x,y); /* 定光标位置 */
r.h.ah=9; /* 第 9 号功能 */
r.h.bh=0; /* 显示 0 页 */
r.x.cx=1; /* 显示 1 次 */
r.h.al=ch; /* 字符放入 AL 寄存器 */
r.h.bl=attrib; /* 属性放入 AH 寄存器 */
int86(0x10,&r,&r); /* 用10H 中断 9 号功能写屏 */
}
write_char2(int x,int y,char ch,int attrib) /* 直接写屏显示一半角字符 */
{
char far *v, far *w;
v=mem+x*160+y*2; /* 计算基本区写入地址 */
w=mmm+x*160+y*2; /* 计算扩展区写入地址 */
*v++=ch; /* 字符 ASCII 码写入基本区 */
*w++=0; /* 扩展区不用,填 ' ' */
*v=attrib; /* 字符属性写入基本区 */
*w=0; /* 扩展区不用,填 ' ' */
}
write_space(int vx,int vy,int k,int att) /* 显示一串空格 */
{ /* vx 行坐标,vy 列坐标,k 空格数,att 显示属性 */
int i;
for(i=vy;ivy+k;i++) write_char(vx,i,32,att); /* 从 vy 到 vy+k-1,显示空格 */
}
roll_scr_up(int a,int b) /* 向上滚屏 */
{
r.x.ax=0x0601; /* 第六号功能,上滚一行 */
r.h.ch=a; /* 左上角行坐标 */
r.h.cl=0; /* 左上角列坐标 */
r.h.dh=b; /* 右下角行坐标 */
r.h.dl=FH; /* 右下角列坐标 */
r.h.bh=TEXT_COLOR; /* 字符属性 */
int86(0x10,&r,&r); /* 调用 INT10H 中断 */
}
roll_scr_down(int a,int b) /* 向下滚屏 */
{
r.x.ax=0x0701; /* 第七号功能,下滚一行 */
r.h.ch=a; /* 右上角行坐标 */
r.h.cl=0; /* 右上角列坐标 */
r.h.dh=b; /* 左下角行坐标 */
r.h.dl=FH; /* 左下角列坐标 */
r.h.bh=TEXT_COLOR; /* 字符属性 */
int86(0x10,&r,&r); /* 调用 INT10H 中断 */
disp(ss_x,x); /* 当前行补显一行 */
}
goto_xy(int vx,int vy) /* 定位光标 */
{
r.h.ah=2; /* 第 2 号功能 */
r.h.dl=vy; /* 光标的列坐标 */
r.h.dh=vx; /* 光标的行坐标 */
r.h.bh=0; /* 光标在 0 页 */
int86(0x10,&r,&r); /* 调用 INT10H 中断 */
}
clss(int a,int b) /* 清屏 */
{
r.x.ax=0x0600; /* 第 6 号功能 */
r.x.bx=0x0700; /* 属性 */
r.h.ch=a; /* 左上角行坐标 */
r.h.cl=0; /* 左上角列坐标 */
r.h.dh=b; /* 右下角行坐标 */
r.h.dl=79; /* 右下角列坐标 */
int86(0x10,&r,&r); /* 调INT10中断 */
}
disp(int a,int i) /* 显示行,a 数组行号,i 屏幕行坐标 */
{
char u=0;
unsigned char *s;
int q,j,n,g,k,jv;
long ux;
k=m*BP; /* 本屏首列的列号 */
s=malloc(HC); /* 给 s 分配内存 */
strcpy(s,ss[a]); /* 将要显示的文本行拷入 s */
g=strlen(s); /* 测字符串长 */
if(*(s+g-1)==0x0A) g-=2; /* 如串尾为回车换行符,串长减 2 */
n=(gZS+k)?(ZS+k):g; /* 如串尾在以后屏, 至串尾字符数取本行
前行字符数之和,否则取字符串长 */
if(g=k) *s=0; /* 如字符串尾在前面屏, 本屏为空串 */
else { /* 如字符串尾不在前面屏 */
for(j=0;jn;j++) {
if(*(s+j)0xA0) u++; /* 计算汉字字节数 */
if(m && j==k-1 && u%2) { /* 如本屏第一字节是汉字后半字节 */
*(s+k)=32; /* 本屏第一字节用空格代替 */
u++; /* 汉字字节数增 1 */
j++; /* 后移一字节 */
}
}
if(u%2) n++; /* 如本屏串尾是汉字前半字节,再多显示一字节 */
*(s+n)=0; /* 截除本屏后字符 */
strcpy(s,s+k); /* 去除本屏前字符,s 即为本屏显示的串 */
}
ux=xx-x+i; /* 计算本行的文本行号 */
q=strlen(s); /* 测 s 字符串长 */
for(;;) { /* 为文本行显示设的循环 */
if(uxksx || uxkwx) { /* 如本行在块首行前或块尾行后 */
write_string(i,0,s,TEXT_COLOR); /* 以文本色显示本行 */
break; /* 跳出循环 */
}
if(ux==kwx) { /* 如本行为块尾行 */
if(kwy=k) { /* 如块尾在本屏首字节之后 */
if(kwy=n) { /* 如块尾在本屏末字节之前 */
if(blck==1) { /* 如只设置了块首 */
if(*(s+kwy-k)0xA0) /* 如块首后一字节为全角 */
jv=kwy-k+2; /* 后移二字节开始显示文本色 */
else jv=kwy-k+1; /* 如为半角,后移一字节开始 */
}
else jv=kwy-k; /* 如已完整定义块,从块尾位置开始 */
write_string(i,jv,s+jv,TEXT_COLOR); /* 用文本色显示块后字串 */
*(s+jv)=0; /* 截除块尾后字节 */
}
}
else { /* 如块尾在本屏首字节前 */
write_string(i,0,s,TEXT_COLOR); /* 用文本色显示字符串 */
break; /* 跳出循环 */
}
}
if(ux==ksx && ksy=k) { /* 如本行为块首行,块首列在本屏首后 */
if(ksy=n) { /* 如块首列在本屏末字节前 */
jv=ksy-k; /* 从块首位置开始显示 */
write_string(i,jv,s+jv,BLCK_COLOR); /* 用字块色显示字块 */
*(s+jv)=0; /* 在 s 中截除块首后字节 */
}
write_string(i,0,s,TEXT_COLOR); /* 用文本色显示剩余部分 */
}
else write_string(i,0,s,BLCK_COLOR);
/* 如块首列在前屏或为块的其它行,用字块色显示 */
break; /* 跳出循环 */
}
write_space(i,q,FH+1-q,TEXT_COLOR); /* 用空格复盖本行串尾后屏幕 */
if(q=ZS) write_char(i,FH,'+',CHAR_COLOR);
/* 如串尾在以后屏,标志行显示+ */
else { /* 如串尾不在以后屏 */
if(ss[a][g]==0x8D) write_char(i,FH,'.',CHAR_COLOR);
/* 如串尾为软回车,标志行显示. */
if(ss[a][g]==0x0D) write_char(i,FH,'',CHAR_COLOR);
/* 如串尾为硬回车,标志行显示 */
}
free(s); /* 释放 s 占用的内存空间 */
}
disp_t() /* 显示一屏 */
{
int i;
for(i=0;i=H3;i++) { /* 为逐行显示设置的循环 */
cc.ii=bioskey(1); /* 判断是否按键 */
if(xx-x && xxttl_x && cc.ch[0]==0 &&
(cc.ch[1]==81 || cc.ch[1]==73 || cc.ch[1]==62))
return; /* 如连续按 PgUp、PgDn、F4 键,则返回 */
else {
if(xx-x+ittl_x) write_space(i,0,80,TEXT_COLOR);
/* 如超出文末行,清文末行后屏幕 */
else disp(ss_x-x+i,i); /* 否则显示一行 */
}
}
}
int key_digit(int e) /* 在 HH 行输入数字,e 为列坐标 */
{
char a[16];
int k=0;
while(1) { /* 为输入数字串设的循环 */
goto_xy(HH,e+k); /* 定光标位置 */
cc.ii=bioskey(0); /* 接收一个按键值 */
clear_prompt(); /* 清提示区 */
if(!cc.ch[0]) /* 如低位字节为 0 */
switch(cc.ch[1]) { /* 判断高位字节 */
case 75: /* 如为 Del 键或左移光标键 */
case 83: goto AA; /* 跳转 AA */
}
else /* 如低位字节不为 0 */
switch(cc.ch[0]) { /* 判断低位字节 */
case 27: return -1; /* ESC 键退回 */
case 13: a[k]=0; /* 按回车时确认值 */
if(!k) return 0; /* 如未输入数字,返回 0 */
return atoi(a); /* 否则,返回输入的数值 */
case 8: /* 如为退格键 */
AA: if(k) { /* 如不在首字节 */
a[--k]=0; /* 后退一字节填 ' ' */
write_char(HH,e+k,' ',PROM_COLOR); /* 原显示字节用空格复盖 */
}
break; /* 跳出开关语句 */
case 3: bk(); /* Ctrl+C 退至DOS下 */
default:
if(cc.ch[0]47 && cc.ch[0]58) { /* 如为数字 */
if(!k) write_space(HH,e,6,PROM_COLOR);
/* 如在首字节,用空格复盖原显示 */
a[k]=cc.ch[0]; /* 字符写入字符串中 */
write_char(HH,e+k,a[k],PROM_COLOR); /* 显示字符 */
k++; /* 移至下一位置 */
}
else write_prompt(4); /* 否则响铃,提示,返回重输 */
}
}
}
int key_string(int j,int e,unsigned char a[],int d) /* 输入字符串 */
{ /* j 行坐标,e 列坐标,a字符串,d显示属性 */
int i,k=0,jv;
while(1) { /* 为输入字符串设的循环 */
goto_xy(j,e+k); /* 光标定位 */
cc.ii=bioskey(0); /* 读击键值 */
if(!cc.ch[0]) /* 如低位字节为 0 */
switch(cc.ch[1]) { /* 判断高位字节 */
case 75: /* 如为删除键或左移箭头键,跳转AA */
case 83: goto AA;
case 73: a[0]=0; /* PgDn 键,返回 -4 */
return -4;
case 81: a[0]=0; /* PgUp 键,返回 -5 */
return -5;
}
else /* 如低位字节不为 0 */
switch(cc.ch[0]) { /* 判断低位字节 */
case 27: return -1; /* ESC 键,返回 -1 */
case 13: a[k]=0; /* 如为回车键,确认 */
return k; /* 返回输入的字节数 */
case 3: bk(); /* Ctrl+C 键,返回 DOS 下 */
case 8: /* 如为退格键 */
AA: if(k) { /* 如不为空串 */
for(;;) { /* 为删除全角字符设的循环 */
a[--k]=0; /* 前移一字节,填 ' ' */
write_char(j,e+k,' ',d);/* 空格复盖显示字节 */
jv=0; /* jv 置初值 0 */
for(i=0;ik;i++) /* 为统计全角字节数设的循环 */
if(a[i]0xA0) jv++; /* 如为全角字节,jv 加 1 */
if(jv%2==0) break; /* 如为偶数,退出 for 循环 */
}
}
continue; /* 继续循环 */
default:
if(cc.ch[0]31) { /* 如不为控制字符 */
a[k++]=cc.ch[0]; /* 写入字符串 */
a[k]=0; a[k+1]=0; /* 字符串结尾 */
write_string(j,e,a,d); /* 重显字符串 */
}
}
}
}
int key_yn(int e) /* 输入 Y 或 N */
{
char sf='N'; /* 置初值为 N */
while(1) {
write_char(HH,e,sf,PROM_COLOR); /* 在提问行显示字符 */
if(e==59) goto_xy(x,y); /* 替代操作时,光标定在找到的字符串尾 */
else goto_xy(HH,e); /* 其余情况下,光标定在提问行 */
cc.ii=bioskey(0); /* 读一击键值 */
clear_prompt(); /* 清提示区 */
if(cc.ch[0]) /* 如低位字节不为 0 */
switch(cc.ch[0]) { /* 判断低位字节 */
case 27: return -1; /* ESC 键,返回 -1 */
case 3 : bk(); /* Ctrl+C 键,返回 DOS 下 */
case 13: if(sf=='Y') return 1; /* 回车键,输入 Y 返回 1 */
else return 0; /* 否则返回 0 */
default:
if(cc.ch[0]=='y'||cc.ch[0]=='n'||cc.ch[0]=='Y'||cc.ch[0]=='N') {
/* 如为 Y 或 N */
sf=toupper(cc.ch[0]); /* 变为大写放入 sf */
write_char(HH,e,sf,PROM_COLOR); /* 显示字符 */
}
else write_prompt(5); /* 否则,提示必须输入 Y 或 N */
}
}
}
int gett() /* 输入用户反应 */
{
cc.ii=bioskey(0); /* 读击键值 */
switch(cc.ch[0]) { /* 根据低位码比较 */
case 27 : return -1; /* Esc 键返回 -1 */
case 3 : bk(); /* Ctrl+C 键退出运行 */
default : return 0; /* 按其他键返回 0 */
}
}