Isolating stdin and stdout within a terminal - c

I'm developing a CLI program, in C, for my systems class project, and it needs to display incoming text while maintaining a command prompt. Left alone, the incoming text will saw through whatever one tries to type. In other applications I've seen the incoming text print above(or below) the prompt itself. Is there any way to implement this in ANSI escapes? ncurses seems like overkill.

You can print \r to erase the prompt: It will return the cursor to the beginning of the current line. You can then print your output followed by some spaces to clear out any remaining input characters, newline, and reprint the prompt.
With ANSI sequences or terminal-specific libraries you can do even more, but this I think is all you can do reliably using only ASCII. Apart from printing 242 blank lines to redraw the whole screen, of course.
Edit: Sorry, I didn't answer the ANSI part properly. With cursor movement control codes and printing space over existing characters, you can pretty much do anything, and there are some convenience actions to help you, such as "delete line". But keep in mind that Windows doesn't play nice w/ ANSI post XP, and neither are other systems guaranteed to.

For one thing, if you want to maintain a prompt, while printing, you can not use things like scanf. You have to intercept keyboard events or use a non waiting method to get input. Then you can get the terminal number of lines (n) and print the last n-1 lines of your output, and then a prompt.
my2c

Related

How can I specify the color of particular characters in a String in c?

I am experimenting with colorized text output to the console in c. I know that you are able to change the color of entire printf statements, but I was wondering if I am able to change the text color of individual characters within a printf statement.
In summary, I would like to be able to print out "asdf" with the a being red, the s being green, the d being blue, and the f being orange.
Thank you in advance.
First of all, in C, characters has no color. They are just numbers. So your question is not at all related to C, which doesn't care at all about how your print things.
What you are referring to, is the fact that some terminals accept some control characters to specific how they should render what is sent to them.
Those are just special characters, that are not meant to be printed, but to modify the terminal behavior. There is no guarantee that your terminal understand those control characters. Nor is there any guarantee that they are the same control characters as other terminals.
Some library (such as ncurses) exist that have knowledge on the terminal you are using, and provide helper functions that make this transparent.
All that being said, the way to print in red (well, the most common one, at least) is
printf("\033[31m");
That switch the terminal to red
and
printf("\033[m");
That switches is back to normal.
Those are control characters. So, from C point of view, just characters like any other, to be printed, that is sent to the terminal. It is then up to the terminal to do whatever it sees fit with it.
Being just characters like other, nothing prevent you to mix them with any normal characters,
So your example
printf("\033[31ma\033[32ms\033[34md\033[33mf\033[m\n");
But there is no guarantee it works. You can't really count on it. There is even no guarantee that it won't print some unwanted chars.
I have found a temporary workaround: using multiple printf statements since they do not go to the next line, I do not like this solution very much.

how print in c without jumping to end of text?

I'm very new to coding in general so please excuse any stupid things I say.
I am trying to print (in c) a rather long text using printf() but since it can't all fit on the screen it jumps to the end of the text and the beginning is not visible unless you scroll up. Is there an easy way to have it print the long text but stay at the beginning and allow the user to scroll down as they read before they put in the next command?
On Unix (including Linux and Mac), there are command line programs built in called more and less that does exactly what you describe. more is a program that simply waits for the user to press enter or space before showing the next page of output. less is slightly improved in that it allows vi editor keystrokes (such as j and k) to scroll up and down in the output.
more is also available on the Windows command line as well. You might even be able to find a version of less for Windows as well.
c:\users\selbie> your_program.exe | more
$> ./your_program | less
As to how to do this programmatically, that's a bit more difficult as it would involve measuring the console width and implementing your own scroll buffers. There might be open-source libraries that provide this functionality, but the console environment already has a solution for apps that produce long output.
Not really, though you may find a reasonable and simple solution is to print only a certain number of lines (say 30), then prompt the user to press Enter before display more lines.
You can even find out the current size of the terminal. That's platform specific; for Linux it's explained here: How to get terminal window width?
Not in a standard way, no.
Your output stream in C is just a stream of characters -- scrolling is handled by your terminal.
Depending on your terminal, it may be possible to control scrolling by outputting special characters, like ANSI escape codes. The ncurses library provides a portable way to manipulate terminals.
However, if you just want a more convenient way to look through your output (or really any command output), #selbie's answer is the best: use more or less. This will avoid any extra complexity in your program.

Using C I would like to format my output such that the output in the terminal stops once it hits the edge of the window

If you type ps aux into your terminal and make the window really small, the output of the command will not wrap and the format is still very clear.
When I use printf and output my 5 or 6 strings, sometimes the length of my output exceeds that of the terminal window and the strings wrap to the next line which totally screws up the format. How can I write my program such that the output continues to the edge of the window but no further?
I've tried searching for an answer to this question but I'm having trouble narrowing it down and thus my search results never have anything to do with it so it seems.
Thanks!
There are functions that can let you know information about the terminal window, and some others that will allow you to manipulate it. Look up the "ncurses" or the "termcap" library.
A simple approach for solving your problem will be to get the terminal window size (specially the width), and then format your output accordingly.
There are two possible answers to fix your problem.
Turn off line wrapping in your terminal emulator(if it supports it).
Look into the Curses library. Applications like top or vim use the Curses library for screen formatting.
You can find, or at least guess, the width of the terminal using methods that other answers describe. That's only part of the problem however -- the tricky bit is formatting the output to fit the console. I don't believe there's any alternative to reading the text word by word, and moving the output to the next line when a word would overflow the width. You'll need to implement a method to detect where the white-space is, allowing for the fact that there could be multiple white spaces in a row. You'll need to decide how to handle line-breaking white-space, like CR/LF, if you have any. You'll need to decide whether you can break a word on punctuation (e.g, a hyphen). My approach is to use a simple finite-state machine, where the states are "At start of line", "in a word", "in whitespace", etc., and the characters (or, rather character classes) encountered are the events that change the state.
A particular complication when working in C is that there is little-to-no built-in support for multi-byte characters. That's fine for text which you are certain will only ever be in English, and use only the ASCII punctuation symbols, but with any kind of internationalization you need to be more careful. I've found that it's easiest to convert the text into some wide format, perhaps UTF-32, and then work with arrays of 32-bit integers to represent the characters. If your text is UTF-8, there are various tricks you can use to avoid having to do this conversion, but they are a bit ugly.
I have some code I could share, but I don't claim it is production quality, or even comprehensible. This simple-seeming problem is actually far more complicated than first impressions suggest. It's easy to do badly, but difficult to do well.

How to replace already-printed text in the command prompt?

A lot of times I've seen text-based programs which replace text which has already been printed. For instance, imagine a program where the progress is printed as
Loading: 5%
and then it says
Loading: 10%
and so on, without printing new text which is appended?
How is this done? I haven't seen any such functions available in the library (in this case C). I have an idea, though: There is a character you can write which returns the prompt to the beginning of current line (\r I believe). Could this be used to "overwrite" what you've already printed to the command prompt?
In most consoles, writing a bare carriage return \r without a newline after it will return the cursor to the beginning of the current line, allowing you to overwrite the existing text. Writing the backspace character \b also moves the cursor back one character.
For simple behavior, such as a progress indicator, this is all you need. For more complex behavior, you need to control the terminal through non-standard means. On Unix-based systems, the ncurses library can be used—it gives you full control over the cursor location, text color, keyboard echoing, more fine-grained keyboard input, and more.
On Windows, there's a suite of functions for manipulating consoles, and they can do mostly the same things as Unix consoles.
One way that I have seen is to just print the backspace character a number of times and then replace whatever you erased with the new text.
The backspace character is an ASCII control character represented by \b.

Carriage return required when printing to the console in Windows?

It seems like just putting a linefeed is good enough, but I know it is supposed to be carriage return + line feed. Does anything horrible happen if you don't put the carriage return and only use line feeds?
This is in ANSI C and not going to be redirected to a file or anything else. Just a normal console app.
The Windows console follows the same line ending convention that is assumed for files, or for that matter for actual, physical terminals. It needs to see both CR and LF to properly move to the next line.
That said, there is a lot of software infrastructure between an ANSI C program and that console. In particular, any standard C library I/O function is going to try to do the right thing, assuming you've allowed it the chance. This is why fopen()'s t and b modifiers for the mode parameter were defined.
With t (the default for most streams, and in particular for stdin and stdout) then any \n printed is converted to a CRLF sequence, and the reverse happens for reads. To turn off that behavior, use the b modifier.
Incidentally, the terminals traditionally hooked to *nix boxes including the DEC VT100 emulated by XTerm also needs both CR and LF. However, in the *nix world, the conversion from a newline character to a CRLF sequence is handled in the tty device driver so most programs don't need to know about it, and the t and b modifiers are both ignored. On those platforms, if you need to send and receive characters on a tty without that modification, you need to look up stty(1) or the system calls it depends on.
If your otherwise ANSI C program is avoiding C library I/O to the console (perhaps because you need access to the console's character color and other attributes) then whether you need to send CR or not will depend on which Win32 API calls you are using to send the characters.
If you're in a *nix environment \n (Linefeed) is probably ok. If you're in Windows and aren't redirecting (now) a linefeed is also ok, but if someone at somepoint redirects, :-(
If you're doing Windows though, there could be issues if the output is redirected to a text file and then another process tries to consume the data.
The console knows what to show, but consumers might not be happy...
If you are using C# You might try the Environment.NewLine "constant".
http://msdn.microsoft.com/en-us/library/system.environment.newline.aspx
If you're really in vanilla c, you're stuck with \r\n. :-)
It depends on what you're using them for. Some programs will not display newlines properly if you don't put both \r and \n.
If you try to only write \n some programs that consume your text file (or output) may display your text as a single line instead of multiple lines.
There are also some file formats and protocols that will completely be invalid without using both \r and \n.
I haven't tried it in so long that I'm not sure I remember what happens... but doesn't a linefeed by itself move down a line without returning to the left column?
Depending on your compiler, the standard output might be opened in text mode, in which case a single linefeed will be translated to \r\n before being written out.
Edit: I just tried a quick test, and in XP a file without returns displays normally. I still don't know if any compilers insert the returns for you.
In C, files (called "streams") come in two flavors - binary or text.
The meaning of this distinction is left implementation/platform dependent, but on Windows (with common implementations that I've seen) when writing to text streams '\n' is automatically translated to "\r\n", and when reading from text streams "\r\n" is automatically translated to '\n'.
The "console" is actually "standard output", which is a stream opened by default as a text stream. So, in practice on Windows, writing "Hello, world!\n" should be quite sufficient - and portable.

Resources