🎨 fix a bug in module/keyboard.cpp that if program exited with an error, the terminal may not echo the text you input
This commit is contained in:
parent
07eeaadf96
commit
dcad554eba
|
@ -7,68 +7,77 @@
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class noecho_input{
|
||||||
|
private:
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static struct termios init_termios;
|
struct termios init_termios;
|
||||||
static struct termios new_termios;
|
struct termios new_termios;
|
||||||
static int peek_char=-1;
|
int peek_char=-1;
|
||||||
|
|
||||||
int kbhit(){
|
|
||||||
unsigned char ch=0;
|
|
||||||
int nread=0;
|
|
||||||
if(peek_char!=-1)
|
|
||||||
return 1;
|
|
||||||
int flag=fcntl(0,F_GETFL);
|
|
||||||
fcntl(0,F_SETFL,flag|O_NONBLOCK);
|
|
||||||
nread=read(0,&ch,1);
|
|
||||||
fcntl(0,F_SETFL,flag);
|
|
||||||
if(nread==1){
|
|
||||||
peek_char=ch;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getch(){
|
|
||||||
int ch=0;
|
|
||||||
if(peek_char!=-1){
|
|
||||||
ch=peek_char;
|
|
||||||
peek_char=-1;
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
read(0,&ch,1);
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
public:
|
||||||
|
noecho_input(){
|
||||||
|
#ifndef _WIN32
|
||||||
|
tcflush(0,TCIOFLUSH);
|
||||||
|
tcgetattr(0,&init_termios);
|
||||||
|
new_termios=init_termios;
|
||||||
|
new_termios.c_lflag&=~(ICANON|ECHO|ECHONL|ECHOE);
|
||||||
|
// vmin=0 is nonblock input, but in wsl there is a bug that will block input
|
||||||
|
// so we use fcntl to write the nonblock input
|
||||||
|
new_termios.c_cc[VMIN]=1;
|
||||||
|
new_termios.c_cc[VTIME]=0;
|
||||||
|
tcsetattr(0,TCSANOW,&new_termios);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
~noecho_input(){
|
||||||
|
#ifndef _WIN32
|
||||||
|
tcflush(0,TCIOFLUSH);
|
||||||
|
tcsetattr(0,TCSANOW,&init_termios);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
int noecho_kbhit(){
|
||||||
|
#ifndef _WIN32
|
||||||
|
unsigned char ch=0;
|
||||||
|
int nread=0;
|
||||||
|
if(peek_char!=-1)
|
||||||
|
return 1;
|
||||||
|
int flag=fcntl(0,F_GETFL);
|
||||||
|
fcntl(0,F_SETFL,flag|O_NONBLOCK);
|
||||||
|
nread=read(0,&ch,1);
|
||||||
|
fcntl(0,F_SETFL,flag);
|
||||||
|
if(nread==1){
|
||||||
|
peek_char=ch;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return kbhit();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
int noecho_getch(){
|
||||||
|
#ifndef _WIN32
|
||||||
|
int ch=0;
|
||||||
|
if(peek_char!=-1){
|
||||||
|
ch=peek_char;
|
||||||
|
peek_char=-1;
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
read(0,&ch,1);
|
||||||
|
return ch;
|
||||||
|
#else
|
||||||
|
return getch();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
noecho_input this_window;
|
||||||
extern "C" nasal_ref nas_getch(std::vector<nasal_ref>& args,nasal_gc& gc){
|
extern "C" nasal_ref nas_getch(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||||
return {vm_num,(double)getch()};
|
return {vm_num,(double)this_window.noecho_getch()};
|
||||||
}
|
}
|
||||||
extern "C" nasal_ref nas_kbhit(std::vector<nasal_ref>& args,nasal_gc& gc){
|
extern "C" nasal_ref nas_kbhit(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||||
return {vm_num,(double)kbhit()};
|
return {vm_num,(double)this_window.noecho_kbhit()};
|
||||||
}
|
}
|
||||||
extern "C" nasal_ref nas_noblock(std::vector<nasal_ref>& args,nasal_gc& gc){
|
extern "C" nasal_ref nas_noblock(std::vector<nasal_ref>& args,nasal_gc& gc){
|
||||||
if(kbhit())
|
if(this_window.noecho_kbhit())
|
||||||
return {vm_num,(double)getch()};
|
return {vm_num,(double)this_window.noecho_getch()};
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
extern "C" nasal_ref nas_init(std::vector<nasal_ref>& args,nasal_gc& gc){
|
|
||||||
#ifndef _WIN32
|
|
||||||
tcflush(0,TCIOFLUSH);
|
|
||||||
tcgetattr(0,&init_termios);
|
|
||||||
new_termios=init_termios;
|
|
||||||
new_termios.c_lflag&=~(ICANON|ECHO|ECHONL|ECHOE);
|
|
||||||
// vmin=0 is nonblock input, but in wsl there is a bug that will block input
|
|
||||||
// so we use fcntl to write the nonblock input
|
|
||||||
new_termios.c_cc[VMIN]=1;
|
|
||||||
new_termios.c_cc[VTIME]=0;
|
|
||||||
tcsetattr(0,TCSANOW,&new_termios);
|
|
||||||
#endif
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
extern "C" nasal_ref nas_close(std::vector<nasal_ref>& args,nasal_gc& gc){
|
|
||||||
#ifndef _WIN32
|
|
||||||
tcflush(0,TCIOFLUSH);
|
|
||||||
tcsetattr(0,TCSANOW,&init_termios);
|
|
||||||
#endif
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
import("lib.nas");
|
|
||||||
|
|
||||||
var libfib=func(){
|
var libfib=func(){
|
||||||
var dl=dylib.dlopen("./module/libfib."~(os.platform()=="windows"?"dll":"so"));
|
var dl=dylib.dlopen("./module/libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||||
var fib=dylib.dlsym(dl,"fib");
|
var fib=dylib.dlsym(dl,"fib");
|
||||||
|
|
|
@ -1,47 +1,12 @@
|
||||||
import("lib.nas");
|
|
||||||
|
|
||||||
var libkey=func(){
|
var libkey=func(){
|
||||||
var lib=dylib.dlopen("./module/libkey"~(os.platform()=="windows"?".dll":".so"));
|
var lib=dylib.dlopen("./module/libkey"~(os.platform()=="windows"?".dll":".so"));
|
||||||
var kb=dylib.dlsym(lib,"nas_kbhit");
|
var kb=dylib.dlsym(lib,"nas_kbhit");
|
||||||
var gt=dylib.dlsym(lib,"nas_getch");
|
var gt=dylib.dlsym(lib,"nas_getch");
|
||||||
var nb=dylib.dlsym(lib,"nas_noblock");
|
var nb=dylib.dlsym(lib,"nas_noblock");
|
||||||
var init=dylib.dlsym(lib,"nas_init");
|
|
||||||
var cls=dylib.dlsym(lib,"nas_close");
|
|
||||||
var call=dylib.dlcall;
|
var call=dylib.dlcall;
|
||||||
var is_init=0;
|
|
||||||
return {
|
return {
|
||||||
init:func(){
|
kbhit:func(){return call(kb);},
|
||||||
# change io mode to no echo
|
getch:func(){return call(gt);},
|
||||||
call(init);
|
nonblock:func(){return call(nb);}
|
||||||
is_init=1;
|
|
||||||
},
|
|
||||||
kbhit:func(){
|
|
||||||
# check if kerboard is hit
|
|
||||||
# if keyboard is hit this function will return 1
|
|
||||||
# until getch() gets all the input characters
|
|
||||||
# and the input flow becomes empty
|
|
||||||
if(!is_init)
|
|
||||||
me.init();
|
|
||||||
return call(kb);
|
|
||||||
},
|
|
||||||
getch:func(){
|
|
||||||
# get input one character without echo
|
|
||||||
# block until get one input
|
|
||||||
if(!is_init)
|
|
||||||
me.init();
|
|
||||||
return call(gt);
|
|
||||||
},
|
|
||||||
nonblock:func(){
|
|
||||||
# nonblock input without echo
|
|
||||||
if(!is_init)
|
|
||||||
me.init();
|
|
||||||
return call(nb);
|
|
||||||
},
|
|
||||||
close:func(){
|
|
||||||
# must call this function before exiting the program
|
|
||||||
# this will change terminal mode to normal io mode
|
|
||||||
call(cls);
|
|
||||||
dylib.dlclose(lib);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}();
|
}();
|
|
@ -178,7 +178,7 @@ var main=func(){
|
||||||
if(os.platform()=="windows")
|
if(os.platform()=="windows")
|
||||||
system("chcp 65001");
|
system("chcp 65001");
|
||||||
print("\ec");
|
print("\ec");
|
||||||
libkey.init();
|
|
||||||
var g=game(15,10);
|
var g=game(15,10);
|
||||||
g.print();
|
g.print();
|
||||||
print("\rpress any key to start...");
|
print("\rpress any key to start...");
|
||||||
|
@ -207,10 +207,10 @@ var main=func(){
|
||||||
g.print();
|
g.print();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
libkey.close();
|
|
||||||
println(g.gameover()<=1?"game over.":"you win!");
|
println(g.gameover()<=1?"game over.":"you win!");
|
||||||
println("enter anything to quit.");
|
println("press 'q' to quit.");
|
||||||
input();
|
while(libkey.getch()!='q'[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
|
@ -275,7 +275,6 @@ var main=func(){
|
||||||
if(os.platform()=="windows")
|
if(os.platform()=="windows")
|
||||||
system("chcp 65001");
|
system("chcp 65001");
|
||||||
|
|
||||||
libkey.init();
|
|
||||||
print(
|
print(
|
||||||
"\ec\e[1:1H",
|
"\ec\e[1:1H",
|
||||||
"╔═════════════════════════╗\n",
|
"╔═════════════════════════╗\n",
|
||||||
|
@ -331,7 +330,7 @@ var main=func(){
|
||||||
unix.sleep(0.02);
|
unix.sleep(0.02);
|
||||||
counter-=1;
|
counter-=1;
|
||||||
}
|
}
|
||||||
libkey.close();
|
|
||||||
print(
|
print(
|
||||||
map.gameover()?
|
map.gameover()?
|
||||||
"\e[31mg\e[32ma\e[33mm\e[34me \e[35mo\e[36mv\e[94me\e[31mr \e[32m~\e[0m\n":
|
"\e[31mg\e[32ma\e[33mm\e[34me \e[35mo\e[36mv\e[94me\e[31mr \e[32m~\e[0m\n":
|
||||||
|
@ -339,10 +338,10 @@ var main=func(){
|
||||||
);
|
);
|
||||||
print(
|
print(
|
||||||
"\e[31me\e[32mn\e[33mt\e[34me\e[35mr ",
|
"\e[31me\e[32mn\e[33mt\e[34me\e[35mr ",
|
||||||
"\e[36ma\e[94mn\e[95my\e[96mt\e[31mh\e[32mi\e[33mn\e[34mg ",
|
"\e[36m'\e[94mq\e[95m' ",
|
||||||
"\e[35mt\e[36mo \e[94mq\e[95mu\e[91mi\e[92mt\e[0m\n"
|
"\e[35mt\e[36mo \e[94mq\e[95mu\e[91mi\e[92mt\e[0m\n"
|
||||||
);
|
);
|
||||||
input();
|
while(libkey.getch()!='q'[0]);
|
||||||
};
|
};
|
||||||
|
|
||||||
main();
|
main();
|
Loading…
Reference in New Issue