Ncurses: Formulare
<<< ncurses-Startseite | ncurses | << Inhaltsverzeichnis |
< Menüs | Mausunterstützung > |
Ein Formular erzeugen und wieder löschen
[Bearbeiten]Der Auf- und Abbau von Formularen folgt dem gleichen Prinzip wie bei Menüs.
Die Erzeugung eines Formulars untergliedert sich in folgende Schritte:
- Speicherplatz für die Formularfelder reservieren: z.B. mittels
calloc
-Funktion - Formularfelder erzeugen:
FIELD *new_field(int height, int width, int toprow, int leftcol, int offscreen, int nbuffers);
FIELD *dup_field(FIELD *field, int toprow, int leftcol);
FIELD *link_field(FIELD *field, int toprow, int leftcol);
- Formular erzeugen:
FORM *new_form(FIELD **fields);
- Formular "posten":
int post_form(FORM *form);
Zu beachten ist, dass das letzte Formularfeld zwingend ein Null-Pointer sein muss.
Das "Abbauen" eines Formulars geschieht in umgekehrter Reihenfolge:
- Formular "unposten":
int unpost_form(FORM *form);
- Formular freigeben:
int free_form(FORM *form);
- Felder freigeben:
int free_field(FIELD *field);
- Reservierten Feld-Speicherplatz freigeben:
free
-Funktion
Der Formulartreiber
[Bearbeiten]Eingabeereignisse für ein Formular werden durch den Formulartreiber abgearbeitet.
int form_driver(FORM *form, int c);
Welche Aktion konkret ausgeführt werden soll, wird durch den Parameter c
bestimmt. Eine schiere Unzahl von Optionen ist verfügbar. Nachfolgend werden nur ein paar dieser Request-Optionen aufgelistet:
REQ_NEXT_FIELD | Cursor zum nächsten Feld bewegen |
REQ_PREV_FIELD | Cursor zum vorherigen Feld bewegen |
REQ_FIRST_FIELD | Cursor zum ersten Feld bewegen |
REQ_LAST_FIELD | Cursor zum letzten Feld bewegen |
REQ_BEG_LINE | Cursor zum Zeilenanfang bewegen |
REQ_END_LINE | Cursor zum Zeilenende bewegen |
REQ_LEFT_CHAR | Cursor im Feld nach links bewegen |
REQ_RIGHT_CHAR | Cursor im Feld nach rechts bewegen |
REQ_UP_CHAR | Cursor im Feld nach oben bewegen |
REQ_DOWN_CHAR | Cursor im Feld nach unten bewegen |
REQ_INS_CHAR | An der Cursorposition ein Leerzeichen einfügen |
REQ_DEL_CHAR | An der Cursorposition ein Zeichen löschen |
REQ_DEL_PREV | Das Zeichen vor der Cursorposition löschen |
REQ_CLR_FIELD | Das ganze Formularfeld löschen |
REQ_OVL_MODE | Überschreibmodus aktivieren |
REQ_INS_MODE | Einfügemodus aktivieren |
Feldfarben und andere Darstellungsattribute
[Bearbeiten]Hintergrundattribute festlegen:
int set_field_fore(FIELD *field, chtype attr);
Vordergrundattribute festlegen:
int set_field_back(FIELD *field, chtype attr);
Beispiel
[Bearbeiten]#include <form.h> #include <stdlib.h> FIELD **fi; FORM *fo; void quit(void) { int i; unpost_form(fo); free_form(fo); for(i=0; i<=3; i++) { free_field(fi[i]); } free(fi); endwin(); } int main(void) { int ch, i; initscr(); atexit(quit); clear(); noecho(); cbreak(); keypad(stdscr, TRUE); start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLUE); init_pair(2, COLOR_BLACK, COLOR_WHITE); bkgd(COLOR_PAIR(1)); fi = (FIELD **)calloc(4, sizeof(FIELD *)); fi[0] = new_field(1, 10, 2, 3, 0, 0); fi[1] = new_field(1, 10, 2, 18, 0, 0); fi[2] = new_field(1, 15, 2, 33, 0, 0); fi[3] = 0; for(i=0; i<3; i++) { set_field_fore(fi[i], COLOR_PAIR(2)); set_field_back(fi[i], COLOR_PAIR(2)); } fo = new_form(fi); post_form(fo); mvaddstr(2, 15, "+"); mvaddstr(2, 30, "="); mvaddstr(5, 3, "Programm mittels F1-Funktionstaste beenden"); refresh(); while((ch=getch()) != KEY_F(1)) { switch(ch) { case KEY_RIGHT: form_driver(fo, REQ_NEXT_FIELD); break; case KEY_LEFT: form_driver(fo, REQ_PREV_FIELD); break; default: /* Feldeingabe */ form_driver(fo, ch); } } return (0); }
Compilieren, Linken:
gcc -o bsp bsp.c -lform -lncurses
Zugriff auf den Formularfeldpuffer
[Bearbeiten]Auf ein bestimmtes Feld zugreifen:
FIELD *current_field(const FORM *); int field_index(const FIELD *field);
Feldpuffer auslesen:
char *field_buffer(const FIELD *field, int buffer);
Feldpuffer belegen:
int set_field_buffer(FIELD *field, int buf, const char *value);
Beispiel
[Bearbeiten]#include <form.h> #include <stdlib.h> #include <string.h> FIELD **fi; FORM *fo; void quit(void) { int i; unpost_form(fo); free_form(fo); for(i=0; i<=3; i++) { free_field(fi[i]); } free(fi); endwin(); } int main(void) { int ch, i; initscr(); atexit(quit); clear(); noecho(); cbreak(); keypad(stdscr, TRUE); start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLUE); init_pair(2, COLOR_BLACK, COLOR_WHITE); bkgd(COLOR_PAIR(1)); fi = (FIELD **)calloc(4, sizeof(FIELD *)); fi[0] = new_field(1, 10, 2, 3, 0, 0); fi[1] = new_field(1, 10, 2, 18, 0, 0); fi[2] = new_field(1, 15, 2, 33, 0, 0); fi[3] = 0; for(i=0; i<3; i++) { set_field_fore(fi[i], COLOR_PAIR(2)); set_field_back(fi[i], COLOR_PAIR(2)); } fo = new_form(fi); post_form(fo); mvaddstr(2, 15, "+"); mvaddstr(2, 30, "="); mvaddstr(5, 3, "Programm mittels F1-Funktionstaste beenden"); refresh(); while((ch=getch()) != KEY_F(1)) { switch(ch) { case KEY_RIGHT: { char str[20]; form_driver(fo, REQ_NEXT_FIELD); if(field_index(current_field(fo)) == 2) { snprintf(str, 20, "%s%s", field_buffer(fi[0], 0), field_buffer(fi[1], 0)); set_field_buffer(fi[2], 0, str); refresh(); } break; } case KEY_LEFT: form_driver(fo, REQ_PREV_FIELD); break; default: /* Feldeingabe */ form_driver(fo, ch); } } return (0); }
Textausrichtung
[Bearbeiten]Die Ausrichtung eines Textes im Formularfeld ist mittels
int set_field_just(FIELD *field, int justification);
einstellbar.
Mögliche Ausrichtungsoptionen sind:
- JUSTIFY_RIGHT
- JUSTIFY_LEFT
- JUSTIFY_CENTER
- NO_JUSTIFICATION
Beispiel (Programmausschnitt)
[Bearbeiten]// ... set_field_fore(fi[i], COLOR_PAIR(2)); set_field_back(fi[i], COLOR_PAIR(2)); set_field_just(fi[i], JUSTIFY_RIGHT); // ...
Feldoptionen
[Bearbeiten]Selbstverständlich gibt es auch für Formularfelder ein Menge Optionen. Gesetzt und abgefragt werden können sie mit diesen Funktionen:
int set_field_opts(FIELD *field, OPTIONS opts); int field_opts_on(FIELD *field, OPTIONS opts); int field_opts_off(FIELD *field, OPTIONS opts); OPTIONS field_opts(const FIELD *field);
Einige der möglichen Optionen sind:
O_VISIBLE | Formularfeldsichtbarkeit |
O_ACTIVE | Feld ist aktiv |
O_PUBLIC | Text ist bei der Eingabe sichtbar (z.B. bei Passworteingaben diese Option deaktivieren) |
O_EDIT | Im Feld kann editiert werden |
O_WRAP | Zeilenumbbruch |
O_AUTOSKIP | Wenn Feld vollgeschrieben ist, gehe automatisch zum nächsten Feld |
O_STATIC | Ein Feld kann nur die Zeichenanzahl entsprechend der Formularfeldgröße aufnehmen. Werden mehr Zeichen eingegeben so wird zum nächsten Formularfeld gesprungen. Ist O_AUTOSKIP deaktiviert, so werden zusätzliche Zeichen ignoriert. Ist O_STATIC ausgeschaltet, so kann das Formularfeld über die Formularfeldgröße Zeichen aufnehmen (die Darstellung wird gescrollt). |
Beispiel: Auswirkungen O_AUTOSKIP und O_STATIC
[Bearbeiten]Beim Eintippen der Zeichenkette "Das ist nicht OK" in ein Formularfeld passiert je nach gesetzten Optionen folgendes
O_AUTOSKIP an, O_STATIC an (Standard): | |
O_AUTOSKIP aus: | |
O_STATIC aus: |
Formularfeldtypen
[Bearbeiten]Oft ist es sinnvoll und notwendig die Eingabemöglichkeiten in ein Formularfeld einzuschränken (z.B. nur Zahlen oder alphabetische Zeichen sind erlaubt). Dies ist mit der form-Bibliothek recht weitgehend möglich. Mit der Funktion
int set_field_type(FIELD *field, FIELDTYPE *type, ...);
lassen sich die Feldtypen einstellen. Folgende Alternativen sind möglich
TYPE_ALPHA | nur Alphabetzeichen sind erlaubt |
TYPE_ALNUM | Alphanumerische Zeichen sind erlaubt |
TYPE_ENUM | Nur Einträge aus einer Stringliste sind erlaubt |
TYPE_INTEGER | Nur ganze Zahlen sind erlaubt (optional mit vorangestelltem + oder -) |
TYPE_NUMERIC | Numerische Daten (optional mit vorangestelltem + oder - und mit Dezimalpunkt) |
TYPE_REGEXP | Feldeintrag muss zu einem regulären Ausdruck passen |
TYPE_IPV4 | Eine IPv4-Adresse |
Es können auch eigene Formularfeldtypen festgelegt werden. Die Abhandlung dieses Themas würde jedoch im Rahmen dieses Tutorials zu weit führen. Nachfolgend ein einfaches Beispiel mit INTEGER- und NUMERIC-Formularfeldern.
Beispiel
[Bearbeiten]#include <form.h> #include <stdlib.h> FIELD **fi; FORM *fo; void quit(void) { int i; unpost_form(fo); free_form(fo); for(i=0; i<=3; i++) { free_field(fi[i]); } free(fi); endwin(); } int main(void) { int ch, i; initscr(); atexit(quit); clear(); noecho(); curs_set(0); cbreak(); keypad(stdscr, TRUE); start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLUE); init_pair(2, COLOR_BLACK, COLOR_WHITE); bkgd(COLOR_PAIR(1)); fi = (FIELD **)calloc(4, sizeof(FIELD *)); fi[0] = new_field(1, 10, 2, 3, 0, 0); fi[1] = new_field(1, 10, 2, 18, 0, 0); fi[2] = new_field(1, 15, 2, 33, 0, 0); fi[3] = 0; for(i=0; i<3; i++) { set_field_fore(fi[i], COLOR_PAIR(2)); set_field_back(fi[i], COLOR_PAIR(2)); field_opts_off(fi[i], O_AUTOSKIP); } set_field_type(fi[0], TYPE_INTEGER, 0, -9999999, 9999999); set_field_type(fi[1], TYPE_NUMERIC, 3, -9999999.999, 9999999.999); field_opts_off(fi[2], O_EDIT); fo = new_form(fi); post_form(fo); mvaddstr(2, 15, "+"); mvaddstr(2, 30, "="); mvaddstr(5, 3, "Programm mittels F1-Funktionstaste beenden"); refresh(); while((ch=getch()) != KEY_F(1)) { switch(ch) { case KEY_RIGHT: { double z1, z2; char str[20]; form_driver(fo, REQ_NEXT_FIELD); if(field_index(current_field(fo)) == 2) { z1 = atof(field_buffer(fi[0], 0)); z2 = atof(field_buffer(fi[1], 0)); snprintf(str, 20, "%f", z1+z2); set_field_buffer(fi[2], 0, str); refresh(); } break; } case KEY_LEFT: form_driver(fo, REQ_PREV_FIELD); break; default: /* Feldeingabe */ form_driver(fo, ch); } } return (0); }
Formularfenster
[Bearbeiten]Das Zuweisen von Haupt- und Unterfenster geschieht äquivalent der Vorgehensweise bei einem Menü.
int set_form_win(FORM *form, WINDOW *win); int set_form_sub(FORM *form, WINDOW *sub); int scale_form(const FORM *form, int *rows, int *columns);
<<< ncurses-Startseite | ncurses | << Inhaltsverzeichnis |
< Menüs | Mausunterstützung > |