-
Notifications
You must be signed in to change notification settings - Fork 0
RawTerminal
Een C-programma dat in een terminal draait, werkt standaard in de zogenoemde cooked mode. In deze mode wordt de input pas doorgestuurd naar het programma als de gebruiker op enter heeft gedrukt. Dit geeft de gebruiker de kans om de input nog te corrigeren (bijvoorbeeld door Backspace te gebruiken) voordat het verwerkt wordt door het programma. In de meeste gevallen is dit handig, behalve als je wilt dat je programma meteen reageert zodra de gebruiker een toets indrukt. Om dit mogelijk te maken, moet je de terminal in de zogenoemde raw mode gebruiken. Hoe je dit doet is afhankelijk van het platform en het type terminal dat je gebruikt.
Als je in een C-programma dat in een terminal draait kleur wilt gebruiken, dan kun je gebruik maken van zogenoemde ANSI/VT100 Terminal Control Escape Sequences. Een overzicht vind je hier: ANSI/VT100 Terminal Control. Ook als je bijvoorbeeld het indrukken van de pijltjestoetsen in je programma wilt afvangen, dan kun je deze ANSI Escape Sequences gebruiken. In de onderstaande programma's is gebruik gemaakt van deze codes om de hexadecimale ASCII-code van een ingetypt karakter in het rood weer te geven.
Bijna alle terminalemulatieprogramma's ondersteunen deze ANSI/VT100 Escape Sequences (bijvoorbeeld PuTTY en TeraTerm). CoolTerm ondersteunt deze codes echter niet. Ook de ingebouwde terminal (Console) in Eclipse ondersteunt deze codes niet.
[TOC]
Windows beschikt over een (niet gestandaardiseerde) library om met raw mode input om te gaan: conio (Conslole Input/Output). In het onderstaande programma wordt de functie _getch() gebruikt om een ingetypt karakter meteen in te lezen.
#include <conio.h>
#include <stdio.h>
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_RESET "\x1b[0m"
int main()
{
puts("Type charakters (de ASCII code van elk karakter wordt voor het karakter in het rood geprint) (0 om te stoppen):");
char c;
do
{
c = _getch();
printf(ANSI_COLOR_RED "0x%02x" ANSI_COLOR_RESET, c);
putchar(c);
if (c == '\r')
{
putchar('\n'); // extra linefeed bij carriage return
}
} while (c != '0');
return 0;
}Om een terminal in raw mode te gebruiken in Eclipse, moeten je het programma m.b.v. de debugger uitvoeren. Omdat de ingebouwde console niet goed werkt moet je daarbij bovendien gebruik maken van een externe console.
Kies in het menu: Run > Debug Configurations... en selecteer vervolgens het tabblad Debugger. Zet een vinkje bij Use external console for inferior (open a new console window for input/output):

Nu verschijnt er een apart console window als de debugger wordt gestart, waarin de output verschijnt en de input ingetypt kan worden.
Deze console biedt echter geen ondersteuning voor de ANSI/VT100 Escape Sequences. Het intypen van Hallo<Enter>Wereld! levert de volgende output op:

Om de ANSI/VT100 Escape Sequences correct weer te geven moeten we een externe terminal in plaats van een extern console gebruiken. Om dit in te stellen klik je met je rechtermuisknop op de titelbalk van het window:

Kies voor Eigenschappen:

Selecteer Windows Terminal en start de debugger opnieuw.
Het intypen van Hallo<Enter>Wereld<Enter> levert nu de volgende output op:

Als je het bovenstaande programma in VS Code runt of debugt, dan verschijnt de (correcte) uitvoer in het ingebouwde TERMINAL window van VS Code:

Om de MSYS2 terminal in raw mode te kunnen gebruiken maken we gebruik van het commando stty. In het onderstaande programma maken we gebruik van de functie system() om de terminal in het begin van het programma in raw mode en aan het einde van het programma weer in cooked mode te zetten. We kunnen dan de standaardfunctie getchar() gebruiken om een ingetypt karakter meteen in te lezen.
#include <stdio.h>
#include <stdlib.h>
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_RESET "\x1b[0m"
int main()
{
setvbuf(stdout, NULL, _IONBF, 0);
system("stty -icanon");
system("stty -echo");
puts("Type charakters (de ASCII code van elk karakter wordt voor het karakter in het rood geprint) (0 om te stoppen):");
char c;
do
{
c = getchar();
printf(ANSI_COLOR_RED "0x%02x" ANSI_COLOR_RESET, c);
putchar(c);
} while (c != '0');
system("stty icanon");
system("stty echo");
return 0;
}Het intypen van Hallo<Enter>Wereld<Enter> levert nu de volgende output op:
