The halfdelay() input option is broken in PDCurses -- wgetch() is always either fully blocking or nonblocking. The problem is in pdcurses/getch.c, in the wgetch() function, after a low-level keyboard read is attempted:
/* keyboard read leaves value in "key", then: */ if (w->_nodelay) { /* * if nodelay and no char, return ERR */ if (key == -1) return( ERR ); else if ( ! SP->echo ) { if ( ! (w->_flags & _PAD) ) { if ( is_wintouched(w) ) wrefresh(w); } else { if (SP->delaytenths) { if (waitingtenths == 0 && key == (-1)) return(ERR); if (key == (-1)) { waitingtenths--; napms(10); continue; } } } The trouble is that the low-level keyboard read function itself depends on the status of w->_nodelay. When it's true, obviously the "SP->delaytenths" section will never be reached; but also, when false, the return value in "key" will never be -1, so although the delay section is reached, it has no function. The remedy is simply to swap around the conditions: test SP->delaytenths first, then w->_nodelay. Note that, for halfdelay() to work then, the window must first be set to nodelay(); since this depends on a specific window, while halfdelay() is global, I haven't included this in the patch. That fixed, there's another problem: nocbreak() does not reset the value set by halfdelay(), as it's supposed to. This is tricky, because if you look at nocbreak() in pdcurses/inopts.c, it appears to be resetting it; but this function is only used in the XCurses port. For the rest, nocbreak() is defined in curses.h: # define nocbreak() (SP->cbreak = FALSE) I just changed this to: # define nocbreak() (SP->cbreak = FALSE, SP->delaytenths = 0) Finally, the pause routine napms() works in Win32 and OS/2 (though the pause seems overlong in OS/2), but not in DOS, with DJGPP or Turbo C++; on those platforms it returns immediately. In the case of DJGPP, I found the explanation in the info page for usleep(), the function PDCurses uses to implement napms() there: Note that, since `usleep' calls `clock' internally, and the latter has a 55-msec granularity, any argument less than 55msec will result in a pause of random length between 0 and 55 msec. Any argument less than 11msec (more precisely, less than 11264 microseconds), will always result in zero-length pause (because `clock' multiplies the timer count by 5). PDCurses is calling usleep() with a 10ms parameter, so there's no pause. I haven't attempted to fix this yet. And I haven't yet figured out why the Turbo C++ routine (based on delay() from TC's dos.h) isn't working. Patches for the first two problems attached. -- William McBrine <[EMAIL PROTECTED]>
*** pdcurses/getch.c.old Wed Jan 10 03:27:01 2001 --- pdcurses/getch.c Sun Mar 3 06:44:06 2002 *************** *** 259,289 **** key = (-1); #endif ! if (w->_nodelay) { ! /* ! * if nodelay and no char, return ERR ! */ ! if (key == -1) ! return( ERR ); ! else if ( ! SP->echo ) { ! if ( ! (w->_flags & _PAD) ) { ! if ( is_wintouched(w) ) ! wrefresh(w); ! } } } else { ! if (SP->delaytenths) { ! if (waitingtenths == 0 && key == (-1)) ! return(ERR); ! if (key == (-1)) ! { ! waitingtenths--; ! napms(10); ! continue; } } } --- 259,289 ---- key = (-1); #endif ! if (SP->delaytenths) { ! if (waitingtenths == 0 && key == (-1)) ! return(ERR); ! if (key == (-1)) ! { ! waitingtenths--; ! napms(10); ! continue; } } else { ! if (w->_nodelay) { ! /* ! * if nodelay and no char, return ERR ! */ ! if (key == -1) ! return( ERR ); ! else if ( ! SP->echo ) { ! if ( ! (w->_flags & _PAD) ) { ! if ( is_wintouched(w) ) ! wrefresh(w); ! } } } } *** curses.h.old Tue Oct 16 07:03:15 2001 --- curses.h Sun Mar 3 06:47:05 2002 *************** *** 2070,2076 **** #define wstandout(w) wattrset(w, A_STANDOUT) #if !defined(UNIX) && !defined(XCURSES) ! # define nocbreak() (SP->cbreak = FALSE) # define cbreak() (SP->cbreak = TRUE) # define nocrmode() (SP->cbreak = FALSE) # define crmode() (SP->cbreak = TRUE) --- 2070,2076 ---- #define wstandout(w) wattrset(w, A_STANDOUT) #if !defined(UNIX) && !defined(XCURSES) ! # define nocbreak() (SP->cbreak = FALSE, SP->delaytenths = 0) # define cbreak() (SP->cbreak = TRUE) # define nocrmode() (SP->cbreak = FALSE) # define crmode() (SP->cbreak = TRUE)