maiha / crt.cr

Bindings for libncursesw and crt class
MIT License
27 stars 10 forks source link

win.getch returns -1 #5

Open hackervera opened 7 years ago

hackervera commented 7 years ago

Is there something special I'm supposed to do?

maiha commented 7 years ago

Yup, do you want to read one char right? I got same error. It would be my fault about CRT initialization. I'll try fix it. Thanks!

maiha commented 7 years ago

@tjgillies C works. But, Crystal doesn't. I think they are logically same codes, weird. It will take more time, sorry.

c

#include <ncursesw/curses.h>

int main()
{
  WINDOW* scr = initscr();
  raw();
  wgetch(scr);
  endwin();

  return 0;
}
gcc test.c -lncursesw
./a.out

crystal

@[Link("ncursesw")]

lib LibTest
  type WindowPtr = Void*
  fun initscr : WindowPtr
  fun raw
  fun wgetch(win : WindowPtr) : Int32
  fun endwin
end

scr = LibTest.initscr
LibTest.raw
LibTest.wgetch(scr)
LibTest.endwin
crystal test.cr
hackervera commented 7 years ago

I was playing around in another library and I think it has to do with setting timeout. Since there is no timeout set it doesn't wait for input and returns -1 immediately.

hackervera commented 7 years ago

https://github.com/jreinert/ncurses-crystal/blob/master/src/ncurses/window.cr#L108

maiha commented 7 years ago

Nice! But it still exit immediately.

@[Link("ncursesw")]

lib LibTest
  type WindowPtr = Void*
  fun initscr : WindowPtr
  fun raw
  fun nodelay(win : WindowPtr, v : Bool) : Int32
  fun notimeout(win : WindowPtr, v : Bool) : Int32
  fun wgetch(win : WindowPtr) : Int32
  fun endwin
end

scr = LibTest.initscr
LibTest.raw
LibTest.nodelay(scr, false)
LibTest.notimeout(scr, true)
LibTest.wgetch(scr)
LibTest.endwin

I don't know why C works. If we lack some method calls, C should fail too.

maxdec commented 7 years ago

You need cbreak.
This works for me:

win = Crt::Window.new(24, 80)
Crt.cbreak
Crt.notimeout(true)
win.clear
win.print(5, 10, "hello world")
win.refresh
key = win.getch
Crt.done
puts key

I've just added fun notimeout(win : WindowPtr, b : Bool) : Int32 in libncursesw.cr and

  def self.notimeout(b : Bool)
    LibNcursesw.notimeout(stdscr, b)
  end

in crc.cr.

MatthewBennington commented 7 years ago

The timeout and wtimeout routines set blocking or non-blocking read for a given window. If delay is negative, blocking read is used (i.e., waits indefinitely for input). If delay is zero, then non-blocking read is used (i.e., read returns ERR if no input is waiting). If delay is positive, then read blocks for delay milliseconds, and returns ERR if there is still no input. Hence, these routines provide the same functionality as nodelay, plus the additional capability of being able to block for only delay milliseconds (where delay is positive).

Sounds like .notimeout should be fixing the issue, not cbreak.

maxdec commented 7 years ago

Yes I know it seems weird, but I need both Crt.notimeout(true) and Crt.cbreak to make it work, otherwise "it still exits immediately". 😕

Edit: using Crt.cooked also "works" (it's waiting for inputs until we press the enter key). Btw that method is actually broken, there's a typo: LibNcursesw.nobreak -> LibNcursesw.nocbreak

MatthewBennington commented 7 years ago

Yeah, you're right. It doesn't make much sense to me, but it's worth updating the README and example.

maiha commented 7 years ago

Hi @maxdec !

Thank you for many information. I tried you code, but unfortunately it still exits immediately in my environment.

It would be a difference of OS where I'm using ubuntu-16.04. So, I'll check crystal sources about src/lib_c/*/c/termios.cr.

Anyway, I fixed typo about nocbreak and added notimeout method. Thanks.