ncurses程序设计介绍

一,使用鼠标
在ncurses中使用鼠标需要几点注意,终端必须在非规范模式下接受鼠标事件,另外,应该有功能键,因为没有他,xterm不会正确的报告鼠标事件。
int raw(void);
int keypad(WINDOW *win, bool bf);
这两个函数用来完成上面要求的工作。

鼠标事件本身通过MEVENT结构来捕获,其定义如下:
typedef struct 
{
short id;
int x, y, z;
mmask_t bstate;
}MEVENT;
id用来区分多个设备,xy用来给出鼠标事件发生的位置,z留给未来使用。bstate则指出事件发生时鼠标的状态。下表是鼠标事件的常量的定义
#define    BUTTON1_RELEASED 000000000001L 按钮 1 松开 
#define    BUTTON1_PRESSED 000000000002L 按钮 1 按下 
#define    BUTTON1_CLICKED 000000000004L 按钮 1 单击 
#define    BUTTON1_DOUBLE_CLICKED 000000000010L 按钮 1 双击 
#define    BUTTON1_TRIPLE_CLICKED 000000000020L 按钮 1 三击 
#define    BUTTON1_RESERVED_EVENT 000000000040L 按钮 1 保留 
#define    BUTTON2_RELEASED 000000000100L 按钮 2 松开
#define    BUTTON2_PRESSED 000000000200L 按钮 2 按下 
#define    BUTTON2_CLICKED 000000000400L 按钮 2 单击 
#define    BUTTON2_DOUBLE_CLICKED 000000001000L 按钮 2 双击  
#define    BUTTON2_TRIPLE_CLICKED 000000002000L 按钮 2 三击 
#define    BUTTON2_RESERVED_EVENT 000000004000L 按钮 2 保留 
#define    BUTTON3_RELEASED 000000010000L 按钮 3 松开 
#define    BUTTON3_PRESSED 000000020000L 按钮 3 按下 
#define    BUTTON3_CLICKED 000000040000L 按钮 3 单击 
#define    BUTTON3_DOUBLE_CLICKED 000000100000L 按钮 3 双击 
#define    BUTTON3_TRIPLE_CLICKED 000000200000L 按钮 3 三击 
#define    BUTTON3_RESERVED_EVENT 000000400000L 按钮 3 保留 
#define    BUTTON4_RELEASED 000001000000L 按钮 4 松开 
#define    BUTTON4_PRESSED 000002000000L 按钮 4 按下 
#define    BUTTON4_CLICKED 000004000000L 按钮 4 单击 
#define    BUTTON4_DOUBLE_CLICKED 000010000000L 按钮 4 双击 
#define    BUTTON4_TRIPLE_CLICKED 000020000000L 按钮 4 三击 
#define    BUTTON4_RESERVED_EVENT 000040000000L 按钮 4 保留 
#define    BUTTON_CTRL 000100000000L 同时 CTRL 键也被按下 
#define    BUTTON_SHIFT 000200000000L 同时 SHIFT 键也被按下 
#define    BUTTON_ALT 000400000000L 同时 ALT 键也被按下 
#define    ALL_MOUSE_EVENTS 000777777777L 接收所有的鼠标消息 
#define    REPORT_MOUSE_POSITION 001000000000L 报告鼠标位置 
鼠标使用步骤:
mmask_t mousemask(mmask_t newmask, mmask_t *oldmask);
首先,调用mousemask来告诉ncurses你对那些鼠标事件感兴趣,他的值是上面列出的值的一个或者多个相或的结果,函数执行成功返回掩码的当前设置,出错则会返回0。

int getmouse(MEVENT *event);
int ungetmouse(MEVENT *event);
当有鼠标事件等待处理是,getch就会返回KEY_MOUSE,在再次调用getch之前,必须获得鼠标事件,否则他就会消失。getmouse用来获得下一个鼠标事件,如果出错将会返回ERR,否则返回OK,并填充传递给他的MEVENT结构,ungetmouse会将鼠标事件返回给鼠标事件队列,也会把KEY_MOUSE事件返回给getch函数正在工作的输入队列。

int mouseinterval(int erval);
另外,一次鼠标击键定义为在一定时间内一个按键被按下又被释放。默认的时间是1/5秒,但你可以使用上面的函数来更改这一时间的设置。erval的单位是千分之一秒,同样,函数成功返回OK,失败返回ERR。

bool wenclose(const WINDOW *win, int y, int x);
bool mouse_trafo(int* pY, int* pX, bool to_screen);
bool wmouse_trafo(const WINDOW* win, int* pY, int* pX, bool to_screen);
最后就是处理鼠标发生的位置。wenclose是用来确定给定的xy是不是在win中,getmouse返回的坐标值是相对于屏幕的,所以要用wenclose里来检测鼠标事件是否发生在你的窗口中。如果真的发生在这个窗口,便可以使用wmouse_trafo来产生相对于屏幕的坐标的值。其中最后一个参数应该为FALSE,如果是将相对子窗口的坐标转换成相对于屏幕的坐标值,则最后一个参数为TRUE。宏mouse_trafo是第一个参数为stdscr的wmouse_trafo函数。
/*show the position of mouse event*/
#include <curses.h>
#include <unistd.h>

int main(void)
{
int key;
int quit = 0;
MEVENT event;

initscr();
raw();
keypad(stdscr, TRUE);
mousemask(BUTTON1_CLICKED | BUTTON2_CLICKED, 0);

while (!quit)
{
key = getch();
switch (key)
{
case KEY_MOUSE :
getmouse(&event);
printw("Y:%d X:%d\n", event.y, event.x);
refresh();
break;
case 'q' :
quit = 1;
break;
default :
printw("Key = %d\n", key);
}
}

endwin();
return 0;
}
/*mouse.c*/
#include <curses.h>
#include <unistd.h>

void showstar(WINDOW * win, const int line);
int main(void)
{
int key;
int quit = 0;
MEVENT mouse;
WINDOW * win;

initscr();
raw();
win = newwin(10, 50, 5, 3);/*this must do before keypad*/
keypad(win, TRUE);         /*then use win.*/
mousemask(BUTTON1_CLICKED | BUTTON2_CLICKED, 0); /*set actions*/
box(win, '|', '-');
mvwaddch(win, 1, 48, 'X');
mvwaddstr(win, 3, 3, "Test 1");
mvwaddstr(win, 4, 3, "Test 2");
mvwaddstr(win, 5, 3, "Test 3");
wrefresh(win);

while (!quit)
{
key = wgetch(win);
switch(key)
{
case KEY_MOUSE : 
getmouse(&mouse); /*get mouse action*/

if (!wenclose(win, mouse.y, mouse.x)) 
break; /*do nothing if not in window*/

wmouse_trafo(win, &mouse.y, &mouse.x, FALSE);

if ((3 <= mouse.x && mouse.x <= 8) 
&& (3 <= mouse.y && mouse.y <= 5))
showstar(win, mouse.y);

if (1 == mouse.y && 48 == mouse.x) /*Clicked 'X'*/
quit = 1;

break;
case 'q' :
quit = 1;
break;
default :
break;
}
}

delwin(win);
endwin();
return 0;
}

void showstar(WINDOW * win, const int line)
{
mvwaddch(win, line, 2, '*');
wrefresh(win);
}
二,使用菜单
一,建立
#include <menu.h>
ITEM *new_item(const char *name, const char *description);
int free_item(ITEM *item);
new_item函数用来建立项目,相对应有free_item来释放相应的空间,

MENU *new_menu(ITEM **items);
int free_menu(MENU *menu);
当项目建立好之后,由new_menu函数来建立菜单,相对应由free_menu释放。

二,显示
int post_menu(MENU *menu);
int unpost_menu(MENU *menu);
绘制菜单,但是不在屏幕上显示,需要使用refresh来完成显示的动作。unpost_menu的动作是将菜单从子窗口擦除,同样也需要refresh来刷新。

三,动作处理
int menu_driver(MENU *menu, int c);
函数menu_driver用来是指菜单将要进行的动作,参数c用来指明动作,他的取值可以是下面的常量:
REQ_LEFT_ITEM     向左移动到一个菜单项 
REQ_RIGHT_ITEM    向右移动到一个菜单项
REQ_UP_ITEM       向上移动到一个菜单项
REQ_DOWN_ITEM     向下移动到一个菜单项
REQ_SCR_ULINE     向上滚动一行
REQ_SCR_DLINE     向下滚动一行
REQ_SCR_DPAGE     向下滚动一页
REQ_SCR_UPAGE     向上滚动一页
REQ_FIRST_ITEM    移动到第一个菜单项
REQ_LAST_ITEM     移动到最后一个菜单项
REQ_NEXT_ITEM     移动到下一个菜单项
REQ_PREV_ITEM     移动到上一个菜单项
REQ_TOGGLE_ITEM   选中/不选中一个菜单项
REQ_CLEAR_PATTERN 清除菜单模式缓冲
REQ_BACK_PATTERN  从模式缓冲中删除前一个字符
REQ_NEXT_MATCH    移动到匹配模式的下一个菜单项
REQ_PREV_MATCH    移动到匹配模式的下一个菜单项

四,其他
int     set_current_item (MENU *menu, const ITEM *item); 把菜单里当前选中的菜单项设置为item
ITEM *  current_item     (const MENU *menu);
int     set_top_row      (MENU *menu, int row); 尝试把row设置为显示的最顶端一行
int     top_row          (const MENU *menu); 返回最顶端菜单的行数
int     item_index       (const ITEM *item);返回项目在菜单中的位置
int     set_item_opts    (ITEM *item, OPTIONS opts);把菜单的选项设置为传递给他的选项
int     item_opts_on     (ITEM *item, OPTIONS opts);打开传递给他的选项其他的选项保持不动。
int     item_opts_off    (ITEM *item, OPTIONS opts);关闭传递给他的选项其他的选项保持不动。
OPTIONS item_opts        (const ITEM *item);返回当前设置的选项位
int     set_item_userptr (ITEM *item, void *userptr);为菜单设置userptr
void *  item_userptr     (const ITEM *item);返回和userptr关联的选项
int     set_item_value   (ITEM *item, bool value);用于选中或不选中可多选的菜单中的菜单项
bool    item_value       (const ITEM *item);对于可以选中多项的菜单,如果菜单项被选中,则返回TRUE,否则返回FALSE
bool    item_visible     (const ITEM *item);判断菜单是否可见,用于菜单长度超过屏幕的时候

int     set_menu_items   (MENU *menu, ITEM **items);用传递给菜单的菜单项改变菜单
ITEM ** menu_items       (const MENU *menu); 返回菜单中菜单项列表
int     item_count       (const MENU *menu); 返回菜单中菜单项的数目
int     set_item_opts    (ITEM *item, OPTIONS opts);
int     item_opts_on     (ITEM *item, OPTIONS opts);
int     item_opts_off    (ITEM *item, OPTIONS opts);
OPTIONS item_opts        (const ITEM *item);把传递给菜单的选项opts都设置为关闭,保持其他选项不动。他的取值可以是:
O_ONEVALUE     菜单中只能选中一项
O_SHOWDESC     显示菜单项的描述
O_ROWMAJOR     以行的顺序显示菜单
O_IGNORECASE   当匹配模式时,忽略大小写
O_SHOWMATCH    移动光标指示模式匹配菜单名
O_NONCYCLIC    在菜单的末尾不折叠显示
int     set_menu_opts    (MENU *menu, OPTIONS opts); 
int     menu_opts_on     (MENU *menu, OPTIONS opts);
int     menu_opts_off    (MENU *menu, OPTIONS opts);
OPTIONS menu_opts        (const MENU *menu);

int     set_menu_win     (MENU *menu, WINDOW *win);设置和菜单相关联的窗口
WINDOW *menu_win         (const MENU *menu);返回菜单关联的窗口
int     set_menu_sub     (MENU *menu, WINDOW *sub);设置和菜单相关联的子窗口
WINDOW *menu_sub         (const MENU *menu);返回菜单使用的子窗口
int     scale_menu       (const MENU *menu, int *rows, int *columns); 返回用于菜单的最小子窗口的大小

int     set_menu_fore    (MENU *menu, chtype attr); set为设置相应的属性
chtype  menu_fore        (const MENU *menu);返回选中菜单项的属性
int     set_menu_back    (MENU *menu, chtype attr); 
chtype  menu_back        (const MENU *menu);返回可选但未选中的菜单项的属性
int     set_menu_grey    (MENU *menu, chtype attr);
chtype  menu_grey        (const MENU *menu);返回未选中菜单项的属性
int     set_menu_pad     (MENU *menu, int pad);
int     menu_pad         (const MENU *menu);返回菜单名和菜单描述分隔的字符

int     set_menu_format  (MENU *menu, int rows, int cols);  设置当前菜单的显示大小,若菜单包含的菜单项比给出的空间大,则滚动显示
void    menu_format      (const MENU *menu, int *rows, int *cols);返回当前菜单的显示大小

int     set_menu_mark    (MENU *menu, const char *mark); 设置选中菜单项的前缀
const char *menu_mark    (const MENU *menu);得到选中菜单项的前缀

const char *menu_request_name (int request); 返回request可打印的名字
int     menu_request_by_name  (const char *name);返回和name相关的请求代码

int     set_menu_spacing (MENU *menu, int spc_description, int spc_rows, int spc_columns); 选择菜单使用的间隔空间
int     menu_spacing     (const MENU *menu, int* spc_description, int* spc_rows, int* spc_columns);返回菜单间隔空间设置

int     set_menu_userptr (MENU *menu, void *userptr); 设置针对应用的特定数据
void *  menu_userptr     (const MENU *menu);返回和菜单相关的针对应用的特定数据

int     pos_menu_cursor  (const MENU *menu);把光标定位在当前选中的菜单项上

int     set_menu_pattern (MENU *menu, const char *pattern); 把模式缓冲内容设置为pattern
char *  menu_pattern     (const MENU *menu); 返回模式缓冲的当前内容
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <curses.h>
#include <menu.h>
#include <errno.h>

char * say_menu[] = {
"Hi", "Say Hi",
"World", "Hello World",
"Quit", "Exit the application",
NULL};

int main(void)
{
int quit = 0;
int key;
int i;
MENU * menu;
ITEM * item[4];

initscr();
raw();
noecho();
keypad(stdscr, TRUE);

for (i = 0; say_menu[i * 2]; i++)
item[i] = new_item(say_menu[i * 2], /*给ITEM *分配空间并初始化*/
say_menu[i * 2 + 1]);
item[i] = NULL;
menu = new_menu(item); /*创建一个新菜单,item必须以NULL结尾。*/
post_menu(menu); /*绘制菜单*/

while (!quit)
{
int code;
ITEM * selected;

key = getch();
switch (key)
{
case KEY_DOWN :
case KEY_RIGHT:
code = menu_driver(menu, REQ_NEXT_ITEM); /*执行动作*/
break;
case KEY_UP : 
case KEY_LEFT :
code = menu_driver(menu, REQ_PREV_ITEM);
break;
case '\n' :
if ((selected = current_item(menu)) != NULL) /*返回当前选中项。*/
{
unpost_menu(menu); /*从子窗口中擦除菜单,需要refresh。*/
mvaddstr(10, 10, "You have selected:");
mvaddstr(11, 15, item_description(selected)); /*返回项目的描述*/
refresh();
sleep(3);
erase();
if (!strcmp("Quit", item_name(selected))) /*返回项目名字*/
quit = 1;
else
post_menu(menu); /*绘制菜单*/
}
break;
case 'q' : 
quit = 1;
break;
default :
if (isprint(key))
if (menu_driver(menu, key) != E_OK)
menu_driver(menu, REQ_CLEAR_PATTERN);
break;
}
}

endwin();
return 0;
}
三,使用窗体
一,建立
FIELD *  new_field  (int height, int width, int toprow, int leftcol, int offscreen, int nbuffers);
FIELD *  dup_field  (FIELD *field, int toprow, int leftcol);
FIELD *  link_field (FIELD *field, int toprow, int leftcol);
int      free_field (FIELD *field);
函数new_field用来建立一个域,参数分别表示这个域的高,宽,左上角的yx的值,跨越屏幕的行数,以及额外的工作缓冲的数量。duo_field函数用来复制域,link_field  用来连接域,free_field用来释放域所占 的内存空间。
FORM *new_form(FIELD **fields);
int free_form(FORM *form);
当域建立完毕之后,就要用函数new_form将他们组成窗体,函数free_form用来释放窗体。

二,显示
int post_form(FORM *form);
int unpost_form(FORM *form);
当建立好窗体之后,就可以用函数post_form来显示,注意,这里需要用refreah函数,将其真正的显示到屏幕上面。unpost_form的动作与post_form函数相反,他清除所在子窗口的窗体。同样也需要用refresh函数。

三,操作
int form_driver(FORM *form, int c);
同menu_driver的性质一样,他也是用来控制的函数,不同的是他所控制的是窗体,而不是菜单。
REQ_NEXT_PAGE    Move to the next page.               
REQ_PREV_PAGE    Move to the previous page.    
REQ_FIRST_PAGE   Move to the first page
REQ_LAST_PAGE    Move to the last field.

REQ_NEXT_FIELD   Move to the next field.
REQ_PREV_FIELD   Move to the previous field.
REQ_FIRST_FIELD  Move to the first field.
REQ_LAST_FIELD   Move to the last field.
REQ_SNEXT_FIELD  Move to the sorted next field.
REQ_SPREV_FIELD  Move to the sorted previous field.
REQ_SFIRST_FIELD Move to the sorted first field.
REQ_SLAST_FIELD  Move to the sorted last field.
REQ_LEFT_FIELD   Move left to a field.
REQ_RIGHT_FIELD  Move right to a field.
REQ_UP_FIELD     Move up to a field.
REQ_DOWN_FIELD   Move down to a field.

REQ_NEXT_CHAR    Move to the next char.
REQ_PREV_CHAR    Move to the previous char.
REQ_NEXT_LINE    Move to the next line.
REQ_PREV_LINE    Move to the previous line.
REQ_NEXT_WORD    Move to the next word.
REQ_PREV_WORD    Move to the previous word.
REQ_BEG_FIELD    Move to the beginning of the field.
REQ_END_FIELD    Move to the end of the field.
REQ_BEG_LINE     Move to the beginning of the line.
REQ_END_LINE     Move to the end of the line.
REQ_LEFT_CHAR    Move left in the field.
REQ_RIGHT_CHAR   Move right in the field.
REQ_UP_CHAR      Move up in the field.
REQ_DOWN_CHAR    Move down in the field.

REQ_NEW_LINE     Insert or overlay a new line.
REQ_INS_CHAR     Insert a blank at the cursor.
REQ_INS_LINE     Insert a blank line at the cursor.
REQ_DEL_CHAR     Delete character at the cursor.
REQ_DEL_PREV     Delete character before the cursor.
REQ_DEL_LINE     Delete line at the cursor.
REQ_DEL_WORD     Delete blank-delimited word at the cursor.
REQ_CLR_EOL      Clear to end of line from cursor.
REQ_CLR_EOF      Clear to end of field from cursor.
REQ_CLR_FIELD    Clear the entire field.
REQ_OVL_MODE     Enter overlay mode.
REQ_INS_MODE     Enter insert mode.

REQ_SCR_FLINE    Scroll the field forward a line.
REQ_SCR_BLINE    Scroll the field backward a line.
REQ_SCR_FPAGE    Scroll the field forward a page.
REQ_SCR_BPAGE    Scroll the field backward a page.
REQ_SCR_FHPAGE   Scroll the field forward half a page.
REQ_SCR_BHPAGE   Scroll the field backward half a page.

REQ_SCR_FCHAR    Scroll the field forward a character.
REQ_SCR_BCHAR    Scroll the field backward a character.
REQ_SCR_HFLINE   Horizontal scroll the field forward a line.
REQ_SCR_HBLINE   Horizontal scroll the field backward a line.
REQ_SCR_HFHALF   Horizontal scroll the field forward half a line.
REQ_SCR_HBHALF   Horizontal scroll the field backward half a line.

REQ_VALIDATION   Validate field.
REQ_NEXT_CHOICE  Display next field choice.
REQ_PREV_CHOICE  Display previous field choice.

四,其他
int     set_form_opts (FORM *form, OPTIONS opts); 用opts设置窗体的选项,O_NL_OVERLOAD:如果用户在域的结尾按了回车,
                                                则强迫窗体驱动移动到下一个域,O_BS_OVERLOAD:如果在域的开头按了退格键
                                               ,则强迫移动到上一个域,默认他们是打开的。
int     form_opts_on  (FORM *form, OPTIONS opts);打开opts,其他不变
int     form_opts_off (FORM *form, OPTIONS opts);关闭opts,其他不变
OPTIONS form_opts     (const FORM *form);返回当前设置

int      set_form_win     (FORM *form, WINDOW *win);设置窗体的窗口
WINDOW * form_win         (const FORM *form);返回窗体的窗口
int      set_form_sub     (FORM *form, WINDOW *sub);设置窗体的子窗口
WINDOW * form_sub         (const FORM *form);返回窗体的子窗口
int      scale_form       (const FORM *form, int *rows, int *columns);返回要求一个窗体的最小尺寸

int      set_form_userptr (FORM *form, void *userptr);为窗体设置针对应用的特定数据的指针
void   * form_userptr     (const FORM *form);返回给定窗体的针对应用的特定数据

const char * form_request_name (int request);返回请求的文字名称
int      form_request_by_name  (const char *name);返回请求的代码


int      set_current_field  (FORM *form, FIELD *field);设置当前域
FIELD *  current_field      (const FORM *);返回当前域
int      set_form_page      (FORM *form, int n);设置窗体的当前页
int      form_page          (const FORM *form);返回当前页号
int      field_index        (const FIELD *field);返回和窗体相关联的域数组中这个域的索引号

int      set_field_buffer   (FIELD *field, int buf, const char *value);
char  *  field_buffer        (const FIELD *field, int buffer);
int      set_field_status   (FIELD *field, bool status);设置域的状态
bool     field_status       (const FIELD *field);检查域状态
int      set_max_field      (FIELD *field, int max);

int      set_form_fields    (FORM *form, FIELD **fields);把窗体的域设置为新传递给窗体的列表,列表以NULL,结尾
FIELD ** form_fields        (const FORM *form); 返回当前和form相关的域数组
int      field_count        (const FORM *form);
int      move_field         (FIELD *field, int frow, int fcol); 

int      set_new_page       (FIELD *field, bool new_page_flag);如果new_page_flag为TRUE,设置域从一个新页开始,FALSE取消设置
bool     new_page           (const FIELD *field);如果域标记了新页的开始则返回TRUE,否则返回FALSE

int      set_form_fields    (FORM *form, FIELD **fields);
FIELD ** form_fields        (const FORM *form);
int      field_count        (const FORM *form);返回当前和form相关联的域的数量
int      move_field         (FIELD *field, int frow, int fcol);把field移动到指定位置上

int      pos_form_cursor    (FORM *form);当光标被窗体库以外的调用移动时,在当前选中域的光标的位置

bool     data_ahead         (const FORM *form);如果form前有数据但有不在屏幕上,返回TRUE
bool     data_behind        (const FORM *form);如果form后有数据但有不在屏幕上,返回TRUE

int      set_field_buffer   (FIELD *field, int buf, const char *value);
char *   field_buffer       (const FIELD *field, int buffer);
int      set_field_status   (FIELD *field, bool status);
bool     field_status       (const FIELD *field);
int      set_max_field      (FIELD *field, int max);设置动态域的最大尺寸

int      field_info         (const FIELD *field, int *rows, int *cols, int *frow, int *fcol, int *nrow, int *nbuf); 返回域在创建时设置的属性
int      dynamic_field_info (const  FIELD  *field, int *rows, int *cols, int *max);返回当前能改变的一个域的属性

int      set_field_fore (FIELD *field, chtype attr);设置域的前景属性
chtype   field_fore     (const FIELD *field);返回域前景属性
int      set_field_back (FIELD *field, chtype attr);设置域的背景属性
chtype   field_back     (const FIELD *field);返回域的背景属性
int      set_field_pad  (FIELD *field, int pad);设置用来填充域的字符文本
int      field_pad      (const FIELD *field);返回用来填充域的字符文本

int      set_field_just (FIELD *field, int justification); 设置域的调整值
int      field_just     (const FIELD *field);

int      set_field_userptr (FIELD *field, void*userptr);
void *   field_userptr     (const FIELD *field);

int      set_field_opts (FIELD *field, OPTIONS opts);
int      field_opts_on  (FIELD *field, OPTIONS opts);
int      field_opts_off (FIELD *field, OPTIONS opts);
OPTIONS  field_opts     (const FIELD *field);
O_VISIBLE     The field is displayed.  If this option is  off,  display  of  the field is suppressed.
O_ACTIVE     The  field  is  visited during processing.  If this option is off, the field will not be reachable by navigation keys. Please  notice that an invisible field appears to be inactive also.
O_PUBLIC     The field contents are displayed as data is entered.
O_EDIT     The field can be edited.
O_WRAP     Words  that  do  not  fit  on a line are wrapped to the next line. Words are blank-separated.
O_BLANK     The field is cleared whenever a character is entered at the  first position.
O_AUTOSKIP  Skip to the next field when this one fills.
O_NULLOK     Allow a blank field.
O_STATIC     Field  buffers  are  fixed  to  field’s  original size.  Turn this option off to create a dynamic field.
O_PASSOK     Validate field only if modified by user.


域类型
int         set_field_type (FIELD *field, FIELDTYPE *type, ...);用来设置一个域的类型
FIELDTYPE * field_type     (const FIELD *field);
void *      field_arg      (const FIELD *field); 返回给验证例程的参数

FIELDTYPE * TYPE_ALNUM;接受字母和数字:set_field_type(field, TYPE_ALNUM, width);
FIELDTYPE * TYPE_ALPHA;接受字母:set_field_type(field, TYPE_ALPHA, width); width设置了数据的最小宽度,如果是一个可选的域,可以设置为0
FIELDTYPE * TYPE_ENUM; 接收范围限制在枚举类型的数据集合中 field_type(field, TYPE_ENUM, valuelist, checkcase, checkunique);其中,valuelist是一个以NULL结尾的字符串数组,checkcase不为0则会区分大小写,
FIELDTYPE * TYPE_INTEGER;接受整数,set_filed_type(filed, TYPE_INITEGER, padding/*前补零的个数*/, vmin, vmax/*指出范围*/);
FIELDTYPE * TYPE_NUMERIC;接受一个十进制数set_filed_type(filed, TYPE_NUMERIC, padding/*前补零的个数*/, vmin, vmax/*指出范围 */);
FIELDTYPE * TYPE_REGEXP;正则表达式匹配 set_field_type(field, TYPE_REGEXP, regexp);
FIELDTYPE * TYPE_IPV4;

FIELDTYPE * new_fieldtype( 
    bool (* const field_check)(FIELD *, const void *),
    bool (* const char_check)(int, const void *)); 控制域的类型

int         free_fieldtype  (FIELDTYPE *fieldtype); 释放fieldtype分配的内存
int         set_fieldtype_arg(
    FIELDTYPE *fieldtype,
    void *(* const make_arg)(va_list *),
    void *(* const copy_arg)(const void *),
    void  (* const free_arg)(void *));设置fieldtype参数。
int         set_fieldtype_choice( 
    FIELDTYPE *fieldtype,
    bool (* const next_choice)(FIELD *, const void *),
    bool (* const prev_choice)(FIELD *, const void *));设置fieldtype_choice参数
FIELDTYPE * link_fieldtype  (FIELDTYPE *type1,FIELDTYPE *type2);连接filetype

int         set_field_init  (FORM *form, void (*func)(FORM *)); 在修改域之后,重画窗体时调用的函数指针
void (*)(FORM *) field_init (const FORM *form);返回field_init钩子函数的函数指针,如果没有则返回NULL
int         set_field_term  (FORM *form, void (*func)(FORM *));在修改域之前,重画窗体时调用的函数指针
void (*)(FORM *) field_term (const FORM *form);返回field_term钩子函数的函数指针,如果没有则返回NULL
int         set_form_init   (FORM *form, void (*func)(FORM *));在修改页之后,重画窗体时调用的函数指针
void (*)(FORM *) form_init  (const FORM *form);返回form_init钩子函数的函数指针,如果没有则返回NULL
int         set_form_term   (FORM *form, void (*func)(FORM *));在修改页之后,重画窗体时调用的函数指针 
void (*)(FORM *) form_term  (const FORM *form);返回form_term钩子函数的函数指针,如果没有则返回NULL
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <curses.h>
#include <form.h>
#include <errno.h>

int main(void)
{
int quit = 0;
int key;
FORM * form;
FIELD * fields[5];

initscr();
fields[0] = new_field(1, 20, 2, 2, 0, 0); /*分配一个新域*/
field_opts_off(fields[0], O_ACTIVE); /*关闭指定选项,其他不变*/
set_field_buffer(fields[0], 0, "Name:");
fields[1] = new_field(1, 50, 3, 5, 0, 0);
fields[2] = new_field(1, 20, 4, 2, 0, 0);
field_opts_off(fields[2], O_ACTIVE);
set_field_buffer(fields[2], 0, "Passwd:");
fields[3] = new_field(1, 50, 5, 5, 0, 0);
fields[4] = new_field(1, 10, 6, 5, 0, 0);
set_field_buffer(fields[4], 0, "--QUIT--");
field_opts_off(fields[4], O_EDIT);
fields[5] = NULL;

form = new_form(fields);
post_form(form);
raw();
noecho();
keypad(stdscr, TRUE);

while (!quit)
{
int code;

key = getch();
switch (key)
{
case KEY_DOWN :
case KEY_RIGHT :
case '\t' :
code = form_driver(form, REQ_NEXT_FIELD);
break;
case '\n' :
if (field_index(current_field(form)) == 4)
quit = 1;
else
code = form_driver(form, REQ_NEXT_FIELD);
break;
case KEY_UP :
case KEY_LEFT:
code = form_driver(form, REQ_PREV_FIELD);
break;
default :
if (isprint(key))
form_driver(form, key);
break;
}
}

endwin();
return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值