diff --git a/module/keyboard.cpp b/module/keyboard.cpp index 742984d..34ddaac 100644 --- a/module/keyboard.cpp +++ b/module/keyboard.cpp @@ -7,68 +7,77 @@ #include #endif +class noecho_input{ +private: #ifndef _WIN32 -static struct termios init_termios; -static struct termios new_termios; -static 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; -} + struct termios init_termios; + struct termios new_termios; + int peek_char=-1; #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& 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& 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& args,nasal_gc& gc){ - if(kbhit()) - return {vm_num,(double)getch()}; - return nil; -} -extern "C" nasal_ref nas_init(std::vector& 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& args,nasal_gc& gc){ -#ifndef _WIN32 - tcflush(0,TCIOFLUSH); - tcsetattr(0,TCSANOW,&init_termios); -#endif + if(this_window.noecho_kbhit()) + return {vm_num,(double)this_window.noecho_getch()}; return nil; } \ No newline at end of file diff --git a/module/libfib.nas b/module/libfib.nas index d68b1b4..49b5457 100644 --- a/module/libfib.nas +++ b/module/libfib.nas @@ -1,5 +1,3 @@ -import("lib.nas"); - var libfib=func(){ var dl=dylib.dlopen("./module/libfib."~(os.platform()=="windows"?"dll":"so")); var fib=dylib.dlsym(dl,"fib"); diff --git a/module/libkey.nas b/module/libkey.nas index 48ba8df..2b11735 100644 --- a/module/libkey.nas +++ b/module/libkey.nas @@ -1,47 +1,12 @@ -import("lib.nas"); - var libkey=func(){ var lib=dylib.dlopen("./module/libkey"~(os.platform()=="windows"?".dll":".so")); var kb=dylib.dlsym(lib,"nas_kbhit"); var gt=dylib.dlsym(lib,"nas_getch"); 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 is_init=0; return { - init:func(){ - # change io mode to no echo - call(init); - 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); - } + kbhit:func(){return call(kb);}, + getch:func(){return call(gt);}, + nonblock:func(){return call(nb);} } }(); \ No newline at end of file diff --git a/test/snake.nas b/test/snake.nas index 254b77e..a925e6b 100644 --- a/test/snake.nas +++ b/test/snake.nas @@ -178,7 +178,7 @@ var main=func(){ if(os.platform()=="windows") system("chcp 65001"); print("\ec"); - libkey.init(); + var g=game(15,10); g.print(); print("\rpress any key to start..."); @@ -207,10 +207,10 @@ var main=func(){ g.print(); } } - libkey.close(); + println(g.gameover()<=1?"game over.":"you win!"); - println("enter anything to quit."); - input(); + println("press 'q' to quit."); + while(libkey.getch()!='q'[0]); } main(); \ No newline at end of file diff --git a/test/tetris.nas b/test/tetris.nas index e02a0a8..1b0542a 100644 --- a/test/tetris.nas +++ b/test/tetris.nas @@ -275,7 +275,6 @@ var main=func(){ if(os.platform()=="windows") system("chcp 65001"); - libkey.init(); print( "\ec\e[1:1H", "╔═════════════════════════╗\n", @@ -331,7 +330,7 @@ var main=func(){ unix.sleep(0.02); counter-=1; } - libkey.close(); + print( map.gameover()? "\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( "\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" ); - input(); + while(libkey.getch()!='q'[0]); }; main(); \ No newline at end of file