版权声明:转发注明出处,共同学习共同进步,感谢支持。 https://blog.csdn.net/AMDDMA/article/details/82879076
一、参考源:
github链接:https://github.com/antirez/linenoise
二、用途:
获取键盘的值,用于在windows的SerurtCRT和Linux上测试键盘数值是否相同,从而实现readline的键盘功能开发。
可以获取单个键和组合键的字符。
三、获取键值小工具源码(环境:CentOS-7.0 平台:x86 内核和编译器没有更改):
/****************************************************************
* 文件名:readline_tool_get_key_value.c
* 功能:获取键盘输入数值
* 版本:V0.1
* 创建时间:2018-9-28 11:47
****************************************************************/
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
static int rawmode = 0; /* 判断当前是否打开输入的 RAW 模式 */
struct termios orig_termios; /* 终端原有模式 */
static char *unsupported_term_type[] = {"dumb","cons25","emacs",NULL}; /* 不受支持的终端类型 */
static int exit_registered_flag = 0;
static int signal_flag = 0;
/* 关闭终端的RAW模式,恢复原有的模式 */
static void terminal_disable_raw_mode(int fd)
{
if (rawmode && tcsetattr(fd,TCSAFLUSH,&orig_termios) != -1)
rawmode = 0;
}
/* 注册为main退出后执行函数 */
void exit_func()
{
terminal_disable_raw_mode(STDIN_FILENO);
}
/****************************************************************
* 函数名:terminal_enable_raw_mode
* 功能:使能终端RAW模式
* 输入:无
* 输出:无
* 返回值:无
* 函数类型:内部函数
****************************************************************/
/* Raw mode: 1960 magic shit. */
//终端类型过于混乱,尤其backspace和delete
static int terminal_enable_raw_mode(int fd)
{
struct termios raw;
/* 判断是否是中断设备 */
if (!isatty(STDIN_FILENO))
return -1;
/* 注册main退出后执行的函数 */
if (!exit_registered_flag)
{
atexit(exit_func);
exit_registered_flag = 1;
}
/* 获取当前终端的tty参数 */
if (tcgetattr(fd,&orig_termios) == -1)
return -1;
/* 在终端原有模式基础上进行修改添加 */
raw = orig_termios;
/* 输入模式:no break, no CR to NL, no parity check, no strip char,no start/stop output control. */
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
/* 输出模式:disable post processing */
raw.c_oflag &= ~(OPOST);
/* 流控制:8bit */
raw.c_cflag |= (CS8);
/* 本地模式:打开回显、规范显示、定义的输入处理。 */
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN );
/* 控制字符设置 */
raw.c_cc[VMIN] = 1; /* 非规范读取数据 */
raw.c_cc[VTIME] = 0; /* 不处理计时器输入 */
//raw.c_cc[VINTR] = 1; /* 打开进程自身信号捕获,该选项使 Ctrl+A 可以终止当前进程 */
if (tcsetattr(fd,TCSAFLUSH,&raw) < 0)
return -1;
rawmode = 1;
return 0;
}
/****************************************************************
* 函数名:print_key_value
* 功能:打印输入字符的值,一次打印一个字符
* (一个方向键包含三个字符)
* 输入:无
* 输出:无
* 返回值:无
* 函数类型:外部可调用
****************************************************************/
void print_key_value(void)
{
char quit[4];
printf("Press keys to see scan codes.\nPress 'Ctrl+Z' or input 'quit' at any time to exit.\n");
if (terminal_enable_raw_mode(STDIN_FILENO) == -1)
return;
memset(quit,' ',4);
while(1)
{
char c;
int n_read;
n_read = read(STDIN_FILENO,&c,1);
if (n_read <= 0)
continue;
memmove(quit,quit+1,sizeof(quit)-1); /* 将前一个字符左移 */
quit[sizeof(quit)-1] = c; /* 将当前输入字符插入字符串 */
printf("char:'%c' value: Hex:0x%.2x Dec:%d\n",isprint(c) ? c : '?',(int)c,(int)c);
printf("\r");/* RAW模式需要手动将光标置左 */
fflush(stdout);
/* 判断是否是退出命令 */
if (memcmp(quit,"quit",sizeof(quit)) == 0)
break;
}
terminal_disable_raw_mode(STDIN_FILENO);
}
/****************************************************************
* 函数名:config_terminal_type
* 功能:查询当前终端的类型,
* 输入:无
* 输出:无
* 返回值:如果是列表中不支持的类型,则返回1
* 函数类型:内部函数
****************************************************************/
static int config_terminal_type(void)
{
char *term = getenv("TERM");//获取环境变量参数
int j;
if (term == NULL)
return 0;
for (j = 0;unsupported_term_type[j];j++)
{
if (!strcasecmp(term,unsupported_term_type[j])) //忽略大小写进行比较,相同为0
{
return 1;
}
}
return 0;
}
/****************************************************************
* 函数名:main
* 功能:程序入口
* 输入:无
* 输出:无
* 返回值:
* 函数类型:主函数
****************************************************************/
void main()
{
printf(">>>>>>>>>>>>Get Key Value Tool<<<<<<<<<<<<<<\n");
if(config_terminal_type())
{
printf("Terminal Unsupported!\n");
return ;
}
print_key_value();
}
四、使用该工具获取键值时需要注意在SecurtCRT下使用的终端模式,终端模式应为Linux,保持与Linux系统的一致性,避免windows下和linux下效果不同。