Ncurses: Formulare


<<< ncurses-Startseite ncurses << Inhaltsverzeichnis
< Menüs Mausunterstützung >


Ein Formular erzeugen und wieder löschenBearbeiten

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 FormulartreiberBearbeiten

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 DarstellungsattributeBearbeiten

Hintergrundattribute festlegen:

 int set_field_fore(FIELD *field, chtype attr);

Vordergrundattribute festlegen:

int set_field_back(FIELD *field, chtype attr);

BeispielBearbeiten

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

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);

BeispielBearbeiten

#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);  
}


 

TextausrichtungBearbeiten

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);
   // ...

 

FeldoptionenBearbeiten

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_STATICBearbeiten

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:  

FormularfeldtypenBearbeiten

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.

BeispielBearbeiten

#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);  
}

 

FormularfensterBearbeiten

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 >