curses是一个在Linux/Unix下广泛应用的图形函数库,作用是可以在终端内绘制简单的图形用户界面。
curses使用两个数据结构映射终端屏幕,stdscr和curscr。stdscr是“标准屏幕”(逻辑屏幕),在curses函数库产生输出时就刷新,是默认输出窗口(用户不会看到该内容)。curscr是“当前屏幕”(物理屏幕),在调用refresh函数是,函数库会将curscr刷新为stdscr的样子。
Ubuntu18.04系统没有自带curses库,需要手动安装。
安装方法:sudo apt-get install libncurses5-dev
所有curses程序必须以initscr函数开始,以endwin函数结束。
WINDOW *initscr(void); //在一个程序中只调用一次
//返回一个指向stdscr结构的指针,失败输出一条诊断信息并使程序结束。
int endwin(void);//成功返回OK,失败返回ERR。
在curses程序中输出字符的过程如下所示:
(1):使用curses函数刷新逻辑屏幕。
(2):要求curses用refresh函数来刷新物理屏幕。
int addch(const chtype char_to_add);//当前位置添加字符
int addchstr(chtype *const string_to_add);//当前位置添加字符串
int printw(char *format, ...);//类似与printf
int refresh(void);//刷新物理屏幕
int box(WINDOW *win_ptr, chtype vertical, chtype horizontal);
//围绕窗口绘制方框,用vertical绘制垂直边,用horizontal绘制水平边
int insch(chtype char_to_insert); //插入一个字符(已有字符后移)
int insertln(void); //插入空白行
int delch(void);//删除光标左边的字符
int deleteln(void); //删除空白行
int beep(void); //终端响铃
int flash(void); //闪烁
chtype inch(void); //返回光标位置字符
int instr(char *string); //读取字符到string所指向的字符串中
int innstr(char *string, int numbers);//读取numbers个字符到string所指向的字符串中
int erase(void);//在屏幕的每个位置写上空白字符
int clear(void);//使用一个终端命令来清除整个屏幕,相当于vi内的Ctrl+L
//内部调用了clearok来执行清屏操作,(在下次调用refresh时可以重现屏幕原文)
int clrtobot(void);//清除光标位置到屏幕结尾的内容
int clrtoeol(void);//清除光标位置到该行行尾的内容
int move(int new_y, int new_x); //移动stdcsr的光标位置
int leaveok(WINDOW *window_ptr,bool leave_flag);
//设置一个标志,用于控制在屏幕刷新后curses将物理光标放置的位置。
指对字符设置加粗,反色显示等等。
A_ALTCHARSET Alternate character set 机翻: 交替字符集
A_BLINK Blinking 闪烁
A_BOLD Extra bright or bold 加粗、高亮度
A_DIM Half bright 半透明
A_INVIS Invisible 无形的
A_PROTECT Protected 保护
A_REVERSE Reverse video 反白
A_STANDOUT Best highlighting mode of the terminal 最好突出显示终端的模式
A_UNDERLINE Underlining 加底线
int attron(chtype attribute);//启用某属性
int attroff(chtype attribute);//关闭某属性
int attrset(chtype attribute);//设置某属性
int standout(void);//启动standout模式(一般使屏幕发色)
int standend(void);//关闭standout模式
int echo();//用于开启键盘输入字符的回显
int noecho(); //用于关闭键盘输入字符的回显
//完成initscr后,输入模式为预处理模式,
//(1)所有处理是基于行的,就是说,只有按下 回车,输入数据才被传给程序;
//(2)键盘特殊字符启用,按下合适组合键会产生信号
int cbreak(); //设置cbreak模式,字符一键入,直接传给程序
int nocbreak(); //关闭
int raw(); //关闭特殊字符处理
int noraw(); //同时h恢复默认模式和特殊字符处
所有函数在失败时都返回整数ERR,在成功完成时则返回OK。
//与标准io库的getchar, gets, scanf类似
int getch();//读取一个字符
int getstr(char *string);//读取一个字符串
int getnstr(char *string, int number); //建议使用
int scanw(char*format,...);
curses函数库支持在一个物理屏幕上显示多个窗口。
WINDOW *newwin(int lines, int cols, int start_y, int start_x);
//创建从(start_y, start_x)开始的lines行,cols列的窗口。
int delwin(WINDOW *window);//销毁上面创建的窗口,千万不要删除stdscr和curscr!
前缀w用于窗口(添加一个WINDOWS指针参数),mv用于光标移动(在该位置执行操作addch或printw)(添加两个坐标值参数),mvw用于在窗口中移动光标。组成如下函数:
int addch(const chtype char);//在当前位置画字符c
int waddch(WINDOW *window_pointer,const chtype char);
int mvaddch(int y,int x,const chtype char);
int mvwaddch(WINDOW *window_pointer,int y,int x,const chtype char);
int printw(char *format,...);
int wprintw(WINDOW *window_pointer,char *format,...);
int mvprintw(int y,int x,char *format,...);
int mvwprintw(WINDOW *window_pointer,int y,int x,char *format,...);
int mvwin(WINDOW *win, int new_y, int new_x); //移动窗口
int wrefresh(WINDOW *win);
int wclear(WINDOW *win);
int werase(WINDOW *win);
//类似于上面的refresh, clear, erase,但是此时针对特定窗口操作,而不是stdcur
int touchwin(WINDOW *win); //指定该窗口内容已改变、
//下次wrefresh时,需重绘窗口。利用该函数,安排要显示的窗口
int scrollok(WINDOW *win, bool flag); //指定是否允许窗口卷屏
int scroll(WINDOW *win); //把窗口内容上卷一行
int wnoutrefresh(WINDOW *window_ptr);
//The wnoutrefresh subroutine determines which parts of the terminal may need updating.
int doupdate(void);
//The doupdate subroutine sends to the terminal the commands to perform any required changes.
子窗口除了没有自己的屏幕字符存储空间外,其他与新窗口相同。
WINDOW *subwin(WINDOW *parent, int lines, int cols, int start_y, int start_x);//创建子窗口。
int delwin(WINDOW *window);//销毁子窗口
窗口转储同屏幕转储的原理一样。getwin()函数(函数原型:getwin(FILE * filep) ——译者注)用来将窗口内容存储到一个指定的文件中。putwin()函数(函数原型:putwin(WINDOW*win, FILE * filep) ——译者注)则调用相应的文件来恢复窗口。copywin()可以将一个窗口拷贝到另一个窗口,即将源窗口矩形区域(由参数指定)中的内容复制到目标窗口指定的矩形区域(由参数指定)里。而最后的参数用来选择是否要覆盖目的窗口:如果参数为TRUE,那么就会覆盖目标窗口的内容;如果参数为FLASE,那么就会重写目的窗口中的内容。以下为函数的原型:
int copywin(
const WINDOW *src, /* 源窗口指针*/
WINDOW *dst, /* 目的窗口指针*/
int sminrow, /* 源窗口所选矩形区域的最小行数*/
int smincol, /* 源窗口所选矩形区域的最小列数*/
int dminrow, /* 目的窗口所选矩形区域的最小行数*/
int dmincol, /* 目的窗口所选矩形区域的最小列数*/
int dmaxrow, /* 目的窗口所选矩形区域的最大行数*/
int dmaxcol, /* 目的窗口所选矩形区域的最大列数*/
int over) /* 是否覆盖目的窗口*/
键盘管理函数部分看到了curses提供了处理键盘的功能。另外,键盘一般还会有方向键,功能键,数字小键盘,Insert, Home等按键。这些键会发送以""(转义字符)开头的字符串序列。解码这些键就要区分“单独按下\键”和“按下功能键而产生\开头的字符串序列”,
在curses函数库中,头文件curses.h提供了一组以KEY_为前缀的定义来管理逻辑键。
curses在启动时会 关闭转义序列与逻辑键之间的转换功能,需要调用如下函数开启:
int keypad(WINDOW *win, bool keypad_on);
//keypad_on参数为true时,启用keypad模式。
//此时读键盘操作能够返回 用户在按下逻辑键时对应的KEY_定义
ncurses定义了八种颜色,在带有彩色支持的终端上用户能够使用这些颜色。 首先,调用start_color()初始化颜色数据结构,然后使用has_colors()检查终端权能。
start_color()将初始化COLORS和COLOR_PAIR。 前者是终端所支持的最多的颜色数目,而后者是用户能够定义的色彩对的最大数目。
bool has_colors(void);
int start_color(void);
int init_pair(short pair_number,short foreground,short background);
//eg: init_pair(1,COLOR_RED,COLOR_GREEN),将红色前景绿色背景定义为一号颜色组合。
int COLOR_PAIR(int pair_number);eg: COLOR_PAIR(1),作为属性来访问,同A_BOLD
int pair_content(short pair_number,short *foreground,short *background);
//和init_pair相反,通过颜色组合号,来获得颜色。
int init_color(short color_number,short red,short green,short blue);
//通过red green blue组合颜色
void getyx(WINDOW *win,int y,int x);//getyx()是一个宏
//得到目前游标的位置. (请注意! 是 y,x 而不是&y,&x )
void getparyx(WINDOW *win, int y, int x);
//用于取得子窗口相对主窗口的起始坐标,它在更新子窗口时经常使用。
void getmaxyx(WINDOW *win, int y, int x);
//函数返回win窗口中最大的行数和最大的列数