Unterabschnitte

libCUI unter eisfair

Es gibt ein paar Gemeinsamkeiten und Richtlinien, die für CUI-Programme in der eisfair-Umgebung gelten. Diese werden hier angesprochen.

Farben und Konfiguration

Einstellungen, die die Darstellung und Funktion von libCUI- Programmen beeinflussen, werden der Bibliothek zur Laufzeit mitgeteilt. Dies sind z.B. die Einstellung für den Farbmodus sowie die Mauseingabe, die als Parameter an die Funktion ''WindowStart'' übergeben werden. Auch dazu gehören die Farbprofile, die über ''WindowAddColScheme'' gesetzt werden.

Aufbau der Konfigurationsdateien

CUI-Programme unter eisfair, die auf der libCUI- Bibliothek aufsetzen, verwenden als gemeinsame Konfiguration die Datei ''/etc/cui.conf''. Dort sind die Optionen hinterlegt, die allen Programmen gemeinsam sind. benötigt ein Programm spezifische Einstellungen, dann sollte es eine eigene Konfigurationsdatei anlegen, die den Namen ''«progname».cui.conf'' trägt. Beispiel: ''/etc/myprog.cui.conf''.

Die Datei ''/etc/cui.conf'' hat den folgenden Aufbau (gekürzt):

#--------------------------------------
# global options
#--------------------------------------

CUI_USE_COLORS='yes'                  
CUI_USE_MOUSE='no'                    

#--------------------------------------
# color scheme "WINDOW"
#--------------------------------------

CUI_WINDOW_WND_COLOR='BLUE'            
CUI_WINDOW_WND_SEL_COLOR='LIGHTGRAY'  
CUI_WINDOW_WND_TXT_COLOR='LIGHTGRAY'  
CUI_WINDOW_SEL_TXT_COLOR='BLACK'       
CUI_WINDOW_INACT_TXT_COLOR='DARKGRAY'  
CUI_WINDOW_HILIGHT_COLOR='YELLOW'      
CUI_WINDOW_TITLE_TXT_COLOR='BLACK'      
CUI_WINDOW_TITLE_BKG_COLOR='LIGHTGRAY' 
CUI_WINDOW_STATUS_TXT_COLOR='BLACK'     
CUI_WINDOW_STATUS_BKG_COLOR='LIGHTGRAY' 

#--------------------------------------
# color scheme "DESKTOP"
#--------------------------------------

...

Neben dem Farbschema ''WINDOW'' gibt es noch die Standardschemata ''DESKTOP'', ''DIALOG'', ''MENU'', ''TERMINAL'' und ''HELP''. Die Namen der Optionen enthalten dann anstelle von ''WINDOW'' den Namen des jeweiligen Schemas. Beispiel: ''CUI_HELP_WND_- COLOR'' anstelle von ''CUI_WINDOW_WND_COLOR''.

Verarbeiten von Konfigurationsdateien

Die libCUI sieht aus Gründen der Verallgemeinerung keinen Code vor, der ein automatisches Einlesen der Konfiguration erlaubt. Vielmehr ist das jeweils vom Hauptprogramm der Anwendung zu leisten, bevor der Fenstermodus aktiviert wird.

Ein Beispiel, das durchaus als Template verwendet werden kann, sieht wie folgt aus:

Zunächst erstmal die Funktion ''main'', die das Einlesen der Konfiguration veranlasst, falls die Datei ''etc/cui.conf'' existiert:

int
main(int argc, char* argv[])
{
   CUIWINDOW* window;

   /* read config file */
   if (FileExists("/etc/cui.conf"))
   {
      ReadConfig("/etc/cui.conf");
   }

   ...

   /* start cui subsystem */
   WindowStart(UseColors, UseMouse);
   atexit(quit);
   
   ...
   
   return WindowRun();
}

Dann die Funktion ''ReadConfig'', die mit Hilfe des Config-Parsers der libCUI die Datei einliest:

static int
ReadConfig(const char* filename)
{
   CONFIG*     cfg;
   CUIWINCOLOR colrec;

   cfg = ConfigOpen(ErrorOut, NULL);

   NumErrors = 0;
   NumWarnings = 0;
   ConfigReadFile(cfg, filename);

   UseColors = ConfigGetBool(cfg, 
                             NULL, 
                             "CUI_USE_COLORS", 
                             REQUIRED, 
                             "yes", 
                             NULL);
   UseMouse  = ConfigGetBool(cfg, 
                             NULL, 
                             "CUI_USE_MOUSE", 
                             REQUIRED, 
                             "no", 
                             NULL);
   if (ReadColorRec(cfg, "WINDOW", &colrec))
   {
      WindowAddColScheme("WINDOW", &colrec);
   }
   if (ReadColorRec(cfg, "DESKTOP", &colrec))
   {
      WindowAddColScheme("DESKTOP", &colrec);
   }

   ...

   ConfigClose(cfg);

   if ((NumErrors != 0) || (NumWarnings != 0))
   {
      char tmp;

      printf("%i error(s), %i warning(s)\n", 
             NumErrors, NumWarnings);
      printf("file: %s", "/etc/cui.conf\n");

      printf("\nPress ENTER to continue\n");
      scanf("%c", &tmp);
   }

   return (NumErrors == 0);
}

die Variablen ''NumErrors'' und ''NumWarnings'' sind global angelegte Ganzzahlenvariablen von Typ ''int''. Ebenso die Variablen ''UseColor'' und ''UseMouse''. Das Einlesen von Farbprofilen wird an die Funktion ''ReadColorRec'' delegiert, der der Name des Profils übergeben wird. Im Sinne der übersichtlichkeit wurde die Liste der Farbprofile auf zwei gekürzt.

Die Funktion ''ReadColorRec'' hat den folgenden Aufbau:

static int
ReadColorRec(CONFIG* cfg, const char* name, 
             CUIWINCOLOR* colrec)
{
   char option[128 + 1];

   sprintf(option, "CUI_%s_WND_COLOR", name);
   if (ConfigGetEntry(cfg, NULL, option, NULL))
   {
      colrec->WndColor = TranslateColor(cfg, 
                                        option, 
                                        "BLUE");

      sprintf(option, "CUI_%s_WND_SEL_COLOR", name);
      colrec->WndSelColor = TranslateColor(cfg, 
                                           option, 
                                           "LIGHTGRAY");

      sprintf(option, "CUI_%s_WND_TXT_COLOR", name);
      colrec->WndTxtColor = TranslateColor(cfg, 
                                           option, 
                                           "LIGHTGRAY");

      ...
      
      return TRUE;
   }
   return FALSE;
}

Wie zu sehen ist, wird hier der zur jeweiligen Farboption passende Optionsname gebildet und dann an die Funktion ''TranslateColor'' übergeben. Erneut wurde das Listing zur besseren übersicht gekürzt.

Zu guter Letzt nun noch das Listing der Funktion ''TranslateColor'':

static int
TranslateColor(CONFIG* cfg, const char* option, 
               const char* defval)
{
   int col = BLACK;
   const char* color;
   
   color = ConfigGetString(cfg, 
                           NULL, 
                           option, 
                           OPTIONAL, 
                           defval, 
                           NULL);

   if (strcasecmp(color,"BLACK") == 0)             
      col = BLACK;
   else if (strcasecmp(color,"RED") == 0)          
      col = RED;
   else if (strcasecmp(color,"GREEN") == 0)        
      col = GREEN;
   else if (strcasecmp(color,"BROWN") == 0)        
      col = BROWN;
   else if (strcasecmp(color,"BLUE") == 0)         
      col = BLUE;
   else if (strcasecmp(color,"MAGENTA") == 0)      
      col = MAGENTA;
   else if (strcasecmp(color,"CYAN") == 0)         
      col = CYAN;
   else if (strcasecmp(color,"LIGHTGRAY") == 0)    
      col = LIGHTGRAY;
   else if (strcasecmp(color,"DARKGRAY") == 0)     
      col = DARKGRAY;
   else if (strcasecmp(color,"LIGHTRED") == 0)     
      col = LIGHTRED;
   else if (strcasecmp(color,"LIGHTGREEN") == 0)   
      col = LIGHTGREEN;
   else if (strcasecmp(color,"YELLOW") == 0)       
      col = YELLOW;
   else if (strcasecmp(color,"LIGHTBLUE") == 0)    
      col = LIGHTBLUE;
   else if (strcasecmp(color,"LIGHTMAGENTA") == 0) 
      col = LIGHTMAGENTA;
   else if (strcasecmp(color,"LIGHTCYAN") == 0)    
      col = LIGHTCYAN;
   else if (strcasecmp(color,"WHITE") == 0)        
      col = WHITE;
   else
   {
      CONFENTRY* entry = ConfigGetEntry(cfg, NULL, 
                                        option, NULL);
      if (entry)
      {
         ErrorOut(NULL, 
                  "invalid color definition", 
                  "", 
                  entry->LineNo, 
                  FALSE);
      }
      col = BLACK;
   }
   return col;
}

Hier wird nun die Option aus der Datei ausgelesen und anhand von String-Vergleichen in eine Konstante umgewandelt. Die gefundene Farbkonstante wird als Rückgabewert zurückgegeben. Falls ein unsinniger Wert in der Konfigurationsdatei steht, erfolgt eine Fehlermeldung über die Funktion ''ErrorOut''.

Um ein vollständiges Bild zu erhalten sei auf die Lektüre der Datei ''main.c'' verwiesen, die in jedem libCUI-Programm zu finden sein sollte.

Holger Bruenjes 2016-12-12