Ncurses: Grundlegendes
<<< ncurses-Startseite | ncurses | << Inhaltsverzeichnis |
< Einleitung | Farben und andere Attribute > |
Installation
[Bearbeiten]ncurses ist zumindest unter Linux (fast) immer Bestandteil der Distributionen und kann, wenn nicht bereits bei der initialen Linuxinstallation geschehen, nachträglich einfach vom Installationsmedium installiert werden. Eine ncurses-Downloadmöglichkeit wird im Kapitel Weblinks genannt.
Die Headerdateien
[Bearbeiten]Die ncurses-Standard-Headerdateien sind
curses.h
oder
ncurses.h
ncurses.h
ist meist nur ein symbolischer Link auf curses.h
Des Weiteren enthält ncurses für Spezialeinsatzfälle noch weitere Header-Dateien:
- Panels:
panel.h
- Menüs:
menu.h
- Formulare:
form.h
Die Bibliotheken
[Bearbeiten]Die ncurses-Standardfunktionen sind in der Bibliothek
libncurses.xx
versammelt, wobei xx
für so
(shared object) oder a
(statische Programmbibliothek) steht.
Äquivalent zu den Header-Dateien gibt es noch zusätzliche ncurses-Bibliotheken:
- Panels:
libpanel.xx
- Menüs:
libmenu.xx
- Formulare:
libform.xx
Die ncurses-man-Pages
[Bearbeiten]Mit ncurses werden umfangreiche und ausführliche Manual-Seiten mitgeliefert.
Der Aufruf der ncurses-Übersichtsseite erfolgt mittels
man ncurses
oder
info ncurses
Auch die Beschreibungen der einzelnen ncurses-Funktionen lassen sich so abfragen, z.B.
man mvaddstr
oder
man 3ncurses mvaddstr
Fenster
[Bearbeiten]Ein Fenster (Window) repräsentiert einen rechteckigen Bildschirmausschnitt. In einer WINDOW
-Datenstruktur werden die notwendigen Attribute und Daten des entsprechenden Bildschirmausschnittes gespeichert. In curses.h
findet sich dieses Konstrukt unter struct _win_st
. WINDOW
ist nur ein Synonym für _win_st
(typedef struct _win_st WINDOW
).
Bildschirme
[Bearbeiten]Bildschirme (Screens) sind Zeiger auf eine WINDOW-Datenstruktur.
ncurses kennt beim Start zwei Screens:
- Standardbildschirm (standard screen):
stdscr
- Aktueller Bildschirm (current screen):
curscr
Der stdscr
ist das Hauptfenster, welches vom Programmierer mittels ncurses-Anweisungen beeinflusst werden kann. Der curscr
repräsentiert das, was momentan am Bildschirm angezeigt wird. Bei einem Refresh werden in diesen Screen die vorgenommenen Änderungen eingebracht und die Darstellung am physikalischen Bildschirm aktualisiert.
ncurses und I/O-Befehle von C
[Bearbeiten]Befindet sich ein Programm im ncurses-Modus, so dürfen (oder sollen, können) die C-Standardfunktionen nicht zur Ein- und Ausgabe (z.B. printf, scanf) verwendet werden. Zu diesem Zweck stellt ncurses eigene Funktionen zur Verfügung.
Termcap und Terminfo
[Bearbeiten]termcap steht für Terminal Capabilities und ist eine Datei, in der die Fähigkeiten (Zeilen-, Spaltenanzahl, ...) zahlreicher Terminals hinterlegt sind.
terminfo leistet prinzipiell das gleiche wie termcap. Allerdings liegen in der terminfo-Datenbank die Terminal-Fähigkeitsbeschreibungen nicht in einer einzigen Gesamtdatei vor, sondern als separate Dateien alphabetisch geordnet in Unterverzeichnissen.
Bei der ncurses-Initialisierung wird mittels der Environmentvariablen TERM
die termcap/terminfo ausgewertet. Daraus kann ncurses die relevanten Daten des verwendeten Terminals ermitteln (z.B. Anzahl der Zeilen und Spalten).
Ncurses initialisieren und beenden
[Bearbeiten]Die ncurses-Initialisierung geschieht mittels der Funktion
WINDOW *initscr (void);
initscr
wird in den meisten Fällen die erste ncurses-Funktion sein, die in einem Programm aufgerufen wird.
Beendet wird der ncurses-Modus mit der Funktion
int endwin (void);
Ein ncurses-Programm soll unbedingt ordentlich mit der endwin
-Funktion beendet werden.
Der ncurses-Modus kann durch endwin
auch zeitweilig unterbrochen werden. Die Rückkehr zum ncurses-Modus erfolgt durch eine Refresh-Anweisung.
Mit der Funktion bool isendwin()
kann abgefragt werden, ob der ncurses-Modus noch aktiv ist.
bool
ist übrigens ein Boolean-Datentyp den ncurses mitbringt. Zulässige Werte sind TRUE
(= 1) und FALSE
(= 0). Dass C++-Compiler oder andere Bibliotheken ebenfalls einen bool
-Datentyp kennen, wird in der ncurses-Headerdatei berücksichtigt.
Das ncurses-Hauptkoordinatensystem
[Bearbeiten]
Zwecks Abfrage von Fenster- und Cursorkoordinaten stehen folgende Makros zur Verfügung:
getyx(win, y, x); // Koordinaten der aktuellen Cursorposition getparyx(win, y, x); // Koordinatenursprung von win bezogen auf das // übergeordnete Fenster getbegyx(win, y, x); // Koordinatenursprung getmaxyx(win, y, x); // Fenstergröße (Anzahl der Zeilen und Spalten)
Wobei win
ein Zeiger auf das abzufragende WINDOW
ist und die Koordinatenwerte als Integerwerte in y
(Zeile) und x
(Spalte) geliefert werden.
Beispiel
[Bearbeiten]#include <curses.h> #include <stdlib.h> //noetig fuer atexit() void quit() { endwin(); } int main(void) { int x, y; initscr(); atexit(quit); curs_set(0); mvprintw(3, 5, "LINES: %d", LINES); mvprintw(4, 5, "COLS: %d", COLS); getyx(stdscr, y, x); mvprintw(5, 5, "Momentane Cursorposition: [%d, %d]", y, x); getbegyx(stdscr, y, x); mvprintw(6, 5, "Koordinatenursprung: [%d, %d]", y, x); getmaxyx(stdscr, y, x); mvprintw(7, 5, "Fenstergröße: [%d, %d]", y, x); mvaddstr(11, 2, "Taste drücken -> Ende"); refresh(); getch(); return(0); }
Die Bedeutung der einzelnen Bildschirmausgabefunktionen wird später näher beschrieben. Das Compilieren und Linken des Beispieles kann mit folgendem Kommando geschehen
gcc -o bsp bsp.c -lncurses
Voraussetzungen für das erfolgreiche Compilieren/Linken dieses Beispiels in der vorgeschlagenen Art und Weise:
- Das Beispiel wurde unter dem Dateinamen
bsp.c
abgespeichert und der Compileraufruf erfolgt aus dem selben Verzeichnis in dembsp.c
gespeichert wurde. - Sie verwenden das C-Frontend der GNU Compiler Collection (GCC). Diese GCC muss für das Compilieren/Linken des Beispiels auf ihrem System installiert sein. Die Verwendung eines anderen Compilers wird einen etwas anderen Compileraufruf erfordern.
- Sie geben das Kommando direkt nach dem Prompt in ein Terminal ein. Für andere Arten der Programmerstellung, z.B. via IDE, sei hier nur der allgemeine Hinweis "die Einbindung der
ncurses
-Bibliothek nicht vergessen" gegeben.
Das ausführbare Programm sollte nach erfolgreichem Compilerlauf unter dem Dateinamen bsp
vorhanden sein. Der Programmstart kann mit
./bsp
direkt aus dem Speicherverzeichnis des Beispielprogramms erfolgen. Das Ergebnis sollte folgendem Screenshot ähneln.
Die konkret angezeigten Zahlenwerte hängen natürlich vom verwendeten Terminal ab.
Cursor
[Bearbeiten]Zwecks Positionierung des Cursors steht die Funktion
int move(int y, int x);
zur Verfügung. Der Cursor bestimmt, an welcher Position die Textausgabe oder ein Echo erfolgt. ncurses-Text-I/O-Funktionen existieren meist zusätzlich als Variante mit einem mv
-Präfix, sodass Cursorpositionierung und Daten-I/O in einem Rutsch erledigt werden können und nicht jeweils zwei Funktionen nacheinander angeschrieben werden müssen.
Die Cursoranzeige lässt sich mit der Funktion
int curs_set(int visibility);
modifizieren. Für visibility
sind folgende Werte möglich:
- 0 ... unsichtbar
- 1 ... sichtbar
- 2 ... "besonders" sichtbar.
Textausgabe
[Bearbeiten]Die ncurses-Bibliothek kennt, ihrem Einsatzzweck entsprechend, eine Vielzahl von Textausgabefunktionen.
Hinzufügen von Einzelzeichen
[Bearbeiten]int addch(const chtype ch); int mvaddch(int y, int x, const chtype ch); int echochar(const chtype ch);
echochar
entspricht einem addch
mit nachfolgendem refresh
.
Einfügen eines Zeichens
[Bearbeiten]int insch(chtype ch); int mvinsch(int y, int x, chtype ch);
Beispiel: Unterschied zwischen addch() und insch()
[Bearbeiten]#include <curses.h> #include <stdlib.h> //noetig fuer atexit() void quit() { endwin(); } int main(void) { initscr(); atexit(quit); curs_set(0); mvaddstr(3, 2, "Der Unterschied zwischen addch() und insch():"); mvaddstr(5, 5, "ADDCH: Hallo, Welt"); mvaddch(5, 13, 'A'); mvaddstr(6, 5, "INSCH: Hallo, Welt"); mvinsch(6, 13, 'A'); refresh(); getch(); return(0); }
Hinzufügen einer Zeichenkette
[Bearbeiten]int addstr(const char *str); int addnstr(const char *str, int n); int mvaddstr(int y, int x, const char *str); int mvaddnstr(int y, int x, const char *str, int n);
Einfügen einer Zeichenkette
[Bearbeiten]int insstr(const char *str); int insnstr(const char *str, int n); int mvinsstr(int y, int x, const char *str); int mvinsnstr(int y, int x, const char *str, int n);
Formatierte Ausgabe
[Bearbeiten]int printw(const char *fmt, ...); int mvprintw(int y, int x, const char *fmt, ...); int vwprintw(WINDOW *win, const char *fmt, va_list var glist);
Die Parameter, insbesondere fmt
, von printw
entsprechen der printf
-Funktion in stdio.h
. Nachfolgend sind auszugsweise einige Konvertierungszeichen zwecks Verwendung in fmt
gegeben
%d, %i | vorzeichenbehaftete Ganzzahl (int) |
%o | vorzeichenlose Ganzahl im Oktalformat |
%u | vorzeichenlose Ganzzahl (unsigned int) |
%x | vorzeichenlose Ganzahl im Hexadezimalformat |
%f, %F | Gleitkommazahl (double) |
%e, %E | Gleitkommazahl (double) in Exponentialdarstellung |
%a, %A | Gleitkommazahl (double) in Hexadezimaldarstellung |
%s | Zeichenkette (const char *) |
%c | Ein Zeichen (char) |
Beispiel
[Bearbeiten]#include <curses.h> #include <stdlib.h> //noetig fuer atexit() void quit() { endwin(); } int main(void) { const int i = 23456; const double f = -12345e-3; initscr(); atexit(quit); curs_set(0); mvprintw(3, 2, "Eine Ganzzahl in Oktal- und Hexadezimaldarstellung: %o | %x\n", i, i); mvprintw(4, 2, "Eine Ganzzahl mit führenden Nullen: %010d\n", i); mvprintw(5, 2, "Eine Gleitkommazahl: %8.3f\n", f); mvprintw(6, 2, "Eine Gleitkommazahl: %8.3e\n", f); mvprintw(7, 2, "Eine Gleitkommazahl in Hexadezimaldarstellung: %a\n", f); refresh(); getch(); return(0); }
Texteingabe
[Bearbeiten]Eine Benutzeroberfläche ohne die Möglichkeit von Benutzereingaben ist in den meisten Fällen relativ nutzlos. Die ncurses-Bibliothek stellt eine Reihe von Funktionen für die Dateneingabe mittels Tastatur zur Verfügung.
Eingabe eines Zeichens
[Bearbeiten]int getch(void); int mvgetch(int y, int x); int ungetch(int ch); int wgetch(WINDOW *win);
getch
entspricht in etwa der getchar
-Funktion aus stdio.h
. ungetch
schreibt das Zeichen ch
zurück in die Eingabe-Queue. wgetch
ist eine Funktion für die Zeicheneingabe in eigens festgegelegten Fenstern. Die Programmierung von Fenstern wird aber erst in einem der folgenden Kapitel näher beschrieben.
Die Interpretation eines Return-Tastendrucks ist nicht einheitlich geregelt. Ncurses bietet zu diesem Zwecke zwei unterschiedliche Funktionen.
int nl(void); int nonl(void);
Bei der Verwendung von nl()
wird ein Return-Tastendruck (Zeilenendezeichen) als 0xA (10dec, LF, Line Feed) interpretiert. Bei der Verwendung von nonl()
entspricht ein Return-Tastendruck nur einem 0xD (13dec, CR, Carriage Return).
Eingabe einer Zeichenkette
[Bearbeiten]getstr(char *str); getnstr(char *str, int n); mvgetstr(int y, int x, char *str); mvgetnstr(int y, int x, char *str, int n);
Formatierte Eingabe
[Bearbeiten]int scanw(char *fmt, ...); int mvscanw(int y, int x, char *fmt, ...); int vwscanw(WINDOW *win, char *fmt, va_list varglist);
scanw
ist vergleichbar mit dem konventionellen scanf
.
Löschaktionen
[Bearbeiten]Ab und zu wird auch eine "tabula rasa"-Aktion fällig.
int clear(void); int clrtobot(void); int clrtoeol(void);
clear
löscht den gesamten Standardscreen. clrtobot
löscht die Inhalte von der aktuellen Cursorposition bis zum Ende des Screens. clrtoeol
löscht die Inhalte von der aktuellen Cursorposition bis zum Zeilenende.
Die Funktion
int deleteln(void);
löscht die gesamte aktuelle Zeile. Alle darauffolgenden Zeilen werden um eine Zeile nach oben verschoben. Andererseits fügt die Funktion
int insertln(void);
eine Leerzeile an der aktuellen Cursorposition ein. Alle folgenden Zeilen werden um eine Zeile nach unten verschoben.
Refresh
[Bearbeiten]Damit die Änderungen im stdscr
in den curscr
übernommen werden und somit der Bildschirm aktualisiert wird, ist folgende Anweisung vorhanden:
int refresh(void);
Scrolling
[Bearbeiten]int scroll(WINDOW *win); int scrl(int n);
scroll
verschiebt den Fensterinhalt um eine Zeile nach oben. scrl
verschiebt den Fensterinhalt von stdscr
um n
Zeilen nach oben.
Damit Scrolling funktioniert, muss vorab folgende Funktion aufgerufen werden.
int scrollok(WINDOW *win, bool bf);
Der Parameter bf
muss für die Aktivierung der Scrollfähigkeit natürlich auf TRUE
gesetzt werden.
Echo ein-/ausschalten
[Bearbeiten]Die Anzeige der Eingabedaten (das Echo) kann mittels der Funktion
noecho()
unterdrückt werden.
echo()
schaltet diese Anzeige wieder ein. Dies ist das Standardverhalten von ncurses.
Pieps und Blitz
[Bearbeiten]Manchmal kann auch ein kurzes Warnsignal an den Benutzer sinnvoll sein. Ncurses bietet zu diesem Zweck zwei standardmäßig vorhandene Funktionen:
int beep(void); int flash(void);
beep()
soll einen kurzen akustischen Ton und flash()
einen kurzen optischen "Flash" erzeugen. Das Ganze ist aber stark abhängig von den Fähigkeiten und Einstellungen des verwendeten Terminals. Besitzt das verwendete Terminal weder Audio- noch Flashfähigkeiten, dann erfolgt weder eine akustische noch eine visuelle Warnung. Teilweise können diese Signale vom Benutzer auch deaktiviert werden, so z.B. bei der KDE-Konsole. Der Gebrauch dieser Funktionen ist deshalb nur von eingeschränktem Nutzen.
gcc -lcurses
[Bearbeiten]Falls ncurses nicht funktioniert, dann sollte man die Compileroption -lcurses versuchen. Beispiel gcc main.c -o demo -lcurses
<<< ncurses-Startseite | ncurses | << Inhaltsverzeichnis |
< Einleitung | Farben und andere Attribute > |