How do console graphics work? (less, curses, vi...) - c

Can someone explain to me how less, vi and curses programs manage graphics output? Can they change individual characters on the screen or do they have to literary clear and redraw the screen whenever something changes?
It would be really neat if someone could hack a tiny less clone together, without all the boilerplate code.

There exist special Escape Codes that, when sent to the terminal, instruct the terminal to reposition the cursor without disrupting what's already being displayed.

Related

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.

Add a string to the input space of the console

I don't really know how to explain this so the title is probably misleading.
I'm making a small text editor in C and I'm saving the contents of an entire file into an array of chars. Now I want to display the entire string to the user in a way that the user will be able to edit the string inside the command window by positioning the cursor/seek and then typing or deleting characters. Pressing enter or some other key would save the text to a new string and write it to the file.
Similar to what happens when you open a file in a linux text editor like nano or vi... You get that cursor which you can move around the file and make changes.
How can that be done in C? I don't need it to be like in the linux editors, simply putting the string inside the input area (as if the user typed the text) would be enough.
You must use Terminal capabilities (a.k.a Termcaps). They are special characters which can be interpreted by your terminal (e.g moving the cursor back and forth, or clearing the screen). Here's what Wikipedia says about Termcap databases :
A termcap database can describe the capabilities of hundreds of
different display terminals. This allows programs to have
character-based display output, independent of the type of terminal.
On-screen text editors such as vi and emacs are examples of programs
that may use termcap.
By using terminal capabilities, you will be able to control the way the cursor behaves in your editor, and how input characters shows up. A good example of this would be using colors for syntax highlighting.
I would suggest that you use the GNU Termcap library to build a cross-terminal application. Once you get the main principles, its usage is relatively straightforward, I used it back in the days to actually build a shell (such as bash, or sh).
Next, you might also want to look at the differences between canonical and non-canonical terminal modes. Given what kind of functionalities you are wanting to implement in your editor, you will likely want to override the way your terminal interprets some inputs.
See also :
Moving the cursor using Termcaps
Characters for Input Editing only available in canonical mode
This is done by writing certain special control characters to stdout, which can do things like set the color, move the cursor, etc. See https://en.wikipedia.org/wiki/ANSI_escape_code for more info.
However, if you want your editor to be portable, or you don't want to worry yourself with details, you may want to consider using the ncurses library (https://en.wikipedia.org/wiki/Ncurses), which editors like nano/vi use rather than doing it themselves.

Is there a way to print something in console that doesn't scroll down? (In C)

Well, maybe if I offer a little context this will be more understandable.
I want to print "Inventory" in the first line of my main, but I don't want "Inventory" to move from its place, so, while the rest of my commands show in console, and will scroll down, this particular line "Inventory will stay in its place."
http://i.stack.imgur.com/hVItr.png
I'm not sure if this can be done in C
This is quite hard in plain C due to how the console works.
There is, however a library that has done everything for you: NCurses: http://www.gnu.org/software/ncurses/

How can you clear (reset) the screen in unix/posix? (not curses/newlines)

I'd like to know (if it's possible) how can you clear/reset the terminal screen in linux/mac/unix (not DOS) like you would do on windows/DOS with clrscr() from "conio.h".
I know there are similar questions here and on the web in general, but I wasn't able to find one that answered my particular case.
ATTENTION: I know about curses/ncurses and solutions that emulate system("clear") but that's not what I want.
I want to reset completely the terminal buffer (i.e. I don't want to scroll down or add newlines to clear the screen), without using curses/ncurses please (I don't like the ncurses screen mode, I want to stick with the default mode).
Is it possible or I'm asking something impossible? :P
I'm trying to make a console-game (not exactly a roguelike) without curses, and I don't like to see what I printed on the screen before clearing it just by scrolling up.
EDIT: I've tried system("reset"), that's not a nice way using a system call, and it's getting a bad delay using that command but it's close to what I want to do.. Is there some kind of function/library that can do something similar?
I think that'll be a good solution as well to do something like move(0,0) and then print again what I need or just blank space (this way I won't have scrolling and the old text above it). But I don't know if there's a library that will do that without going un curses mode.
For now see my own answer below, I'm using
printf("\033c");
this is working fine for now and solved my problem. If anybody knows any issue with this solution please let me know.
I have an issue with the cursor visibility. If it was hidden this code will show it again, do you know a fix for this?
Thanks,
Zorgatone
I've just discovered thanks to Jayesh that this escape code will clear my screen correctly,
thanks!
printf("\033c");
EDIT: need fix! This will set the cursor visible if it was hidden previously.. How do I get the same thing without changing the cursor visibility?
If anybody will point out any issue about portability on posix/unix (linux/mac) systems, I will update the answer with a better solution.
Cheers
#include<stdio.h>
#include<conio.h>
main()
{
printf("Press any key to run clrscr().\n");
getch();
clrscr();
printf("After clearing the screen.\n");
printf("Press any key to exit..\n");
getch();
return 0;
}
in linux system(clear); :)
For POSIX, you can use terminfo. Request the "clear" command using tigetstr and output the command using putp.
For Windows, you would be looking at using FillConsoleOutputCharacter and filling the console with spaces.
Then just abstract the two methods and you have a cross-platform mechanism.
I am using this one:
write(STDOUT_FILENO, "\x1b[2J", 4);
alias cls='printf "\e[3J\033c"'
Clears the screen and the scrollback buffer.

Display pixel on screen in C

How would I change a pixel on a display, in C?
Assume NOTHING: I am using a linux machine from console to do this. I do not want to use GUI toolkits or frameworks to draw the pixel. I do not want to draw the pixel in a window. I want to draw the pixel directly to the screen.
EDIT: I have a screen. I'm on a laptop running linux from console. I'd prefer a solution not using X as I'd rather learn how X works than how to use X.
If theres more information, ask, but don't assume. I'm not trying to build a GUI, and that was the main purpose of blocking assumptions as I don't want people to assume I'm doing things the long way when in reality I'm just tinkering.
EDIT 2: You may use any X11 related libraries provided that you can explain how they work.
If we really assume nothing, can we even assume that X is running? For that matter, can we even assume that there is a video card? Perhaps Linux is running headless and we're accessing it over a serial console.
If we are allowed to assume a few things, let's assume that Linux has booted with framebuffer support. (It's been a couple years since I worked with Linux framebuffers, I may get some of the details wrong.) There will be a device created, probably /dev/fb or /dev/fb0. Open that file and start writing RGB values at an offset, and the screen will change, pretty much regardless of anything: text console, graphical console, full-fledged desktop envrionment, etc. If you want to see if framebuffer support is working, do dd if=/dev/zero of=/dev/fb on the command line, and the display should go all black.
C doesnt have any graphics capabilities - you'd need to use a third party library for this.
You cannot assume a display in C. There is literally no way to do what you ask.
Edit: Okay, you have a display, but again, there's not a whole lot you can get from there. The point is that there are a TON of competing standards for graphics displays, and while some of them (VGA interfaces, for example) are standardized, a lot of the others (display driver interfaces, for example) are NOT. Much of what X (and other display device drivers, such as Windows or the like) do, is have specific interface code for how to talk to the display drivers; they abstract out the complexity of dealing with the display drivers. The windowing systems, though, have HUGE libraries of complicated and specific code for dealing with the display drivers; the fact that these things are relatively transparent is an indication of just how much work they've put into these things over time.
Very primitive and making a lot of assumptions:
fd = open("/dev/fb0", O_RDWR);
lseek(fd, 640*y+x, SEEK_SET);
write(fd, "\377\377\377\377", 4);
In reality, you would use mmap rather than write, and use the appropriate ioctl to query the screen mode rather than assuming 640xHHH 32bpp. There are also endian issues, etc.
So in real reality, you might use some sort of library code that handles this kind of thing for you.
I suppose you could paint to the terminal program that you are using as your console. All you have to do is figure out which one that is and look it up.
Whoops I assumed a terminal. :P
I think what you are looking for is information on how to write to the frame buffer. The easiest way would be to use SDL and render to the frame buffer, or else use GTK+ with DirectFB, although that goes against your edict on not using toolkits or frameworks.

Resources