我正在创设一个互动的指挥线应用,该应用应当既适用于六氯环己烷,也适用于Windows操作系统。 在该方案内,有要求从<代码>stdin中获取关键投入的提示。 每当即,用户只能进入特定的ASCII特性和特定特性。 如果<代码><E> or <Enter>
keys are pressed;<Enter>
提交由内部方案国家迅速评估的指令,<爱因>>和>;
触发指示,无须迅速提交。 目前,这只促使在欧罗特开展工作,因为我不知道如何将其用于Windows。
The input prompt is currently implemented via two functions: the generic handler function prompt_user_input
, and the platform-layer function platform_console_read_key
, which only has a working Linux implementation at the moment--not Windows.
www.un.org/spanish/ecosoc 类似工作:
- Immediately read up to six bytes from
stdin
into a buffer (multiple bytes allows for parsing ANSI escape codes for non-ASCII keys). - If the first byte read is not an escape sequence indicator, the first byte is returned as a regular ASCII character.
- If the first byte is an escape sequence indicator, bytes 2-6 of the buffer are parsed.
- If the rest of the buffer is empty, then the character is standalone, so do step 2.
- If there is something in the latter part of the buffer, then it is actually an escape sequence. Attempt to parse and return it as an "extended key code" (which is just a
#define
for an integer > 255). - If there is something in the latter part of the buffer, and it is an escape code which is not handled by the function, return the special value
0
.
- If there is any kind of critical I/O error, return the special value
KEY_COUNT
.
因此,我照此读了这样的特性,因为我处理通过<条码>归还的每项关键代码,这些代码分别载于<条码>prompt_user_input,以确定如何开展该方案。 <代码>prompt_user_input 类似工作:
- Take an argument which is the maximum number of characters which may be input.
- Read keys via
platform_console_read_key
in an infinite loop. - If last key matches
<Enter>
or<Escape>
, break from the loop. - Otherwise, see if it is a valid key using a
filter_user_input
predicate.- If it is valid, add it to an input buffer, as long as the number of the characters written to the buffer does not exceed that allowed by the function argument. Also print it to the screen (i.e. "echo" functionality).
- If max writes reached, or key is invalid, continue (i.e. goto step 2).
我的问题是,我如何为Windows平台层执行platform_console_read_key
。 我怎么能立即读到Windows终端的关键板投入的6种? 此外,我如何确定这些六种 by子的编排方式,以便我能够把视窗的关键代码描绘成功能的回报值,从而使功能的行为与光栅版的相同?
下面是实用的六氯环己烷代码,平台层包括<代码><termios.h>和<unistd.h>
。 我略去了一些不相干的代码,并添加了一些<条码><>印本/代码>的说明,以澄清和方便测试。 注:prompt_user_input
参考了全球<代码>(*state ).in ,即投入缓冲;假设该代码总是大于所供应的<代码>char_count。
bool
prompt_user_input
( const u8 char_count
)
{
printf ( "Type your response: " );
// Clear any previous user input.
memset ( ( *state ).in , 0 , sizeof ( ( *state ).in ) );
KEY key;
u8 indx = 0;
for (;;)
{
key = platform_console_read_key ();
if ( key == KEY_COUNT )
{
// ERROR
return false;
}
// Submit response? Y/N
if ( key == KEY_ENTER )
{
return true;
}
// Quit signal? Y/N
if ( key == KEY_ESCAPE )
{
//...
return true;
}
// Handle backspace.
if ( key == KEY_BACKSPACE )
{
if ( !indx )
{
continue;
}
indx -= 1;
( *state ).in[ indx ] = 0;
}
// Response too long? Y/N
else if ( indx >= char_count )
{
indx = char_count;
continue;
}
// Invalid keycode? Y/N
else if ( !filter_user_input ( key ) )
{
continue;
}
// Write to input buffer.
else
{
( *state ).in[ indx ] = key;
indx += 1;
}
// Render the character.
printf ( "%s"
, ( key == KEY_BACKSPACE ) ? " "
: ( char[] ){ key , 0 }
);
}
}
KEY
platform_console_read_key
( void )
{
KEY key = KEY_COUNT;
// Configure terminal for non-canonical input.
struct termios tty;
struct termios tty_;
tcgetattr ( STDIN_FILENO , &tty );
tty_ = tty;
tty_.c_lflag &= ~( ICANON | ECHO );
tcsetattr ( STDIN_FILENO , TCSANOW , &tty_ );
fflush ( stdout ); // In case echo functionality desired.
// Read the key from the input stream.
char in[ 6 ]; // Reserve up to six bytes to handle special keys.
platform_memory_clear ( in , sizeof ( in ) );
i32 result = read ( STDIN_FILENO , in , sizeof ( in ) );
// I/O error.
if ( result < 0 )
{
key = KEY_COUNT;
goto platform_console_read_key_end;
}
// End of transmission (I/O error).
if ( in[ 0 ] == 4
|| in[ 1 ] == 4
|| in[ 2 ] == 4
|| in[ 3 ] == 4
|| in[ 4 ] == 4
|| in[ 5 ] == 4
)
{
key = KEY_COUNT;
goto platform_console_read_key_end;
}
// ANSI escape sequence.
if ( *in == 33 || *in == ~ )
{
// Standalone keycode.
if ( !in[ 1 ] )
{
switch ( *in )
{
case 33 : key = KEY_ESCAPE ;break;
case ~ : key = ~ ;break;
default : key = 0 ;break;
}
goto platform_console_read_key_end;
}
// Composite keycode.
else
{
if ( in[ 1 ] == [ )
{
// ...
}
else
{
key = 0;
}
goto platform_console_read_key_end;
}
}
// Standalone ASCII character.
else
{
// Backspace key is mapped to ASCII delete (for some reason).
key = ( *in == KEY_DELETE ) ? KEY_BACKSPACE : *in;
goto platform_console_read_key_end;
}
// Reset terminal to canonical input mode.
platform_console_read_key_end:
tcsetattr ( STDIN_FILENO , TCSANOW , &tty );
fflush ( stdout ); // In case echo functionality desired.
return key;
}