Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103593112
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类:

2008-03-25 20:48:00


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

CLFIELDNODE **cl_readfields(hm, fhm)
char        *hm;
char        *fhm;
{

        int        i;
        int        cnt;

        CLFIELDNODE        **fnode;

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

        if((cnt = cl_readhuamian(hm, fhm)) <= 0)       
                return((CLFIELDNODE **)0);
       
        fnode = (CLFIELDNODE **)calloc(cnt + 1, sizeof(CLFIELDNODE));
       
        for(i = 0; i < cnt; i++)        {
                fnode[i] = cl_convdefine(huamian->slavelist[i]);
        }

        fnode[cnt] = (CLFIELDNODE *)0;
       
        return(fnode);

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

        static char        *t = NULL;

        CLFIELDNODE        *data;
       
        data = (CLFIELDNODE *)malloc(sizeof(CLFIELDNODE));
        memset(data, 0, sizeof(CLFIELDNODE));

        t = strstr(slave.length, ".");
        data->pad = atoi(++t);
        t = strtok(slave.length, ".");
        data->length = atoi(t);
        data->id = atoi(slave.seri);
        data->y = atoi(slave.y);
        data->x = atoi(slave.x);

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

        switch(CONV_TYPE(slave.just))        {
                case 'C' :
                        data->just = JUSTIFY_CENTER;
                        break;
                case 'L' :
                        data->just = JUSTIFY_LEFT;
                        break;
                case 'R' :
                        data->just = JUSTIFY_RIGHT;
                        break;
                case 'N' :
                        data->just = NO_JUSTIFICATION;
                        break;
                default :
                        data->just = NO_JUSTIFICATION;
                        break;

        }

        data->ftype = _caseyn(slave.ftype);
        data->selectable = _caseyn(slave.selectable);
        data->inputflag = _caseyn(slave.inputflag);
        data->visible = _caseyn(slave.visible);
        data->passflag = _caseyn(slave.passflag);
        data->enable = _caseyn(slave.enable);
        data->autoskip = 0;
        data->fullflag = _caseyn(slave.fullflag);
        data->pageflag = _caseyn(slave.pageflag);
        data->recvflag = _caseyn(slave.recvflag);
        data->retuflag = _caseyn(slave.retuflag);
        data->retubuff = atoi(slave.retubuf);

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

        switch(CONV_TYPE(slave.dtype))        {
                case 'A' :
                        switch(slave.dtype[1])        {
                                case 'N' :
                                        data->dtype = 0;
                                        break;
                                case 'L' :
                                        data->dtype = 2;
                                        break;
                                case 'M' :
                                        data->dtype = 8;
                                        break;
                                default :
                                        data->dtype = 0;
                                        break;
                        }
                        break;

                case 'E' :
                        data->dtype = 3;
                        break;
                case 'P' :
                        data->dtype = 4;
                        break;
                case 'D' :
                        if(slave.dtype[1] == 'I')
                                data->dtype = 1;
                        else        data->dtype = 5;
                        break;
                case 'R' :
                        data->dtype = 6;
                        break;
                case 'S' :
                        data->dtype = 7;
                        break;
                default :
                        data->dtype = 0;
                        break;
        }

        return(data);
}

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

        int        p = 0;
        int        cnt = 0;
        int        *t_ps = &cnt;

        static char        hm[80];
        static char        tmpstr[8];
        static char        tstr[200];

        FILE        *pfp;

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

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

        pfp = popen(hm, "r");
       

        while(fgets(tstr, 180, pfp) != NULL)        {
                p = 0;
        strcpy(tmpstr, ut_readtext(tstr, "|", &p));
        strcpy(tmpstr, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].seri, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].name, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].y, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].x, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].length, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].ftype, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].bufnum, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].just, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].selectable, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].inputflag, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].fullflag, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].enable, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].visible, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].passflag, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].dtype, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].ddefault, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].pageflag, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].recvflag, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].retuflag, ut_readtext(tstr, "|", &p));
        strcpy(huamian->slavelist[*t_ps].retubuf, ut_readtext(tstr, "|", &p));
                (*t_ps)++;
        }
        pclose(pfp);

        return((*t_ps));

}

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

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

FORM *cl_createform(hm, fhm)
char        *hm, *fhm;
{
       
        static        FORM        *form;
        static        int        fldcnt;

        fldcnt = cl_countfldnum(hm, fhm);
        if(fldcnt > 0)        {
                form = new_form(cl_createfields(cl_readfields(hm,fhm), fldcnt));
                return(form);
        }

/*
        if(form)        return(form);
*/
        else        return((FORM *)0);
}

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

        int        cnt = 0;
        int        *t_ps = &cnt;

        static char        hm[80];
        static char        tstr[200];

        FILE        *pfp;

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

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

        pfp = popen(hm, "r");
       

        while(fgets(tstr, 180, pfp) != NULL)        {
                (*t_ps)++;
        }
        pclose(pfp);

        return((*t_ps));

}

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

        int        i;

        FIELD        **workfld;
       

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

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

        for(i = 0; i < fieldcnt; i++)        {
                if(nodelist[i]->ftype)
                        workfld[i] = cl_createfield(nodelist[i]);
                else        workfld[i] = cl_createlabel(nodelist[i]);
        }

        workfld[fieldcnt] = (FIELD *)0;
        return(workfld);
}

FIELD *cl_createfield(no)
CLFIELDNODE        *no;
{

        FIELD        *f;
        if(!no)        return((FIELD *)0);

        f = new_field(1, no->length, no->y, no->x, 0, no->buffnum);
        set_field_userptr(f, (void *)0);
        set_field_just(f, no->just);
        if(no->inputflag)        {
                field_opts_off(f, O_ACTIVE);
        }
        switch(no->dtype)        {
        case        0:
                break;
        case        1:
                set_field_type(f, TYPE_INTEGER, no->pad, -10000000, 10000000);
                break;
        case        2:
                set_field_type(f, TYPE_ALNUM, no->pad);
                break;
        case        3:
                set_field_type(f, TYPE_ENUM, (char **)0, FALSE, FALSE);
                break;
        case        5:
/*
                set_field_type(f, TYPE_REGEXP,
"(19|20)\d\d[- /.](0[[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])");
                set_field_type(f, TYPE_REGEXP,
                "[1-2][0-9][0-9][0-9](0[1-9]\r1[012])[0-3][0-9]");
*/
                set_field_type(f, TYPE_REGEXP,
                "[1-2][0-9][0-9][0-9][0-1][0-9][0-3][0-9]");
                break;
        case        6:
                set_field_type(f, TYPE_REGEXP, "[a-zA-Z,<>/\\~0-9]");
                break;
        case        7:
                break;
        case        8:
                set_field_type(f, TYPE_NUMERIC, no->pad, -10000000, 10000000);
                break;
        default :
                break;
        }
       
        if(f)        return(f);
        else        return((FIELD *)0);
}
               
FIELD *cl_createlabel(no)
CLFIELDNODE        *no;
{
        FIELD        *f;

        int        len;
       
        if(!no)        return((FIELD *)0);

        if(!no->length)       
                len = strlen(no->name);
        else        len = no->length;
       
        f = new_field(1, len, no->y, no->x, 0, 0);
       
        if(f)        {
                set_field_buffer(f, 0, no->name);
                set_field_just(f, no->just);
                field_opts_off(f, O_ACTIVE);
                return(f);
        }
        else        return((FIELD *)0);
}

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

这几个函数之间的关系:

+-----------------------------------------+
|cl_dispform()                            |
|->cl_createform()                        |
|    |->cl_countfldnum()                  |
|       |->cl_createfields()              |
|            |->cl_readfields()           |
|                 |->cl_readhuamian()     |
|                 |->cl_convdefine()      |
|            |->cl_createfield()          |
|            |->cl_createlabel()          |         
|    |->new_field()                       |
+-----------------------------------------+

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

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

        fldcnt = field_count(form);
        cl_setcurrent(win);

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

        while(!finish)        {
                switch(form_driver(form, rc = cl_virtualize(form, workwin)))
                {
                case        E_OK:
                                break;
                case        E_UNKNOWN_COMMAND :
                                switch(cl_getrequest(rc))        {
                                case        9:
                                        finish = 9;
                                        break;
                                case        4:
                                        finish = 4;
                                        form_driver(form, REQ_VALIDATION);
                                        flist = form_fields(form);
for(fldidx = 0; fldidx < fldcnt; fldidx++)        {
        if(ut_getbits(imask, fldidx))        {
                if(field_info(flist[fldidx], &rows, &cols,
                &frow, &fcol, &nrow, &nbuf) == E_OK && nbuf > 0)        {
                        strcat(idata, field_buffer(flist[fldidx], 1));
                        strcat(idata, "|");
                } else {
                        strcat(idata, field_buffer(flist[fldidx], 0));
                        strcat(idata, "|");
                }
        }
}
                                        break;
                                default :
                                        finish = 0;
                                        break;
                                }        /* switch */
                        break;
                default :
/*
------------------------if using this then form input no loop ---------------
                        finish = -1;
*/
                        break;
                }        /* switch */
        }                /* while */
        return(rc);
}
这里的cl_outputdata()用于显示用户数据缓冲区的原始内容,ut_getbit()是筛选掩码用的函数,看哪位是1,如该位为1,则使用
该位代表的域数据。然后看是否是密码域,是则使用1号域缓冲区,否则使用默认域缓冲区。
阅读(460) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~