char * __cdecl _cgets ( char *string ) { ULONG oldstate; ULONG num_read; char *result; _mlock(_CONIO_LOCK); /* lock the console */ string[1] = 0; /* no chars read yet */ result = &string[2]; /* * _coninpfh, the handle to the console input, is created the first * time that either _getch() or _cgets() or _kbhit() is called. */ if ( _coninpfh == -2 ) __initconin(); if ( _coninpfh == -1 ) { _munlock(_CONIO_LOCK); /* unlock the console */ return(NULL); /* return failure */ } GetConsoleMode( (HANDLE)_coninpfh, &oldstate ); SetConsoleMode( (HANDLE)_coninpfh, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT ); if ( !ReadConsole( (HANDLE)_coninpfh, (LPVOID)result, (unsigned char)string[0], &num_read, NULL ) ) result = NULL; if ( result != NULL ) { /* set length of string and null terminate it */ if (string[num_read] == '\r') { string[1] = (char)(num_read - 2); string[num_read] = '\0'; } else if ( (num_read == (ULONG)(unsigned char)string[0]) && (string[num_read + 1] == '\r') ) { /* special case 1 - \r\n straddles the boundary */ string[1] = (char)(num_read -1); string[1 + num_read] = '\0'; } else if ( (num_read == 1) && (string[2] == '\n') ) { /* special case 2 - read a single '\n'*/ string[1] = string[2] = '\0'; } else { string[1] = (char)num_read; string[2 + num_read] = '\0'; } } SetConsoleMode( (HANDLE)_coninpfh, oldstate ); _munlock(_CONIO_LOCK); /* unlock the console */ return result; }
int __cdecl _kbhit_nolock ( void ) { DWORD NumPending; DWORD NumPeeked; int ret = FALSE; PINPUT_RECORD pIRBuf=NULL; /* * if a character has been pushed back, return TRUE */ if ( chbuf != -1 ) return TRUE; /* * _coninpfh, the handle to the console input, is created the first * time that either _getch() or _cgets() or _kbhit() is called. */ if ( _coninpfh == -2 ) __initconin(); /* * Peek all pending console events */ if ( (_coninpfh == -1) || !GetNumberOfConsoleInputEvents((HANDLE)_coninpfh, &NumPending) || (NumPending == 0)) { return FALSE; } pIRBuf=(PINPUT_RECORD)_calloca(NumPending, sizeof(INPUT_RECORD)); if ( pIRBuf == NULL ) { return FALSE; } if ( PeekConsoleInput( (HANDLE)_coninpfh, pIRBuf, NumPending, &NumPeeked ) && (NumPeeked != 0L) && (NumPeeked <= NumPending) ) { /* * Scan all of the peeked events to determine if any is a key event * which should be recognized. */ PINPUT_RECORD pIR; for ( pIR = pIRBuf ; NumPeeked > 0 ; NumPeeked--, pIR++ ) { if ( (pIR->EventType == KEY_EVENT) && (pIR->Event.KeyEvent.bKeyDown) && ( pIR->Event.KeyEvent.uChar.AsciiChar || _getextendedkeycode( &(pIR->Event.KeyEvent) ) ) ) { /* * Key event corresponding to an ASCII character or an * extended code. In either case, success! */ ret = TRUE; } } } _freea( pIRBuf ); return ret; }
errno_t __cdecl _cgetws_s ( wchar_t *string, size_t sizeInWords, size_t * pSizeRead ) { ULONG oldstate; ULONG num_read; errno_t err = 0; _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE((string != NULL), EINVAL); _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE((sizeInWords > 0), EINVAL); _RESET_STRING(string, sizeInWords); _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE((pSizeRead != NULL), EINVAL); _mlock(_CONIO_LOCK); /* lock the console */ __TRY /* * We need to decrement sizeInWords because ReadConsole reads as * many characters as the parameter passed, doesn't null terminate */ --sizeInWords; *pSizeRead = 0; /* * If the __console_whcar_buffer_used is set, then first fill the * buffered character and then proceed. */ if (__console_wchar_buffer_used != 0 && sizeInWords > 0) { *string++ = __console_wchar_buffer; __console_wchar_buffer = 0; --sizeInWords; (*pSizeRead)++; if (__console_wchar_buffer == L'\0') sizeInWords = 0; } /* if the user only asked for one character, we have now filled their request */ if (sizeInWords != 0) { /* * _coninpfh, the handle to the console input, is created the first * time that either _getch() or _cgets() or _kbhit() is called. */ if ( _coninpfh == -2 ) __initconin(); if ( _coninpfh != -1 ) { GetConsoleMode( (HANDLE)_coninpfh, &oldstate ); SetConsoleMode( (HANDLE)_coninpfh, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT ); // First try usual way just as _cgets if ( bUseW) { if ( !ReadConsoleW( (HANDLE)_coninpfh, (LPVOID)string, (DWORD)sizeInWords, &num_read, NULL ) ) { if ( bUseW == 2 ) { if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) bUseW = FALSE; else bUseW = TRUE; } } else { bUseW = TRUE; /* set length of string and null terminate it */ if (string[num_read - 2] == L'\r') { (*pSizeRead) += num_read - 2; string[num_read - 2] = L'\0'; } else if ( (num_read == sizeInWords) && (string[num_read - 1] == L'\r') ) { /* special case 1 - \r\n straddles the boundary */ (*pSizeRead) += num_read -1; string[num_read - 1] = L'\0'; } else if ( (num_read == 1) && (string[0] == L'\n') ) { /* special case 2 - read a single '\n'*/ string[0] = L'\0'; (*pSizeRead) += 0; } else { (*pSizeRead) += num_read; string[num_read] = L'\0'; } } } // If ReadConsoleW is not present, use ReadConsoleA and then convert // to Wide Char. if ( !bUseW) { static char AStr[BUF_MAX_LEN +1]; static int in_buff = 0, was_buff_full = 0; unsigned int Copy, Sz, consoleCP; unsigned int last_read = 0, i; consoleCP = GetConsoleCP(); do { if (!in_buff) { if ( ReadConsoleA( (HANDLE)_coninpfh, (LPVOID)AStr, BUF_MAX_LEN, &num_read, NULL) && num_read <= BUF_MAX_LEN ) { if (num_read >= 2 && AStr[num_read -2] == '\r') { AStr[num_read -2] = '\0'; } else if (num_read == BUF_MAX_LEN && AStr[num_read -1] == '\r') AStr[num_read -1] = '\0'; else if (num_read == 1 && AStr[0] == '\n') AStr[0] = '\0'; else AStr[num_read] = '\0'; } else { _dosmaperr(GetLastError()); err = errno; } } for ( i = 0; AStr[i] != '\0' && i < (BUF_MAX_LEN) && last_read < sizeInWords; i += Sz) { // Check if this character is lead byte. If yes, the size // of this character is 2. Else 1. if ( IsDBCSLeadByteEx( GetConsoleCP(), AStr[i])) Sz = 2; else Sz = 1; if ( (Copy = MultiByteToWideChar( consoleCP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, &AStr[i], Sz, &string[last_read], (int)sizeInWords - last_read))) { last_read += Copy; } } // Check if this conversion was from buffer. If yes, was // buffer fully filled when it was first read using // ReadConsoleA. If the buffer not fully filled, we don't need // to read more from buffer. This is necessary to make it // behave same as if we are reading using ReadConsoleW. if ( in_buff && i == strlen(AStr)) { in_buff = 0; if ( was_buff_full) { was_buff_full = 0; continue; } else { break; } } else if ( i < (BUF_MAX_LEN)) break; } while (last_read < sizeInWords); // We save the buffer to be used again. if ( i < strlen(AStr)) { in_buff = 1; if ( strlen(AStr) == (BUF_MAX_LEN)) was_buff_full = 1; memmove(AStr, &AStr[i], BUF_MAX_LEN +1 - i); } string[last_read] = '\0'; (*pSizeRead) += last_read; } SetConsoleMode( (HANDLE)_coninpfh, oldstate ); } else { _dosmaperr(GetLastError()); err = errno; } } __FINALLY _munlock(_CONIO_LOCK); /* unlock the console */ __END_TRY_FINALLY if (err != 0) { errno = err; } return err; }
int __cdecl _getch_nolock ( void ) { INPUT_RECORD ConInpRec; DWORD NumRead; const CharPair *pCP; int ch = 0; /* single character buffer */ DWORD oldstate; /* * check pushback buffer (chbuf) a for character */ if ( chbuf != EOF ) { /* * something there, clear buffer and return the character. */ ch = (unsigned char)(chbuf & 0xFF); chbuf = EOF; return ch; } /* * _coninpfh, the handle to the console input, is created the first * time that either _getch() or _cgets() or _kbhit() is called. */ if ( _coninpfh == -2 ) __initconin(); if (_coninpfh == -1) return EOF; /* * Switch to raw mode (no line input, no echo input) */ GetConsoleMode( (HANDLE)_coninpfh, &oldstate ); SetConsoleMode( (HANDLE)_coninpfh, 0L ); for ( ; ; ) { /* * Get a console input event. */ if ( !ReadConsoleInput( (HANDLE)_coninpfh, &ConInpRec, 1L, &NumRead ) || (NumRead == 0L) ) { ch = EOF; break; } /* * Look for, and decipher, key events. */ if ( (ConInpRec.EventType == KEY_EVENT) && ConInpRec.Event.KeyEvent.bKeyDown ) { /* * Easy case: if uChar.AsciiChar is non-zero, just stuff it * into ch and quit. */ if ( ch = (unsigned char)ConInpRec.Event.KeyEvent.uChar.AsciiChar ) break; /* * Hard case: either an extended code or an event which should * not be recognized. let _getextendedkeycode() do the work... */ if ( pCP = _getextendedkeycode( &(ConInpRec.Event.KeyEvent) ) ) { ch = pCP->LeadChar; chbuf = pCP->SecondChar; break; } } } /* * Restore previous console mode. */ SetConsoleMode( (HANDLE)_coninpfh, oldstate ); return ch; }