第五章 终端

来源:互联网 发布:淘宝如何做企业店铺 编辑:程序博客网 时间:2024/06/02 04:04

menu1.c

#include <stdio.h>#include <stdlib.h>char *menu[] = {    "a - add new record",    "d - delete record",    "q - quit",    NULL};int getchoice(char *greet, char *choices[]);int main(){    int choice = 0;    do {        choice = getchoice("Please select an action", menu);        printf("You have chosen: %c\n", choice);    } while (choice != 'q');    exit(0);}int getchoice(char *greet, char *choices[]){    int chosen = 0;    int selected;    char **option;    do {        printf("Choice: %s\n", greet);        option = choices;        while(*option){            printf("%s\n", *option);            option++;        }        selected = getchar();        option = choices;        while(*option){            if(selected == *option[0]){                chosen = 1;                break;            }            option++;        }        if(!chosen){            printf("Incorrect choice, select again\n");        }    } while(!chosen);    return selected;}

isatty

#include <unistd.h>int isatty(int fd);

password.c

#include <termios.h>#include <stdio.h>#include <stdlib.h>#define PASSWORD_LEN 8int main(){    struct termios initialrsetting, newrsetting;    char password[PASSWORD_LEN];    tcgetattr(fileno(stdin), &initialrsetting);    newrsetting = initialrsetting;    newrsetting.c_flag &= ~ECHO;    printf("Enter password: ");    if(tcsetattr(fileno(stdin), TCSAFLUSH, &newrsetting) != 0)        fprintf(stderr, "Could not set attributes\n");    else {        fgets(password, PASSWORD_LEN, stdin);        tcsetattr(fileno(stdin), TCSANOW, *initialrsetting);        fprintf(stdout, "\nYou entered %s\n", password);    }    exit(0);}

menu3.c:输入输出重定向至/dev/tty

#include <stdio.h>#include <unistd.h>#include <stdlib.h>char *menu[] = {    "a - add new record",    "d - delete record",    "q - quit",    NULL};int getchoice(char *greet, char *choices[], FILE *in, FILE *out);int main(){    int choice = 0;    FILE *input, *output;    if(!isatty(fileno(stdout)))        fprintf(stderr, "You are not a terminal.OK!\n");    input = fopen("/dev/tty", "r");    output = fopen("/dev/tty", "w");    if(!input || !output){        fprintf(stderr, "Unable to opem /dev/tty\n");        exit(1);    }    do {        choice = getchoice("Please select an action",                 menu, input, output);        printf("You have select %c\n", choice);    }   while(choice != 'q');    exit(0);}int getchoice(char *greet, char *choices[], FILE *in,              FILE *out){    int chosen = 0;    int selected;    char **option;    do {        fprintf(out, "choice: %s\n",greet);        option = choices;        while(*option){            fprintf(out, "%s\n", *option);            option++;        }        do {            selected = fgetc(in);        } while(selected == '\n');        option = choices;        while(*option){            if(selected == *option[0]){                fprintf(out, "%s\n", *option);                chosen = 1;                break;            }            option++;        }        if(!chosen)            fprintf(out, "Incorrect choice, select again                    \n");    } while(!chosen);    return selected;}

使用terminfo标志

#include <term.h>int setupterm(char *term, int fd, int errret);
  1. setupterm库函数将当前终端类型设置为参数term所指向的值,如果term是空指针使用环境变量TERM的值
  2. 参数fd为一个打开的文件描述符,它用于向终端写数据
  3. 如果errret被设置为空指针,setupterm函数会在失败时输出一条诊断信息并导致程序直接退出
  4. 如果参数errret不是一个空指针,则函数的返回值保存在该参数指向的的整型变量中,下面给出了可能写入的值:
     
    -1: terminfo数据库不存在
    0 : terminfo数据库中没有匹配的数据项
    1 : 成功

setupterm..c

#include <stdio.h>#include <term.h>#include <curses.h>#include <stdlib.h>int main(){    setupterm("unlisted", fileno(stdout), (int *)0);    printf("Done.\n");    exit(0);}

tigetflag, tigetnum, tigetstr

#include <term.h>int tigetflag(char *capname);int tigetnum(char *capname);char *tigetstr(char *capname);
  1. tigetflag, tigetnum和tigetstr分别返回terminfo中的布尔功能标志,数值功能标志和字符串功能标志的值.
  2. 失败时,tigetflag函数返回-1,tigetnum函数返回-2,tigetstr函数返回(char *)-1
  3. tigetstr函数用来获取xterm终端类型的光标移动功能标志cup的值

sizeterm.c:通过获取terminfo中的cols和lines功能标志来查找当前终端的显示区大小

#include <stdio.h>#include <term.h>#include <curses.h>#include <stdlib.h>int main(){    int nrows, ncolumns;    setupterm(NULL, fileno(stdout), (int *)0);    nrows = tigetnum("lines");    ncolumns = tigetnum("cols");    printf("This terminal has %d columns and %d rows\n", nrows, ncolumns);    exit(0);}

tparm:tparm函数用实际的数值替换功能标志中的参数,一次最多可以替换9个参数,并返回一个可用的escape转义序列

#include <term.h>char *tparm(char *cap, long p1, long p2, ..., long p9);

putp, tputs:将tparm函数构造好的escape转移序列发送给终端,不能使用printf

#include <term.h>int putp(char *const str);int fputs(char *const str, int affect, int (*putfunc)(int));
  1. putp函数在成功时返回OK, 失败时返回ERR,他以一个终端控制字符串为参数,并将其发送到标准输出stdout
  2. 如果要将光标移动到屏幕的第5行第30列,可以使用如下代码:
     
    char *cursor;
    char *esc_sequence;
    cursor = tigetstr("cup");
    esc_sequence = tparm(cursor, 5, 30);
    putp(esc_sequence);
  3. tputs函数是为不能通过标准输出stdout访问终端的情况准备的,他可以指定一个用于输出字符的函数
  4. tputs函数的返回值是用户指定的函数putfunc的返回结果
  5. 参数affcnt的作用是表名受这一行变化影响的行数,他被设置为1
  6. 真正用于输出控制字符串的函数的参数和返回值类型必须与putchar函数相同
  7. 事实上,putp(string)就等于tputs(string, 1, putchar)

完整的终端控制:menu5.c

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <termios.h>#include <term.h>#include <curses.h>static FILE *output_stream = (FILE *)0;char *menu[] = {    "a - add new record",    "d - delete record",    "q - quit",    NULL};int getchoice(char *greet, char *choices[],              FILE *in, FILE *out);int char_to_terminal(int char_to_write);int main(){    int choice = 0;    FILE *input;    FILE *output;    struct termios initial_setting, new_setting;    if(!isatty(fileno(stdout)))        fprintf(stderr, "You are not a terminal, OK.\n");    input = fopen("/dev/tty", "r");    output = fopen("/dev/tty", "w");    if(!input || !output){        fprintf(stderr, "Unable to open /dev/tty\n");        exit(1);    }    tcgetattr(fileno(input), &initial_setting);    new_setting = initial_setting;    new_setting.c_lflag = ~ICANON;    new_setting.c_lflag = ~ECHO;    new_setting.c_cc[VMIN] = 1;    new_setting.c_cc[VTIME] = 0;    new_setting.c_lflag = ~ISIG;    if(tcsetattr(fileno(input), TCSANOW, &new_setting) != 0)        fprintf(stderr, "could not set attributes\n");    do {        choice = getchoice("Please select an action", menu, input, output);        printf("You have chosen: %c\n", choice);    } while(choice != 'q');    tcsetattr(fileno(input), TCSANOW, &initial_settting);    exit(0);}int getchoice(char *greet, char *choices[],              FILE *in, FILE *out){    int chosen = 0;    int selected;    int screenrow, secreencol = 10;    char **option;    char *cursor, *clear;    output_stream = out;    setupterm(NULL, fileno(out), (int *)0);    cursor = tigetstr("cup");    clear = tigetstr("clear");    screenrow = 4;    tputs(clear, 1, (int *) char_to_terminal);    tputs(tparm(cursor, screenrow, screencol),          1, char_to_terminal);    fprintf(out, "choice: %s", greet);    screenrow +=2;    option = choices;    while(*option){        tputs(tparm(cursor, screenrow, screencol),              1, char_to_terminal);        fprintf(out, "%s", *option);        screenrow++;        option++;    }    fprintf(out, "\n");    do {        fflush(out);        selected = fgetc(in);        option = choices;        while(*option){            if(selected == *option[0]){                chosen = 1;                break;            }            option++;        }        if(!chosen){            tputs(tparm(cursor, screenrow, screencol),                  1, char_to_terminal);            fprintf(out, "Incorrect choice, select again\n");        }    } while(!chosen);    tputs(clear, 1, char_to_terminal);    return selected;}int char_to_terminal(int char_to_write){    if(output_stream)        putc(char_to_write, output_stream);    return 0;}
0 0