Crypt-SecretBuffer
view release on metacpan or search on metacpan
secret_buffer_console.c view on Meta::CPAN
state->hdl= tmp;
state->own_fd= true;
}
return true;
}
static bool sb_console_state_get_echo(sb_console_state *state) {
return state->mode & ENABLE_ECHO_INPUT;
}
static bool sb_console_state_set_echo(sb_console_state *state, bool enable) {
DWORD mode= enable? (state->mode | ENABLE_ECHO_INPUT)
: (state->mode & ~ENABLE_ECHO_INPUT);
if (SetConsoleMode(state->hdl, mode)) {
state->mode= mode;
return true;
}
return false;
}
static bool sb_console_state_get_line_input(sb_console_state *state) {
return state->mode & ENABLE_LINE_INPUT;
}
static bool sb_console_state_set_line_input(sb_console_state *state, bool enable) {
DWORD mode= enable? (state->mode | ENABLE_LINE_INPUT)
: (state->mode & ~ENABLE_LINE_INPUT);
if (SetConsoleMode(state->hdl, mode)) {
state->mode= mode;
return true;
}
return false;
}
static bool sb_console_state_restore(sb_console_state *state) {
if (SetConsoleMode(state->hdl, state->orig_mode)) {
state->mode= state->orig_mode;
return true;
}
return false;
}
static void sb_console_state_destroy(pTHX_ sb_console_state *state) {
if (state->hdl != INVALID_HANDLE_VALUE) {
if (state->auto_restore)
if (!sb_console_state_restore(state))
warn("failed to restore console state");
if (state->own_fd)
if (!CloseHandle(state->hdl))
warn("BUG: CloseHandle failed");
state->hdl= INVALID_HANDLE_VALUE;
}
state->pending_high_surrogate= 0;
}
static bool
sb_console_state_wait_char_readable(pTHX_ sb_console_state *state, SV *timeout_sv) {
return sb_wait_win32_handle_readable(aTHX_ state->hdl, timeout_sv);
}
/* Windows API provides unicode key characters when you use ReadConsoleInputW.
* SecretBuffer is UTF-8 by default, so this function translates them.
* Returns true if it added a character, and false if no character is available yet,
* and croaks on OS errors or invalid surrogate pairs.
* It only appends whole characters (encoded as UTF-8) and may store half a
* surrogate pair into `state` to be combined with a subsequent call.
*/
static bool
sb_append_console_char(pTHX_ sb_console_state *state, secret_buffer *dest) {
INPUT_RECORD in_rec[16];
const char *error= NULL;
DWORD err_code= 0;
int cp= -1;
/* Inspect pending console events until we find a real character-producing key event,
* including looking for surrogate pair if half a character is received.
* Discard non-character events.
*/
while (cp < 0 && !error) {
DWORD i, nread;
if (!PeekConsoleInputW(state->hdl, in_rec, sizeof(in_rec)/sizeof(*in_rec), &nread)) {
error= "PeekConsoleInputW failed";
err_code= GetLastError();
translate_to_errno();
break;
}
if (!nread)
break;
for (i = 0; i < nread && cp < 0 && !error; i++) {
if (in_rec[i].EventType == KEY_EVENT
&& in_rec[i].Event.KeyEvent.bKeyDown
&& in_rec[i].Event.KeyEvent.uChar.UnicodeChar != 0
) {
cp= (int) in_rec[i].Event.KeyEvent.uChar.UnicodeChar;
if (state->pending_high_surrogate) {
/* this needs to be the low surrogate, or die */
if (cp >= 0xDC00 && cp <= 0xDFFF) {
/* combine them */
cp = 0x10000 + ((state->pending_high_surrogate - 0xD800) << 10) + (cp - 0xDC00);
state->pending_high_surrogate= 0;
} else {
/* croak, but also clear the surrogate so the next read can succeed */
state->pending_high_surrogate= 0;
error= "received unpaired high UTF-16 surrogate";
break; /* stop before i++ so that this event is available later */
}
}
/* new high surrogate? */
else if (cp >= 0xD800 && cp <= 0xDBFF) {
state->pending_high_surrogate= cp;
cp= -1; /* keep looping since the low surrogate is probably in a following event */
}
/* low surrogate without high surrogate */
else if (cp >= 0xDC00 && cp <= 0xDFFF) {
error= "received unpaired low UTF-16 surrogate";
}
}
}
/* discard consumed events */
if (i > 0) {
DWORD nread2;
if (!ReadConsoleInputW(state->hdl, in_rec, i, &nread2)) {
( run in 1.109 second using v1.01-cache-2.11-cpan-d8267643d1d )