| <<< ncurses-Startseite | ncurses | << Inhaltsverzeichnis |
| < Menüs | Mausunterstützung > |
Ein Formular erzeugen und wieder löschen
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
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
Hintergrundattribute festlegen:
int set_field_fore(FIELD *field, chtype attr);
Vordergrundattribute festlegen:
int set_field_back(FIELD *field, chtype attr);
Beispiel
#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
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
#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
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)
// ... set_field_fore(fi[i], COLOR_PAIR(2)); set_field_back(fi[i], COLOR_PAIR(2)); set_field_just(fi[i], JUSTIFY_RIGHT); // ...

Feldoptionen
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
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
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
#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
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 > |
