ASCII user interface in C++ w/ Unix PuTTY terminal using escape sequences - c++

I'm trying to make a simple ASCII user interface for a simple internet chat program. I'm planning it to look like this:
(name): message
(name): message
---------------------------------------------
(you): message |(cursor)
I was going to use ASCII (ANSI?) control characters to accomplish this.
Whenever the chat client receives a message from the server, it should update so that the message appears as the first message above the dash-line, then return the cursor to its previous position so the user can continue typing where they left off.
My initial plan was:
1. save the current cursor position (\e7)
2. move the cursor up 1 line (to the dash-line) and to the beginning of that line (\e[1F])
3. move the dash line down (\n)
4. move the cursor up one line again (to the now empty line) (\e[1A)
5. print the message from the server
6. restore previous cursor position (\e8)
all together: "\e7\e[1F\n\e[1A" << message << "\e8";
Where I'm having trouble is that the newline character seems only to move the cursor to the next line, and not actually insert a blank line. How can I accomplish this behavior?
This is for a homework assignment, but this is just an extra bit of flair i wanted to add on for myself. The actual assignment is already completed.
note: algorithm for handling user's input on their own screen is handled correctly already.

Look into something like pdcurses. It's cross platform. That will make all of those manipulations a lot easier. You can also check into curses on *nix and the ancient conio library on Windows if you don't mind your code not being portable.

If you are using bash, you can do it with special commands using characters escapes.
See http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html

Seriously consider using a curses library (see Wikipedia for more information).

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.

How to manipulate the terminal output buffer directly

I want to write a game in Linux terminal(In C/C++), so firstly I should be able to print the character I want to it. I tried with "printf()", but it seems a little inconvenient. I think there should be a character buffer for the output characters for a terminal. Is there any way to directly manipulate the buffer?
Thanks a lot.
It goes in a way different manner.
A terminal is nothing else, but a character device, which means it is practically unbuffered. Despite of this, you still can manipulate the screen position with appropriate sequences of characters, called "escape sequences". For example, if you issue the \e[A (0x1B 0x91 0x41) sequence, the cursor goes one line up while leaving the characters intact, while if you issue \e[10;10H, (0x1B 0x91 0x31 0x30 0x3B 0x31 0x30 0x48), your cursor will go to column 10 of row 10 (exactly what you want). After you moved the cursor, the next character you write out goes to that position. For further information on escape sequences, look at this link.
Another important thing to know about is the dimensions of your terminal. ioctl can inform you about the size of the terminal window:
#include <stdio.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
int main ()
{
struct winsize ws;
ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws);
printf ("Rows: %d, Cols: %d\n", ws.ws_row, ws.ws_col);
return 0;
}
Note that the technique mentioned above is a solution to send commands to the terminal emulator connected to your pseudo terminal device. That is, the terminal device itself remains unbuffered, the commands are interpreted by the terminal emulator.
You might want to use the setbuf function, which allows you tell printf which buffer to be used. You can use your own buffer and control the contents.
However, this is the wrong approach for 2 reasons.
1st, it won't save you work compared to printf(), fwrite() and putchar().
2nd, and more important, even these functions won't help you. From your comment it's clear that you want to manipulate a character on the screen, for example, replace a '.' (empty floor) by a D (Dragon) when that Dragon approaches. You can't do this by manipulating the output buffer of printf(). Once the '.' is displayed, the output buffer has been flushed to the terminal, and if you manipulate that buffer, it has no effect. The terminal has received a copy of that buffer, and has displayed what the data in the buffer instructed it to display. In order to change what is displayed, you have to send new commands.
And this is exactly what ncurses does for you. It keeps track of the state of the terminal, the current content, the curser position and all the nasty details, like, how to make a character appear bold.
You won't succeed with printf. That's hopeless. You need to learn what ncurses can do for you, and then everything else is easy.
TLDR: use ncurses
This answer focuses on the why?
Why?
There probably is a way to modify the buffer used by the terminal emulator on your system, given that you have sufficient priviledges to write into respective memory and maybe even modify other system resources, as required.
As terminals historically have been distinct, isolated, physical devices rather than beeing conceptually emulated in software, you couldn't access them in any way other than sending them data.
(I mean, you could always print a message locally, to instruct a human to take a screwdriver and physically mess around with the physical terminal device, but that's not been the way how humans wanted to solve the contemporary issue of "how do I change the cursor position and rewrite characters on my (and potentially any other connected) terminal?").
As others have pointed out, most physical terminals have (at some point) been built to give special meaning to certain input sequences, instead of printing them, which makes them escape sequences in this context, according to how wikipedia.org defines them, that is.
A behavioral convention in how to respond to certain input sequences emerged (presumably for the sake of interoperability or for reasons of market predominance)and got standardized as ANSI escape codes.
Those input sequences survived the transition from physical termial devices to their emulated counterparts and even though you could probably manipulate the terminal emulator's memory using system calls, libraries such as ncurses allow you to easily make use of said ANSI escape codes in your console application.
Also, using such libraries is the obvious solution to make your application work remotely:
Yes, technically, you could ssh into another system (or get access in any other more obscure way that works for you),and cause system calls or any other event that would interfere with the terminal emulator in the desired way.
Firstly, I doubt most users would want to grant you priviledge to modify their terminal emulator's memory merely to enjoy your text adventure.
Also, interoperability would reduce, as you couldn't easily support that one user, who still has a VT100 and insists on using it to play your game.

Async Console Output

I have a problem with my application win32 console.
The console is used to give commands to my application. However, at the same time it is used to output log messages which mostly comes from asynchronous threads. This becomes a problem when the user tries to write some input and simultaneously an async log message is printed, thus thrashing the display of the users input.
I would like to have some advice in regards to how to handle such a situtation?
Is it possible for example to dedicate the last line in the console to input, similarly to how it looks in the in-game consoles for some games?
You can use SetConsoleMode to disable input echo and line editing mode. You can then echo back input whenever your program is ready to do so. Note that this means you will need to implement things like backspace manually. And don't forget to reset the mode back when you're done with the console!
This is possible using the Console API, but it involves quite a bit of work and all the threads that use the console will have to cooperate by calling your output method rather than directly calling the Console API functions or the runtime library output functions.
The basic idea is to have your common output function write to the console screen buffer, and scroll the buffer in code rather than letting the text flow onto the last line and scroll automatically. As I recall, you'll have to parse the output for newlines and other control characters, and handle them correctly.
You might be able to get away with using "cooked" console input on the last line, although in doing so you risk problems if the user enters more text than will fit on a single line. Also, the user hitting Enter at the end of the line might cause it to scroll up. Probably best in this situation to use raw console input.
You'll want to become very familiar with Windows consoles.
Any time you have asyncronous threads trying to update the same device at once, you are going to have issues like this unless something synchronizes them.
If you have access to everyone's source code, the thing to do would probably be to create some kind of sync object that every task must use to access the console (semaphore, etc).

Update and multiple console windows

I want to write a simple c++/c console app, to show my process 1% 2%.
for now, i print it line by line like
finished 1%
finished 2%
and etc
How can I just update percentage x% without printing a new line?
Also, I want to open two console windows one show messages one show the process as above. How do I open another console window?
On most-all terminals, you can print the ASCII carriage return '\r' (value 13 decimal) to return the cursor to the left of the current line, allowing you to overwrite the previous value. Or, you can send backspaces ('\b', ASCII 8) to move a single character left. Neither will automatically remove content already displayed, but you can always overwrite anything you no longer want to see with some spaces. Alternatively, you can use control codes supported by your particular console (e.g. vt100, vt220...), which will probably have more advanced features such as "clear-to-end-of-line". Many libraries are available to detect the terminal type and use codes it supports, or synthesize advanced operations from many simpler ones where necessary: on Linux and UNIX, the ncurses library is a good choice.
C++ has no concept of console windows. Opening a second window depends a lot on the operating system you're using, and perhaps the graphics library, neither of which you specified. On any OS though, you can have your application write some messages into a file, then inspect that file from another window that you open yourself. On Linux/UNIX, the utility "less" is great for inspecting log files - as well as showing you the contents at the time you ran less, you can ask it to "follow" new data as it is written into the file.
On windows you can move the cursor to any location on the screen, then start printing from there:
COORD c;
c.X = x; c.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
Of course, you need to include windows.h
You can update your progress message in several ways. You can print out backspace characters to move the cursor to the left and then write over the old output. If your console supports ANSI escape sequences, you can use an escape sequence to blank out the line and re-draw it.
The best technique to use will probably depend on the console you are using (different consoles support different things). What platform are you using, and what console?
It seems that you're talking about Windows console apps.
Each Windows process is associated with at most one console window.
It you want two console windows then you can start another process and pipe output to it, or communicate with it via sockets or Windows "mailslots" or whatever.

How can I overwrite the same portion of the console in a Windows native C++ console app, without using a 3rd Party library?

I have a console app that needs to display the state of items, but rather than having text scroll by like mad I'd rather see the current status keep showing up on the same lines. For the sake of example:
Running... nn% complete
Buffer size: bbbb bytes
should be the output, where 'nn' is the current percentage complete, and 'bbbb' is a buffer size, updated periodically on the same lines of the console.
The first approach I took simply printed the correct number of backspaces to the console before printing the new state, but this has an obnoxious flicker that I want to get rid of. I also want to stick to either standard library or MS-provided functionality (VC 8) so as not to introduce another dependency for this one simple need.
You can use SetConsoleCursorPosition. You'll need to call GetStdHandle to get a handle to the output buffer.
Joseph, JP, and CodingTheWheel all provided valuable help.
For my simple case, the most straight-forward approach seemed to be based on CodingTheWheel's answer:
// before entering update loop
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
GetConsoleScreenBufferInfo(h, &bufferInfo);
// update loop
while (updating)
{
// reset the cursor position to where it was each time
SetConsoleCursorPosition(h, bufferInfo.dwCursorPosition);
//...
// insert combinations of sprintf, printf, etc. here
//...
}
For more complicated problems, the full console API as provided by JP's answer, in coordination with the examples provided via the link from Joseph's answer may prove useful, but I found the work necessary to use CHAR_INFO too tedious for such a simple app.
If you print using \r and don't use a function that will generate a newline or add \n to the end, the cursor will go back to the beginning of the line and just print over the next thing you put up. Generating the complete string before printing might reduce flicker as well.
UPDATE: The question has been changed to 2 lines of output instead of 1 which makes my answer no longer complete. A more complicated approach is likely necessary. JP has the right idea with the Console API. I believe the following site details many of the things you will need to accomplish your goal. The site also mentions that the key to reducing flicker is to render everything offscreen before displaying it. This is true whenever you are displaying anything on the screen whether it is text or graphics (2D or 3D).
http://www.benryves.com/tutorials/?t=winconsole
In case the Joseph's suggestion does not give you enough flexibility, have a look at the Console API: http://msdn.microsoft.com/en-us/library/ms682073(VS.85).aspx.
In Linux, you can accomplish this by printing \b and/or \r to stderr. You might need to experiment to find the right combination of things in Windows.