\chapter{libCUI unter eisfair}

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

\section{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"ur den Farbmodus
sowie die Mauseingabe, die als Parameter an die Funktion
''WindowStart'' "ubergeben werden. Auch dazu geh"oren die Farbprofile,
die "uber ''WindowAddColScheme'' gesetzt werden.

\subsection{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"otigt ein Programm spezifische
Einstellungen, dann sollte es eine eigene Konfigurationsdatei
anlegen, die den Namen ''<<progname>>.cui.conf'' tr"agt.
Beispiel: ''/etc/myprog.cui.conf''.

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

\begin{verbatim}

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

...

\end{verbatim}

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''.


\subsection{Verarbeiten von Konfigurationsdateien}

Die libCUI sieht aus Gr"unden 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"achst erstmal die Funktion ''main'', die das Einlesen der
Konfiguration veranlasst, falls die Datei ''etc/cui.conf'' 
existiert:

\begin{verbatim}

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

\end{verbatim}

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

\begin{verbatim}

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

\end{verbatim}

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 "ubergeben wird.
Im Sinne der "ubersichtlichkeit wurde die Liste der Farbprofile auf
zwei gek"urzt.

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

\begin{verbatim}

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

\end{verbatim}

Wie zu sehen ist, wird hier der zur jeweiligen Farboption passende
Optionsname gebildet und dann an die Funktion ''TranslateColor''
"ubergeben. Erneut wurde das Listing zur besseren "ubersicht
gek"urzt.

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

\begin{verbatim}

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

\end{verbatim}

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

Um ein vollst"andiges Bild zu erhalten sei auf die Lekt"ure der
Datei ''main.c'' verwiesen, die in jedem libCUI-Programm zu finden
sein sollte.

