Problem with getch and nodelay, backspace key

  • Follow


Hello All,

Currently added new code to our system using nodelay for our key
capture routines that use getch.  All the keys work, except backspace
key only works intermittently.  Getch will sometimes return nothing
(-2) or just happen to catch the backspace key.  At the same time
without using nodelay(stdscr, TRUE) getch works perfectly fine with the
backspace key returning promptly.

Further upon investigation I've found that gnu ncurses library works
fine when running my demo.  Even more, the following code taken from
another post (Floyd Davidson) will not allow backspace key to return as
fluently as the other keys do:

int
kbhit(void)
{
  int                   cnt = 0;
  int                   error;
  static struct termios Otty, Ntty;

  tcgetattr(0, &Otty);
  Ntty = Otty;

  Ntty.c_iflag          = 0;       /* input mode                */
  Ntty.c_oflag          = 0;       /* output mode               */
  Ntty.c_lflag         &= ~ICANON; /* line mode                 */
  Ntty.c_cc[VMIN]       = CMIN;    /* minimum time to wait      */
  Ntty.c_cc[VTIME]      = CTIME;   /* minimum characters to wait for */

  if (0 == (error = tcsetattr(0, TCSANOW, &Ntty))) {
    struct timeval      tv;
    error     += ioctl(0, FIONREAD, &cnt);
    error     += tcsetattr(0, TCSANOW, &Otty);
    tv.tv_sec  = 0;
    tv.tv_usec = 100;
    select(1, NULL, NULL, NULL, &tv);  /* a small time delay */
  }

  return (error == 0 ? cnt : -1 );

}



I'm using AIX 4.3.3, have the problems on all systems (5L), using
various emulation modes.

I also notice there are two libraries for curses, libcur and
libxcurses. I'm using libcur which allows the extended keys, where
xcurses doesn't seem to, but does work as far as bringing back the
backspace key correctly.


Anyone have any ideas as to why I'm having problems with the Backspace
key?

0
Reply Charris 9/29/2005 3:24:12 PM

"Charris" <chrisandharris@gmail.com> wrote:
>Hello All,
>
>Currently added new code to our system using nodelay for our key
>capture routines that use getch.  All the keys work, except backspace
>key only works intermittently.  Getch will sometimes return nothing
>(-2) or just happen to catch the backspace key.  At the same time
>without using nodelay(stdscr, TRUE) getch works perfectly fine with the
>backspace key returning promptly.
>
>Further upon investigation I've found that gnu ncurses library works
>fine when running my demo.  Even more, the following code taken from
>another post (Floyd Davidson) will not allow backspace key to return as
>fluently as the other keys do:

Interesting, though I have no experience with AIX and not a clue
as to what is happening.  But, I'd like to know what happens if
you modify this code slightly, and maybe try a few variations.

>int
>kbhit(void)
>{
>  int                   cnt = 0;
>  int                   error;
>  static struct termios Otty, Ntty;
>
>  tcgetattr(0, &Otty);
>  Ntty = Otty;
>
>  Ntty.c_iflag          = 0;       /* input mode                */
>  Ntty.c_oflag          = 0;       /* output mode               */
>  Ntty.c_lflag         &= ~ICANON; /* line mode                 */
>  Ntty.c_cc[VMIN]       = CMIN;    /* minimum time to wait      */
>  Ntty.c_cc[VTIME]      = CTIME;   /* minimum characters to wait for */
>
>  if (0 == (error = tcsetattr(0, TCSANOW, &Ntty))) {
>    struct timeval      tv;
>    error     += ioctl(0, FIONREAD, &cnt);
>    error     += tcsetattr(0, TCSANOW, &Otty);
>    tv.tv_sec  = 0;
>    tv.tv_usec = 100;
>    select(1, NULL, NULL, NULL, &tv);  /* a small time delay */
>  }

Change the above to put the time delay before the ioctl() call:

  if (0 == (error = tcsetattr(0, TCSANOW, &Ntty))) {
    tv.tv_sec  = 0;
    tv.tv_usec = 100;
    select(1, NULL, NULL, NULL, &tv);  /* a small time delay */
    struct timeval      tv;
    error     += ioctl(0, FIONREAD, &cnt);
    error     += tcsetattr(0, TCSANOW, &Otty);
  }

If that doesn't work any differently, try changing the time
delay, tv.tv_usec, to 1000, 10000 and then 100000.

That code originally did not have the time delay at all, and
someone had the nerve to put it into a very tight loop... which
it failed!  So the time delay is there to force a context
switch, and for that only the absolute smallest delay is
sufficient.  However, it may be that your backspace is getting
extra processing, and timing might be critical.

>  return (error == 0 ? cnt : -1 );
>
>}
>
>I'm using AIX 4.3.3, have the problems on all systems (5L), using
>various emulation modes.
>
>I also notice there are two libraries for curses, libcur and
>libxcurses. I'm using libcur which allows the extended keys, where
>xcurses doesn't seem to, but does work as far as bringing back the
>backspace key correctly.
>
>Anyone have any ideas as to why I'm having problems with the Backspace
>key?

-- 
Floyd L. Davidson            <http://www.apaflo.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska)                         floyd@apaflo.com
0
Reply floyd 9/29/2005 4:07:36 PM


Yeah definitely something to do with timing/polling I guess?  I might
hit backspace 15 times and get response, but the 16, 17, 18, it's a
dead key.

0
Reply Charris 9/29/2005 5:52:48 PM

Ok this is strange.  Backspace if anything is much more responsive,
that's for sure.  But if I printout the return value of kbhit(), it
will count up to about 14-20, then reset it resets to 0, where as any
other key would count up to infinity.

Does this mean that maybe my routine that uses getch with nodelay's
needs to have a slight delay for the context switch?

Originally we did have a usleep(200) in there, but I've found problems
either way.

0
Reply Charris 9/29/2005 6:01:53 PM

Found my solution.

Basically this version/set of curses (libcur.a using cur00.h-cur05.h)
was not taking the terminal out of 'cooked mode', a mode that does some
special processing on the erase key (namely backspace I presume).  It
looks like ncurses does this by default possibly or when setting
nodelay, but this is not the default behavior for AIX libcur.a,
eventhough odly enough, AIX's sister, libcurses.a, does.

Anyway, most of the curses libraries do this by using cbreak().
However, even more conveniently, libcur.a does not support cbreak, you
will get a segfault for even trying, which upon further digging I found
crmode();

Hope this helps

0
Reply Charris 10/6/2005 2:22:27 PM

4 Replies
482 Views

(page loaded in 0.094 seconds)

Similiar Articles:










7/23/2012 3:42:17 PM


Reply: