_tracecchar_t2 (int bufnum, const cchar_t *ch) { char *buf = _nc_trace_buf(bufnum, BUFSIZ); attr_t attr; const char *found; strcpy(buf, l_brace); if (ch != 0) { attr = AttrOfD(ch); if ((found = _nc_altcharset_name(attr, CharOfD(ch))) != 0) { (void) _nc_trace_bufcat(bufnum, found); attr &= ~A_ALTCHARSET; } else if (isWidecExt(CHDEREF(ch))) { (void) _nc_trace_bufcat(bufnum, "{NAC}"); attr &= ~A_CHARTEXT; } else { PUTC_DATA; int n; PUTC_INIT; (void) _nc_trace_bufcat(bufnum, "{ "); do { PUTC_ch = PUTC_i < CCHARW_MAX ? ch->chars[PUTC_i] : L'\0'; PUTC_n = wcrtomb(PUTC_buf, ch->chars[PUTC_i], &PUT_st); if (PUTC_ch == L'\0') --PUTC_n; if (PUTC_n <= 0) { if (PUTC_ch != L'\0') { /* it could not be a multibyte sequence */ (void) _nc_trace_bufcat(bufnum, _tracechar(UChar(ch->chars[PUTC_i]))); } break; } for (n = 0; n < PUTC_n; n++) { if (n) (void) _nc_trace_bufcat(bufnum, ", "); (void) _nc_trace_bufcat(bufnum, _tracechar(UChar(PUTC_buf[n]))); } ++PUTC_i; } while (PUTC_ch != L'\0'); (void) _nc_trace_bufcat(bufnum, " }"); } if (attr != A_NORMAL) { (void) _nc_trace_bufcat(bufnum, " | "); (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr)); } } return (_nc_trace_bufcat(bufnum, r_brace)); }
_tracechtype2(int bufnum, chtype ch) { const char *found; strcpy(_nc_trace_buf(bufnum, BUFSIZ), l_brace); if ((found = _nc_altcharset_name(ChAttrOf(ch), ch)) != 0) { (void) _nc_trace_bufcat(bufnum, found); } else (void) _nc_trace_bufcat(bufnum, _tracechar((int)ChCharOf(ch))); if (ChAttrOf(ch) != A_NORMAL) { (void) _nc_trace_bufcat(bufnum, " | "); (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, ChAttrOf(ch))); } return (_nc_trace_bufcat(bufnum, r_brace)); }
static inline int fifo_pull(void) { 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; }
static int kgetch(EVENTLIST_0th(_nc_eventlist * evl)) { 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; }
_nc_wgetch(WINDOW *win, unsigned long *result, int use_meta EVENTLIST_2nd(_nc_eventlist * evl)) { int ch; #ifdef NCURSES_WGETCH_EVENTS long event_delay = -1; #endif T((T_CALLED("_nc_wgetch(%p)"), win)); *result = 0; if (win == 0 || SP == 0) 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); }
static inline int fifo_push(EVENTLIST_0th(_nc_eventlist * evl)) { 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; }
char *_tracechtype2(int bufnum, chtype ch) { char *buf = _nc_trace_buf(bufnum, BUFSIZ); char *found = 0; strcpy(buf, "{"); if (ch & A_ALTCHARSET) { char *cp; static const struct {unsigned int val; const char *name;} names[] = { {'l', "ACS_ULCORNER"}, /* upper left corner */ {'m', "ACS_LLCORNER"}, /* lower left corner */ {'k', "ACS_URCORNER"}, /* upper right corner */ {'j', "ACS_LRCORNER"}, /* lower right corner */ {'t', "ACS_LTEE"}, /* tee pointing right */ {'u', "ACS_RTEE"}, /* tee pointing left */ {'v', "ACS_BTEE"}, /* tee pointing up */ {'w', "ACS_TTEE"}, /* tee pointing down */ {'q', "ACS_HLINE"}, /* horizontal line */ {'x', "ACS_VLINE"}, /* vertical line */ {'n', "ACS_PLUS"}, /* large plus or crossover */ {'o', "ACS_S1"}, /* scan line 1 */ {'s', "ACS_S9"}, /* scan line 9 */ {'`', "ACS_DIAMOND"}, /* diamond */ {'a', "ACS_CKBOARD"}, /* checker board (stipple) */ {'f', "ACS_DEGREE"}, /* degree symbol */ {'g', "ACS_PLMINUS"}, /* plus/minus */ {'~', "ACS_BULLET"}, /* bullet */ {',', "ACS_LARROW"}, /* arrow pointing left */ {'+', "ACS_RARROW"}, /* arrow pointing right */ {'.', "ACS_DARROW"}, /* arrow pointing down */ {'-', "ACS_UARROW"}, /* arrow pointing up */ {'h', "ACS_BOARD"}, /* board of squares */ {'i', "ACS_LANTERN"}, /* lantern symbol */ {'0', "ACS_BLOCK"}, /* solid square block */ {'p', "ACS_S3"}, /* scan line 3 */ {'r', "ACS_S7"}, /* scan line 7 */ {'y', "ACS_LEQUAL"}, /* less/equal */ {'z', "ACS_GEQUAL"}, /* greater/equal */ {'{', "ACS_PI"}, /* Pi */ {'|', "ACS_NEQUAL"}, /* not equal */ {'}', "ACS_STERLING"}, /* UK pound sign */ {'\0',(char *)0} }, *sp; for (cp = acs_chars; cp[0] && cp[1]; cp += 2) { if (TextOf(cp[1]) == TextOf(ch)) { found = cp; /* don't exit from loop - there may be redefinitions */ } } if (found != 0) { ch = TextOf(*found); for (sp = names; sp->val; sp++) if (sp->val == ch) { (void) strcat(buf, sp->name); ch &= ~A_ALTCHARSET; break; } } } if (found == 0) (void) strcat(buf, _tracechar(TextOf(ch))); if (AttrOf(ch) != A_NORMAL) (void) sprintf(buf + strlen(buf), " | %s", _traceattr2(bufnum+20,AttrOf(ch))); strcat(buf, "}"); return(buf); }