Sunday, February 26, 2012
Wednesday, January 11, 2012
[L] curses
curses里面封装了一下对terminal 还有cursor的用法,从我之前一篇blog也可以看出如果不封装是多么令人肾虚。
需要搞明白一点的是,前面是对terminal进行操作,这个是对X window进行操作。所以从本质上来讲是不一样的。但是用起来感觉没什么大不同。。
1. initscr(), endwin()
init之后,整个屏幕被刷掉,生成一个新屏幕。在这里只能用curses里面的printw,scanw之类的。因为这是它自己的屏幕。之后endwin()退出。
2. move(x,y)
封装得够简单了。
3. attron, attroff
对输出属性进行设置,试一下就知道了。
至于属性设置参考这里:
http://www.mkssoftware.com/docs/man3/curs_attr.3.asp
4. refresh()
把整个屏幕刷新一遍。比如initscr之后,如果不refresh,那么屏幕原来有的还在,很混乱。
本来应该是所有动作之后都应该refresh一下,但是有些试了下不要也行。个人猜测是覆盖的原因。如果有覆盖的话要refresh().
还有一点要注意的就是,必须有change 才会刷新。如果没有change还是不变的。如果没有change硬要刷新的话也行,用touchwin(WINDOW).
5. cbreak(), echo()
前者相当于之前的non-canonical,就是不是一行输入了。变成一个个输入,包括换行。
后者指定是否回显。
实践代码如下,因为都是终端运行即可见了,所以样例也不用贴了。
代码一:
*注意一点:中间getchar()的时候,不论输入什么也不会回显的。这是因为被流弄走了,但是不会保留在window上。而getstr(), getch()则会留在屏幕上,如果不把echo()关掉的话。
/*
* =====================================================================================
*
* Filename: screen1.c
*
* Description: Uses of curses.h
*
* Version: 1.0
* Created: Wednesday, January 11, 2012 02:55:22 HKT
* Revision: none
* Compiler: gcc
*
* Author: Hongchao Deng (fengjingchao), fengjingchao@gmail.com
* Company: Sun Yat-sen University
*
* =====================================================================================
*/
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <curses.h>
#define PW_LEN 256
#define NAME_LEN 256
/*
* === FUNCTION ======================================================================
* Name: main
* Description: main function
* =====================================================================================
*/
int
main ( int argc, char *argv[] )
{
/* Parameters */
char *scan_ptr;
char witch_one[] = "First Witch ";
char witch_two[] = "Second Witch ";
/* TODO */
initscr();
move(5,15);
attron(A_BOLD);
printw("%s", "Macintosh");
attroff(A_BOLD);
refresh();
getchar();
move(8,15);
attron(A_STANDOUT);
printw("Thunder and lighting");
attroff(A_STANDOUT);
refresh();
getchar();
move(10,10);
printw("TEST PRINT");
move(11,23);
printw("TEST PRINT");
refresh();
getchar();
attron(A_DIM);
scan_ptr = witch_one + strlen(witch_one) - 1;
while(scan_ptr != witch_one){
move(10,10);
insch(*--scan_ptr);
}
attroff(A_DIM);
refresh();
getchar();
move(LINES -1, COLS -1);
printw("%s",witch_two);
refresh();
getchar();
clear();
char name[NAME_LEN];
char password[PW_LEN];
char *real_password = "123456";
move(5,10);
printw("Please login");
move(7,10);
printw("User name: ");
getstr(name);
move(8,10);
printw("Password: ");
// refresh();
cbreak();
noecho();
memset(password,0,sizeof(password));
int i=0;
for(;i<PW_LEN;i++){
password[i] = getch();
if( password[i] == '\n') break;
move(8,20+i);
addch('*');
// refresh();
}
echo();
nocbreak();
endwin();
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
代码二:
展示多个window的情况
/*
* =====================================================================================
*
* Filename: multiw.c
*
* Description: Managing Multiple Windows
*
* Version: 1.0
* Created: Wednesday, January 11, 2012 07:42:44 HKT
* Revision: none
* Compiler: gcc
*
* Author: Hongchao Deng (fengjingchao), fengjingchao@gmail.com
* Company: Sun Yat-sen University
*
* =====================================================================================
*/
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <curses.h>
/*
* === FUNCTION ======================================================================
* Name: main
* Description: main function
* =====================================================================================
*/
int
main ( int argc, char *argv[] )
{
WINDOW *new_window_ptr;
WINDOW *popup_window_ptr;
int x_loop;
int y_loop;
char letter = 'a';
initscr();
move(5,5);
printw("Testing multiple windows");
refresh();
sleep(1);
for ( y_loop = 0;y_loop < LINES -1 ;++y_loop ) {
for (x_loop = 0; x_loop < COLS -1; ++x_loop) {
mvaddch(y_loop,x_loop,letter);
letter++;
if(letter >'z') letter = 'a';
}
}
refresh();
getchar();
new_window_ptr = newwin(10,20,5,5);
mvwprintw(new_window_ptr,2,5,"Testing multiple windows");
mvwprintw(new_window_ptr,5,10,"*********************************************************");
wrefresh(new_window_ptr);
getchar();
letter = '0';
for ( y_loop = 0;y_loop < LINES -1 ;++y_loop ) {
for (x_loop = 0; x_loop < COLS -1; ++x_loop) {
mvaddch(y_loop,x_loop,letter);
letter++;
if(letter >'9') letter = '0';
}
}
refresh();
getchar();
wrefresh(new_window_ptr);
getchar();
touchwin(new_window_ptr);
wrefresh(new_window_ptr);
getchar();
endwin();
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
需要搞明白一点的是,前面是对terminal进行操作,这个是对X window进行操作。所以从本质上来讲是不一样的。但是用起来感觉没什么大不同。。
1. initscr(), endwin()
init之后,整个屏幕被刷掉,生成一个新屏幕。在这里只能用curses里面的printw,scanw之类的。因为这是它自己的屏幕。之后endwin()退出。
2. move(x,y)
封装得够简单了。
3. attron, attroff
对输出属性进行设置,试一下就知道了。
至于属性设置参考这里:
http://www.mkssoftware.com/docs/man3/curs_attr.3.asp
4. refresh()
把整个屏幕刷新一遍。比如initscr之后,如果不refresh,那么屏幕原来有的还在,很混乱。
本来应该是所有动作之后都应该refresh一下,但是有些试了下不要也行。个人猜测是覆盖的原因。如果有覆盖的话要refresh().
还有一点要注意的就是,必须有change 才会刷新。如果没有change还是不变的。如果没有change硬要刷新的话也行,用touchwin(WINDOW).
5. cbreak(), echo()
前者相当于之前的non-canonical,就是不是一行输入了。变成一个个输入,包括换行。
后者指定是否回显。
实践代码如下,因为都是终端运行即可见了,所以样例也不用贴了。
代码一:
*注意一点:中间getchar()的时候,不论输入什么也不会回显的。这是因为被流弄走了,但是不会保留在window上。而getstr(), getch()则会留在屏幕上,如果不把echo()关掉的话。
/*
* =====================================================================================
*
* Filename: screen1.c
*
* Description: Uses of curses.h
*
* Version: 1.0
* Created: Wednesday, January 11, 2012 02:55:22 HKT
* Revision: none
* Compiler: gcc
*
* Author: Hongchao Deng (fengjingchao), fengjingchao@gmail.com
* Company: Sun Yat-sen University
*
* =====================================================================================
*/
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <curses.h>
#define PW_LEN 256
#define NAME_LEN 256
/*
* === FUNCTION ======================================================================
* Name: main
* Description: main function
* =====================================================================================
*/
int
main ( int argc, char *argv[] )
{
/* Parameters */
char *scan_ptr;
char witch_one[] = "First Witch ";
char witch_two[] = "Second Witch ";
/* TODO */
initscr();
move(5,15);
attron(A_BOLD);
printw("%s", "Macintosh");
attroff(A_BOLD);
refresh();
getchar();
move(8,15);
attron(A_STANDOUT);
printw("Thunder and lighting");
attroff(A_STANDOUT);
refresh();
getchar();
move(10,10);
printw("TEST PRINT");
move(11,23);
printw("TEST PRINT");
refresh();
getchar();
attron(A_DIM);
scan_ptr = witch_one + strlen(witch_one) - 1;
while(scan_ptr != witch_one){
move(10,10);
insch(*--scan_ptr);
}
attroff(A_DIM);
refresh();
getchar();
move(LINES -1, COLS -1);
printw("%s",witch_two);
refresh();
getchar();
clear();
char name[NAME_LEN];
char password[PW_LEN];
char *real_password = "123456";
move(5,10);
printw("Please login");
move(7,10);
printw("User name: ");
getstr(name);
move(8,10);
printw("Password: ");
// refresh();
cbreak();
noecho();
memset(password,0,sizeof(password));
int i=0;
for(;i<PW_LEN;i++){
password[i] = getch();
if( password[i] == '\n') break;
move(8,20+i);
addch('*');
// refresh();
}
echo();
nocbreak();
endwin();
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
代码二:
展示多个window的情况
/*
* =====================================================================================
*
* Filename: multiw.c
*
* Description: Managing Multiple Windows
*
* Version: 1.0
* Created: Wednesday, January 11, 2012 07:42:44 HKT
* Revision: none
* Compiler: gcc
*
* Author: Hongchao Deng (fengjingchao), fengjingchao@gmail.com
* Company: Sun Yat-sen University
*
* =====================================================================================
*/
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <curses.h>
/*
* === FUNCTION ======================================================================
* Name: main
* Description: main function
* =====================================================================================
*/
int
main ( int argc, char *argv[] )
{
WINDOW *new_window_ptr;
WINDOW *popup_window_ptr;
int x_loop;
int y_loop;
char letter = 'a';
initscr();
move(5,5);
printw("Testing multiple windows");
refresh();
sleep(1);
for ( y_loop = 0;y_loop < LINES -1 ;++y_loop ) {
for (x_loop = 0; x_loop < COLS -1; ++x_loop) {
mvaddch(y_loop,x_loop,letter);
letter++;
if(letter >'z') letter = 'a';
}
}
refresh();
getchar();
new_window_ptr = newwin(10,20,5,5);
mvwprintw(new_window_ptr,2,5,"Testing multiple windows");
mvwprintw(new_window_ptr,5,10,"*********************************************************");
wrefresh(new_window_ptr);
getchar();
letter = '0';
for ( y_loop = 0;y_loop < LINES -1 ;++y_loop ) {
for (x_loop = 0; x_loop < COLS -1; ++x_loop) {
mvaddch(y_loop,x_loop,letter);
letter++;
if(letter >'9') letter = '0';
}
}
refresh();
getchar();
wrefresh(new_window_ptr);
getchar();
touchwin(new_window_ptr);
wrefresh(new_window_ptr);
getchar();
endwin();
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
Tuesday, January 10, 2012
[L] termios, curses, Terminal Control
好吧,终于到 terminal 了。那真叫一个纠结,最后还是看完了。。
附上实践:
/*
* =====================================================================================
*
* Filename: menu.c
*
* Description: Reading Each Character,
* Without processing some signal characters even like C-c
* Using Terminal Control
*
* Version: 2.0
* Created: Wednesday, December 28, 2011 11:27:45 HKT
* Revision: none
* Compiler: gcc
*
* Author: Hongchao Deng (fengjingchao), fengjingchao@gmail.com
* Company: Sun Yat-sen University
*
* =====================================================================================
*/
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <term.h>
#include <ncurses.h>
char *menu[] = {
"a - add new record",
"d - delete record" ,
"q - quit",
NULL
};
FILE *output_stream = NULL;
/*
* === FUNCTION ======================================================================
* Name: char_to_terminal
* Description: use output_stream to which the program writes the output.
* Otherwise in the getchoice() function we can use putp();
* =====================================================================================
*/
int
char_to_terminal ( int char_to_write )
{
if (output_stream) putc(char_to_write, output_stream);
return 0;
} /* ----- end of function char_to_terminal ----- */
/*
* === FUNCTION ======================================================================
* Name: getchoice
* Description: get the choice from prompt.
* it will simply discard any invalid input including chars like ^C
* =====================================================================================
*/
int
getchoice ( FILE *input, FILE *output)
{
int choice;
int chosen = 0;
int screenrow = 4, screencol = 10;
char **option;
char *cursor, *clear;
output_stream = output;
setupterm(0,1,0);
cursor = tigetstr("cup");
clear = tigetstr("clear");
tputs(clear, 1, char_to_terminal );
while(!chosen){
tputs(tparm(cursor,screenrow++,screencol), 1, char_to_terminal);
fprintf(output,"Please select an option:\n");
for(option = menu; *option != NULL; option++, screenrow++){
tputs(tparm(cursor,screenrow++,screencol), 1, char_to_terminal);
fprintf(output,"%s\n", *option);
}
for(choice = '\n'; choice == '\n';choice = fgetc(input));
for(option = menu; *option != NULL; option++){
if(choice == *option[0]){
chosen = 1; break;
}
}
if(!chosen) {
tputs(tparm(cursor,screenrow++,screencol), 1, char_to_terminal);
fprintf(output, "Incorrect choice: '%c'\n",choice);
}
}
tputs(clear, 1, char_to_terminal );
return choice;
} /* ----- end of function getchoice ----- */
/*
* === FUNCTION ======================================================================
* Name: main
* Description: main function
* =====================================================================================
*/
int
main ( int argc, char *argv[] )
{
int choice = 0;
FILE *input; /* input-file pointer */
input = fopen( "/dev/tty", "r" );
FILE *output;
output = fopen( "/dev/tty", "w");
if ( input == NULL || output == NULL ) {
fprintf ( stderr, "couldn't open file '%s'; %s\n",
"/dev/tty", strerror(errno) );
exit (EXIT_FAILURE);
}
struct termios initialSetting, newSetting;
tcgetattr(fileno(stdin),&initialSetting);
newSetting = initialSetting;
newSetting.c_lflag &= ~ISIG;
newSetting.c_lflag &= ~ECHO;
newSetting.c_cc[VMIN] = 1;
newSetting.c_cc[VTIME]= 0;
newSetting.c_lflag &= ~ICANON;
if(tcsetattr(fileno(stdin), TCSANOW , &newSetting) != 0)
fprintf(stderr, "Could not set terminal attributes!");
for(choice = 0; choice != 'q';){
choice = getchoice(input, output);
printf("You have chosen %c\n",choice);
sleep(1);
}
tcsetattr(fileno(stdin), TCSANOW , &initialSetting);
if( fclose(input) == EOF || fclose(output) == EOF ) {/* close input file */
fprintf ( stderr, "couldn't close file '%s'; %s\n",
"/dev/tty", strerror(errno) );
exit (EXIT_FAILURE);
}
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
输出可以当场试,都已经是 terminal 了。。
总结一下:
功能:
1. 能调整光标的行列。
2. 能使得输入输出不显示,操作输入输出怎么读写。
经验:
1. setupterm就直接 setupterm(0,1,0), 不知道第二个参数 (flie descriptor) 干嘛用的。
2. 逃过stdout , 用‘/dev/tty’ .. 但是注意对terminal输出控制的时候不能用putp()了,要用tputs().
3. 其实操作terminal都是一堆字符输过去的,而且不同类型的terminal还有不同的控制方法,所以才有 curses这个库。
4. 父进程会直接将stdin这些copy到子进程里面,就是说如果不回复过来的话,那么terminal就变成那样了。。所以对std 三剑客in,out,err做修改之前一定要保存一份,程序结束后回复。
我也不太懂。。下次弄个牛逼一点的再写份好点的总结。这次算记录。。
Sunday, January 1, 2012
Subscribe to:
Comments (Atom)