当前位置:网站首页>>电脑技术>>C、C++语言>>我的著作 双击自动滚屏
中西文全屏幕编辑程序的设计和编制(八)

发表日期:2006年1月1日      已经有3959位读者读过此文

                        第九章    用数字小键盘输入全角制表符

    用中文编辑软件画表格是人们经常进行的工作,全屏幕编辑软件的字块拷贝功能,使操作者只要画少数几行表格线,就能迅速复制出整个空表格来。但是不少汉字操作系统设计时没有考虑全角制表符的输入问题,因此操作者不得不用区位码方式输入中文制表符,费工费时,如果一时找不到国标区位码表,更是欲画不能。为了妥善地解决这个问题,我们介绍一种非常方便实用的方法,即用数字小键盘输入全角的中文制表符。

                           9.1 用数字小键盘画表格线的构想

    在微机键盘的右部有一个数字小键盘,它既可以当数组键盘用,又可以当Home、End、 PgUp、PgDn、Ins、Del 和箭头键用。两种功能的切换是依靠 Num_Lock 键进行的,也可以使用 Shift 键和这些键的组合来实现。
    用数字小键盘输入全角制表符是通过编制一定的转换程序来实现的,使操作者按小键盘的各数字键或“+”“-”键时,程序将它自动转换成对应的全角制表符,输入到编辑文本中去。
    国标 GB 5007-85 图形字符代码表的第九区中规定的全角制表符共有七十多个,包含了用粗实线和细实线画制表符的各种组合,要用数字小键盘的键对应这么多的制表符,显然是难于做到的。但是仔细分析一下,就可以发现,如果只用一种实线画表格,则只要十一个制表符就够了。这样画出来的表格已基本上能满足大部分情况下工作的需要。这十一个制表符是:

    ┃  ━  ┏  ┳  ┓  ┣  ┫  ┗  ┻  ┛  ╋

    为了便于记忆,将它们和数字小键盘相关的键分别按图 9.1 对应:


      ┌──┬──┬──┬──┐             ┌──┬──┬──┬──┐
      │ 7 │ 8 │ 9 │ - │             │ ┏ │ ┳ │ ┓ │ ━ │
      │    │    │    │    │             │    │    │    │    │
      ├──┼──┼──┼──┤             ├──┼──┼──┼──┤
      │ 4 │ 5 │ 6 │ + │             │ ┣ │ ┃ │ ┫ │ ╋ │
      │    │    │    │    │             │    │    │    │    │
      ├──┼──┼──┼──┘             ├──┼──┼──┼──┘
      │ 1 │ 2 │ 3 │                   │ ┗ │ ┻ │ ┛ │
      │    │    │    │                   │    │    │    │
      └──┴──┴──┘                   └──┴──┴──┘

            数字小键盘键位                         对应全角制表符


                     图 9.1 全角制表符和数字小键盘键位对应图


    数字小键盘上的数字键和加号、减号键的键盘扫描码和主键盘上这些键的扫描码是有区别的。如果用第 2.2 节中提供的测键盘扫描码的小程序 key 测试,可以发现两者扫描码的低位是对应相同的,但高位不同,并各有确定的值 (见表 9.1)。在设置为“表线”状态时,程序要同时判断高位和低位扫描码,以认定按的是否是数字小键盘上的键,这样就不会影响主键盘上数字键的正常使用了。


            ━━━━┳━━━━━━━━━┳━━━━━━━━━━
                    ┃  主键盘扫描码值  ┃ 数字小键盘扫描码值
             键  名 ┣━━━━┳━━━━╋━━━━┳━━━━━
                    ┃ 高  位 ┃ 低  位 ┃ 高  位 ┃ 低  位
            ━━━━╋━━━━╋━━━━╋━━━━╋━━━━━
               -    ┃   12   ┃   45   ┃   74   ┃   45
                    ┃        ┃        ┃        ┃
               +    ┃   13   ┃   43   ┃   78   ┃   43
                    ┃        ┃        ┃        ┃
               1    ┃    2   ┃   49   ┃   79   ┃   49
                    ┃        ┃        ┃        ┃
               2    ┃    3   ┃   50   ┃   80   ┃   50
                    ┃        ┃        ┃        ┃
               3    ┃    4   ┃   51   ┃   81   ┃   51
                    ┃        ┃        ┃        ┃
               4    ┃    5   ┃   52   ┃   75   ┃   52
                    ┃        ┃        ┃        ┃
               5    ┃    6   ┃   53   ┃   76   ┃   53
                    ┃        ┃        ┃        ┃
               6    ┃    7   ┃   54   ┃   77   ┃   54
                    ┃        ┃        ┃        ┃
               7    ┃    8   ┃   55   ┃   71   ┃   55
                    ┃        ┃        ┃        ┃
               8    ┃    9   ┃   56   ┃   72   ┃   56
                    ┃        ┃        ┃        ┃
               9    ┃   10   ┃   57   ┃   73   ┃   57
            ━━━━┻━━━━┻━━━━┻━━━━┻━━━━━


                     表 9.1 主键盘和小键盘扫描码对照表


                          9.2 表格线状态的切换

    为了不影响小键盘原有的功能,把 F10 键设计成表格线功能的“开关”键,调用函数 F10() 进行切换。当按一次 F10 键,小键盘的数字键切换成表格线状态,屏幕信息行显示醒目的“表线”二字,表格线状态开关变量 tab 置为真 (等于 1);再按一次 F10 键,小键盘又恢复数字输入状态,屏幕信息行的“表线”二字被抹去,表格线状态开关变量 tab置为假 (等于 0)。tab 是全局变量,它的初值为 0。读者不难看出,F10() 函数的格式和插入状态开关函数 Ins() 的工作原理是一样的。

F10()
{
  if(tab) {                          /* 如 tab 为真 */
    tab=0;                           /* 转置 tab 为 0 */
    write_space(H1,4,4,TEXT_COLOR);  /* 用空格盖掉屏幕上“表线”提示 */
  }
  else  {                            /* 如 tab 为假 */
    tab=1;                           /* 转置 tab 为 1 */
    write_string(H1,4,"表线",0x1E);  /* 显示“表线”二字 */
  }
}

                 9.3 用数字小键盘输入全角制表符的实现

    在第 8.4 节介绍的字符输入函数 Chr() 中调用了一个函数 make_tab(),这个函数的作用就是:当表格线开关变量 tab 为真时,判断所按的键是否是数字小键盘上的对应于全角制表符的键,如果是的话,把它转换成相应全角制表符的两个字节的 ASCII 码。它的第一字节均为0xA9,代替原来从键盘接收的扫描码,放在 cc.ch[0] 中,第二字节暂存在字符型变量 two 中,并将表格线标志变量 qq 置为 1。全局变量 qq 的初值在 Chr() 中被置为 0。
    从表 9.1 可以看出小键盘上的数字键和“+”、“-”号键的高位码为 71─81,低位码为 0 时对应 Home、End 等功能键,低位码不为 0 时对应数字键,因而可据此进行判断。

make_tab()                         /* 形成表格线 */
{
  if(tab && cc.ch[1]>70 && cc.ch[1]<82 && cc.ch[0])  {
                                   /* 如为表格线状态,并是小键盘的数字键 */
    switch(cc.ch[0])  {            /* 判断按键低位码 */
      case 45: two=0xA5;           /* 如为“-”键,定“━”的第二字节 */
               break;              /* 跳出开关语句 */
      case 43: two=0xEF;           /* 如为“+”键,定“╋”的第二字节 */
               break;              /* 跳出开关语句 */
      case 49: two=0xBB;           /* 如为“1”键,定“┗”的第二字节 */
               break;              /* 跳出开关语句 */
      case 50: two=0xDF;           /* 如为“2”键,定“┻”的第二字节 */
               break;              /* 跳出开关语句 */
      case 51: two=0xBF;           /* 如为“3”键,定“┛”的第二字节 */
               break;              /* 跳出开关语句 */
      case 52: two=0xC7;           /* 如为“4”键,定“┣”的第二字节 */
               break;              /* 跳出开关语句 */
      case 53: two=0xA7;           /* 如为“5”键,定“┃”的第二字节 */
               break;              /* 跳出开关语句 */
      case 54: two=0xCF;           /* 如为“6”键,定“┫”的第二字节 */
               break;              /* 跳出开关语句 */
      case 55: two=0xB3;           /* 如为“7”键,定“┏”的第二字节 */
               break;              /* 跳出开关语句 */
      case 56: two=0xD7;           /* 如为“8”键,定“┳”的第二字节 */
               break;              /* 跳出开关语句 */
      case 57: two=0xB7;           /* 如为“9”键,定“┓”的第二字节 */
               break;              /* 跳出开关语句 */
    }
    cc.ch[0]=0xA9;                 /* 定表格线第一字节 */
    qq=1;                          /* 表格线字符标志置 1 */
  }
}

    让我们再回到第 8.4 节的函数 Chr(),Chr() 中把一个字节写入字符串后,有以下一段程序:

if(qq)  {                    /* 如为全角制表符 */
  qq=0;                      /* 表格线标志变量置 0 */
  cc.ch[0]=two;              /* 暂存在 two 中的表格线第二字节放入 cc.ch[0] */
  goto AA;                   /* 返回 AA,进行排版,并写入第二字节 */
}

    在这段程序里,当判定为全角制表符时,把 make_tab() 暂存在 two 中的表格线第二字节放入 cc.ch[0],用 goto 语句回到前面标号 AA 处,如同又从键盘接收到一个字符一样,再进行排版,并写入编辑文本,表格线标志变量 qq 恢复初值 0。
    上面程序里用的都是粗实线构成的全角制表符,如果读者希望改成细实线的全角制表符,只要改变相应的 two 值。

                        第十章  文本的存盘和退出编辑

    文本的存盘旨在保存编辑工作的成果,文本存盘根据存盘后是否退出编辑可分为两种情况,一种是存盘后退出编辑,另一种是存盘但不退出编辑。我们指定按 F1 键,调用 F1() 函数实现存盘退出,按组合键 Shift+F1 调用函数 Shift_F1()实现存盘不退出。在编辑时按 Esc 键或按组合键 Ctrl+C,则放弃编辑文本,退出编辑。

                            10.1 编辑文本的存盘

    由于在编辑过程中文本文件并不都在编辑数组里,在编辑修改一个老文件时,可能出现以下的复杂情况,即文件开头的一部分在临时文件 1 中(带后扩展名 $1$,文件名在 file1 里,文件指针为 fp1),接下来的一部分在编辑数组里,其后一部分在临时文件 2 中(带扩展名 $2$,文件名在 file2 里,文件指针为 fp2),最后的从未读入编辑数组的部分还在老文件中 (文件名在 mfile 里,文件指针为 fp)。存盘操作必须把这几部分文本按次序集中到一个磁盘文件里,存盘操作函数的设计就是基于上述典型情况来考虑的。
    把几部分集中到一个文件里的方法可以是各种各样的,本文中的 F1() 函数按以下步骤进行:
    (1) 先根据标志变量 chg 判断文本文件是否修改过,如文本文件没有修改过 (chg 为假),则无须重新存盘,如 chg 为真则进行存盘操作。
    (2) 如果原来有扩展名为 BAK 的后备文件,删除该后备文件。
    (3) 如原有老文件,测出它的当前读写指针位置,保存在变量 b 中,关闭该文件,并将其改名为扩展名为 BAK 的后备文件。用只读方式打开该后备文件,文件指针为 fp3。
    (4) 用写方式建立新的正文文件,文件指针仍赋于 fp。
    (5) 临时文件 1 中的记录拷入 fp 里。从临时文件 1 的文首开始,在一个循环中,交替使用库函数 fread() 把每次写入 fp1 的文本放入一个内存缓冲区和用 fwrite() 把缓冲区中的内容写入 fp,直到 fp1 的当前读写位置为止。
    (6) 把编辑数组中的文本写入 fp,可利用已建立的函数 write_to(),把编辑数组中的实有文本,即从数组第 0 行起到 ss_max 行的共 ss_max+1 行,用 write_to() 函数写入 fp。
    (7) 把 fp2 中的内容并入 fp。因为 fp2 中的文本不是顺序摆放的,这在图 1.3 中看得很清楚, 所以必须反方向分区段一块一块地搬到 fp 中去。以图 1.3 中的情况为例,最后 fp2 (即 AAA.$2$) 前面绝对位移 wrb[0]─wrb[1] 之间放的是文本第 500─699 行,从 wrb[1]─wrb[2] 间放的是文本第 300─499 行。这样在文本存盘时就要先把 fp2 的读写指针移到 wrb[1] 处,把第 300─499 行用库函数 fread() 读出到内存缓冲区,用 fwrite() 写到 fp 里,然后再把 fp2 的读写指针移到 wrb[0],用同样的方法把第 500─699 行移到 fp 中去。
    (8) 用库函数 ftell() 测出 fp 当前读写指针位置,放入全局变量 vw,此值在继续编辑时为正文文件的当前读写位置。
    (9) 如果标志 fp_end 为假, 老的正文文件中尚未读完,其内容已经转移到后备文件中去了,用 fseek 使 fp3 恢复 b 中保存的读写指针位置,用库函数 fread() 和 fwrite()分一次或多次把原老文件中中剩余部分拷至 fp,最后用库函数 fputc() 加一个文件结束符号 0x1A 到 fp 末尾,fp 中已是应存盘的完整的正文文件了。这时可用库函数 fclose() 关闭 fp3 和 fp。
    (10) F1() 带有形式参数 a,当 a 为真时,通过函数 bk() 退出运行。参数 a 是供区别存盘退出和存盘不退出用的。

F1(int a)                          /* 文本存盘,a=1 退出,a=0 不退出 */
{
  unsigned int i,j;
  long b;
  if(chg) {                        /* 如文件已修改过 */
    write_prompt(0);               /* 提示“请稍候...” */
    if(!findfirst(bfile,pt,0))     /* 如有后备文件 */
      remove(bfile);               /* 删除原后备文件 */
    if(old) {                      /* 如原有老文件 */
      b=ftell(fp);                 /* 测出老文件当前读写指针位置 */
      fclose(fp);                  /* 关闭老文件 */
      rename(mfile,bfile);         /* 改为带扩展名 BAK 的后备文件 */
    }
    fp3=fopen(bfile,"rb");         /* 打开后备文件,文件指针赋于 fp3 */
    fp=fopen(mfile,"wb+");         /* 重建正文文件,文件指针仍放 fp 中 */
    ddd=malloc(KK);                /* 为 ddd 分配内存 */
    i=0;                           /* i 置初值 0 */
    while(i<oa)  {                 /* fp1 中记录并入 fp */
      fseek(fp1,wra[i++],SEEK_SET);/* fp1 指针移到读写起始处 */
      j=wra[i]-wra[i-1];           /* 计算读入字节数 */
      fread(ddd,sizeof(char),j,fp1);  /* 从 fp1 读入 j 字节至 ddd */
      fwrite(ddd,sizeof(char),j,fp);  /* 将 ddd 中内容写入 fp */
    }
    write_to(0,ss_max+1,fp);       /* 缓冲区数组的记录写入 fp */
    write_prompt(0);               /* 提示“请稍候...” */
    i=ob;                          /* ob 为 fp2 中最后一次读写指针数组序号 */
    while(i)  {                    /* fp2 中记录并入 fp */
      fseek(fp2,wrb[--i],SEEK_SET);/* fp2 指针移到前一读写起始处 */
      j=wrb[i+1]-wrb[i];           /* 计算读入字节数 */
      fread(ddd,sizeof(char),j,fp2);   /* 从 fp2 读入 j 字节至 ddd */
      if(*(ddd+j)==0)  j-=1;           /* 消除 wfp2() 读入文末部分时加的 ''''\0'''' */
      fwrite(ddd,sizeof(char),j,fp);   /* 将 ddd 中内容写入 fp */
    }
    vw=ftell(fp);                  /* 保存 fp 指针位置 */
    if(!fp_end) {                  /* 如原文件未全部读完,剩余部分拷入 fp */
      fseek(fp3,b,SEEK_SET);       /* 移至原老文件当前读写位置 */
      for(;;)  {
        j=fread(ddd,sizeof(char),KK,fp3);  /* 每次从 fp3 读入 KK 字节到 ddd */
        fwrite(ddd,sizeof(char),j,fp);     /* 将 ddd 中内容写入 fp */
        if(j<KK)  break;           /* 如读出字节数不足 KK,文件已读完,退出 */
      }
    }
    else   fputc(0x1A,fp);         /* 否则加文件结束标志 */
    fclose(fp3);                   /* 关闭 fp3 */
    fclose(fp);                    /* 关闭 fp */
    free(ddd);                     /* 释放 ddd 占用的内存空间 */
  }
  if(a)  bk();                     /* 如 a 为真,退出运行 */
}

                         10.2 存盘不退出编辑

    按组合键 Shift+F1 可以实现存盘后不退出编辑,操作者在编辑过程中,可定时进行此操作, 旨在预防因发生突然掉电等意外情况,而使编辑劳动全功尽弃。本功能调用的函数为 Shift_F1()。当文件修改标志变量为真时,执行的步骤为:先调用函数 F1(0) 存盘,因为存盘后不退出,所以 F1() 带的实参为 0。不论开始编辑时是否存在老文件,用 F1() 存盘后,存盘的正文文件均应被视为老文件,故将老文件标志变量 old 置为真。重新打开正文文件,fp 的当前读写指针位置在函数 F1() 中已用库函数 ftell() 测出并放在全局变量 vw 中,应用库函数 fseek() 恢复 fp 的读写指针位置。因文本已经存盘,编辑将重新开始,故文件修改标志 chg 置为 0。
    至此已完全恢复到存盘前的编辑状态,可以继续进行编辑操作了。在整个存盘过程中,当前光标位置没有发生任何变化,因此不须改变屏幕显示。

Shift_F1()                         /* 存盘,不退出编辑 */
{
  int i,j;
  if(chg) {                        /* 如果文件已修改过 */
    F1(0);                         /* 存盘 */
    old=1;                         /* 有老文件标志置 1 */
    fp=fopen(mfile,"rb");          /* 重新打开正文文件 */
    fseek(fp,vw,SEEK_SET);         /* fp 读写指针复原 */
  }
  clear_prompt();                  /* 清提示区 */
  chg=0;                           /* 文件已修改标志置 0 */
}

                             10.3 不存盘退出

    不存盘退出是操作者对编辑文本的修改或输入不满意,而决定不保留编辑文本所采取的动作。BJ 设计了两种不存盘退出方式,一种通过按 Esc 键调用函数 Esc() 完成的,另一种是按组合键 Ctrl+C 调用函数 bk() 强行退出的。

Esc()                            /* 放弃存盘,退出编辑 */
{
  if(chg) {                      /* 如文本已修改过 */
    write_ques(0);               /* 提问:是否放弃并退出编辑 */
    if(key_yn(26)<1) {           /* 如输入的不是 Y */
      clear_ques();              /* 清提问区 */
      return;                    /* 返回,继续编辑 */
    }
  }
  bk();                          /* 退出程序,至 DOS 下 */
}

    为了防止因误按 Esc 键未存盘退出,使编辑文本丢失,在文本文件已修改过的前提下,函数 Esc() 先提问:“是否放弃并退出编辑 (Y/N)”,以提醒操作者,如操作者回答“N”,则继续编辑。如回答“Y”,调用函数 bk() 退出运行,至 DOS 提示符下。而用 Ctrl+C 退出则是不加上述保护的。
    函数 bk() 用库函数 fcloseall() 关闭所有打开的文件,删除临时文件,清全部屏幕,置光标于屏幕左上角,最后通过 exit() 使程序退出运行,把控制权交回操作系统。

bk()                         /* 退出运行,至 DOS 下 */
{
  fcloseall();               /* 关闭所有打开的文件 */
  remove(file1);             /* 删除临时文件 1 */
  remove(file2);             /* 删除临时文件 2 */
  clss(0,HH);                /* 清屏 */
  goto_xy(0,0);              /* 光标置屏幕左上角 */
  exit(0);                   /* 退出运行 */
}

                            第十一章    文本的打印

    许多编辑软件打印文本是在退出编辑的情况下,在文件级通过菜单选择进行的。怎样做到在编辑状态下打印文本呢 我们采用了一个简单的办法,即用函数 Shift_F1() 把编辑文本的各部分存盘,放入正文文件 fp 中,再打印这个文件。打印操作是通过按 Ctrl+P 完成的。

                             11.1 打印参数的输入

    为了适应最基本的打印需要,本文的打印模块设置了分页打印的功能,要进行分页打印,首先要输入有关参数,如每页打印的行数、页号所在的列坐标、打印起始页号等。Ctrl_P() 函数中这一部分的操作可以用以下的一段指令来完成:

Ctrl_P()
{
   int j,k,pg;
   ........
   write_ques(8);                        /* 提问每页打印行数 */
   if((j=key_digit(22))<=0) {            /* 输入行数,如为空串或按 ESC 键 */
      clear_ques();                      /* 清提问区 */
      return;                            /* 退出本功能 */
   }
   write_ques(12);                       /* 提问页号位置 */
   if((k=key_digit(20))<=0) {            /* 输入起始列号,如为空串或按ESC键 */
      clear_ques();                      /* 清提问区 */
      return;                            /* 退出本功能 */
   }
   write_ques(13);                       /* 提问起始页号 */
   if((pg=key_digit(16))<=0) {           /* 输入起始页号,如为空串或按ESC键 */
      clear_ques();                      /* 清提问区 */
      return;                            /* 退出本功能 */
   }
   ........
}

                              11.2 打印输出操作

    在用户输完有关打印参数之后,Ctrl_P() 调用存盘不退出函数 Shift_F1() 将当前编辑的文本集中存放到正文文件中,把打印机视同一个字符流文件用写方式打开,其指针赋给 fpw,打开主文本文件 mfile,指针赋给 fpr。

Ctrl_P()
{
   FILE *fpw,*fpr;
   ........
   Shift_F1();                         /* 存盘不退出 */
   fpw=fopen("PRN","w");               /* 打开设备文件(打印机),指针赋于 fpw */
   if((fpr=fopen(mfile,"rb"))==NULL) { /* 打开正文文件,指针赋于fpr,失败返回 */
      clear_ques();                    /* 清提问区 */
      return;                          /* 退出打印 */
   }
   ........
}

    程序还要提醒操作者将打印机和打印纸调整好,这个提示是用 write_ques(10) 函数完成的。如果用户对“请调好打印纸,按任一键开始打印。”的提示按 Esc 键,则退出打印,如按动了回车或其他键,则程序进入打印操作状态。Ctrl_P() 中这段程序如下:

Ctrl_P()
{
   ........
   write_ques(10);                     /* 提示:调整好打印机,按一键开始打印 */
   if(gett()==-1||tpt()==-1) {         /* 测打印机,如按 Esc 键 */
      fclose(fpr);                     /* 关闭 fpr */
      clear_ques();                    /* 清提问区 */
      return;                          /* 退出打印 */
   }
   ........
}

    函数 gett() 等待一个按键,如接收的是 Esc 键则返回-1,如为 Ctrl+C 组合键则调用 bk() 退出编辑,对其他键均返回 0。在上面这段程序中还调用了一个函数 tpt(),这是一个打印机测试函数,我们将在下一节中讲述。
    文本的打印是依靠以下程序完成的:

Ctrl_P()                                   /* 文本打印 */
{
  unsigned char prt[HC];                   /* 为读文本行设置的缓冲区 */
  int i,b=0;
  ........            /* (文本存盘、输入打印参数和打开文本文件和设备文件) */
  while(1) {                               /* 为分页打印设的循环 */
    ........                        /* (提示调整好打印机和测试打印机状态) */
    for(i=0;i<j;i++) {                     /* 为一页内分行打印设的循环 */
      if(fgets(prt,255,fpr)==NULL) {       /* 从 fpr 读入一行至 prt, 如失败 */
         while(i++<j) {                    /* 未打满一页则循环 */
           fprintf(fpw,"\n");              /* 打印一空行 */
           b=1;                            /* 文件结束标志置 1 */
         }
         break;                            /* 跳出 for 循环 */
      }
      for(a=0;prt[a];a++) {                /* 去除字符串中的回车换行符 */
        if(prt[a]==0x0D || prt[a]==0x8D)
        break;
      }
      prt[a]=0;                            /* 字符串以''''\0''''定界 */
      fprintf(fpw,"%s\n",prt);             /* 打印一行 */     
    }
    fprintf(fpw,"\n");                     /* 打印一空行 */
    for(a=0;a<k;a++) fprintf(fpw," ");     /* 打印页号前空格 */
    fprintf(fpw,"·%d·\n",pg++);          /* 打印页号 */
    if(b) break;                           /* 如打印完全文,退出 while 循环 */
  }
  ........
}

    整个打印过程在一个 while(1) 循环中完成,每页循环一次,直到全文打印完毕才跳出循环。打印时采用从文本文件中读一行后,再向打印机输出一行的操作。也就是用 fgets()从 fpr 读出一行至 prt 中,除掉行末的回车换行符,再送到 fpw 打印。一页打印完后,隔一空行,打印页号。在文本最后一页,如果打印的行数少于满页行数,则用空行补足,再打印页号。
    以上介绍的是文件打印最基本的程序,当然有兴趣的读者不妨在这一模块中再做点文章,使得打印的方式更加丰富多彩。文件打印完毕,系统将返回打印前的文本文件编辑状态。

                          11.3 打印机状况的测试

     在打印机未打开或缺纸等情况发生时,有必要提醒操作者及时采取措施,判断打印机是否已准备好,方法是从 0x379 端口取一字节,如果该字节等于 0xDF,则可判定打印机已准备好,否则提示“打印机未准备好,请准备好打印机,按任一键继续。”。实现这个功能的函数是 tpt():

int tpt()                         /* 打印机状态测试 */
{
  while(1)  {                     /* 为重复测试建的循环 */
    if(inp(0x379)==0xDF)  break;  /* 取 0x379 端口值,如等于 0xDF,跳出循环 */
    else  write_ques(9);          /* 否则提示打印机未准备好 */
    if(gett()==-1)   {            /* 等待按键,Esc 键返回 -1,否则继续循环 */
      clear_ques();               /* 清提问区 */
      return -1;                  /* 返回 -1 */
    }
  }
  write_ques(11);                 /* 提示“正在打印...” */
  return 0;                       /* 返回 0 */
}

    至此本书讲述的内容已告结束,必须指出,本书介绍的设计编制一个全屏幕编辑软件的总体构思和各种操作功能的实现方法都不是唯一的,也未必是最好的,仅希望起到一个抛砖引玉的作用。在编制 C 语言程序时,我们主张把一个复杂的问题分成许多个小块,而不是编成一个大函数,每个小块编制一个函数,这样做的好处是各部分功能单一,相对独立。就象搭积木一样,有了这许许多多小“积木”,就能组合成丰富多彩的图案来。
    本文附录为读者提供了一个完整的中西文全屏幕编辑软件 BJ 的全部源程序清单,把它正确的输入计算机,用 2.0 以上版本的 Turbo C 用 Compact 模式编译、连接成可执行的 BJ.EXE 文件,就是一个功能很强的编辑软件,而它的大小却只有 32K,充分体现了 C 语言代码简洁、效率高的优点。
    读者完全可以在这个程序的基础上,增加新的功能模块,进一步扩展功能。例如希望增添一个“帮助”功能,就可以编写一个功能函数,先在当前屏幕文本显示区用 clss() 函数清出几行屏幕,用 write_string() 函数把各功能键的提示显示在里面,并用 gett() 函数等待用户的反应,当接收用户一个击键后,用 disp_t() 函数重显编辑屏幕。


相关专题: 我的著作
专题信息:
  C语言速成(第三章 程序控制语句)(2006-1-1 13:51:28)[9418]
  C语言速成(第七章 联合、枚举和自定义数据类型)(2006-1-1 13:51:46)[10048]
  C语言速成(第六章 结构)(2006-1-1 13:52:05)[8827]
  C语言速成(第五章 指针)(2006-1-1 17:28:54)[4568]
  C语言速成(第四章 数组)(2006-1-1 13:52:42)[4713]

相关信息:
 没有相关信息
  打印本页
设为首页 | 加入收藏 | 联系我们 | 管理入口
皖ICP备05018956号
Copyright © 2003 J.W.SHEN All Rights Reserved
后台管理系统 V1.0 制作