ein Kapitel zurück                                           ein Kapitel weiter

Wollen wir uns nun Möglichkeiten ansehe, wie wir mittes ncurses, Zeichen von der Tastatur einlesen und wieder ausgeben können.

Zuerst Funktionen zu den Optionen der Tastaturein/ausgabe.......

DER TASTATURMODUS


int cbreak(void);
int nobreak(void);  

Mit diesen beiden Funktionen können sie das Puffern (Zeilenweise unter Linux) abstellen (cbreak) oder wieder aktivieren (nobreak). Mit cbreak() bearbeitet der Tastaturtreiber nur noch die Tastenkombination CTRL+S und CTRL+Q und CTRL+C Standardmäßig ist unter Linux logischweise (auch unter ncurses) der Puffer eingeschalten.

Wollen sie auch das noch unterbinden gibt es die Funktion....

int raw(void);  

Damit wäre Ihre Tastatur quasi nicht mehr einsetzbar. Rückgängig machen sie die Funktion raw() mit......

int noraw(void)  

Damit keine Tasturcodes oder Zeichen mehr auf dem Bildschrim ausgegeben werden, verwendet ncurse die Funktion.....

int noecho(void);  

...welche übrigens die Voreinstellung ist. Rückgängig machen können sie noecho (keine Ausgabe) mit......

int echo(void);  

Jetzt nur noch die Funktion.....

int keypad(WINDOW *win, bool bf);  

...womit wir testen können ob die Tasten wie z.B. Cursor UP, Page down, Home, Cursor DOWN, End, F1 ......usw. betätigt haben. Die Variable WINDOW *win haben wir berreits am Anfang bei initscr() initialisiert (stdscr) und mit bool bf können sie TRUE für wahr oder FALSE für falsch einsetzen. Mit....

keypad(stdscr,TRUE);  

...legen sie das Verhalten für den gesamten Bildschirm fest und gibt den Wert für die Funktions-und Cursortasten zurück.

EIN UND AUSGABE

Um Ausgabefunktionen von Curses zu aktivieren muss die Routine...

refresh();  

...aufgerufen werden. Aber dazu später mehr.
Bei Curses haben fast alle Routinen zur Ein und Ausgabe zwei Varianten. Zum einen die normalen und zum anderen die mit einem mv-Präfix beginnen. Beide Schreibweisen sind die selben nur das wir mit dem mv-Präfix (mv=move) den Cursor erst auf die Position y,x stellen. Achtung falls sie die Koordinaten von conio.h noch im Kopf haben (x,y), bei curses geben wir zuerst die y-Koordinate und dann die x-Koordinaten an.

int getch(void);
int mvgetch(int y, int x);  

Mit der Funktion getch() lesen wir ein Zeichen von der Tastatur ein. mvgetch(y,x) hat die selbe Funktion nur eben noch mit den Koordinaten y und x.(Zeile und Spalte). getch() ist natürlich auch abhängig von cbreak(),raw() und nocbreak(),noraw()(siehe Kapitel zuvor). Mit getch() können ja auch Werte jenseits von 0...255 zurückgegeben werden. Dadurch können sie auch wenn wir die Funktionstastenerkennung keypad(stdscr,TRUE) aktiviert wurde den Integerwert zurückgeben.....

/*Download:cur2.c*/
#include <curses.h> int main() { int c,x=1; while(x) { initscr(); /*curses initialisieren*/ keypad(stdscr,TRUE); while((c=getch()) == KEY_DOWN || c==KEY_UP || c==KEY_LEFT || c==KEY_RIGHT); x=0; } endwin(); return 0; }

Wenn wir das Programm ausführen aktivieren wir mit keypad(stdscr,TRUE) die Cursor- und Funktionstasten. In unserem Fall können sie solange die Tasten Pfeilnachunten, Pfeilnachoben,Pfeilnachrechts und Pfeilnachlinks (KEY_DOWN,KEY_UP,KEY_RIGHT,KEY_LEFT) drücken und es wird nichts passieren. Sollten sie aber eine Andere außer den 4 Tasten betätigen wird das Programm beendet. Unter anderem sind außer den Tasten KEY_DOWN,KEY_UP,KEY_RIGHT,KEY_LEFT noch folgende Tastaturcodes in der Headerdatei curses.h definiert.....

#define KEY_CODE_YES 0400 /* A wchar_t contains a key code */
#define KEY_MIN 0401     /* Minimum curses key */
#define KEY_BREAK 0401    /* Break key (unreliable) */
#define KEY_DOWN 0402    /* Down-arrow */
#define KEY_UP 0403     /* Up-arrow */
#define KEY_LEFT 0404    /* Left-arrow */
#define KEY_RIGHT 0405    /* Right-arrow */
#define KEY_HOME 0406     /* Home key (upward+left arrow) */
#define KEY_BACKSPACE 0407    /* Backspace (unreliable) */
#define KEY_F0 0410    /* Function keys. Space for 64 */
#define KEY_F(n) (KEY_F0+(n))    /* Value of function key n */
#define KEY_DL 0510     /* Delete line */
#define KEY_IL 0511     /* Insert line */
#define KEY_DC 0512    /* Delete character */
#define KEY_IC 0513    /* Insert char or enter insert mode */
#define KEY_EIC 0514    /* Exit insert char mode */
#define KEY_CLEAR 0515    /* Clear screen */
#define KEY_EOS 0516    /* Clear to end of screen */
#define KEY_EOL 0517    /* Clear to end of line */
#define KEY_SF 0520    /* Scroll 1 line forward */
#define KEY_SR 0521    /* Scroll 1 line backward (reverse) */
#define KEY_NPAGE 0522    /* Next page */
#define KEY_PPAGE 0523    /* Previous page */
#define KEY_STAB 0524    /* Set tab */
#define KEY_CTAB 0525    /* Clear tab */
#define KEY_CATAB 0526    /* Clear all tabs */
#define KEY_ENTER 0527    /* Enter or send (unreliable) */
#define KEY_SRESET 0530    /* Soft (partial) reset (unreliable) */
#define KEY_RESET 0531    /* Reset or hard reset (unreliable) */
#define KEY_PRINT 0532    /* Print */
#define KEY_LL 0533    /* Home down or bottom (lower left) */  

Natürlich waren das noch nicht alle. Weiter Funktionstasten können sie unter /usr/include/curses.h nachlesen.

Zwei Funktionen zur Eingabe von Strings sind...

int getstr(char *string);
int getnstr(char *string, int n);  

getstr() entspricht der Version die sie mit gets() bereits kennen. Und getnstr() ist ähnlich von fgets(). Es wird empfohlen getnstr() zu benutzten, da durch den zusätzlichen Parameter n ein Pufferüberlauf verhindert werden kann. Als Alternativen zur genauen Cursorpositionierung gibt es auch hier die mv-Funktionen....

int mvgetstr(char *string);
int mvgetstr(int y, int x, char *string, int n);  

Hierzu noch ein kurzes Programmbeispiel....

/*Download:cur3.c*/
#include <curses.h> #define MAX 100 int main() { char string[MAX]; char string2[MAX]; initscr(); /*curses initialisieren*/ getnstr(string,MAX); mvgetnstr(10,20,string2,MAX); endwin(); /*und beenden*/ printf("Die 1.Eingabe lautet : %s \n",string); printf("Die 2.Eingabe lautet : %s \n",string2); return 0; }

Dann gibt es eigentlich nur noch die Funktion....

int ungetch(char zeichen);  

...womit wir ein Zeichen wieder zurück in den Eingabepuffer schicken.

Kommen wir jetzt zu den Ausgabe-Funktionen von curses.h . Alle Ausgabe-Funktionen müssen mit....

int refresh();  

...aktiviert werden um auf dem Bildschirm etwas anzuzeigen.

int move(int y, int x);  

Mit move positionieren wir unseren Cursor in der y-ten Zeile und x-ten Spalte.

int deleteln(void);  

Mit deleteln löschen wir die Zeile in der unser Cursor gerade steht. Die unteren Zeilen werden nach oben gezogen.

int insertln(void);  

Mit insertln fügen wir eine Leerzeile über der aktuellen Zeile unseres Cursors ein. Die unterste Zeile geht dabei verloren.

int insdelln(int anzahl);  

Mit insdelln fügen wir anzahl Zeilen über die aktuelle Cursorposition ein und schiebt die unteren Zeilen nach unten. Dadurch gehen die untersten anzahl Zeichen verloren.

int printw(char *format, ...);
int mvprintw(int y, int x, char *format, ...);  

printw ist gleichwertig mit mit printf aus der C-Standartbibliothek und mit mvprintw ersparen wir uns die Funktion move(). Mit printw sind keine ACS_ Sonderzeichen darstellbar da char nur 8 Bit breit ist. Was ACS_ Sonderzeichen sind erfahren sie gleich. Wir Zeit wieder ein kleines Beispielprogramm mit dem bisher Erlernten zu schreiben :

/*Download:cur4.c*/
#include <curses.h> #define MAX 100 int main() { char string[MAX],p[1]; char string2[MAX]; char string3[] = "Dies ist der neue String3\n"; int c; initscr(); /*curses initialisieren*/ printw("Bitte Eingabe für String machen : "); getnstr(string,MAX); mvprintw(3,0,"Bitte Eingabe für 2. String machen : "); getnstr(string2,MAX); mvprintw(7,20,"String ist gleich : %s\n",string); mvprintw(8,20,"Diese Zeile wird nun mit deleteln() gelöscht\n"); mvprintw(9,20,"String 2 ist gleich : %s\n",string2); mvprintw(14,20,"Weiter mit TASTE"); noecho(); c=getch(); move(8,20); deleteln(); /*Zeile löschen*/ noecho(); c=getch(); move(8,20); insertln(); /*Leerzeile einfügen*/ mvprintw(8,20,string3); noecho(); c=getch(); clear(); /*Bildschirm löschen*/ refresh(); mvprintw(12,38,"ENDE"); halfdelay(20); /*Wartet 20 Zehntelsec. auf getch()*/ /*ansonsten beendet sich das Progr. selber*/ c=getch(); endwin(); return 0; }



int addch(chtype zeichen);  

Mit addch() geben wir ein Zeichen an der aktuellen Position aus. Der Typ chtype kann 32 - Bit Werte aufnehmen und dadurch können wir Attribute setzen mit dem Bitweisen ODER-Operator '|'. Das heißt wir können Attribute mit dem Zeichen verknüpfen. Folgende Sonderzeichen können wir damit darstellen....

#define ACS_ULCORNER (acs_map['l']) /* upper left corner */
#define ACS_LLCORNER (acs_map['m'])     /* lower left corner */
#define ACS_URCORNER (acs_map['k'])     /* upper right corner */
#define ACS_LRCORNER (acs_map['j'])    /* lower right corner */
#define ACS_LTEE (acs_map['t'])    /* tee pointing right */
#define ACS_RTEE (acs_map['u'])    /* tee pointing left */
#define ACS_BTEE (acs_map['v'])    /* tee pointing up */
#define ACS_TTEE (acs_map['w'])    /* tee pointing down */
#define ACS_HLINE (acs_map['q'])    /* horizontal line */
#define ACS_VLINE (acs_map['x'])    /* vertical line */
#define ACS_PLUS (acs_map['n'])    /* large plus or crossover */
#define ACS_S1 (acs_map['o'])    /* scan line 1 */
#define ACS_S9 (acs_map['s'])    /* scan line 9 */
#define ACS_DIAMOND (acs_map['`'])    /* diamond */
#define ACS_CKBOARD (acs_map['a'])    /* checker board (stipple) */
#define ACS_DEGREE (acs_map['f'])    /* degree symbol */
#define ACS_PLMINUS (acs_map['g'])    /* plus/minus */
#define ACS_BULLET (acs_map['~'])    /* bullet */  

Bei folgenden Typen kann es passieren das Diese nicht richtig dargestellt werden. Als Alternative werden stattdessen einfache ASCII-Zeichen dargestellt. Z.B. für Pfeil nach Links '<' Pfeil nach rechts '>' ...

/* Teletype 5410v1 symbols begin here */
#define ACS_LARROW (acs_map[','])    /* arrow pointing left */
#define ACS_RARROW (acs_map['+'])    /* arrow pointing right */
#define ACS_DARROW (acs_map['.'])    /* arrow pointing down */
#define ACS_UARROW (acs_map['-'])    /* arrow pointing up */
#define ACS_BOARD (acs_map['h'])    /* board of squares */
#define ACS_LANTERN (acs_map['i'])     /* lantern symbol */
#define ACS_BLOCK (acs_map['0'])     /* solid square block */  

Zur Demonstration will ich Ihnen ein kleines Beispiel schreiben. Wir Zeichnen einen einfachen Würfel und schreiben mitten in den Würfel ein Wort :

/*Download:cur5.c*/
#include <curses.h> int main() { int i,j; initscr(); addch(ACS_ULCORNER); for(i=0; i<20; i++) addch(ACS_HLINE); addch(ACS_URCORNER); addch('\n'); for(i=0; i<10; i++) for(j=0; j<=21; j++) if(j==0) addch(ACS_VLINE); else if(j==21) { addch(ACS_VLINE); addch('\n'); } else addch(' '); addch(ACS_LLCORNER); for(i=0; i<20; i++) addch(ACS_HLINE); addch(ACS_LRCORNER); addch('\n'); mvprintw(5,7,"<TASTE>"); getch(); endwin(); return 0; }




So siehts aus:



Natürlich gibt es außer addch auch noch....

int addstr(char *string);  

...womit wir einen ganzen String ausgeben können oder.....

int addnstr(char *string, int anzahlzeichen);  

....Beispiel....

addstr("Hallo Welt");  

...oder...

addnstr("Hallo Welt",5);    //Wird nur Hallo ausgegeben  

Natürlich gibt es auch bei diesen Positionen weiter mit dem vorangestellten mv-Präfix zum Positionieren. Es gibt da noch mehr Funktionen dieser Art. Lesen sie bitte dazu...

man addstr  

...die Man-Pages dazu falls noch weitere benötigen. Ehemalige MS-DOS´ler sehen schon das dort wo conio.h aufhört fängt curses.h erst an!



int clrtobot(void);  

Damit löschen wir den Bildschirm von der aktuelle Position aus.

int clrtoeol(void);  

Damit löschen wir den Rest (nicht die ganze Zeile) der Zeile in der der Cursor steht.

int delch(void);
int mvdelch(int y, int x);  

Damit können sie das Zeichen löschen auf dem der Cursor steht. Alle weiter Zeichen in der gleichen Zeile werden um ein Position nach links versetzt. Beispiel:

/*Download:cur6.c*/
#include <curses.h> int main() { initscr(); mvprintw(5,5,"Diese Zeile enthält einen Fehhler"); mvprintw(6,5,"Bitte Taste drücken für Fehlerkorrektur"); getch(); mvdelch(5,33); mvprintw(7,5,"Fehler wurde koregiert! Bitte Taste drücken!"); getch(); endwin(); return 0; }

In diesem Programm haben wir das Wort 'Fehhler' mit zwei 'h' geschrieben und wollen diesen Fehler mittels mvdelch(y,x) löschen.

int erase(void);
int clear(void);  

Beide Funktionen löschen den Bildschirm. Mit clear() wird bei dem nächsten refresh() Aufruf der Bildschirm komplett neu Ausgegeben.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf