For my situation, say Tim and Bob are chatting using my C chat client and server. My chat client and server is executed on a bash terminal. The cursor for this chat program is the ~ key.
Tim sends Bob a message that says, "Hey". Now say that Bob receives this message as he's typing a message to Tim. Bob wants to send "Hello" to Tim, but he hasn't finished writing it yet (so he's only written "Hel" so far).
I would like my application to be able to keep Bob's prompt and his entry so far at the bottom of the terminal, and display Tim's message above the prompt. Bob should still be able to finish his message to Tim, as well as being able to see Tim's message. Below is a diagram of what I mean, from the view of Bob's client. Is there any way of accomplishing something like this using C?
........................Before............................................................................................After...............................
............................... .................................
............................... <Tim> Hey
Enter Message> Hel~ Enter Message> Hel~
If you know that you're using an ANSI compatible terminal AND know your prompt length AND cursor position (assuming you allow editing of input so that the cursor may not be at the end of the current input) AND don't allow more than one line of input [ a lot of assumptions there ] then it would seem you can output one or more 'cursor up' sequences then a carriage return, your message from Tim, a carriage return, a linefeed and then lots of 'cursor right' sequences to put the cursor back where it was.
Basically, though, if you want to handle this sort of complication then you're going to head to a curses/ncurses/terminfo kind of library.
Related
I am trying to code a little console chat-program in C on linux.
So far I coded it in a way that both chatting partners are only able to alternately send/recv, because these function calls are blocking by default.
Now I would like to modify that program, so that both are able to send and receive simultaneously.
The problem that I find is, that once you typed some input to the terminal, I don't know how to output received messages, without messing up the current input line of the terminal.
If there was a way to delete that current input line, you could temporarily save that line, print the new message and put the input line right back.
However, I was not able to find a solution for this problem on the internet.
Is it possible to delete the current input line, and if not, how else could I achieve what I want?
I think you should look into ncurses as Edd said in his comment.
It would allow you to easily manage contents in your terminal window, which sounds like a good idea for your chat program.
All you'd need to do is store your messages in 2 character arrays:
char incoming[MSG_MAX]
and
char outgoing[MSG_MAX]
Then you can output those messages wherever you want in your terminal window, since ncurses allows you to specify x,y coordinates on where to put your text.
Then a simple wrapper for one of ncurses erase() family functions would allow you to delete characters from specify x,y coordinates in your terminal window.
Edit: MSG_MAX is not an actual ncurses macro.
I'm writing a C program that requires to hide the characters a user types from the screen during the program execution. For example, when running the following loop
while (1)
{
//do some work
}
the console displays the blinking cursor (that's good). BUT, when the user types keys on the keyboard, these keys are being echoed out to the console. To visualize it better:
Step 1: Starting the program
root#debian:/home/root# ./program
_
Step 2: User types some characters (even though he shouldn't)
root#debian:/home/root# ./program
AdajfsaSJ_
The characters get echoed on the console. How can I stop this? I know it's theoretically possible, but I can't find out how to implement it.
If you need a better example for what I want to achieve, use the screen command on an empty serial port. screen /dev/tty30 for example. This empties the console and runs the program, HOWEVER, the user is not able to enter any characters (there's a blinking white cursor block and no keyboard characters are being echoed to the console). That's what I need.
Any insight would help, thanks!
Use termios() to turn off the ECHO flag of the terminal.
To turn off the text cursor, use the termcap library to control the cursor visibility.
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!
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.
My embedded system has one background program which generates some output message to console.
When it's not finished, the login program starts and prompt login string to same console as well.
My question is, when the login prompt string comes out, the output message generated by the background program is not aligned like this:
Embedded System login: msg_line1...
msg_line2...
msg_line3...
The expected output should be:
Embedded System login: msg_line1...
msg_line2...
msg_line3...
msg_line4...
Have no idea how to resolve the problem...
Could anyone help?
THX!!
Configure your terminal program to autolinefeed, so that it generates the \r internally whenever it receives a \n.
use a redirection for your background program
YourBackStuff.sh >/tmp/back_out.1 2>/tmp/Back_out.2 &
or refresh the screen.
Notice that only the appearance is modified, the real output ou current application/shell (so not the background one) is correct, only the terminal show your all the info received. So
YourFrontApp.sh | tee /tmp/front_out.1
cat /tmp/front_out.1
will produce a correct display (when background process stop)
Looks to me like your messages are sent with a new-line character (represented by \n in C) at the end of each line. This requests a new line from the terminal, which it duly provides. It does not request a carriage return (i.e. "go back to the left hand edge"). This would be represented in C as a \r.
To fix it, you need to set your terminal application to interpret \n as \n\r - it will have a setting for "treat newlines as newline+CR" or some such.
I'm trying to write a chat client and server and the client should be able to print the messeges from the server while also writing something on the console.
So I created a pthread that should read the user input and the main thread prints the messeges from the server. But when I type something and while typing a messege is received, the text I was typing is pushed up on the console. How can i fix that?
for example:
I'm typing "abcdef" and then when I get a messege from the server (but didn't finish typing yet) it will look like this:
abcdef[Chatuser1]:Hello
Use synchronization technique like semaphore or mutex to synchronize input and output in your multi threaded program
I would really recommend doing something like this in a GUI with two seperate edit box elements and not in a console.
If you still want to do it in a console, you will need to do direct console buffer modification.
Every time a new output message arrives, the current input message has to be backed up so you can savely write to the console then do some custom scrolling and add the input message back again. Thread syncronisation is needed to prevent mixing of input and output in the buffer.
I think you also would not get around custom key handling, because otherwise you have no access to partialy typed input.