Termio
Termio

Reputation: 31

Reprinting input to terminal in C

i am writing a terminal chat and would like to reprint the content the user has typed in, if a new message from another user has arrived asynchronously.

if a new message arrives i print "\x1B[2K" to stdout (ANSI ESCAPE CODE for erasing the current line) to clear the current line, then i print "\r" to move the cursor to the leftmost position, then i print the received message with a newline

now i would like to reprint the characters the user has typed - i found out that there is a special character VREPRINT (http://www.gnu.org/software/libc/manual/html_node/Editing-Characters.html) that can be used and if a hit CTRL-R it actually works... but if print the character to stdout using the character placed in c_cc[VREPRINT] of a struct termios, it does not work - is it even possible to do it that way?

I do not want to use any other libraries like readline or ncurses, since this would be plain overkill... i just would like to make my solution work using ICANON terminal mode if possible

Thanks in advance!

Upvotes: 3

Views: 335

Answers (1)

aks
aks

Reputation: 2348

While it is possible to write to the same tty device that you are reading from, this doesn't mean that the characters that appear will be processed as input characters.

You can test this yourself, using two separate shell sessions (using screen, tmux, or, if you are on MacOSX, iTERM.app sessions).

in Session 1, get the current tty name:

tty

Let's assume the tty name of Session 1 is /dev/ttys000.

Then enter the following, without a return or newline -- just leave it pending:

echo abc def-

In Session 2 (using the tty name from Session 1), enter the following command:

echo foo >/dev/ttys000

The string foo should appear on the pending line in Session 1, like this:

echo abc def-foo

Now, go back to Session 1, and hit an "enter" (or return), causing the input buffer to be completed and sent to the shell, which will parse the first word as the echo command, with the subsequent arguments as text to be printed.

You should see the string "abc def-" echoed -- but not the foo.

This test makes it clear that the string foo was never placed into the input buffer, even though it was sent to the same tty being used for input (and output).

You can try to see if special control characters are recognized and processed; but they won't be. These characters are only being output to the terminal, but not processed.

In order for the special characters to be processed, they have to be received via the socket connected to the input device.


To accomplish what you are trying to do, you'll have to go non-canonical (stty -icanon) and process every character in your code, in order to collect the pending input and also be able to produce asynchronous output.

Alternatively, using nurses is not hard at all, and if you are writing a terminal-based chat program, I would suggest creating at least two panels: a "chat" panel for all output, and an "input" panel for user input. This allows output from other users, as well as the completed commands from the "input" panel, to be received and written to the "chat" panel asynchronously without disturbing the current command in progress by the user in the "input" panel.

Upvotes: 1

Related Questions