0

I'm writing a chat in C that can be used in terminal...

For receiving text messages, i have a thread that will print that message out on STDOUT

Another thread is reading from stdin...

The problem is, if a new message is printed to stdout while typing, it will be printed between what i typed.

I researched several hours an experimented with GNU readline to prevent this problem. I thougth the "Redisplay" function will help me here.. but I could not compile my program on Mac OSX if I used certain redisplay functions (it said ld: undefined symbols) whereas other functions worked properly... I compiled this program on an Ubuntu machine and there it worked... i really have no idea why...

Nevertheless, how can achieve that everything that is written to stdout will be above the text i'm currently writing?

  • 1
    Try the [ncurses](http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/index.html) library. – Piotr Praszmo Jun 01 '14 at 15:59
  • Print only from a single thread, perhaps a printer thread. – Kerrek SB Jun 01 '14 at 16:10
  • If you post the errors you received when compiling under OS X, perhaps we could help you solve those? – Bill Lynch Jun 01 '14 at 16:17
  • This happens if i want to use the rl_reset_line_state function... the error also occurs with other redisplay functions except eg. rl_forced_update_display(): `$ make gcc -Wall -pthread -c -o dchat.o dchat.c gcc dchat.o dchat_decoder.o log.o -lreadline -lhistory -o dchat Undefined symbols for architecture x86_64: "_rl_reset_line_state", referenced from: _print_text_message in dchat.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [dchat] Error 1` – user3697084 Jun 01 '14 at 16:39
  • Well printing from a single thread does not solve my problem: since if you type something, it will be printed to stdout immediatly.. – user3697084 Jun 01 '14 at 16:43

2 Answers2

0

You have basically two solutions.

The first is to use something that helps you dividing your screen in different pieces and as @Banthar said ncurses is the standard solution.

The second is to synchronize your writings and readings. The thread that is reading from the network and writing to the console may simply postpone the messages until you entered something from the keyboard, at that time you can simply flush your messages-buffer by writing all the messages at once. Caveat: this solution may cause your buffer to be overflow, you may either forget too old messages or flush the buffer when full.

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
0

If your requirement it to use only stdin and stdout (ie a dumb terminal), you will have to first configure you console input as not line buffered which is the default (stty -icanon on Unix like systems). Unfortunately I could not find a portable way to do that programatically, but you will find more on that in this other question on SO How to avoid press enter with any getchar().

Then, you will have to collate next outgoing message character by character. So when an input message is ready to be delivered in the middle of the writing of an output one, you jump on line, write the output message, (eventually jump one other line or do what is normally done for prompting) and rewrite be input buffer so the user has exactly the characters he allready typed.

You will have to use a kind of mutual exclusion to avoid that the input thread makes any access to the input buffer while the output thread does all that work.

Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252