git subrepo clone https://github.com/libretro/libretro-common.git deps/libretro-common
[pcsx_rearmed.git] / deps / libretro-common / streams / stdin_stream.c
CommitLineData
3719602c
PC
1/* Copyright (C) 2010-2020 The RetroArch team
2 *
3 * ---------------------------------------------------------------------------------------
4 * The following license statement only applies to this file (stdin_stream.c).
5 * ---------------------------------------------------------------------------------------
6 *
7 * Permission is hereby granted, free of charge,
8 * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include <stdio.h>
23#include <stdint.h>
24#include <stddef.h>
25#include <string.h>
26#include <ctype.h>
27
28#ifdef _WIN32
29#ifndef _XBOX
30#include <windows.h>
31#endif
32#include <direct.h>
33#else
34#include <unistd.h>
35#endif
36
37#include <boolean.h>
38#include <retro_environment.h>
39#include <streams/stdin_stream.h>
40
41#if (defined(_WIN32) && defined(_XBOX)) || defined(__WINRT__) || !defined(__PSL1GHT__) && defined(__PS3__)
42size_t read_stdin(char *buf, size_t size)
43{
44 /* Not implemented. */
45 return 0;
46}
47#elif defined(_WIN32)
48size_t read_stdin(char *buf, size_t size)
49{
50 DWORD i;
51 DWORD has_read = 0;
52 DWORD avail = 0;
53 bool echo = false;
54 HANDLE hnd = GetStdHandle(STD_INPUT_HANDLE);
55
56 if (hnd == INVALID_HANDLE_VALUE)
57 return 0;
58
59 /* Check first if we're a pipe
60 * (not console). */
61
62 /* If not a pipe, check if we're running in a console. */
63 if (!PeekNamedPipe(hnd, NULL, 0, NULL, &avail, NULL))
64 {
65 INPUT_RECORD recs[256];
66 bool has_key = false;
67 DWORD mode = 0;
68 DWORD has_read = 0;
69
70 if (!GetConsoleMode(hnd, &mode))
71 return 0;
72
73 if ((mode & (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))
74 && !SetConsoleMode(hnd,
75 mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)))
76 return 0;
77
78 /* Win32, Y U NO SANE NONBLOCK READ!? */
79 if (!PeekConsoleInput(hnd, recs,
80 sizeof(recs) / sizeof(recs[0]), &has_read))
81 return 0;
82
83 for (i = 0; i < has_read; i++)
84 {
85 /* Very crude, but should get the job done. */
86 if (recs[i].EventType == KEY_EVENT &&
87 recs[i].Event.KeyEvent.bKeyDown &&
88 (isgraph(recs[i].Event.KeyEvent.wVirtualKeyCode) ||
89 recs[i].Event.KeyEvent.wVirtualKeyCode == VK_RETURN))
90 {
91 has_key = true;
92 echo = true;
93 avail = size;
94 break;
95 }
96 }
97
98 if (!has_key)
99 {
100 FlushConsoleInputBuffer(hnd);
101 return 0;
102 }
103 }
104
105 if (!avail)
106 return 0;
107
108 if (avail > size)
109 avail = size;
110
111 if (!ReadFile(hnd, buf, avail, &has_read, NULL))
112 return 0;
113
114 for (i = 0; i < has_read; i++)
115 if (buf[i] == '\r')
116 buf[i] = '\n';
117
118 /* Console won't echo for us while in non-line mode,
119 * so do it manually ... */
120 if (echo)
121 {
122 HANDLE hnd_out = GetStdHandle(STD_OUTPUT_HANDLE);
123 if (hnd_out != INVALID_HANDLE_VALUE)
124 {
125 DWORD has_written;
126 WriteConsole(hnd_out, buf, has_read, &has_written, NULL);
127 }
128 }
129
130 return has_read;
131}
132#else
133size_t read_stdin(char *buf, size_t size)
134{
135 size_t has_read = 0;
136
137 while (size)
138 {
139 ssize_t ret = read(STDIN_FILENO, buf, size);
140
141 if (ret <= 0)
142 break;
143
144 buf += ret;
145 has_read += ret;
146 size -= ret;
147 }
148
149 return has_read;
150}
151#endif