I want to make a more dynamic interface rather than print out a whole new page every time but do not know how to implement it. For example, if we have a download bar that goes from 0% to 100%, I want to change the number directly on the terminal instead of printing out 100 lines with 1%, 2%, 3%. What should I do with it?
The simpler choice, if you want to keep it on a single line, would be to use \r.
Printing \r will move your cursor to the beginning of the line, giving you the ability to print hover the old characters.
A solution would look something like
for (i = 0; i < 100; ++i)
{
printf("\r%3i%%", i);
fflush(stdout);
/* ... */
}
If you need more advanced control over the terminal, you can use termcaps.
You could print a \r character, which is called the 'carriage-return' and should in most cases return the cursor to the beginning of the line so you can print over the text that's already there. I say should because it's not guaranteed and it depends on the shell the program is running in. If you want to do more exotic stuff you should look into ncurses.
You should use a cross-platform terminal access library, such as libncurses.
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 have to write a self-refreshing progress bar to the terminal - that denotes how much of a file has been copied so far. I tend to refresh the output every 1000 bytes or so. To refresh the screen, I have used the following outline:
printf("\r"); // clear previous output
// output is the progress bar, percent is an integer (0 to 100)
printf("%s %d file written", output, percent);
It works fine when the terminal is large. However, when the terminal is small, such that the entirety of the progress bar doesn't fit into it, the carriage return doesn't work. It only clears the visual single line, not the entire line. I wrote a sample program to demonstrate:
printf(
"abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"
"abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghi"
"j");
printf("\rCHECK");
As you can see in the below image, since the terminal is small, only some part of the entire print output is deleted.
Putting multiple carriage returns has no effect.
Then, what is a good way to build such a continuously refreshing terminal output in C?
I also tried clear screen (printf("\033[2J");) but it didn't work for me. It tends to insert arbitrary number of whitespaces at the beginning of the output, see image for example:
Generally, the only way to tell if your message has wrapped to the next line of the terminal is to compare it to the terminal width (number of columns). You can get that info by using terminfo(3)
#include <term.h>
int main() {
setupterm(0, 1, 0); /* default terminal setup from the TERM envvar */
Now you can access the global var columns to know how many columns there are on the terminal. You can also use putp(tigetstr("cuu1")); to go up one line on the terminal. So you can keep track of how long your status message is and figure out how far up you need to go to get back to the beginning of it.
would like to get some help on a c project i am currently working on. I have a string/array of output to the terminal, but somehow the standard terminal is too small for my output. Even after i manually expand the window of the console the output is still cut off, instead of printing in a single line, it just gets cut off and go to the next row automatically.
hope to get help.
I think that the only way to correct this is by splitting your one-line output in multiple lines, using "\n" at the end of every line.
By doing this you can control when and where it has to write in the next line, and you can make it look more like you wanted to.
Is it possible,somehow,to return to the beginning of the page, not line, page.
Using something like "hello\r" would,obviously, write "hello" and return to the start of the line.
But what about when I am on a second line?
So after "hello\n" it would put me on a second line.
Can I somehow return back to the 1st line.
From the research I have conducted it seems that you can only operate on 1 line, but I am not 100% sure and thus would like someone to confirm this.
Programming in C and using RealTerm.
RealTerm has an ANSI terminal emulation mode.
Find the "Display Formatting " configuration dialog and select the Ansi option.
Now you can embed an escape sequence for Cursor Home much like you embed the newline.
<ESC>[H
Where, of course, <ESC> means the single character 0x1b. You can implement it like this
sprintf(buffer, "%c[Hmy text\n", 27);
transmit(buffer);
or similar.
If for the following code:
printf("HEllo\n"); // do not change this line.
printf("\b\bworld");
I need an output: Helloworld (In a single line). But this does not work fine. Could anyone please explain the reason? And other escape sequence if any.
There is no platform-independent control character to move back up a line. This harkens back to the days of line printers, where printf actually would print a line of text onto a sheet of paper and there was no way of retracting the paper to overwrite what had already been printed.
That said, there are libraries like ncurses that let you move the cursor around the console. They're just not part of the standard libraries.
How about simply:
printf("Helloworld");
\n is an escape sequence for a new line. Since you want everything to appear on the same line, there's no reason to specify \n.
The problem is you can't reliably move back up a line (using \b) after you've printed a new line. But if you require that there be two lines of code in your source, you can simply omit both escape sequences:
printf("HEllo");
printf("world");
If you're writing a Win32 console application, you can take advantage of the Console Screen Buffer API. The following code will move 1 line up:
printf("HEllo\n");
CONSOLE_SCREEN_BUFFER_INFO coninfo;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &coninfo);
coninfo.dwCursorPosition.Y -= 1; // move up one line
coninfo.dwCursorPosition.X += 5; // move to the right the length of the word
SetConsoleCursorPosition(hConsole, coninfo.dwCursorPosition);
printf("world");
Output:
HElloworld
Remove "\n" from your first printf. It moves the cursor to a new line.
Here is the list of escape sequences.
If you can't remove "\n", then you can do make a copy of a substring without these charaters. See the following example:
const char* from = "12345678";
char *to = (char*) malloc(6);
strncpy(to, from+2, 5);
All you need is to determine the index of "\n" characters.
The backspace character, when sent to a stream (such as through the printf() family of functions), does not seek backward in the file, it is sent as-is. If you run your example, the backspace character will be output as "garbage".
If you don't want a new line, don't post a newline character.
It is because '\b' is a terminal escape code... (sans the 'escape' of course ;-)
so it only modifies what you see on the terminal. That is, the terminal adjusts its display to respond to the backspace code, even though it received everything prior to it. A file also receives everything, including the backspace code, but it is not a tty device so the file's content is not modified; it keeps everything you send to it.
If printing an extra blank is a problem, then you should code some extra logic to print the trailing blank on every output except the last.
Reference This is in reference to files but maybe same idea applies. You might want to check out this link there is a very detailed explanation that most probably answers your question.
In a console, you can't go up a line. You can clear the screen and redraw it (which simulate going up a line.) Or you can rewrite on the same line. \r will take you to the beginning of the line you just printed.
You can do it actually in a platform-independent* way, assuming that you can somehow calculate the x offset of the previous line.
int x = printf("Hello, World!\n");
gotoxy(x-1-1,gety()-1); // One for the length-offset difference and the other to skip \n
printf("\b \b");
You can avoid using that variable by directly replacing it with x.
Note: printf() returns an int (the length of the passed String (of characters)). Use it wisely :)