@@ -41,7 +41,7 @@ static int nc_awake_fds[2];
4141static unsigned char nc_readbuffer [NC_READBUFLEN ];
4242static size_t nc_readlen = 0 ;
4343static size_t nc_readpos = 0 ;
44- static size_t nc_peekpos = 0 ;
44+ static bool nc_hidecur = 0 ;
4545
4646#endif /* __unix__ */
4747
@@ -51,15 +51,20 @@ static size_t nc_peekpos = 0;
5151
5252static int handleClosingLuaState (lua_State * L )
5353{
54- bool unrestricted = false ;
54+ bool restricted = true ;
5555 if (lua_rawgetp (L , LUA_REGISTRYINDEX , NOCURSES_MODULE_NAME ) == LUA_TUSERDATA ) {
5656 if (lua_touserdata (L , -1 ) == udata ) {
57- unrestricted = true ;
57+ restricted = false ;
5858 }
5959 }
6060 lua_pop (L , 1 );
61- if (unrestricted ) {
61+ if (! restricted ) {
6262 if (atomic_set_if_equal (& initStage , 1 , 0 )) {
63+ if (nc_hidecur ) {
64+ nc_hidecur = false;
65+ showcursor ();
66+ fflush (stdout );
67+ }
6368 }
6469 }
6570 return 0 ;
@@ -123,6 +128,12 @@ static bool hasInputAt(int i)
123128 return (nc_readpos + i < nc_readlen );
124129}
125130
131+ static void clearInput ()
132+ {
133+ nc_readpos = 0 ;
134+ nc_readlen = 0 ;
135+ }
136+
126137static bool hasInput ()
127138{
128139 return (nc_readpos < nc_readlen );
@@ -177,23 +188,21 @@ static bool waitForInput(const double timeout)
177188
178189static int Nocurses_wait (lua_State * L )
179190{
191+ clearInput ();
180192#if defined(__unix__ )
181- bool wasEnter = false;
182193 while (true) {
183- if (hasInput () || waitForInput (-1 )) {
194+ if (waitForInput (-1 )) {
184195 if (fgetc (stdin ) == '\n' ) {
185196 break ;
186197 }
187198 } else {
188199 break ;
189200 }
190201 }
191- lua_pushboolean (L , wasEnter );
192202#else
193203 while (fgetc (stdin ) != '\n' );
194- lua_pushboolean (L , true);
195204#endif
196- return 1 ;
205+ return 0 ;
197206}
198207
199208/* ============================================================================================ */
@@ -351,8 +360,7 @@ static int nc_getch()
351360 return nc_readbuffer [0 ];
352361 }
353362 else {
354- nc_readpos = 0 ;
355- nc_readlen = 0 ;
363+ clearInput ();
356364 return -1 ;
357365 }
358366}
@@ -417,8 +425,31 @@ static int nc_skipch(int skip)
417425}
418426#endif
419427
428+ /* ============================================================================================ */
429+
430+ static int assureUnrestricted (lua_State * L )
431+ {
432+ bool restricted = true;
433+ if (lua_rawgetp (L , LUA_REGISTRYINDEX , NOCURSES_MODULE_NAME ) == LUA_TUSERDATA ) { // -> nocurses
434+ if (lua_touserdata (L , -1 ) == udata ) { // -> nocurses
435+ restricted = false;
436+ }
437+ }
438+ lua_pop (L , 1 ); // ->
439+ if (restricted ) {
440+ return luaL_error (L , "function must be called from main thread" );
441+ }
442+ else {
443+ return 0 ;
444+ }
445+ }
446+
447+ /* ============================================================================================ */
448+
420449static int Nocurses_getch (lua_State * L )
421450{
451+ assureUnrestricted (L );
452+
422453 double timeout = -1 ;
423454 if (!lua_isnoneornil (L , 1 )) {
424455 timeout = luaL_checknumber (L , 1 );
@@ -448,6 +479,8 @@ static int Nocurses_getch(lua_State* L)
448479
449480static int Nocurses_peekch (lua_State * L )
450481{
482+ assureUnrestricted (L );
483+
451484 int offs = 0 ;
452485 if (!lua_isnoneornil (L , 1 )) {
453486 offs = luaL_checkinteger (L , 1 ) - 1 ;
@@ -478,6 +511,8 @@ static int Nocurses_peekch(lua_State* L)
478511
479512static int Nocurses_skipch (lua_State * L )
480513{
514+ assureUnrestricted (L );
515+
481516 int skip = 1 ;
482517 if (!lua_isnoneornil (L , 1 )) {
483518 skip = luaL_checkinteger (L , 1 ) ;
@@ -520,6 +555,31 @@ static int Nocurses_resetcolors(lua_State* L)
520555
521556/* ============================================================================================ */
522557
558+ static int Nocurses_showcursor (lua_State * L )
559+ {
560+ assureUnrestricted (L );
561+
562+ nc_hidecur = false;
563+ showcursor ();
564+ fflush (stdout );
565+
566+ return 0 ;
567+ }
568+
569+ /* ============================================================================================ */
570+
571+ static int Nocurses_hidecursor (lua_State * L )
572+ {
573+ assureUnrestricted (L );
574+
575+ nc_hidecur = true;
576+ hidecursor ();
577+ fflush (stdout );
578+ return 0 ;
579+ }
580+
581+ /* ============================================================================================ */
582+
523583#if defined(__unix__ )
524584
525585static int Nocurses_awake (lua_State * L )
@@ -602,6 +662,8 @@ static const luaL_Reg ModuleFunctions[] =
602662 { "skipch" , Nocurses_skipch },
603663 { "clrline" , Nocurses_clrline },
604664 { "resetcolors" , Nocurses_resetcolors },
665+ { "showcursor" , Nocurses_showcursor },
666+ { "hidecursor" , Nocurses_hidecursor },
605667#if defined(__unix__ )
606668 { "awake" , Nocurses_awake },
607669#endif
@@ -655,9 +717,9 @@ DLL_PUBLIC int luaopen_nocurses(lua_State* L)
655717
656718 /* ---------------------------------------- */
657719
658- bool unrestricted = false ;
720+ bool restricted = true ;
659721 if (atomic_set_if_equal (& initStage , 0 , 1 )) {
660- unrestricted = true ;
722+ restricted = false ;
661723 #if defined(__unix__ )
662724 initAwake ();
663725 #endif
@@ -672,7 +734,7 @@ DLL_PUBLIC int luaopen_nocurses(lua_State* L)
672734 else {
673735 if (lua_rawgetp (L , LUA_REGISTRYINDEX , NOCURSES_MODULE_NAME ) == LUA_TUSERDATA ) {
674736 if (lua_touserdata (L , -1 ) == udata ) {
675- unrestricted = true ;
737+ restricted = false ;
676738 }
677739 }
678740 lua_pop (L , 1 );
@@ -685,10 +747,10 @@ DLL_PUBLIC int luaopen_nocurses(lua_State* L)
685747 int module = ++ n ; lua_newtable (L );
686748
687749 lua_pushvalue (L , module ); /* --> module */
688- if (unrestricted ) {
689- luaL_setfuncs (L , ModuleFunctions , 0 );
690- } else {
750+ if (restricted ) {
691751 luaL_setfuncs (L , RestrictedModuleFunctions , 0 );
752+ } else {
753+ luaL_setfuncs (L , ModuleFunctions , 0 );
692754 }
693755 lua_newtable (L ); /* --> module, key */
694756 for (const InputSequence * seq = inputSequences ; seq -> name ; ++ seq ) {
@@ -709,7 +771,7 @@ DLL_PUBLIC int luaopen_nocurses(lua_State* L)
709771#endif
710772 lua_pushstring (L , NOCURSES_MODULE_NAME ); /* -> meta, "nocurses" */
711773 lua_setfield (L , -2 , "__metatable" ); /* -> meta */
712- if (unrestricted ) {
774+ if (! restricted ) {
713775 int rc = luaL_loadstring (L ,
714776 "local t, k = ...\n"
715777 "if type(k) == 'string' then\n"
0 commit comments