/*** *cgets.c - buffered keyboard input * * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved. * *Purpose: * defines _cgets() - read a string directly from console * *Revision History: * 06-09-89 PHG Module created, based on asm version * 03-12-90 GJF Made calling type _CALLTYPE1, added #include * and fixed copyright. Also, cleaned * up the formatting a bit. * 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits * 07-24-90 SBM Removed '32' from API names * 08-13-90 SBM Compiles cleanly with -W3 * 09-28-90 GJF New-style function declarator. * 12-04-90 SRW Changed to include instead of * 12-13-90 GJF Fixed a couple of bugs. * 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. * 01-16-91 GJF ANSI naming. * 01-25-91 SRW Get/SetConsoleMode parameters changed (_WIN32_) * 02-18-91 SRW Get/SetConsoleMode required read/write access (_WIN32_) * 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_) * 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_) * 07-26-91 GJF Took out init. stuff and cleaned up the error * handling [_WIN32_]. * 04-06-93 SKS Replace _CRTAPI* with __cdecl * 04-19-93 GJF Use ReadConsole instead of ReadFile. * 09-06-94 CFW Remove Cruiser support. * 12-03-94 SKS Clean up OS/2 references * 03-02-95 GJF Treat string[0] as an unsigned value. * 12-08-95 SKS _coninph is now initialized on demand * 02-07-98 GJF Changes for Win64: _coninph is now an intptr_t. * 04-29-02 GB Added try-finally arounds lock-unlock. * *******************************************************************************/ #include #include #include #include #include #include /* * mask to clear the bits required to be 0 in the handle state passed to * DOSSETFHSTATE. */ #define FHSTATEMASK 0xffd07888 /* * declaration for console handle */ extern intptr_t _coninpfh; /*** *char *_cgets(string) - read string from console * *Purpose: * Reads a string from the console via ReadConsole on a cooked console * handle. string[0] must contain the maximum length of the * string. Returns pointer to str[2]. * * NOTE: _cgets() does NOT check the pushback character buffer (i.e., * _chbuf). Thus, _cgets() will not return any character that is * pushed back by the _ungetch() call. * *Entry: * char *string - place to store read string, str[0] = max length. * *Exit: * returns pointer to str[2], where the string starts. * returns NULL if error occurs * *Exceptions: * *******************************************************************************/ char * __cdecl _cgets ( char *string ) { ULONG oldstate; ULONG num_read; char *result; _mlock(_CONIO_LOCK); /* lock the console */ __TRY 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 ) { result=NULL; } else { 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 ); } __FINALLY _munlock(_CONIO_LOCK); /* unlock the console */ __END_TRY_FINALLY return result; }