Curses was created to help one do just this, portably, decades ago.
POSIX users already have one installed (almost certainly), either ncurses (in Linux) or some BSD variant on the BSD systems and Macs. For DOS and Windows, there is PDCurses, which is not only free but in public domain. You don't need to compile it yourself, either, there are Windows DLLs you can download there.
On Linux distributions, you probably do need to install the development version of the curses library; currently libncurses5-dev (Debian variants like Mint and Ubuntu) or libncurses-devel (RPM-based distributions) and/or their wide-character variants libncurses5w-dev or libncursesw-devel.
Here is a trivial example:
Code:
#include <locale.h>
#include "curses.h"
int main()
{
int c;
/* Initialize locale, for wide-character support. */
setlocale(LC_ALL, "");
/* Start curses mode. */
initscr();
/* No line buffering. */
raw();
/* No echoing keypresses to the screen. */
noecho();
/* We want F1 et cetera. */
keypad(stdscr, TRUE);
/* We "print" stuff to the screen,
* moving the cursor to the next line '\n',
* and to the beginning of that line '\r'. */
printw("Press Q to quit.\n\r");
/* We do need to tell the curses library
* to update the changes made thus far,
* i.e. that all changes are visible on screen. */
refresh();
while (1) {
/* Wait for user input (one keypress). */
c = getch();
if (c == 'Q' || c == 'q')
break;
switch (c) {
case KEY_UP: printw("Up\n\r"); break;
case KEY_DOWN: printw("Down\n\r"); break;
case KEY_LEFT: printw("Left\n\r"); break;
case KEY_RIGHT: printw("Right\n\r"); break;
case '\n': printw("Enter\n\r"); break;
case ' ': printw("Space\n\r"); break;
default: printw("Code 0x%x\n\r", c);
}
refresh();
}
/* End curses mode. */
endwin();
return 0;
}
In Linux, you can compile and run the above using
Code:
gcc -Wall -I/usr/include/ncursesw example.c -lncursesw -o example
./example
In Windows, the command depends on which compiler you are using, and where you extracted the PDCurses library and header files, but the command should be very similar. If you use one of the IDEs, their user community almost certainly has a curse template project for you to use. (I don't use Windows myself.)
I like the wide-character variant (and used it in the example above), because I can use Unicode box-drawing characters like ╔╗, or even emoticons like 😎, as long as my source code is written using the UTF-8 character set. That means that if I add printw("Here's a kitty for you: 😺\n\r"); before the while loop, it'll show up just like a kitty face in all correctly-configured terminal emulators -- even in PuTTY (if configured to use UTF-8 to connect to this machine).
I'm not certain if PDcurses handles that correctly for the Windows command-line prompt, though. If you use Windows, you could check and let us know!