Skip to content

Instantly share code, notes, and snippets.

@kou1okada
Last active October 22, 2019 04:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kou1okada/1642394e874c6054a077 to your computer and use it in GitHub Desktop.
Save kou1okada/1642394e874c6054a077 to your computer and use it in GitHub Desktop.
tty_getkey - Multiplatform simplified non-blocking keyboard input routine.
/**
* msleep - sleep for microseconds
* Copyright 2014 (c) Koichi OKADA. All rights reserved.
* This file is distributed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*/
#ifndef MSLEEP_H
#define MSLEEP_H
#if defined(_WIN32)
#include <windows.h>
#define msleep Sleep
#define sleep(x) Sleep((x)*1000)
#elif defined(__unix__)
#include <unistd.h>
#define msleep(x) usleep((x)*1000)
#endif//defined(_WIN32),defined(__unix__)
#endif//USLEEP_H
/**
* tty_getkey - Multiplatform simplified non-blocking keyboard input routine.
* Copyright 2014 (c) Koichi OKADA. All rights reserved.
* This file is distributed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*/
// Reference:
// comp.lang.c FAQ list * Question 19.1
// Q: How can I read a single character from the keyboard without waiting for the RETURN key?
// How can I stop characters from being echoed on the screen as they're typed?
// http://c-faq.com/osdep/cbreak.html
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "tty_getkey.h"
// Reference:
// C/C++ tip: How to detect the operating system type using compiler predefined macros
// http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
#if defined(_WIN32)
void tty_setxy(int x, int y)
{
gotoxy(x + 1, y + 1);
}
int tty_getx(void)
{
return wherex() - 1;
}
int tty_gety(void)
{
return wherey() - 1;
}
int tty_getw(void)
{
struct text_info info;
gettextinfo(&info);
return info.screenwidth;
}
int tty_geth(void)
{
struct text_info info;
gettextinfo(&info);
return info.screenheight;
}
static char *initial_txt = NULL;
static int initial_x;
static int initial_y;
static int initial_w;
static int initial_h;
int tty_begin(void)
{
textmode(C80X21);
initial_x = tty_getx();
initial_y = tty_gety();
initial_w = tty_getw();
initial_h = tty_geth();
initial_txt = malloc(initial_w * initial_h * 2);
gettext(1, 1, initial_w, initial_h, initial_txt);
clrscr();
return 0;
}
int tty_end(void)
{
puttext(1, 1, initial_w, initial_h, initial_txt);
free(initial_txt);
tty_setxy(initial_x, initial_y);
return 0;
}
int tty_getkey(void)
{
int c = getch();
if (c == 0) {
switch (c = getch()) {
case 0x3b: c = KEY_F1; break;
case 0x3c: c = KEY_F2; break;
case 0x3d: c = KEY_F3; break;
case 0x3e: c = KEY_F4; break;
case 0x3f: c = KEY_F5; break;
case 0x40: c = KEY_F6; break;
case 0x41: c = KEY_F7; break;
case 0x42: c = KEY_F8; break;
case 0x43: c = KEY_F9; break;
case 0x44: c = KEY_F10; break;
case 0x47: c = KEY_HOME; break;
case 0x48: c = KEY_UP; break;
case 0x49: c = KEY_PAGEUP; break;
case 0x4b: c = KEY_LEFT; break;
case 0x4d: c = KEY_RIGHT; break;
case 0x4f: c = KEY_END; break;
case 0x50: c = KEY_DOWN; break;
case 0x51: c = KEY_PAGEDOWN; break;
case 0x52: c = KEY_INSERT; break;
case 0x53: c = KEY_DELETE; break;
case 0x54: c = KEY_F13; break;
case 0x55: c = KEY_F14; break;
case 0x56: c = KEY_F15; break;
case 0x57: c = KEY_F16; break;
case 0x58: c = KEY_F17; break;
case 0x59: c = KEY_F18; break;
case 0x5a: c = KEY_F19; break;
case 0x5b: c = KEY_F20; break;
case 0x5c: c = KEY_F21; break;
case 0x5d: c = KEY_F22; break;
case 0x5e: c = KEY_F25; break;
case 0x5f: c = KEY_F26; break;
case 0x60: c = KEY_F27; break;
case 0x61: c = KEY_F28; break;
case 0x62: c = KEY_F29; break;
case 0x63: c = KEY_F30; break;
case 0x64: c = KEY_F31; break;
case 0x65: c = KEY_F32; break;
case 0x66: c = KEY_F33; break;
case 0x67: c = KEY_F34; break;
case 0x68: c = KEY_F37; break;
case 0x69: c = KEY_F38; break;
case 0x6a: c = KEY_F39; break;
case 0x6b: c = KEY_F40; break;
case 0x6c: c = KEY_F41; break;
case 0x6d: c = KEY_F42; break;
case 0x6e: c = KEY_F43; break;
case 0x6f: c = KEY_F44; break;
case 0x70: c = KEY_F45; break;
case 0x71: c = KEY_F46; break;
case 0x85: c = KEY_F11; break;
case 0x86: c = KEY_F12; break;
case 0x87: c = KEY_F23; break;
case 0x88: c = KEY_F24; break;
case 0x89: c = KEY_F35; break;
case 0x8a: c = KEY_F36; break;
case 0x8b: c = KEY_F47; break;
case 0x8c: c = KEY_F48; break;
}
} else {
switch (c) {
case 0x08: c = KEY_BACKSPACE; break;
case 0x0d: c = KEY_ENTER; break;
}
}
return c;
}
int tty_iskeyhit(void)
{
return kbhit();
}
#elif defined(__unix__)
void tty_setxy(int x, int y)
{
move(y, x);
}
int tty_getx(void)
{
int x, y;
getyx(stdscr, y, x);
return x;
}
int tty_gety(void)
{
int x, y;
getyx(stdscr, y, x);
return y;
}
int tty_getw(void)
{
int x, y;
getmaxyx(stdscr, y, x);
return x;
}
int tty_geth(void)
{
int x, y;
getmaxyx(stdscr, y, x);
return y;
}
// Reference:
// How can I perform pre-main initialization in C/C++ with avr-gcc?
// http://stackoverflow.com/questions/949890/how-can-i-perform-pre-main-initialization-in-c-c-with-avr-gcc
int tty_begin(void)
{
initscr();
noecho();
cbreak();
keypad(stdscr, TRUE);
return 0;
}
int tty_end(void)
{
echo();
nocbreak();
endwin();
return 0;
}
int tty_getkey(void)
{
int c = getch();
switch (c) {
case 0x0a: c = KEY_ENTER; break;
}
return c;
}
int tty_iskeyhit(void)
{
int c;
timeout(0);
c = tty_getkey();
timeout(-1);
if (c != ERR) {
ungetch(c);
}
return c != ERR;
}
#else
#error "_WIN32 and __unix__ macro is undefined."
#endif//defined(_WIN32),defined(__unix__)
/**
* tty_getkey - Multiplatform simplified non-blocking keyboard input routine.
* Copyright 2014 (c) Koichi OKADA. All rights reserved.
* This file is distributed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*/
#ifndef TTY_GETKEY_H
#define TTY_GETKEY_H
#if defined(_WIN32)
#include <conio.h>
#define KEY_DOWN 0x102
#define KEY_UP 0x103
#define KEY_LEFT 0x104
#define KEY_RIGHT 0x105
#define KEY_HOME 0x106
#define KEY_BACKSPACE 0x107
#define KEY_PPAGE 0x153
#define KEY_NPAGE 0x152
#define KEY_HOME 0x106
#define KEY_END 0x168
#define KEY_IC 0x14b
#define KEY_DC 0x14a
#define KEY_F1 0x109
#define KEY_F2 0x10a
#define KEY_F3 0x10b
#define KEY_F4 0x10c
#define KEY_F5 0x10d
#define KEY_F6 0x10e
#define KEY_F7 0x10f
#define KEY_F8 0x110
#define KEY_F9 0x111
#define KEY_F10 0x112
#define KEY_F11 0x113
#define KEY_F12 0x114
#define KEY_F13 0x115
#define KEY_F14 0x116
#define KEY_F15 0x117
#define KEY_F16 0x118
#define KEY_F17 0x119
#define KEY_F18 0x11a
#define KEY_F19 0x11b
#define KEY_F20 0x11c
#define KEY_F21 0x11d
#define KEY_F22 0x11e
#define KEY_F23 0x11f
#define KEY_F24 0x120
#define KEY_F25 0x121
#define KEY_F26 0x122
#define KEY_F27 0x123
#define KEY_F28 0x124
#define KEY_F29 0x125
#define KEY_F30 0x126
#define KEY_F31 0x127
#define KEY_F32 0x128
#define KEY_F33 0x129
#define KEY_F34 0x12a
#define KEY_F35 0x12b
#define KEY_F36 0x12c
#define KEY_F37 0x12d
#define KEY_F38 0x12e
#define KEY_F39 0x12f
#define KEY_F40 0x130
#define KEY_F41 0x131
#define KEY_F42 0x132
#define KEY_F43 0x133
#define KEY_F44 0x134
#define KEY_F45 0x135
#define KEY_F46 0x136
#define KEY_F47 0x137
#define KEY_F48 0x138
#define KEY_ENTER 0x157
#define tty_printf cprintf
#elif defined(__unix__)
#include <ncurses/curses.h>
#define KEY_BS KEY_BACKSPACE
#define tty_printf printw
#endif//defined(_WIN32),defined(__unix__)
#define KEY_TAB 0x09
#define KEY_ESC 0x1b
#define KEY_SPACE 0x20
#define KEY_SP 0x20
//#define KEY_ENTER 0x0a
#define KEY_BS KEY_BACKSPACE
#define KEY_PAGEUP KEY_PPAGE
#define KEY_PAGEDOWN KEY_NPAGE
#define KEY_DEL KEY_DC
#define KEY_DELETE KEY_DC
#define KEY_INS KEY_IC
#define KEY_INSERT KEY_IC
void tty_setxy(int x, int y);
int tty_getx(void);
int tty_gety(void);
int tty_getw(void);
int tty_geth(void);
//int tty_printf(char *format, ...);
int tty_begin(void);
int tty_end(void);
int tty_getkey(void);
int tty_iskeyhit(void);
#endif//TTY_GETKEY_H
/**
* tty_getkey_sample - sample program for tty_getkey
* Copyright 2014 (c) Koichi OKADA. All rights reserved.
* This file is distributed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*/
#include <stdio.h>
#include <stdlib.h>
#include "tty_getkey.h"
#include "msleep.h"
int main()
{
int c;
tty_begin();
while(tty_iskeyhit() == 0) {
msleep(1);
}
c = tty_getkey();
tty_printf("%#x key was hit.\n", c);
tty_printf("Hit ESC key to exit.\n");
while(KEY_ESC != tty_getkey()) {
;
}
tty_end();
return EXIT_SUCCESS;
}
/**
* tty_getkey_sample - sample program for tty_getkey
* Copyright 2014 (c) Koichi OKADA. All rights reserved.
* This file is distributed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*/
#include <stdio.h>
#include <stdlib.h>
#include "tty_getkey.h"
int main(int argc, char *argv[])
{
int c;
int x, y, w, h;
tty_begin();
w = tty_getw();
h = tty_geth();
x = w / 2;
y = h / 2;
tty_setxy(x, y);
tty_printf("*");
while (KEY_ESC != (c = tty_getkey())) {
switch (c) {
case KEY_UP: y--; break;
case KEY_DOWN: y++; break;
case KEY_RIGHT: x++; break;
case KEY_LEFT: x--; break;
}
x = x < 1 ? 1 : w - 2 < x ? w - 2 : x;
y = y < 1 ? 1 : h - 2 < y ? h - 2 : y;
tty_setxy(0,0);
tty_printf("(%2d,%2d) : %#06x", x, y, c);
tty_setxy(x, y);
tty_printf("*");
}
tty_end();
return EXIT_SUCCESS;
}
/**
* tty_getkey_sample - sample program for tty_getkey
* Copyright 2014 (c) Koichi OKADA. All rights reserved.
* This file is distributed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*/
#include <stdio.h>
#include <stdlib.h>
#include "tty_getkey.h"
#include "msleep.h"
#define frand() (rand() / (RAND_MAX + 1.0))
int main()
{
int c, d;
tty_begin();
while(tty_iskeyhit() == 0) {
d = frand() * 6 + 1;
tty_setxy(0, 0);
tty_printf("%d", d);
msleep(1);
}
msleep(3000);
tty_end();
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment