Back to index

tetex-bin  3.0
Defines | Functions | Variables
lib_getch.c File Reference
#include <curses.priv.h>
#include <fifo_defs.h>

Go to the source code of this file.

Defines

#define TWAIT_MASK   3
#define wgetch_should_refresh(win)

Functions

static int check_mouse_activity (int delay EVENTLIST_2nd(_nc_eventlist *evl))
static int fifo_peek (void)
static int fifo_pull (void)
static int fifo_push (EVENTLIST_0th(_nc_eventlist *evl))
static void fifo_clear (void)
static int kgetch (EVENTLIST_0th(_nc_eventlist *evl))
 _nc_wgetch (WINDOW *win, unsigned long *result, int use_meta EVENTLIST_2nd(_nc_eventlist *evl))
 wgetch (WINDOW *win)

Variables

 ESCDELAY = 1000

Define Documentation

#define TWAIT_MASK   3

Definition at line 53 of file lib_getch.c.

#define wgetch_should_refresh (   win)
Value:
(\
       (is_wintouched(win) || (win->_flags & _HASMOVED)) \
       && !(win->_flags & _ISPAD))

Definition at line 218 of file lib_getch.c.


Function Documentation

_nc_wgetch ( WINDOW win,
unsigned long *  result,
int use_meta   EVENTLIST_2nd_nc_eventlist *evl 
)

Definition at line 223 of file lib_getch.c.

{
    int ch;
#ifdef NCURSES_WGETCH_EVENTS
    long event_delay = -1;
#endif

    T((T_CALLED("_nc_wgetch(%p)"), win));

    *result = 0;
    if (!win)
       returnCode(ERR);

    if (cooked_key_in_fifo()) {
       if (wgetch_should_refresh(win))
           wrefresh(win);

       *result = fifo_pull();
       returnCode(OK);
    }
#ifdef NCURSES_WGETCH_EVENTS
    if (evl && (evl->count == 0))
       evl = NULL;
    event_delay = _nc_eventlist_timeout(evl);
#endif

    /*
     * Handle cooked mode.  Grab a string from the screen,
     * stuff its contents in the FIFO queue, and pop off
     * the first character to return it.
     */
    if (head == -1 &&
       !SP->_notty &&
       !SP->_raw &&
       !SP->_cbreak &&
       !SP->_called_wgetch) {
       char buf[MAXCOLUMNS], *sp;
       int rc;

       TR(TRACE_IEVENT, ("filling queue in cooked mode"));

       SP->_called_wgetch = TRUE;
       rc = wgetnstr(win, buf, MAXCOLUMNS);
       SP->_called_wgetch = FALSE;

       /* ungetch in reverse order */
#ifdef NCURSES_WGETCH_EVENTS
       if (rc != KEY_EVENT)
#endif
           ungetch('\n');
       for (sp = buf + strlen(buf); sp > buf; sp--)
           ungetch(sp[-1]);

#ifdef NCURSES_WGETCH_EVENTS
       /* Return it first */
       if (rc == KEY_EVENT) {
           *result = rc;
           returnCode(OK);
       }
#endif

       *result = fifo_pull();
       returnCode(OK);
    }

    if (win->_use_keypad != SP->_keypad_on)
       _nc_keypad(win->_use_keypad);

    if (wgetch_should_refresh(win))
       wrefresh(win);

    if (!win->_notimeout && (win->_delay >= 0 || SP->_cbreak > 1)) {
       int delay;

       TR(TRACE_IEVENT, ("timed delay in wgetch()"));
       if (SP->_cbreak > 1)
           delay = (SP->_cbreak - 1) * 100;
       else
           delay = win->_delay;

#ifdef NCURSES_WGETCH_EVENTS
       if (event_delay >= 0 && delay > event_delay)
           delay = event_delay;
#endif

       TR(TRACE_IEVENT, ("delay is %d milliseconds", delay));

       if (head == -1) {    /* fifo is empty */
           int rc = check_mouse_activity(delay EVENTLIST_2nd(evl));

#ifdef NCURSES_WGETCH_EVENTS
           if (rc & 4) {
              *result = KEY_EVENT;
              returnCode(OK);
           }
#endif
           if (!rc)
              returnCode(ERR);
       }
       /* else go on to read data available */
    }

    if (win->_use_keypad) {
       /*
        * This is tricky.  We only want to get special-key
        * events one at a time.  But we want to accumulate
        * mouse events until either (a) the mouse logic tells
        * us it's picked up a complete gesture, or (b)
        * there's a detectable time lapse after one.
        *
        * Note: if the mouse code starts failing to compose
        * press/release events into clicks, you should probably
        * increase the wait with mouseinterval().
        */
       int runcount = 0;
       int rc;

       do {
           ch = kgetch(EVENTLIST_1st(evl));
           if (ch == KEY_MOUSE) {
              ++runcount;
              if (SP->_mouse_inline(SP))
                  break;
           }
           if (SP->_maxclick < 0)
              break;
       } while
           (ch == KEY_MOUSE
            && (((rc = check_mouse_activity(SP->_maxclick
                                        EVENTLIST_2nd(evl))) != 0
                && !(rc & 4))
               || !SP->_mouse_parse(runcount)));
#ifdef NCURSES_WGETCH_EVENTS
       if ((rc & 4) && !ch == KEY_EVENT) {
           ungetch(ch);
           ch = KEY_EVENT;
       }
#endif
       if (runcount > 0 && ch != KEY_MOUSE) {
#ifdef NCURSES_WGETCH_EVENTS
           /* mouse event sequence ended by an event, report event */
           if (ch == KEY_EVENT) {
              ungetch(KEY_MOUSE);  /* FIXME This interrupts a gesture... */
           } else
#endif
           {
              /* mouse event sequence ended by keystroke, store keystroke */
              ungetch(ch);
              ch = KEY_MOUSE;
           }
       }
    } else {
       if (head == -1)
           fifo_push(EVENTLIST_1st(evl));
       ch = fifo_pull();
    }

    if (ch == ERR) {
#if USE_SIZECHANGE
       if (SP->_sig_winch) {
           _nc_update_screensize();
           /* resizeterm can push KEY_RESIZE */
           if (cooked_key_in_fifo()) {
              *result = fifo_pull();
              returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK);
           }
       }
#endif
       returnCode(ERR);
    }

    /*
     * If echo() is in effect, display the printable version of the
     * key on the screen.  Carriage return and backspace are treated
     * specially by Solaris curses:
     *
     * If carriage return is defined as a function key in the
     * terminfo, e.g., kent, then Solaris may return either ^J (or ^M
     * if nonl() is set) or KEY_ENTER depending on the echo() mode. 
     * We echo before translating carriage return based on nonl(),
     * since the visual result simply moves the cursor to column 0.
     *
     * Backspace is a different matter.  Solaris curses does not
     * translate it to KEY_BACKSPACE if kbs=^H.  This does not depend
     * on the stty modes, but appears to be a hardcoded special case.
     * This is a difference from ncurses, which uses the terminfo entry.
     * However, we provide the same visual result as Solaris, moving the
     * cursor to the left.
     */
    if (SP->_echo && !(win->_flags & _ISPAD)) {
       chtype backup = (ch == KEY_BACKSPACE) ? '\b' : ch;
       if (backup < KEY_MIN)
           wechochar(win, backup);
    }

    /*
     * Simulate ICRNL mode
     */
    if ((ch == '\r') && SP->_nl)
       ch = '\n';

    /* Strip 8th-bit if so desired.  We do this only for characters that
     * are in the range 128-255, to provide compatibility with terminals
     * that display only 7-bit characters.  Note that 'ch' may be a
     * function key at this point, so we mustn't strip _those_.
     */
    if (!use_meta)
       if ((ch < KEY_MIN) && (ch & 0x80))
           ch &= 0x7f;

    T(("wgetch returning : %s", _tracechar(ch)));

    *result = ch;
    returnCode(ch >= KEY_MIN ? KEY_CODE_YES : OK);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int check_mouse_activity ( int delay   EVENTLIST_2nd_nc_eventlist *evl) [static]

Definition at line 60 of file lib_getch.c.

{
    int rc;

#if USE_SYSMOUSE
    if ((SP->_mouse_type == M_SYSMOUSE)
       && (SP->_sysmouse_head < SP->_sysmouse_tail)) {
       return 2;
    }
#endif
    rc = _nc_timed_wait(TWAIT_MASK, delay, (int *) 0 EVENTLIST_2nd(evl));
#if USE_SYSMOUSE
    if ((SP->_mouse_type == M_SYSMOUSE)
       && (SP->_sysmouse_head < SP->_sysmouse_tail)
       && (rc == 0)
       && (errno == EINTR)) {
       rc |= 2;
    }
#endif
    return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fifo_clear ( void  ) [inline, static]

Definition at line 209 of file lib_getch.c.

{
    memset(SP->_fifo, 0, sizeof(SP->_fifo));
    head = -1;
    tail = peek = 0;
}

Here is the caller graph for this function:

static int fifo_peek ( void  ) [inline, static]

Definition at line 83 of file lib_getch.c.

{
    int ch = SP->_fifo[peek];
    TR(TRACE_IEVENT, ("peeking at %d", peek));

    p_inc();
    return ch;
}

Here is the caller graph for this function:

static int fifo_pull ( void  ) [inline, static]

Definition at line 93 of file lib_getch.c.

{
    int ch;
    ch = SP->_fifo[head];
    TR(TRACE_IEVENT, ("pulling %s from %d", _tracechar(ch), head));

    if (peek == head) {
       h_inc();
       peek = head;
    } else
       h_inc();

#ifdef TRACE
    if (_nc_tracing & TRACE_IEVENT)
       _nc_fifo_dump();
#endif
    return ch;
}

Here is the caller graph for this function:

static int fifo_push ( EVENTLIST_0th(_nc_eventlist *evl)  ) [inline, static]

Definition at line 113 of file lib_getch.c.

{
    int n;
    int ch = 0;
    int mask = 0;

    (void) mask;
    if (tail == -1)
       return ERR;

#ifdef HIDE_EINTR
  again:
    errno = 0;
#endif

#ifdef NCURSES_WGETCH_EVENTS
    if (evl
#if USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE
       || (SP->_mouse_fd >= 0)
#endif
       ) {
       mask = check_mouse_activity(-1 EVENTLIST_2nd(evl));
    } else
       mask = 0;

    if (mask & 4) {
       T(("fifo_push: ungetch KEY_EVENT"));
       ungetch(KEY_EVENT);
       return KEY_EVENT;
    }
#elif USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE
    if (SP->_mouse_fd >= 0) {
       mask = check_mouse_activity(-1 EVENTLIST_2nd(evl));
    }
#endif

#if USE_GPM_SUPPORT || USE_EMX_MOUSE
    if ((SP->_mouse_fd >= 0) && (mask & 2)) {
       SP->_mouse_event(SP);
       ch = KEY_MOUSE;
       n = 1;
    } else
#endif
#if USE_SYSMOUSE
       if ((SP->_mouse_type == M_SYSMOUSE)
           && (SP->_sysmouse_head < SP->_sysmouse_tail)) {
       SP->_mouse_event(SP);
       ch = KEY_MOUSE;
       n = 1;
    } else if ((SP->_mouse_type == M_SYSMOUSE)
              && (mask <= 0) && errno == EINTR) {
       SP->_mouse_event(SP);
       ch = KEY_MOUSE;
       n = 1;
    } else
#endif
    {                       /* Can block... */
       unsigned char c2 = 0;
       n = read(SP->_ifd, &c2, 1);
       ch = c2;
    }

#ifdef HIDE_EINTR
    /*
     * Under System V curses with non-restarting signals, getch() returns
     * with value ERR when a handled signal keeps it from completing.
     * If signals restart system calls, OTOH, the signal is invisible
     * except to its handler.
     *
     * We don't want this difference to show.  This piece of code
     * tries to make it look like we always have restarting signals.
     */
    if (n <= 0 && errno == EINTR)
       goto again;
#endif

    if ((n == -1) || (n == 0)) {
       TR(TRACE_IEVENT, ("read(%d,&ch,1)=%d, errno=%d", SP->_ifd, n, errno));
       ch = ERR;
    }
    TR(TRACE_IEVENT, ("read %d characters", n));

    SP->_fifo[tail] = ch;
    SP->_fifohold = 0;
    if (head == -1)
       head = peek = tail;
    t_inc();
    TR(TRACE_IEVENT, ("pushed %s at %d", _tracechar(ch), tail));
#ifdef TRACE
    if (_nc_tracing & TRACE_IEVENT)
       _nc_fifo_dump();
#endif
    return ch;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int kgetch ( EVENTLIST_0th(_nc_eventlist *evl)  ) [static]

Definition at line 492 of file lib_getch.c.

{
    struct tries *ptr;
    int ch = 0;
    int timeleft = ESCDELAY;

    TR(TRACE_IEVENT, ("kgetch() called"));

    ptr = SP->_keytry;

    for (;;) {
       if (cooked_key_in_fifo() && SP->_fifo[head] >= KEY_MIN) {
           break;
       } else if (!raw_key_in_fifo()) {
           ch = fifo_push(EVENTLIST_1st(evl));
           if (ch == ERR) {
              peek = head;  /* the keys stay uninterpreted */
              return ERR;
           }
#ifdef NCURSES_WGETCH_EVENTS
           else if (ch == KEY_EVENT) {
              peek = head;  /* the keys stay uninterpreted */
              return fifo_pull();  /* Remove KEY_EVENT from the queue */
           }
#endif
       }

       ch = fifo_peek();
       if (ch >= KEY_MIN) {
           /* If not first in queue, somebody put this key there on purpose in
            * emergency.  Consider it higher priority than the unfinished
            * keysequence we are parsing.
            */
           peek = head;
           /* assume the key is the last in fifo */
           t_dec();         /* remove the key */
           return ch;
       }

       TR(TRACE_IEVENT, ("ch: %s", _tracechar((unsigned char) ch)));
       while ((ptr != NULL) && (ptr->ch != (unsigned char) ch))
           ptr = ptr->sibling;

       if (ptr == NULL) {
           TR(TRACE_IEVENT, ("ptr is null"));
           break;
       }
       TR(TRACE_IEVENT, ("ptr=%p, ch=%d, value=%d",
                       ptr, ptr->ch, ptr->value));

       if (ptr->value != 0) {      /* sequence terminated */
           TR(TRACE_IEVENT, ("end of sequence"));
           if (peek == tail)
              fifo_clear();
           else
              head = peek;
           return (ptr->value);
       }

       ptr = ptr->child;

       if (!raw_key_in_fifo()) {
           int rc;

           TR(TRACE_IEVENT, ("waiting for rest of sequence"));
           rc = check_mouse_activity(timeleft EVENTLIST_2nd(evl));
#ifdef NCURSES_WGETCH_EVENTS
           if (rc & 4) {
              TR(TRACE_IEVENT, ("interrupted by a user event"));
              /* FIXME Should have preserved remainder timeleft for reusal... */
              peek = head;  /* Restart interpreting later */
              return KEY_EVENT;
           }
#endif
           if (!rc) {
              TR(TRACE_IEVENT, ("ran out of time"));
              break;
           }
       }
    }
    ch = fifo_pull();
    peek = head;
    return ch;
}

Here is the call graph for this function:

Here is the caller graph for this function:

wgetch ( WINDOW win)

Definition at line 461 of file lib_getch.c.

{
    int code;
    unsigned long value;

    T((T_CALLED("wgetch(%p)"), win));
    code = _nc_wgetch(win,
                    &value,
                    SP->_use_meta
                    EVENTLIST_2nd((_nc_eventlist *) 0));
    if (code != ERR)
       code = value;
    returnCode(code);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

ESCDELAY = 1000

Definition at line 48 of file lib_getch.c.