wint_t input_readch() { int i; CHECK_BLOCK( R_NULL ); /* Clear the interrupted flag */ reader_interrupted(); /* Search for sequence in mapping tables */ while( 1 ) { input_mapping_t *generic = 0; for( i=0; i<al_get_count( &mappings); i++ ) { input_mapping_t *m = (input_mapping_t *)al_get( &mappings, i ); wint_t res = input_try_mapping( m ); if( res ) return res; if( wcslen( m->seq) == 0 ) { generic = m; } } /* No matching exact mapping, try to find generic mapping. */ if( generic ) { wchar_t arr[2]= { 0, 0 } ; arr[0] = input_common_readch(0); return input_exec_binding( generic, arr ); } /* No action to take on specified character, ignore it and move to next one. */ input_common_readch( 0 ); } }
/// Process the characters we receive as the user presses keys. static void process_input(bool continuous_mode) { bool first_char_seen = false; double prev_tstamp = 0.0; printf("Press a key\n\n"); while (keep_running) { wchar_t wc = input_common_readch(first_char_seen && !continuous_mode); if (wc == WEOF) { return; } else if (wc > 255) { printf("\nUnexpected wide character from input_common_readch(): %lld / 0x%llx\n", (long long)wc, (long long)wc); return; } unsigned char c = wc; prev_tstamp = output_elapsed_time(prev_tstamp, first_char_seen); output_info_about_char(c); output_matching_key_name(c); if (should_exit(c)) { printf("\nExiting at your request.\n"); break; } first_char_seen = true; } }
/// Process the characters we receive as the user presses keys. static void process_input(bool continuous_mode) { bool first_char_seen = false; double prev_tstamp = 0.0; std::vector<wchar_t> bind_chars; fprintf(stderr, "Press a key\n\n"); while (keep_running) { wchar_t wc = input_common_readch(true); if (wc == R_TIMEOUT || wc == R_EOF) { output_bind_command(bind_chars); if (first_char_seen && !continuous_mode) { return; } continue; } prev_tstamp = output_elapsed_time(prev_tstamp, first_char_seen); add_char_to_bind_command(wc, bind_chars); output_info_about_char(wc); if (output_matching_key_name(wc)) { output_bind_command(bind_chars); } if (should_exit(wc)) { fprintf(stderr, "\nExiting at your request.\n"); break; } first_char_seen = true; } }
/** Try reading the specified function mapping */ static wint_t input_try_mapping( input_mapping_t *m) { int j, k; wint_t c=0; /* Check if the actual function code of this mapping is on the stack */ c = input_common_readch( 0 ); if( c == input_function_get_code( m->command ) ) { return input_exec_binding( m, m->seq ); } input_unreadch( c ); if( m->seq != 0 ) { for( j=0; m->seq[j] != L'\0' && m->seq[j] == (c=input_common_readch( j>0 )); j++ ) ; if( m->seq[j] == L'\0' ) { return input_exec_binding( m, m->seq ); } else { /* Return the read characters */ input_unreadch(c); for( k=j-1; k>=0; k-- ) { input_unreadch( m->seq[k] ); } } } return 0; }
wchar_t input_common_readch(int timed) { if (!has_lookahead()) { if (timed) { fd_set fds; FD_ZERO(&fds); FD_SET(0, &fds); struct timeval tm = {wait_on_escape_ms / 1000, 1000 * (wait_on_escape_ms % 1000)}; int count = select(1, &fds, 0, 0, &tm); if (count <= 0) { return R_TIMEOUT; } } wchar_t res; mbstate_t state = {}; while (1) { wint_t b = readb(); if (b >= R_NULL && b < R_END_INPUT_FUNCTIONS) return b; if (MB_CUR_MAX == 1) { // return (unsigned char)b; // single-byte locale, all values are legal return b; // single-byte locale, all values are legal } char bb = b; size_t sz = mbrtowc(&res, &bb, 1, &state); switch (sz) { case (size_t)(-1): { memset(&state, '\0', sizeof(state)); debug(2, L"Illegal input"); return R_NULL; } case (size_t)(-2): { break; } case 0: { return 0; } default: { return res; } } } } else { if (!timed) { while (has_lookahead() && lookahead_front() == R_TIMEOUT) lookahead_pop(); if (!has_lookahead()) return input_common_readch(0); } return lookahead_pop(); } }
char_event_t input_common_readch_timed(bool dequeue_timeouts) { char_event_t result{char_event_type_t::timeout}; if (has_lookahead()) { result = lookahead_pop(); } else { fd_set fds; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); struct timeval tm = {wait_on_escape_ms / 1000, 1000 * (wait_on_escape_ms % 1000)}; if (select(1, &fds, 0, 0, &tm) > 0) { result = input_common_readch(); } } // If we got a timeout, either through dequeuing or creating, ensure it stays on the queue. if (result.is_timeout()) { if (!dequeue_timeouts) lookahead_push_front(char_event_type_t::timeout); return char_event_type_t::timeout; } return result; }
/** Test if the specified character sequence has been entered on the keyboard */ static int try_sequence( const char *seq ) { int j, k; wint_t c=0; for( j=0; seq[j] != '\0' && seq[j] == (c=input_common_readch( j>0 )); j++ ) ; if( seq[j] == '\0' ) { return 1; } else { input_common_unreadch(c); for(k=j-1; k>=0; k--) input_common_unreadch(seq[k]); } return 0; }
/// Process the characters we receive as the user presses keys. void process_input(bool continuous_mode) { bool first_char_seen = false; while (true) { wchar_t wc = input_common_readch(first_char_seen && !continuous_mode); if (wc == WEOF) { return; } if (wc > 255) { printf("\nUnexpected wide character from input_common_readch(): %lld / 0x%llx\n", (long long)wc, (long long)wc); return; } long long int curr_tstamp, delta_tstamp; timeval char_tstamp; gettimeofday(&char_tstamp, NULL); curr_tstamp = char_tstamp.tv_sec * 1000000 + char_tstamp.tv_usec; delta_tstamp = curr_tstamp - prev_tstamp; if (delta_tstamp >= 1000000) delta_tstamp = 999999; if (delta_tstamp >= 200000 && continuous_mode) { printf("\n"); printf("Type 'exit' or 'quit' to terminate this program.\n"); printf("\n"); } prev_tstamp = curr_tstamp; unsigned char c = wc; if (c < 32) { // Control characters. if (ctrl_equivalents[c]) { printf("%6lld usec dec: %3u hex: %2x char: %s (aka \\c%c)\n", delta_tstamp, c, c, ctrl_equivalents[c], c + 64); } else { printf("%6lld usec dec: %3u hex: %2x char: \\c%c\n", delta_tstamp, c, c, c + 64); } } else if (c == 32) { // The space character. printf("%6lld usec dec: %3u hex: %2x char: <space>\n", delta_tstamp, c, c); } else if (c == 127) { // The "del" character. printf("%6lld usec dec: %3u hex: %2x char: \\x7f (aka del)\n", delta_tstamp, c, c); } else if (c >= 128) { // Non-ASCII characters (i.e., those with bit 7 set). printf("%6lld usec dec: %3u hex: %2x char: non-ASCII\n", delta_tstamp, c, c); } else { // ASCII characters that are not control characters. printf("%6lld usec dec: %3u hex: %2x char: %c\n", delta_tstamp, c, c, c); } char *const name = key_name(c); if (name) { printf("FYI: Saw sequence for bind key name \"%s\"\n", name); free(name); } if (should_exit(c)) { printf("\nExiting at your request.\n"); break; } first_char_seen = true; } }
/** Read a character from keyboard */ static wint_t readch() { struct mapping { const char *seq; wint_t bnd; } ; struct mapping m[]= { { "\x1b[A", LINE_UP } , { key_up, LINE_UP } , { "\x1b[B", LINE_DOWN } , { key_down, LINE_DOWN } , { key_ppage, PAGE_UP } , { key_npage, PAGE_DOWN } , { " ", PAGE_DOWN } , { "\t", PAGE_DOWN } , { 0, 0 } } ; int i; for( i=0; m[i].bnd; i++ ) { if( !m[i].seq ) { continue; } if( try_sequence(m[i].seq ) ) return m[i].bnd; } return input_common_readch(0); }
wchar_t input_common_readch( int timed ) { if( lookahead_count == 0 ) { if( timed ) { int count; fd_set fds; struct timeval tm= { 0, 1000 * WAIT_ON_ESCAPE } ; FD_ZERO( &fds ); FD_SET( 0, &fds ); count = select(1, &fds, 0, 0, &tm); switch( count ) { case 0: return WEOF; case -1: return WEOF; break; default: break; } } wchar_t res; static mbstate_t state; while(1) { wint_t b = readb(); char bb; int sz; if( (b >= R_NULL) && (b < R_NULL + 1000) ) return b; bb=b; sz = mbrtowc( &res, &bb, 1, &state ); switch( sz ) { case -1: memset (&state, '\0', sizeof (state)); debug( 2, L"Illegal input" ); return R_NULL; case -2: break; case 0: return 0; default: return res; } } } else { if( !timed ) { while( (lookahead_count >= 0) && (lookahead_arr[lookahead_count-1] == WEOF) ) lookahead_count--; if( lookahead_count == 0 ) return input_common_readch(0); } return lookahead_arr[--lookahead_count]; } }
int main( int argc, char **argv) { setlocale( LC_ALL, "" ); if( argc == 2 ) { static char term_buffer[2048]; char *termtype = getenv ("TERM"); char *tbuff = malloc( sizeof(char)*9999); char *res; tgetent( term_buffer, termtype ); res = tgetstr( argv[1], &tbuff ); if( res != 0 ) { while( *res != 0 ) { printf("%d ", *res ); res++; } printf( "\n" ); } else { printf("Undefined sequence\n"); } } else { char scratch[1024]; unsigned int c; struct termios modes, /* so we can change the modes */ savemodes; /* so we can reset the modes when we're done */ input_common_init(0); tcgetattr(0,&modes); /* get the current terminal modes */ savemodes = modes; /* save a copy so we can reset them */ modes.c_lflag &= ~ICANON; /* turn off canonical mode */ modes.c_lflag &= ~ECHO; /* turn off echo mode */ modes.c_cc[VMIN]=1; modes.c_cc[VTIME]=0; tcsetattr(0,TCSANOW,&modes); /* set the new modes */ while(1) { if( (c=input_common_readch(0)) == EOF ) break; if( (c > 31) && (c != 127) ) sprintf( scratch, "dec: %d hex: %x char: %c\n", c, c, c ); else sprintf( scratch, "dec: %d hex: %x\n", c, c ); writestr( scratch ); } /* reset the terminal to the saved mode */ tcsetattr(0,TCSANOW,&savemodes); input_common_destroy(); } return 0; }
wchar_t input_common_readch(int timed) { if (! has_lookahead()) { if (timed) { int count; fd_set fds; struct timeval tm= { 0, 1000 * WAIT_ON_ESCAPE } ; FD_ZERO(&fds); FD_SET(0, &fds); count = select(1, &fds, 0, 0, &tm); switch (count) { case 0: return WEOF; case -1: return WEOF; break; default: break; } } wchar_t res; mbstate_t state = {}; while (1) { wint_t b = readb(); char bb; size_t sz; if ((b >= R_NULL) && (b < R_NULL + 1000)) return b; bb=b; sz = mbrtowc(&res, &bb, 1, &state); switch (sz) { case (size_t)(-1): memset(&state, '\0', sizeof(state)); debug(2, L"Illegal input"); return R_NULL; case (size_t)(-2): break; case 0: return 0; default: return res; } } } else { if (!timed) { while (has_lookahead() && lookahead_top() == WEOF) lookahead_pop(); if (! has_lookahead()) return input_common_readch(0); } return lookahead_pop(); } }