Echo characters in istream to an unusual "device" - c++

I want to make a version of cin that works in a graphics display window (it's SDL, but I don't think that matters here): that is, when you type, the characters echo into that window rather than the console window. The solution should be cross-platform.
I have this page to tell me how to get characters NOT to echo to the console window: Reading a password from std::cin
...but what I don't know how to do is to make the characters echo on the new graphics display window.
One thing I could do is intercept keyboard events, and if one happens, print the character. But this wouldn't perfectly echo the actual behavior of the istream buffer, because of repeating keys, backspace, enter, tab, and also the real behavior of cin in that if you are typing before C++ gets to the cin, it will put that stuff you typed on the screen at that point.
I think this echoing is done inside the call to _read (read in the Unix world), and that I'm not sure how to access.
TIA.

The behaviors you're talking about are not done by cin nor read() syscall; buffering and processing of special character is done by the terminal emulator and the shell.
You do need to intercept key events and implement these yourself. Alternatively, some terminal emulators (e.g. VTE widget in Gnome) were designed so they can be embedded into another program. You might want to look at that option.

Considering your application is running in a window you shouldn't read input from the console . It's probably possible but you'll have to switch to the terminal window from where you started the window each time you want to input text. If you take this route you need to disable tty echo: http://man7.org/tlpi/code/online/dist/tty/no_echo.c.html (for Linux). Check out http://www.cplusplus.com/forum/general/12256/ for some solutions for Windows too. I don't think there is a solution that works for both so you'll need to bury some #ifdef's in some utility functions.
Since you're using SDL you should probably use SDL's input functions.
Check out http://www.libsdl.org/docs/html/guideinputkeyboard.html
And, more specific to your needs: http://wiki.libsdl.org/moin.fcg/Tutorials/TextInput

Related

Masking the user input as asterisks in Windows?

I need to create a simple password program where the program asks user to input password and when user inputs, it shows the characters as asterisks.
Every tutorial out there uses getch() (in conio.h). But I don't want to use it. Is there any easy alternative for doing so?
I'm using Windows 10.
P.S: Please don't confuse this to be a duplicate of this question: Alternative function in iostream.h for getch() of conio.h?
Because that question asks for holding screen output whereas I need to mask the input as asterisks.
We are here in non standard functionality. So, whatever you'll do, it will not be portable.
The native console way would be to ReadConsoleInput() as explained here. In your case, you would first disable the echo and the line input mode by clearing the console mode flags ENABLE_LINE_INPUT and ENABLE_ECHO_INPUT. Then you would react on key events by displaying '*'. Don't forget to restore the inital console mode at the end.
A shortcut would be to just save and change the console mode (as shown in the code above), an then looping for cin.get() and echoing cout<<'*'; followed by cout.flush(); to be sure that the output doesn't wait in a buffer, creating discomfort for the user.

Prevent mixing of console output and written text

I have a C++ console application that prints some output constantly while it also accepts commands (using std::cin) from the user - output and input happen in separate threads.
If I write a text while some output appears the written text is mixed with application output. How can I prevent this behaviour?
To solve this problem, I need to display the program one line above the line where the text is typed. I'd inspire myself in Minecraft Bukkit server's solution - however I need the same for C++.
Assuming you want the output to appear while things are being typed, you'll need some screen control facilities to have the output go somewhere different than the input area. If I were tasked to implement something like this writing to a terminal I would refresh my ncurses experience. I realize you are on a Windows console and I have no idea if the Windows console is capable of the screen control needed to make it happen.
You can possibly tie custom stream buffers into std::cin and std::cout using the curses functionality under the hood but it may not be worth it. In any case, it isn't entirely trivial.
There's a windows port of ncurses called pdcurses. But if you are using visual studio there's a simple function provided called SetConsoleCursorPosition()

Detect keypress in console application?

I need to detect a keypress in a console application, without prompting the user. Basically, my app is normally a daemon that listens to a special input device, but i need to simulate it on a dev box using the keyboard in interactive mode. How can I do this? - Im on a Linux system.
If you can't block while waiting for input, then you can use e.g. select to check if the STDIN_FILENO file descriptor is ready for reading, and if it is then you can use normal input functions (scanf, fgets std::getline, etc.).
You check this answer which explains how to read from the input events ( usually /dev/input/event0)
Or directly check the answer's source :
Credits do not go to me, this code is taken from the Ventriloctrl hack to get keystrokes.
http://public.callutheran.edu/~abarker/ventriloctrl-0.4.tar.gz
This text explaines hw to do such a thing. http://thc.org/papers/writing-linux-kernel-keylogger.txt

Linux - Discard keyboard input

First, a bit of background: I'm running the latest stable build of Crunchbang Linux inside a VirtualBox VM. I'm designing a custom text-based user interface to run on top of bash. This is being done with a combination of C++ and bash scripts.
I need to, at times, completely and totally remove the ability for the user to provide the system with any sort of standard keyboard input. This is because, when I run a part of the system, the user is forced to wait for certain amounts of time.
Unfortunately, the user can still type while this is going on, and whatever they type is put on the screen. This happens when I'm running a C++ program as well as a bash script. The reason this is a problem is that there is text on the screen which the user is to read, and if they can type, it displaces the text. There will be other uses for this later, as well, like making the system seem like it has frozen up.
So, the question - How do I
disable the keyboard, or
prevent anything pressed on the keyboard from showing up on the screen?
Turn off echo mode with stty -echo or the equivalent C code (which would use tcgetattr and tcsetattr). When you are ready to accept input again, turn it back on. You may also wish to discard the input that arrived while you weren't expecting it. That would be done with tcflush but be aware that some users (like me) would consider that an annoyance. Typeahead is a feature, not a bug!
To see how user input to a certain process or tty can be intercepted, the man page and source code of interceptty may be enlightening. (have no experience with it)
However, you can hardly (totally) prevent user input. The user is probably always able to switch to a different virtual terminal (if any) or at least to reboot the system with Alt+Print+B (Magic SysRq_key) if not disabled. It is two different things to ignore input on a given tty and disabling keyboard input altogether.

Make a 'press any key' routine that is compatible with redirected standard input

I've got a C/C++ program that runs in a console window, and prompts the user to press any key to continue, or 'q' to quit. It currently uses _kbhit() to detect if a key has been pressed, and then uses _getch() to determine what character it was.
Now I want to be able to automate this program (from a C# app using a Process with RedirectStandardInput and CreateNoWindow set). Obviously I can no longer rely on _kbhit() as it uses ReadConsoleInput(), which fails when launched using my C# app. In my C# app I use process.StandardInput.Write("A") to push something onto the stream in an attempt to get my console app to continue.
In the console app I have used SetConsoleMode() to clear the ENABLE_LINE_INPUT flag so that I can use getchar() to return as soon as a character is pressed, and this works reasonably well (when I press a character key in the console window as well as when the call is made from the c# app). However, it has flaws in that it now only accepts characters keys (i.e. no F, Alt, Shift keys etc.) which isn't too big a problem, but moreso I seem to have to press return twice (and this is a key that lots of people will likely choose to press in the 'any key' situation).
Does anyone know how I can make the console app respond to a key (any a bonus, charcters and return only is acceptable) pressed ONCE, whilst still responding to a single character pushed onto the stream from my C# app?
Something I did notice, calling system("PAUSE") gives the exact behaviour I want, other than knowing what key was pressed so that I can quit on 'q'. I don't know how PAUSE does it though, and it doesn't let me use my custom message either :(.
I'm sure there's a really obvious solution, but it has been driving me mad. Any thoughts are much appreciated!
There are two issues with the resolutions:
Neither the C or C++ languages have
portable functions for waiting for a
keyboard key to be hit. It's an
operating system (platform) issue.*
C and C++ have different methods for
resolving I/O. Choose your
language, C or C++.
In my C++ console applications, I ask the user to "Press Enter to Continue" and use the ignore method of cin:
void Pause(void)
{
std::cout << "Press ENTER to continue.\n";
std::cout.flush(); // Insurance, make sure the text is displayed.
std::cin.ignore(100000, '\n'); // Ignore characters until an ENTER (newline) is received.
return;
}
I suggest you create a single file with the Pause function. You can write different versions for different platforms and let the build system select the correct file.
Not all platforms that run C or C++ are required to have keyboards. Many embedded systems don't have keyboards. Also, many windowing systems receive messages, events or signals when a key is pressed. Again, something different and not standard.
Here is a very good implementation for C++. Be sure to read over the entire tutorial, as I it may initially appear that it doesn't help you.
http://www.daniweb.com/forums/thread90228.html
Use cin.get(). This returns the appropriate key.
Thank you for all your responses, I've learned a lot about handling input!
However, I couldn't get anything to work exactly how I wanted, so I had to abandon the unified approach and put in a check to see if it was running in a window. If it is, I stick with _kbhit(), and if not I use PeekNamedPipe(), which gives me the number of characters sent from my C# app without transfering them into the stdin buffer. There's still a few issues that I have to work out to do with clearing any data that I don't want from the pipe, but it's solved my initial problem.
Thanks again for all the suggestions, they will undoubtably come in handy next time I have an input nightmare :)