免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4528 | 回复: 6
打印 上一主题 下一主题

[SCO UNIX] 在Sco下利用Curses/Form建立简单的用户界面(三) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-01-27 00:27 |只看该作者 |倒序浏览
在Sco下利用Curses/Form建立简单的用户界面(三)

  1. 在使用表单工作时,有时不希望使用new_field()来一个域一个域地建立表单,这样做不仅麻烦也不便与修改,每次画面变更之后还要重新编译。这里我们采用一个更加通用的方法--建立一个表单格式定义文件,使程序代码在每次调用表单时都读取这个文件,搜索指定表单,不用重新编译,就可以马上改变画面。
  2. 这个表单定义文件的格式是:
  3. 1001*0*联机签到
  4. 1001|0|000|柜   员:|12|24||......
  5. 1001|0|001||12|32|8|......
  6. 1001|0|002|密   码:|14|24||......
  7. 1001|0|003||14|32|8|......
  8. 1002*0*修改柜员密码
  9. ......
  10. 每个表单在此文件中有一个唯一的主画面号。比如1001等,几个副画面号如0 1 等,在定义时用*分隔;而表单中的每一个域都在此文件中定义,表单域的各特征项如所属主画面号、副画面号、序号、名称、位置、长度、是否标签域、是否密码域、是否返回、所用缓冲区号、对齐、类型等等都用|分隔。这些时建域时使用的。
  11. 要利用此文本文件建域,就需要一些工作:
  12. 首先以画面号、副画面号来读取文件中的域定义:

  13. CLFIELDNODE **cl_readfields(hm, fhm)
  14. char        *hm;
  15. char        *fhm;
  16. {

  17.         int        i;
  18.         int        cnt;

  19.         CLFIELDNODE        **fnode;

  20.         huamian = (CLHMFORM *)malloc(sizeof(CLHMFORM));
  21.         memset(huamian, 0, sizeof(CLHMFORM));

  22.         if((cnt = cl_readhuamian(hm, fhm)) <= 0)       
  23.                 return((CLFIELDNODE **)0);
  24.        
  25.         fnode = (CLFIELDNODE **)calloc(cnt + 1, sizeof(CLFIELDNODE));
  26.        
  27.         for(i = 0; i < cnt; i++)        {
  28.                 fnode[i] = cl_convdefine(huamian->slavelist[i]);
  29.         }

  30.         fnode[cnt] = (CLFIELDNODE *)0;
  31.        
  32.         return(fnode);

  33. }
  34. 注意,这里的huamian是一个全局量,定义为CLHMFORM类型指针,此类型在头文件中定义为:
  35. typedef        struct        _master        {
  36.         char        hmlevel[1];
  37.         char        hmname[20];
  38.         char        hmtype[1];
  39.         CLSLAVE        slavelist[MAX_FIELDS];
  40. }        CLHMFORM;
  41. CLSLAVE的定义是与画面定义文件中的域的每一行的项目一一对应,含有各域的各种特性。
  42. cl_convdefine()函数转换从表单定义文件读取的域特性信息,他将CLSLAVE类型转换成可用于域属性设置及可用于set_field()和new_field()等函数的类型。CLFIELDNODE结构成员与CLSLAVE的成员一一对应,只不过成员的类型已经从字符数组变成了可用于建域的各种类型。
  43. CLFIELDNODE *cl_convdefine(slave)
  44. CLSLAVE        slave;
  45. {

  46.         static char        *t = NULL;

  47.         CLFIELDNODE        *data;
  48.        
  49.         data = (CLFIELDNODE *)malloc(sizeof(CLFIELDNODE));
  50.         memset(data, 0, sizeof(CLFIELDNODE));

  51.         t = strstr(slave.length, ".");
  52.         data->pad = atoi(++t);
  53.         t = strtok(slave.length, ".");
  54.         data->length = atoi(t);
  55.         data->id = atoi(slave.seri);
  56.         data->y = atoi(slave.y);
  57.         data->x = atoi(slave.x);

  58. /*
  59.         strncpy(data->name, ut_stripstring(slave.name, " "), 32);
  60. */
  61.         strncpy(data->name, slave.name, LABEL_MAX_LEN);
  62.         data->buffnum = atoi(slave.bufnum);

  63.         switch(CONV_TYPE(slave.just))        {
  64.                 case 'C' :
  65.                         data->just = JUSTIFY_CENTER;
  66.                         break;
  67.                 case 'L' :
  68.                         data->just = JUSTIFY_LEFT;
  69.                         break;
  70.                 case 'R' :
  71.                         data->just = JUSTIFY_RIGHT;
  72.                         break;
  73.                 case 'N' :
  74.                         data->just = NO_JUSTIFICATION;
  75.                         break;
  76.                 default :
  77.                         data->just = NO_JUSTIFICATION;
  78.                         break;

  79.         }

  80.         data->ftype = _caseyn(slave.ftype);
  81.         data->selectable = _caseyn(slave.selectable);
  82.         data->inputflag = _caseyn(slave.inputflag);
  83.         data->visible = _caseyn(slave.visible);
  84.         data->passflag = _caseyn(slave.passflag);
  85.         data->enable = _caseyn(slave.enable);
  86.         data->autoskip = 0;
  87.         data->fullflag = _caseyn(slave.fullflag);
  88.         data->pageflag = _caseyn(slave.pageflag);
  89.         data->recvflag = _caseyn(slave.recvflag);
  90.         data->retuflag = _caseyn(slave.retuflag);
  91.         data->retubuff = atoi(slave.retubuf);

  92.         strncpy(data->ddefault, slave.ddefault, LABEL_MAX_LEN);
  93. /*
  94.         strncpy(data->ddefault, ut_stripstring(slave.ddefault, " "), 32);
  95. */

  96.         switch(CONV_TYPE(slave.dtype))        {
  97.                 case 'A' :
  98.                         switch(slave.dtype[1])        {
  99.                                 case 'N' :
  100.                                         data->dtype = 0;
  101.                                         break;
  102.                                 case 'L' :
  103.                                         data->dtype = 2;
  104.                                         break;
  105.                                 case 'M' :
  106.                                         data->dtype = 8;
  107.                                         break;
  108.                                 default :
  109.                                         data->dtype = 0;
  110.                                         break;
  111.                         }
  112.                         break;

  113.                 case 'E' :
  114.                         data->dtype = 3;
  115.                         break;
  116.                 case 'P' :
  117.                         data->dtype = 4;
  118.                         break;
  119.                 case 'D' :
  120.                         if(slave.dtype[1] == 'I')
  121.                                 data->dtype = 1;
  122.                         else        data->dtype = 5;
  123.                         break;
  124.                 case 'R' :
  125.                         data->dtype = 6;
  126.                         break;
  127.                 case 'S' :
  128.                         data->dtype = 7;
  129.                         break;
  130.                 default :
  131.                         data->dtype = 0;
  132.                         break;
  133.         }

  134.         return(data);
  135. }

  136. cl_readhuamian()函数打开表单定义文件,用正规式和fgets()读取表单主、副画面号和域定义,他以主、副画面号为参数,利用读取带分隔符字符串的函数ut_readtext()将此画面的域定义读到全局量huamian。返回此表单画面的域数量。
  137. int cl_readhuamian(h, f)
  138. char        *h, *f;
  139. {

  140.         int        p = 0;
  141.         int        cnt = 0;
  142.         int        *t_ps = &cnt;

  143.         static char        hm[80];
  144.         static char        tmpstr[8];
  145.         static char        tstr[200];

  146.         FILE        *pfp;

  147.         if(strcmp(f, " "))        sprintf(hm, FMT2, h, '*', f);
  148.         else        sprintf(hm, "grep \"^%s\\%c\\*\" %s | tail -1", h, '*', EFPATH);

  149.         memset(tstr, 0, 200);
  150.         if(strcmp(f, " "))        sprintf(hm, FMT1, h, f);
  151.         else        sprintf(hm, FMT1, h, "|");

  152.         pfp = popen(hm, "r");
  153.        

  154.         while(fgets(tstr, 180, pfp) != NULL)        {
  155.                 p = 0;
  156.         strcpy(tmpstr, ut_readtext(tstr, "|", &p));
  157.         strcpy(tmpstr, ut_readtext(tstr, "|", &p));
  158.         strcpy(huamian->slavelist[*t_ps].seri, ut_readtext(tstr, "|", &p));
  159.         strcpy(huamian->slavelist[*t_ps].name, ut_readtext(tstr, "|", &p));
  160.         strcpy(huamian->slavelist[*t_ps].y, ut_readtext(tstr, "|", &p));
  161.         strcpy(huamian->slavelist[*t_ps].x, ut_readtext(tstr, "|", &p));
  162.         strcpy(huamian->slavelist[*t_ps].length, ut_readtext(tstr, "|", &p));
  163.         strcpy(huamian->slavelist[*t_ps].ftype, ut_readtext(tstr, "|", &p));
  164.         strcpy(huamian->slavelist[*t_ps].bufnum, ut_readtext(tstr, "|", &p));
  165.         strcpy(huamian->slavelist[*t_ps].just, ut_readtext(tstr, "|", &p));
  166.         strcpy(huamian->slavelist[*t_ps].selectable, ut_readtext(tstr, "|", &p));
  167.         strcpy(huamian->slavelist[*t_ps].inputflag, ut_readtext(tstr, "|", &p));
  168.         strcpy(huamian->slavelist[*t_ps].fullflag, ut_readtext(tstr, "|", &p));
  169.         strcpy(huamian->slavelist[*t_ps].enable, ut_readtext(tstr, "|", &p));
  170.         strcpy(huamian->slavelist[*t_ps].visible, ut_readtext(tstr, "|", &p));
  171.         strcpy(huamian->slavelist[*t_ps].passflag, ut_readtext(tstr, "|", &p));
  172.         strcpy(huamian->slavelist[*t_ps].dtype, ut_readtext(tstr, "|", &p));
  173.         strcpy(huamian->slavelist[*t_ps].ddefault, ut_readtext(tstr, "|", &p));
  174.         strcpy(huamian->slavelist[*t_ps].pageflag, ut_readtext(tstr, "|", &p));
  175.         strcpy(huamian->slavelist[*t_ps].recvflag, ut_readtext(tstr, "|", &p));
  176.         strcpy(huamian->slavelist[*t_ps].retuflag, ut_readtext(tstr, "|", &p));
  177.         strcpy(huamian->slavelist[*t_ps].retubuf, ut_readtext(tstr, "|", &p));
  178.                 (*t_ps)++;
  179.         }
  180.         pclose(pfp);

  181.         return((*t_ps));

  182. }

  183. 读取了表单画面文件中的域定义内容之后,就经过转换就可以利用new_field()建立各域,利用前面讲的cl_dispform()和cl_inputdata()就可以显示表单、进入输入循环了。

  184. cl_dispform()调用了cl_createform()。他接收两个参数:主画面号、副画面号,返回一个FORM结构指针。

  185. FORM *cl_createform(hm, fhm)
  186. char        *hm, *fhm;
  187. {
  188.        
  189.         static        FORM        *form;
  190.         static        int        fldcnt;

  191.         fldcnt = cl_countfldnum(hm, fhm);
  192.         if(fldcnt > 0)        {
  193.                 form = new_form(cl_createfields(cl_readfields(hm,fhm), fldcnt));
  194.                 return(form);
  195.         }

  196. /*
  197.         if(form)        return(form);
  198. */
  199.         else        return((FORM *)0);
  200. }

  201. 先说明一下cl_countfldnum(),他的主要作用是返回一个整形变量来表示本画面共有多少个域。借助一个自增的整型指针。
  202. int cl_countfldnum(h, f)
  203. char        *h, *f;
  204. {

  205.         int        cnt = 0;
  206.         int        *t_ps = &cnt;

  207.         static char        hm[80];
  208.         static char        tstr[200];

  209.         FILE        *pfp;

  210.         if(strcmp(f, " "))        sprintf(hm, FMT2, h, '*', f);
  211.         else        sprintf(hm, "grep \"^%s\\%c\\*\" %s | tail -1", h, '*', EFPATH);

  212.         memset(tstr, 0, 200);
  213.         if(strcmp(f, " "))        sprintf(hm, FMT1, h, f);
  214.         else        sprintf(hm, FMT1, h, "|");

  215.         pfp = popen(hm, "r");
  216.        

  217.         while(fgets(tstr, 180, pfp) != NULL)        {
  218.                 (*t_ps)++;
  219.         }
  220.         pclose(pfp);

  221.         return((*t_ps));

  222. }

  223. 再来说明一下函数cl_createfields(),他利用CLFIELDNODE指针列表和本画面域数量建立各域:确定域类型,是否是标签,是调用cl_createlabel()否则cl_createfield()。他遍历CLFIELDNODE指针列表,一个节点、一个节点地检查,分别建立各域,最后返回FIELD指针数组给cl_createfields()建立表单。
  224. FIELD **cl_createfields(nodelist, fieldcnt)
  225. CLFIELDNODE        **nodelist;
  226. int        fieldcnt;
  227. {

  228.         int        i;

  229.         FIELD        **workfld;
  230.        

  231.         if(fieldcnt <= 0)        return((FIELD **)0);

  232.         workfld = (FIELD **)calloc(fieldcnt + 1, sizeof(FIELD));

  233.         for(i = 0; i < fieldcnt; i++)        {
  234.                 if(nodelist[i]->ftype)
  235.                         workfld[i] = cl_createfield(nodelist[i]);
  236.                 else        workfld[i] = cl_createlabel(nodelist[i]);
  237.         }

  238.         workfld[fieldcnt] = (FIELD *)0;
  239.         return(workfld);
  240. }

  241. FIELD *cl_createfield(no)
  242. CLFIELDNODE        *no;
  243. {

  244.         FIELD        *f;
  245.         if(!no)        return((FIELD *)0);

  246.         f = new_field(1, no->length, no->y, no->x, 0, no->buffnum);
  247.         set_field_userptr(f, (void *)0);
  248.         set_field_just(f, no->just);
  249.         if(no->inputflag)        {
  250.                 field_opts_off(f, O_ACTIVE);
  251.         }
  252.         switch(no->dtype)        {
  253.         case        0:
  254.                 break;
  255.         case        1:
  256.                 set_field_type(f, TYPE_INTEGER, no->pad, -10000000, 10000000);
  257.                 break;
  258.         case        2:
  259.                 set_field_type(f, TYPE_ALNUM, no->pad);
  260.                 break;
  261.         case        3:
  262.                 set_field_type(f, TYPE_ENUM, (char **)0, FALSE, FALSE);
  263.                 break;
  264.         case        5:
  265. /*
  266.                 set_field_type(f, TYPE_REGEXP,
  267. "(19|20)\d\d[- /.](0[[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])");
  268.                 set_field_type(f, TYPE_REGEXP,
  269.                 "[1-2][0-9][0-9][0-9](0[1-9]\r1[012])[0-3][0-9]");
  270. */
  271.                 set_field_type(f, TYPE_REGEXP,
  272.                 "[1-2][0-9][0-9][0-9][0-1][0-9][0-3][0-9]");
  273.                 break;
  274.         case        6:
  275.                 set_field_type(f, TYPE_REGEXP, "[a-zA-Z,<>/\\~0-9]");
  276.                 break;
  277.         case        7:
  278.                 break;
  279.         case        8:
  280.                 set_field_type(f, TYPE_NUMERIC, no->pad, -10000000, 10000000);
  281.                 break;
  282.         default :
  283.                 break;
  284.         }
  285.        
  286.         if(f)        return(f);
  287.         else        return((FIELD *)0);
  288. }
  289.                
  290. FIELD *cl_createlabel(no)
  291. CLFIELDNODE        *no;
  292. {
  293.         FIELD        *f;

  294.         int        len;
  295.        
  296.         if(!no)        return((FIELD *)0);

  297.         if(!no->length)       
  298.                 len = strlen(no->name);
  299.         else        len = no->length;
  300.        
  301.         f = new_field(1, len, no->y, no->x, 0, 0);
  302.        
  303.         if(f)        {
  304.                 set_field_buffer(f, 0, no->name);
  305.                 set_field_just(f, no->just);
  306.                 field_opts_off(f, O_ACTIVE);
  307.                 return(f);
  308.         }
  309.         else        return((FIELD *)0);
  310. }

  311. cl_createfield()函数传递一个参数:CLFIELDNODE指针no,然后调用new_field()利用CLFIELDNODE的域信息建立新域,调用set_field_userptr()、set_field_just()、set_field_type()等调正域属性,返回域指针。
  312. 而cl_createlable()就比较简单,他的参数与返回值与cl_createfield()一样,他利用域的坐标建立一个域,然后调用
  313. set_field_buffer(f, 0, no->name);
  314. set_field_just(f, no->just);
  315. set_opts_off(f, O_ACTIVE);
  316. 来使他显示标签名称,光标不在其上停留。

  317. 这几个函数之间的关系:

  318. +-----------------------------------------+
  319. |cl_dispform()                            |
  320. |->cl_createform()                        |
  321. |    |->cl_countfldnum()                  |
  322. |       |->cl_createfields()              |
  323. |            |->cl_readfields()           |
  324. |                 |->cl_readhuamian()     |
  325. |                 |->cl_convdefine()      |
  326. |            |->cl_createfield()          |
  327. |            |->cl_createlabel()          |         
  328. |    |->new_field()                       |
  329. +-----------------------------------------+

  330. 顺便说以下数据输入函数cl_inputdata(),这个函数在显示表单后,等待用户输入数据,他和cl_dispform()一起构成了用户的主界面。他的返回值现在有两个:一个是F4一个是ESC。ESC取消F4提交。他的主要参数是一个WINDOW指针,以确定表单窗口,一个FORM指针,即用户表单,由cl_dispform()返回,一个数据缓冲区,保存用户数据,一个32位掩码,对应32个域,以确定那些域可以返回以填充数据缓冲区。
  331. int cl_inputdata(win, form, imask, idata)
  332. WINDOW        *win;
  333. FORM        *form;
  334. unsigned long        imask;
  335. char        *idata;
  336. {
  337.        
  338.         int        rc;
  339.         int        finish = 0;
  340.         int        fldidx;
  341.         int        fldcnt;
  342.         int        rows, cols, frow, fcol, nrow, nbuf;

  343.         FIELD        **flist = (FIELD **)0;

  344.         fldcnt = field_count(form);
  345.         cl_setcurrent(win);

  346.         cl_outputdata(win, form, imask, idata, 1);
  347.         memset(idata, 0, DATA_DEFAU_LEN);

  348.         while(!finish)        {
  349.                 switch(form_driver(form, rc = cl_virtualize(form, workwin)))
  350.                 {
  351.                 case        E_OK:
  352.                                 break;
  353.                 case        E_UNKNOWN_COMMAND :
  354.                                 switch(cl_getrequest(rc))        {
  355.                                 case        9:
  356.                                         finish = 9;
  357.                                         break;
  358.                                 case        4:
  359.                                         finish = 4;
  360.                                         form_driver(form, REQ_VALIDATION);
  361.                                         flist = form_fields(form);
  362. for(fldidx = 0; fldidx < fldcnt; fldidx++)        {
  363.         if(ut_getbits(imask, fldidx))        {
  364.                 if(field_info(flist[fldidx], &rows, &cols,
  365.                 &frow, &fcol, &nrow, &nbuf) == E_OK && nbuf > 0)        {
  366.                         strcat(idata, field_buffer(flist[fldidx], 1));
  367.                         strcat(idata, "|");
  368.                 } else {
  369.                         strcat(idata, field_buffer(flist[fldidx], 0));
  370.                         strcat(idata, "|");
  371.                 }
  372.         }
  373. }
  374.                                         break;
  375.                                 default :
  376.                                         finish = 0;
  377.                                         break;
  378.                                 }        /* switch */
  379.                         break;
  380.                 default :
  381. /*
  382. ------------------------if using this then form input no loop ---------------
  383.                         finish = -1;
  384. */
  385.                         break;
  386.                 }        /* switch */
  387.         }                /* while */
  388.         return(rc);
  389. }
  390. 这里的cl_outputdata()用于显示用户数据缓冲区的原始内容,ut_getbit()是筛选掩码用的函数,看哪位是1,如该位为1,则使用
  391. 该位代表的域数据。然后看是否是密码域,是则使用1号域缓冲区,否则使用默认域缓冲区。

  392. (结束,源码以后再传)
复制代码

第一部分.
第二部分.

[ 本帖最后由 unixsystem 于 2007-1-27 00:33 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-02-02 10:45 |只看该作者
正好找这方面的资料,万分感谢阿

论坛徽章:
0
3 [报告]
发表于 2007-02-03 09:43 |只看该作者
高手!!!!!

论坛徽章:
0
4 [报告]
发表于 2007-02-04 20:25 |只看该作者
严重支持!

论坛徽章:
0
5 [报告]
发表于 2007-02-08 20:30 |只看该作者
想请教一下如何获取form中输入字符串的长度

论坛徽章:
0
6 [报告]
发表于 2007-06-25 13:19 |只看该作者
我有现成开发好的一个平台, 通过配置可以自动生成源代码, 并且完成了和数据库的访问,有人要吗?
联系QQ:79124027

论坛徽章:
0
7 [报告]
发表于 2007-06-25 17:14 |只看该作者
不搞开发,看到这么多代码就眼晕,呵呵
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP