Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
4.9 KiB

  1. /***
  2. *cgets.c - buffered keyboard input
  3. *
  4. * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * defines _cgets() - read a string directly from console
  8. *
  9. *Revision History:
  10. * 06-09-89 PHG Module created, based on asm version
  11. * 03-12-90 GJF Made calling type _CALLTYPE1, added #include
  12. * <cruntime.h> and fixed copyright. Also, cleaned
  13. * up the formatting a bit.
  14. * 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits
  15. * 07-24-90 SBM Removed '32' from API names
  16. * 08-13-90 SBM Compiles cleanly with -W3
  17. * 09-28-90 GJF New-style function declarator.
  18. * 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
  19. * 12-13-90 GJF Fixed a couple of bugs.
  20. * 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
  21. * 01-16-91 GJF ANSI naming.
  22. * 01-25-91 SRW Get/SetConsoleMode parameters changed (_WIN32_)
  23. * 02-18-91 SRW Get/SetConsoleMode required read/write access (_WIN32_)
  24. * 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_)
  25. * 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_)
  26. * 07-26-91 GJF Took out init. stuff and cleaned up the error
  27. * handling [_WIN32_].
  28. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  29. * 04-19-93 GJF Use ReadConsole instead of ReadFile.
  30. * 09-06-94 CFW Remove Cruiser support.
  31. * 12-03-94 SKS Clean up OS/2 references
  32. * 03-02-95 GJF Treat string[0] as an unsigned value.
  33. * 12-08-95 SKS _coninph is now initialized on demand
  34. * 02-07-98 GJF Changes for Win64: _coninph is now an intptr_t.
  35. *
  36. *******************************************************************************/
  37. #include <cruntime.h>
  38. #include <oscalls.h>
  39. #include <mtdll.h>
  40. #include <conio.h>
  41. #include <stdlib.h>
  42. #include <internal.h>
  43. /*
  44. * mask to clear the bits required to be 0 in the handle state passed to
  45. * DOSSETFHSTATE.
  46. */
  47. #define FHSTATEMASK 0xffd07888
  48. /*
  49. * declaration for console handle
  50. */
  51. extern intptr_t _coninpfh;
  52. /***
  53. *char *_cgets(string) - read string from console
  54. *
  55. *Purpose:
  56. * Reads a string from the console via ReadConsole on a cooked console
  57. * handle. string[0] must contain the maximum length of the
  58. * string. Returns pointer to str[2].
  59. *
  60. * NOTE: _cgets() does NOT check the pushback character buffer (i.e.,
  61. * _chbuf). Thus, _cgets() will not return any character that is
  62. * pushed back by the _ungetch() call.
  63. *
  64. *Entry:
  65. * char *string - place to store read string, str[0] = max length.
  66. *
  67. *Exit:
  68. * returns pointer to str[2], where the string starts.
  69. * returns NULL if error occurs
  70. *
  71. *Exceptions:
  72. *
  73. *******************************************************************************/
  74. char * __cdecl _cgets (
  75. char *string
  76. )
  77. {
  78. ULONG oldstate;
  79. ULONG num_read;
  80. char *result;
  81. _mlock(_CONIO_LOCK); /* lock the console */
  82. string[1] = 0; /* no chars read yet */
  83. result = &string[2];
  84. /*
  85. * _coninpfh, the handle to the console input, is created the first
  86. * time that either _getch() or _cgets() or _kbhit() is called.
  87. */
  88. if ( _coninpfh == -2 )
  89. __initconin();
  90. if ( _coninpfh == -1 ) {
  91. _munlock(_CONIO_LOCK); /* unlock the console */
  92. return(NULL); /* return failure */
  93. }
  94. GetConsoleMode( (HANDLE)_coninpfh, &oldstate );
  95. SetConsoleMode( (HANDLE)_coninpfh, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT |
  96. ENABLE_ECHO_INPUT );
  97. if ( !ReadConsole( (HANDLE)_coninpfh,
  98. (LPVOID)result,
  99. (unsigned char)string[0],
  100. &num_read,
  101. NULL )
  102. )
  103. result = NULL;
  104. if ( result != NULL ) {
  105. /* set length of string and null terminate it */
  106. if (string[num_read] == '\r') {
  107. string[1] = (char)(num_read - 2);
  108. string[num_read] = '\0';
  109. } else if ( (num_read == (ULONG)(unsigned char)string[0]) &&
  110. (string[num_read + 1] == '\r') ) {
  111. /* special case 1 - \r\n straddles the boundary */
  112. string[1] = (char)(num_read -1);
  113. string[1 + num_read] = '\0';
  114. } else if ( (num_read == 1) && (string[2] == '\n') ) {
  115. /* special case 2 - read a single '\n'*/
  116. string[1] = string[2] = '\0';
  117. } else {
  118. string[1] = (char)num_read;
  119. string[2 + num_read] = '\0';
  120. }
  121. }
  122. SetConsoleMode( (HANDLE)_coninpfh, oldstate );
  123. _munlock(_CONIO_LOCK); /* unlock the console */
  124. return result;
  125. }