Why can't I read Ctrl+S in C? - c

I have this program in C that reads the input like this:
cod1 = getch ();
if (kbhit())
cod2 = getch ();
I can read every Ctrl+Char possible sequences, except for Ctrl+C, that closes the program - that is OK, and Ctrl+S, that simple is not catch. But I wanted to make Ctrl+S to be the save function in my program; how could I do that? Furthermore, is it possible to read Alt+Char characters? Because it reads it as a regular character, e.g., Alt+A is read with the same codes as A.

Your problem is that input probably gets eaten by terminal emulator.
For example Alt+<Whatever> is often reserved for menu shortcuts (e.g. Alt+F opens File menu). Matching characters are often hilighted once you hold Alt (F get's underscored in File).
Ctrl+S is reserved for Stops all output on screen (XOFF) (again your terminal emulator does that).
As for using Alt+<...> as shortcuts in your command line application. As far as I'm concerned holding Alt doesn't affect character received, it just sets flags which are hard to access in console. Even in GUI application (in Windows) it's quite tricky and you have to use function like GetAsyncState() to check whether alt was pressed.

Related

Differentiate clipboard event when using read() function in c from stdin

I am working on terminal based text editor and stuck at a point where I need to differentiate whether the input text from read() function is a clipboard paste text or a keyboard text input.
#include <unistd.h>
char read_key_input() {
char ch;
int read_count;
while ((read_count = read(STDIN_FILENO, &ch, 1)) != 1)
{
// Handle error if any
}
return ch;
}
...
Edit: Here's what I ended up doing.
void read_key_input(void (*callback)(int)) {
char* text = malloc(UINT8_MAX);
int read_count;
while ((read_count = read(STDIN_FILENO, text, UINT8_MAX)) == -1)
{
// Handle error if any
}
// Handle escape sequences if found and return early
...
if (read_count > 1) {
// It's probably a clipboard text. So change the editor mode to input and loop through all the characters one by one.
else {
// It's a user keyboard text input
}
// Revert back to the original editor mode if changed
}
I updated the code to retrieve more than one byte at a time (as suggested by #AnttiHaapala) and process each byte. Seems to be sufficient for my text editor's need for now. Will post back if I update.
Usually you can differentiate this by counting the number of characters you've received in rapid succession. So if you get the keypresses more rapidly than say 1000 characters per minute, then it is likely a clipboard paste... or nonsense.
Furthermore, if you've set the terminal to raw mode, then you can easily monitor individual keypresses. Also make read accept more than one byte at once - with read that is the maximum number of bytes to receive without blocking when available anyway.
One example of such an interactive terminal program would be IPython - here two lines typed separately:
In [1]: print("Hello")
Hello
In [2]: print("World")
World
And here pasted in one go:
In [3]: print("Hello")
...: print("World")
...:
Hello
World
Notice how the prompt is different, and the program runs only after there has been a separate Enter key hit after a small delay.
AFAIK, you cannot do what you want (reliably).
The clipboard is related (usually) to some display server, e.g. Xorg or Wayland server (Weston). And X11 might have distant clients (hence, a clipboard operation could be slow, if crossing some ocean).
Some Linux machines (perhaps the web server at Stackoverflow) do not run any display server.
You could code a GUI application, e.g. using GTK or Qt.
You could test if your standard input is a terminal with termios(3) functions or isatty(3) (i.e. with isatty(STDIN_FILENO) or isatty(STDOUT_FILENO) for standard output)
If your program is run inside a crontab(1) job, or a unix pipeline, the standard input won't be a terminal, and there might not even be any display server running.
You could take inspiration from the source code of GNU emacs, which does detect when a display server is available (probably using environ(7), e.g. getenv(3) of "DISPLAY"...)
On Linux you might open(2) /dev/tty (see tty(4)) to access your terminal. In some cases, it does not exist.
Hey #jiten not sure if you checked like
its key input detect and check wether it's input is one by one key
or its instant bulk input.

Delete current terminal input line

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.

Stopping Linux console from echoing input during program execution

I'm writing a C program that requires to hide the characters a user types from the screen during the program execution. For example, when running the following loop
while (1)
{
//do some work
}
the console displays the blinking cursor (that's good). BUT, when the user types keys on the keyboard, these keys are being echoed out to the console. To visualize it better:
Step 1: Starting the program
root#debian:/home/root# ./program
_
Step 2: User types some characters (even though he shouldn't)
root#debian:/home/root# ./program
AdajfsaSJ_
The characters get echoed on the console. How can I stop this? I know it's theoretically possible, but I can't find out how to implement it.
If you need a better example for what I want to achieve, use the screen command on an empty serial port. screen /dev/tty30 for example. This empties the console and runs the program, HOWEVER, the user is not able to enter any characters (there's a blinking white cursor block and no keyboard characters are being echoed to the console). That's what I need.
Any insight would help, thanks!
Use termios() to turn off the ECHO flag of the terminal.
To turn off the text cursor, use the termcap library to control the cursor visibility.

Interactive input that doesn't appear on the in the window in C

I'm writing a program that needs to ask the user a yes or no question at the end. Going based off the example .exe my teacher provided us, the line is supposed to print out "Would you like to print an Amortization Table(Y/N)?Y" and it looks for one keystroke from the user. The Y is printed out following the question like I typed, as it is supposed to represent the default choice so if the user presses [y], [shift + y], or [enter] it goes to the function that does the amortization table and if the user presses anything else it goes to the next line When it gets the input from the user it processes the keystroke instantly as it is pressed (it does not need [enter] to process the input) without letting the keystroke appear on the command prompt. I have tried all the functions I can think of to do this (getc, getchar, getche) but everything I have tried ends up printing the user's input. Does anyone know what function he used or what trick he is doing to keep the keystroke from appearing in the command prompt? Thanks for your help in advance, I am obviously new to programming.
For the Windows platform, use the _getch() function from <conio.h> to read a keypress without buffering or echo.
Read the function description on MSDN

How do I accept Tab as input from STDIN to autofill text

How do I do autofill a text when Tab key is pressed after a period from STDIN using C?
Input would look like,
C:\>autofil.exe Hello
C:\>autofil.exe Hello. ( When I enter a period, it should autofil Hello after the period)
C:\>autofil.exe Hello.World *World is autofilled when period was entered.
Second requirement is if I am at
C:\>autofil.exe Hello.World (And when i press Tab key, `World` should print with other suggestions, as `Friend`, and if I press Tab again, print `Matt`, and scroll so on when tab is pressed... )
Well, that is my requirement. Tab complete to autofill text. Also, want to know how to read the Tab key from STDIN.
Thanks!
You could use Readline GNU library For Windows, is pretty easy to use, the other way around is to use PDcurses/Ncurses (are almost the same) and do it by hand (handling console behavior and such).
In case you use readline, to acomplish autocomplete is as simple as doing:
rl_bind_key('\t', rl_complete);
char *input = readline("C:\>");
In case you use Ncurses/PDcurses, you will have to do a little more work :)
First you save actual console parameters.
Then you set echo of the input off with noecho().
You will have to handle input and parse the arguments to call programs.
Also you will have to search in dirs (current and the ones on PATH variable) for things matching your current input.
Before ending your program set again the saved console parameters.
Ncurses How-To Is an easy right to the point guide.
Posix curses definition Contains functions and key definitions.

Resources