In my C program I would like to know where my cursor is located in terminal. For example, another program could have written something before mine and I would like to know how much space is left before the last column of the terminal, or I could not know the terminal reaction to some special sequences (like colors: I could write it but they are not showed).
Any suggestion?
Edit: it would be better avoiding over complicated solutions like ncurses (ncurses doesn't know where's the cursor directly: it computes its position).
Edit 2: I found a way to do it, but it works only in non-graphical terminals: https://www.linuxquestions.org/questions/programming-9/get-cursor-position-in-c-947833/
Edit 3: Nice code and it works well, but it uses /dev/vcsaN (same problem of Edit 2): http://dell9.ma.utexas.edu/cgi-bin/man-cgi?vcs+4
Ncurses is a big and powerful library for creating terminal-based text interfaces.
tputs is a simple low-level universal function for manipulating terminal capabilities.
Either one could serve your needs.
You could try using ncurses' getyx().
This solution is not optimal because it refers to /dev/vcsa*. Hope this could help someone else.
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
int fd;
char *device = "/dev/vcsa2";
struct {unsigned char lines, cols, x, y;} scrn;
fd = open(device, O_RDWR);
if (fd < 0) {
perror(device);
exit(EXIT_FAILURE);
}
(void) read(fd, &scrn, 4);
printf("%d %d\n", scrn.x, scrn.y);
exit(EXIT_SUCCESS);
}
Generally you are supposed to remember where you've left the cursor.
However, most terminals do respond to DSR; Device Status Request. By sending
CSI 6 n
you'll receive a CPR; cursor position report, in the form of
CSI Pl;Pc R
where Pl and Pc give the cursor line and column number, indexed from 1.
Related
I want to know: how to clean screen on an UNIX-based system? I searched on the Internet, but I've just found how to do it on Windows: system("CLS")
I don't want exactly to clean cpmpletely the screen, but I want to open a "new page", such as in the NANO and VI editors. Thanks
Maybe you can make use of escape codes
#include <stdio.h>
#define clear() printf("\033[H\033[J")
int main(void)
{
clear();
return 0;
}
But keep in mind that this method is not compatible with all terminals
You can use the following code which use termcap for clear screen.
(don't forget to link with the library)
#include <stdio.h>
#include <stdlib.h>
#include <termcap.h>
void clear_screen()
{
char buf[1024];
char *str;
tgetent(buf, getenv("TERM"));
str = tgetstr("cl", NULL);
fputs(str, stdout);
}
#include <stdlib.h>
int main(void)
{
system("clear");
}
Portable UNIX code should be using the terminfo database for all cursor and screen manipulation. This is what libraries like curses uses to achieve its effects like windowing and so forth.
The terminfo database maintains a list of capabailities (like clear which is what you would use to clear the screen and send the cursor to the top). It maintains such capabilities for a wide range of devices so that you don't have to worry about whether you're using a Linux console or a (very dated) VT52 terminal.
As to how you get the character streams for certain operations, you can choose the time-honored but rather horrible method of just using system to do it:
system ("tput clear");
Or you can capture the output of that command to a buffer so later use involve only outputting the characters rather than re-running the command:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static char scrTxtCls[20]; static size_t scrSzCls;
// Do this once.
FILE *fp = popen ("tput clear", "r");
scrSzCls = fread (scrTxtCls, 1, sizeof(scrTxtCls), fp);
pclose (fp);
if (scrSzCls == sizeof(scrTxtCls)) {
actIntelligently ("you may want to increase buffer size");
}
// Do this whenever you want to clear the screen.
write (1, cls, clssz);
Or, you can link with ncurses and use its API to get whatever capabilities you want, though this might drag in quite a bit of stuff for something as simple as clearing the screen. Still, it's an option to be considered seriously since it gives you a lot more flexibility.
It is usually not a matter of just clearing the screen, but of making a terminal aware application.
You should use the ncurses library and read the NCURSES programming HowTo
(You could perhaps use some ANSI escape codes as David RF answered, but I don't think it is a good idea)
You can achieve this using CSI sequences:
#include <stdio.h>
int main()
{
printf("\x1b[H\x1b[J");
}
What does \x1b[H?
Actually it is the same as \x1b[1;1;H, it means that it will move the cursor to row 1 and column 1.
What does \x1b[J a.k.a \x1b[0;J?
If n is 0 or missing, it will clear from cursor to end of screen.
Source: https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences
Just use #include<stdlib.h> after #include<stdio.h>.
Then you can use the command system("clear");after main() {
i.e:
#include<stdio.h>
#include<stdlib.h>
int main()
{
system("clear");
After these commands you can continue with your program.
Hope this helps :)
To clear the screen using termcaps, use this :
write(1, tgetstr("cl", 0), strlen(tgetstr("cl", 0)));
Use system("clear"); with header #include <stdlib.h> (for C Language) or #include <cstdlib> (for C++).
This code is for clear screen with reset scrollbar position in terminal style windows
#include <iostream>
int main(){
std::cout << "\033c";
return 0;
}
While there is an easy way of using both file redirection and piping, as well as interactive user input reading , with main(), as shown in this C code snippet...
#define SIZ 1024
#include <stdio.h>
extern void do_something_with_the_array(float *a[], int *n);
int main(int argc, const char * argv[])
{
float f[SIZ];
int k = 0;
while ((scanf("%f", &f[k]) == 1)&&(k < SIZ)) {
k++;
}
do_something_with_the_array(f, k);
return 0;
}
… I'm not sure if there is a modern UNIX source compatible and easy way of programmatically achieving any of the three possibilities in a main() in C, depending on the context ?
interactive reading of a string of numbers as user input
reading of the same string of numbers as command line arguments
file redirection and piping
I understand piping and redirection "belong" to the shell which intercepts the program before it even starts executing, while command line arguments and interactive reading "belong" to the main() itself and therefore there may not be an easy way of doing this.
I see using stdin or file input or pipe input pretty self-explanatory. However, reading command line arguments is a different story. Here's a demo how I usually code it, but it looks kind of heavy-handed and hacked to me. Also, in more complicated scenarios with options, this could become a pretty messy piece of code. I'm also not sure how fail-safe or fool proof this is...
#define SIZ 1024
#include <stdio.h>
#include <stdlib.h>
extern void do_something_with_the_array(float *, int);
int main(int argc, const char * argv[])
{
float f[SIZ];
int k = 0;
if(argc > 2){
for(k = 0; k < argc - 1; k++)
f[k] = (float)atof(argv[k+1]);
}
else while ((scanf("%f", &f[k]) == 1)&&(k < SIZ))
k++;
do_something_with_the_array(f, k);
return 0;
}
Thanks in advance!
I do not know off-hand of a C library that will make the three specific cases you mentioned look the same (although someone who does, please answer because I'd like to know, too!). I think you're looking for something not unlike the diamond <> operator in Perl, but for individual arguments rather than files containing arguments.
I think #David Hoelzer has the right idea: handle the three cases separately. For example, when processing command-line or file arguments, don't generate "Enter a value" prompts that you might print for interactive input. For command-line processing, getopt is a good place to start.
Now, a challenge to you: Wrap those three operations in a library and make it open-source so the rest of us can benefit! :)
Quite a few programs do care if they're invoked with keyboard input vs. file input, including the shell itself.
Let us take /bin/sh as our first example. If you call it directly, it starts an interactive shell, but if you pipe something into it, it starts as a non-interactive reading shell. The main difference between the two is if it is not interactive, it doesn't display the $ prompt. However just in case it really is interactive, it can be started with the -i option to make it assume its interactive when it would normally decide otherwise.
The magic involved here is isatty(); see man 3 isatty.
In addition, some programs like to receive keyboard input while processing redirected standard input. There are two generally favored ways of doing this; either opening and reading from /dev/tty or reading standard error, depending on context. Most stuff in an interactively started pipeline doesn't have standard error redirected, so this tends to work well (reading a redirected standard error yields an error immediately as the handle isn't open for read). If you want to make it potentially fully automatable, you read standard error, otherwise you read /dev/tty.
Just trying to seek to understand. I'm writing a small program that will read in a keystroke event from the keyboard, and trigger certain events (using a switch statement). I'm making some assumptions, and attempting to treat the keyboard like a txt file to read from.
I'm kind of at a loss as to the simplest way to do this.
What i WANT to do it open the file(keyboard event4), and use something like fgets to read it in character by character in an infinite while loop, then use a switch statement to break out of the loop and exit.
Where i'm getting stuck is the fact that these are system calls, and i'm basically unsure how to handle them.
The code below definitely won't compile, just putting it there as a rough demonstration of what i am trying to do.
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
// errors on opening
int fd = open("/dev/input/event4", O_RDONLY);
if(fd < 0)
{
printf("error while opening/n");
return 1;
}
int keystroke = 0;
while (1)
{
keystroke = fgetsc(fd);
switch(keystroke)
{
case '1' :
break;
case '2' :
break;
case '3' :
break;
default:
printf("waiting for 1, 2, 3/n");
}
close(fd);
return 0;
}
1) Read "raw keyboard input" is generally OS-dependent. The APIs and techniques can vary greatly depending if you're on Windows vs Linux, for example.
2) It sounds like you're on a *nix variant (Linux or MacOS, for example). If you want to do all the "grunge" yourself, here's a great "howto":
http://www.tldp.org/HOWTO/pdf/Keyboard-and-Console-HOWTO.pdf
3) You'll need to put the keyboard device into "raw", "unbuffered" mode in order to read keystrokes. Among other things...
4) I would encourage you, however, to leverage a higher-level library, like ncurses or SDL.
'Hope that helps!
What I am trying to do
So, I have been trying to access keyboard input in Linux. Specifically, I need to be able to access modifier key presses without other keys being pressed. Furthermore, I want to be able to do this without an X system running.
So, in short, my requirements are these:
Works on Linux
Does not need X11
Can retrieve modifier key press without any other keys being pressed
This includes the following keys:
Shift
Control
Alt
All I need is a simple 0 = not pressed, 1 = currently pressed to let me know if
the key is being held down when the keyboard is checked
My computer setup
My normal Linux machine is on a truck towards my new apartment; so, I only have a Macbook Air to work with right now. Therefore, I am running Linux in a VM to test this out.
Virtual Machine in VirtualBox
OS: Linux Mint 16
Desktop Environment: XFCE
Everything below was done in this environment. I've tried both with X running and in one of the other ttys.
My Thoughts
I'll alter this if someone can correct me.
I've done a fair bit of reading to realize that higher-level libraries do not provide this kind of functionality. Modifier keys are used with other keys to provide an alternate key code. Accessing the modifier keys themselves through a high-level library in Linux isn't as easy. Or, rather, I haven't found a high-level API for this on Linux.
I thought libtermkey would be the answer, but it doesn't seem to support the Shift modifier key any better than normal keystroke retrieval. I'm also not sure if it works without X.
While working with libtermkey (before I realized it didn't get shift in cases like Shift-Return), I was planning to write a daemon that would run to gather keyboard events. Running copies of the daemon program would simply pipe requests for keyboard data and receive keyboard data in response. I could use this setup to have something always running in the background, in case I cannot check key code statuses at specific times (have to be receive key codes as they happen).
Below are my two attempts to write a program that can read from the Linux keyboard device. I've also included my small check to make sure I had the right device.
Attempt #1
I have tried to access the keyboard device directly, but am encountering issues. I have tried the suggestion here that is in another Stack Overflow thread. It gave me a segmentation fault; so, I changed it from fopen to open:
// ...
int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-0-event-kbd", O_RDONLY);
char key_map[KEY_MAX/8 + 1];
memset(key_map, 0, sizeof(key_map));
ioctl(fd, EVIOCGKEY(sizeof key_map), key_map);
// ...
While there was no segmentation fault, there was no indicator of any key press (not just modifier keys). I tested this using:
./foo && echo "TRUE" || echo "FALSE"
I've used that to test for successful return codes from commands quite a lot; so, I know that's fine. I've also outputted the key (always 0) and mask (0100) to check. It just doesn't seem to detect anything.
Attempt #2
From here, I thought I'd try a slightly different approach. I wanted to figure out what I was doing wrong. Following this page providing a snippet demonstrating printing out key codes, I bundled that into a program:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char** argv) {
uint8_t keys[128];
int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-event-kbd", O_RDONLY);
for (;;) {
memset(keys, 0, 128);
ioctl (fd, EVIOCGKEY(sizeof keys), keys);
int i, j;
for (i = 0; i < sizeof keys; i++)
for (j = 0; j < 8; j++)
if (keys[i] & (1 << j))
printf ("key code %d\n", (i*8) + j);
}
return 0;
}
Previously, I had the size to 16 bytes instead of 128 bytes. I should honestly spend a bit more time understanding ioctl and EVIOCGKEY. I just know that it supposedly maps bits to specific keys to indicate presses, or something like that (correct me if I'm wrong, please!).
I also didn't have a loop initially and would just hold down various keys to see if a key code appeared. I received nothing; so, I thought a loop might make the check easier to test in case a missed something.
How I know the input device is the right one
I tested it by running cat on the input device. Specifically:
$ sudo cat /dev/input/by-path/platform-i8042-serio-0-event-kbd
Garbage ASCII was sent to my terminal on key press and release events starting with the return (enter) key when I began the output using cat. I also know that this seems to work fine with modifier keys like shift, control, function, and even Apple's command key on my Macbook running a Linux VM. Output appeared when a key was pressed, began to appear rapidly from subsequent signals sent by holding the key down, and outputted more data when a key was released.
So, while my approach may not be the right one (I'm willing to hear any alternative), the device seems to provide what I need.
Furthermore, I know that this device is just a link pointing to /dev/input/event2 from running:
$ ls -l /dev/input/by-path/platform-i8042-serio-0-event-kbd
I've tried both programs above with /dev/input/event2 and received no data. Running cat on /dev/input/event2 provided the same output as with the link.
Open the input device,
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <string.h>
#include <stdio.h>
static const char *const evval[3] = {
"RELEASED",
"PRESSED ",
"REPEATED"
};
int main(void)
{
const char *dev = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";
struct input_event ev;
ssize_t n;
int fd;
fd = open(dev, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Cannot open %s: %s.\n", dev, strerror(errno));
return EXIT_FAILURE;
}
and then read keyboard events from the device:
while (1) {
n = read(fd, &ev, sizeof ev);
if (n == (ssize_t)-1) {
if (errno == EINTR)
continue;
else
break;
} else
if (n != sizeof ev) {
errno = EIO;
break;
}
The above snippet breaks out from the loop if any error occurs, or if the userspace receives only a partial event structure (which should not happen, but might in some future/buggy kernels). You might wish to use a more robust read loop; I personally would be satisfied by replacing the last break with continue, so that partial event structures are ignored.
You can then examine the ev event structure to see what occurred, and finish the program:
if (ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2)
printf("%s 0x%04x (%d)\n", evval[ev.value], (int)ev.code, (int)ev.code);
}
fflush(stdout);
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}
For a keypress,
ev.time: time of the event (struct timeval type)
ev.type: EV_KEY
ev.code: KEY_*, key identifier; see complete list in /usr/include/linux/input.h
ev.value: 0 if key release, 1 if key press, 2 if autorepeat keypress
See Documentation/input/input.txt in the Linux kernel sources for further details.
The named constants in /usr/include/linux/input.h are quite stable, because it is a kernel-userspace interface, and the kernel developers try very hard to maintain compatibility. (That is, you can expect there to be new codes every now and then, but existing codes rarely change.)
So I'm familiar with printf and the like, but I need to update a single line on the screen without having multiple lines scrolling. I have found libraries to do this in windows (conio.h) but not in unix. I need to be able to run this in cygwin, but any unix examples would be welcome.
I found the following stackoverflow article , but I don't think it quite closes the question for my needs.
Thanks for your help
It depends on whether you're trying to do a text-mode full-screen application (in which case ncurses is probably what you want) or just want to update a single line in-place (e.g., you want to update an "X percent done" indicator from 1 to 100, with all the output appearing on the same line so when X percent done is printed, it prints "over" the previous X-1 percent done indicator). In the latter case, you can write code that's relatively portable, and considerably simpler as well. For example, something like this:
#include <windows.h> // Used only for "Sleep" in our simulated work load
#include <stdio.h>
void do_work() {
// Simulated work load. Just waste some time:
Sleep(100);
}
int main() {
for (int i=0; i<100; i++) {
char buffer[82];
sprintf(buffer, "%d percent done", i+1);
printf("\r%-79s", buffer);
do_work();
}
return 0;
}
You want Ncurses for this. It's a library which allows you to edit any character on the screen.