键盘数值的获取工具

版权声明:转发注明出处,共同学习共同进步,感谢支持。 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下效果不同。

猜你喜欢

转载自blog.csdn.net/AMDDMA/article/details/82879076
今日推荐