/*********************************************************************/
/*  bibView: Administration of BibTeX-Databases                      */
/*           (Verwaltung von BibTeX-Literaturdatenbanken)            */
/*                                                                   */
/*  Module:  rc_file.c                                               */
/*                                                                   */
/*             - Handling of Configuration files                     */
/*             -                                                     */
/*                                                                   */
/*  Author:  Holger Martin,  martinh@informatik.tu-muenchen.de       */
/*           Peter M. Urban, urban@informatik.tu-muenchen.de         */
/*                                                                   */
/*  History:                                                         */
/*    11.22.91  HM   created                                         */
/*    05.26.92       Version 1.0 released                            */
/*                                                                   */
/*  Copyright 1992 TU MUENCHEN                                       */
/*    See ./Copyright for complete rights and liability information. */
/*                                                                   */
/*********************************************************************/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <sys/param.h>
#include <sys/stat.h>

#include "bibview.h"

/* imported global variables */
/* ------------------------- */


/* macros and definitions */
/* ---------------------- */
#define STR_TRUE 		"TRUE"
#define STR_BEEP_ON_ERROR_OPT	"BeepOnError"
#define STR_ICON_ON_DESK_OPT	"IconsOnDesk"
#define STR_MAKE_BACKUPS_OPT	"MakeBackups"
#define STR_AUTO_CHECK_BIB_OPT	"AutoCheckBib"
#define STR_REQUIRED_FIELDS_OPT "RequiredFields"
#define STR_IGNORE_CASE         "IgnoreCase"
#define STR_PRINT_AS_BIB        "PrintAsBib"
#define STR_DISPLAY_ERRWIN      "DisplayErrWin"

#define STR_FLDINDENT           "fldindent"
#define STR_CONTINDENT          "contindent"
#define STR_NEWLINEINDENT       "newlineindent"
#define STR_MAXLINELEN          "maxlinelen"

#define MAX_TAGLEN		80
#define MAX_CFGLINELEN		255

typedef enum {
   findTag,         /* Modus: Suche nach Tag in Konfigdatei        */
   illegalTag,      /*        Tag gefunden, aber ungueltig         */
   optionTags,      /*        Optionen-Tag, jetzt folgen Optionen  */ 
   userFldTags,     /*        Benutzerdefinierte Felder folgen     */
   predefTags,      /*        Vordefinierte Feldinhalte  folgen    */
   latexHeadTags,   /*        Kopfzeilen der LaTeX-Druckdatei      */
   latexFootTags,   /*        Fusszeilen der LaTeX-Druckdatei      */
   indentTags,      /*        indentation in BibTeX Format         */
   sortedByTags,    /*        default how List is Sorted           */
   sortFieldTags,   /*        fields by which files can be sorted  */
   searchFieldTags, /*        fields considered in a search        */
   annoteFieldTags, /*        name of annote field                 */
   styleFileTags,   /*        default Style File                   */
   listFieldTags,   /*        layout of list entry                 */
   typeTags,        /*        define new types                     */
   defaultDirTags   /*        default Directory                    */
} CfgMode;

typedef struct {
   char *tagStr;
   CfgMode mode;
} TagType;


/* local function prototypes */
/* ------------------------- */
static CfgMode  getCfgFileTag        (char *str);
static int      procOptionLine       (char *str);
static int      procPredefLine       (char *str);
static int      procUserFldLine      (char *str);
static int      procLatexHeadLine    (char *str);
static int      procLatexFootLine    (char *str);
static int      procIndentLine       (char *str);
static int      procTypeLine         (char *str);
static int      procSortFieldLine    (char *str);
static int      procSortedByLine     (char *str);
static int      procStyleFileLine    (char *str);
static int      procSearchFieldLine  (char *str);
static int      procListFieldLine    (char *str);
static int      procAnnoteFieldLine  (char *str);
static int      build_path 	     (char *str1, char *str2);


/* exported variables */
/* ------------------ */
UserDefFld userDefFlds[MAX_BIBTEX_TYPES+1];

PredefLists predefLst;

char *latexHeader = NULL;
int latexHeaderLen = 0;
char *latexFooter = NULL;
int latexFooterLen = 0;
int fld_indent, cont_indent, newline_indent, max_linelen;

char *actual_path;
extern char *style_file;
extern int sortedby;
extern listEntry list_layout;

extern char requiredfields[MAX_BIBTEX_TYPES+1][MAX_FIELDS];
extern char standardfields[MAX_BIBTEX_TYPES+1][MAX_FIELDS];
extern String cardNames[];
extern String fieldNames[];
extern int max_fields;
extern int max_bibtex_types;
extern char sort_field[];
extern char is_search_field[];


/* local global variables */
/* ---------------------- */

TagType tagTypes[] = {
   { "Options",       optionTags },
   { "UserFields",    userFldTags },
   { "Predefines",    predefTags },
   { "LatexHeader",   latexHeadTags },
   { "LatexFooter",   latexFootTags },
   { "Indent",        indentTags },
   { "BibDir", 	      defaultDirTags},
   { "SortedBy",      sortedByTags},  
   { "SortFields",    sortFieldTags},  
   { "SearchFields",  searchFieldTags},  
   { "AnnoteField",   annoteFieldTags},  
   { "StyleFile",     styleFileTags},
   { "ListFields",    listFieldTags},
   { "Types",         typeTags},
   { NULL,            illegalTag }
};

static Boolean processOptions = TRUE,
               prtToStd = TRUE;
               
static int akttype;



/*********************************************************************/
/* rcfReadCfgFile:                                                   */
/*    Reads and processes .bibrc configuration file                  */
/*********************************************************************/
int
rcfReadCfgFile (char *cfgFname)
{
FILE *cfgFP;
CfgMode curMode;
char cfgLine[MAX_CFGLINELEN+1]; 
char *cfgp;
int  i;
char processLine;

   /* throw away old values */
   if (latexHeader) {
      XtFree(latexHeader);
      latexHeader = NULL;
      latexHeaderLen = 0;
   }
   if (latexFooter) {
      XtFree(latexFooter);
      latexFooter = NULL;
      latexFooterLen = 0;
   }
   
   if (glbContIllegalChar(cfgFname) != 1) {
      return(ERR_NO_CFGFILE);
   }


   if ((cfgFP = fopen(cfgFname, "r")) == NULL) {
      return(ERR_NO_CFGFILE);
   }

   curMode = findTag;
   while (TRUE) {
      /* Zeile in Zeilenpuffer lesen */
      /* for (i=0; (i <= MAX_CFGLINELEN) && (cfgLine[i-1] != '\n'); i++) { */
       for (i=0; (i <= MAX_CFGLINELEN) && ((i==0) || (cfgLine[i-1] != '\n')); i++) { 
         if (fread(&cfgLine[i], 1, 1, cfgFP) == 0)
            break;
      }
      if (feof(cfgFP))  /* Ende der Konfigdatei */
         break;
      if (cfgLine[0] == '\n')  /* Leerzeilen ueberspringen */
         continue;
      cfgLine[i-1] = '\0';  /* Stringende setzen */

      /* gelesene Zeile bearbeiten */
      cfgp = cfgLine;
      while (isspace(*cfgp)) cfgp++;
 
/*      switch (cfgLine[0]) { */
      switch (*cfgp) { 
         case '#':  /* Kommentarzeile */
                    processLine = FALSE;
                    break;
         case '[':  /* Neuer Abschnitt in Konfigdatei */
              /*      curMode = getCfgFileTag(cfgLine); */
                    curMode = getCfgFileTag(cfgp);
		    if (curMode == listFieldTags)
                       list_layout.number = 0;
                    if (curMode != illegalTag)
                       continue; 
                    processLine = TRUE;
		    break;
         default:   /* Zeile je nach aktuellem Modus bearbeiten */
                    processLine = TRUE;
      } /* endswitch */

      if (processLine) {
         switch (curMode) {
            case optionTags:  /* Optionszeilen bearbeiten */
                              procOptionLine(cfgLine);
                              break;
            case predefTags:  /* Vordef.zeilen bearbeiten */
                              procPredefLine(cfgLine);
                              break;
            case userFldTags: /* Ersetzungsdef bearbeiten */
                              procUserFldLine(cfgLine);
                              break;
            case latexHeadTags: /* Kopfzeilen bearbeiten */
                              procLatexHeadLine(cfgLine);
                              break;
            case latexFootTags: /* Fusszeilen bearbeiten */
                              procLatexFootLine(cfgLine);
                              break;
            case indentTags:  /* bearbeiten */
                              procIndentLine(cfgLine);
                              break;
            case defaultDirTags: /* Default Directory */
                              procDefaultDirLine(cfgLine);
                              break;
            case sortedByTags: /* Style File */
                              procSortedByLine(cfgLine);
                              break;
            case sortFieldTags: /* fields considered for sorting */
                              procSortFieldLine(cfgLine);
                              break;
            case searchFieldTags: /* fields considered in search */
                              procSearchFieldLine(cfgLine);
                              break;
            case annoteFieldTags: /* Style File */
                              procAnnoteFieldLine(cfgLine);
                              break;
            case styleFileTags: /* Style File */
                              procStyleFileLine(cfgLine);
                              break;
            case listFieldTags: /* layout for list */
                              procListFieldLine(cfgLine);
                              break;
            case typeTags: /* Style File */
                              procTypeLine(cfgLine);
                              break;
            case illegalTag:  /* Fehler im Tag aufgetreten */
                              if (prtToStd)
				 fprintf(stderr, "bibview: illegal tag %s in %s\n", cfgLine, cfgFname); 
                              curMode = findTag;
                              break;
            case findTag:     ;
            default:          ;
         } /* endswitch */
      } /* endif */
   } /* endwhile */

   fclose(cfgFP);
   return(OK);
}


/*********************************************************************/
/* rcfSetPrintMode:                                                  */
/*    Sets whether messages go to stderr or not                      */
/*********************************************************************/
Errcode
rcfSetPrintMode (Boolean bool)
{
   prtToStd = bool;
   return(OK);
}


/*********************************************************************/
/* rcfReadOptions:                                                   */
/*    Sets flag whether options in rc file should be processed       */
/*********************************************************************/
Errcode
rcfReadOptions (Boolean bool)
{
   processOptions = bool;
   return(OK);
}



/*********************************************************************/
/* LOCAL FUNCTIONS                                                   */
/*********************************************************************/

/*********************************************************************/
/* getCfgFileTag:                                                    */
/*    Finds next paragraph of config file                            */
/*********************************************************************/
static CfgMode
getCfgFileTag (char *str)
{
char token[MAX_TAGLEN+1] = "";
TagType *tptr;

   sscanf(str, "[%[^]]s", token);

   for (tptr = &tagTypes[0];
	tptr->tagStr != NULL && strcmp(token, tptr->tagStr);
	tptr++) ;

   return( (tptr->tagStr != NULL) ? tptr->mode : illegalTag);
}


/*********************************************************************/
/* procOptionLine:                                                   */
/*    Process line containing option defs                            */
/*********************************************************************/
static int
procOptionLine (char *str)
{
char token[MAX_TAGLEN+1] = "",
     value[MAX_CFGLINELEN+1] = "";
char *p;
int width, fieldnr;
   
   if ((p = strchr(str, ':')) == NULL) {
      if (prtToStd)
	 fprintf(stderr, "bibview: illegal [Options] format: %s\n", str);
      return(OK);
   }

   *p = '\0';
   strcpy(token, str);
   glbTrimString(token);
   strcpy(value, p+1);
   glbTrimString(value);
 
   if (!processOptions)
      return(OK);

   if (strcmp(token, STR_BEEP_ON_ERROR_OPT) == 0) {
      optionsStatus[OPT_BEEP_ON_ERROR] = 
			       (strcmp(strupr(value), STR_TRUE) == 0);
   }
   else if (strcmp(token, STR_ICON_ON_DESK_OPT) == 0) {
      optionsStatus[OPT_ICON_ON_DESKTOP] = 
			       (strcmp(strupr(value), STR_TRUE) == 0);
   }
   else if (strcmp(token, STR_MAKE_BACKUPS_OPT) == 0) {
      optionsStatus[OPT_BACKUP_ON_SAVE] = 
			       (strcmp(strupr(value), STR_TRUE) == 0);
   }
   else if (strcmp(token, STR_AUTO_CHECK_BIB_OPT) == 0) {
      optionsStatus[OPT_AUTO_CHECK_BIB] = 
			       (strcmp(strupr(value), STR_TRUE) == 0);
   }
   else if (strcmp(token, STR_REQUIRED_FIELDS_OPT) == 0) {
      optionsStatus[OPT_REQUIRED_FIELDS] = 
			       (strcmp(strupr(value), STR_TRUE) == 0);
   }
   else if (strcmp(token, STR_IGNORE_CASE) == 0) {
      optionsStatus[OPT_IGNORE_CASE] = 
			       (strcmp(strupr(value), STR_TRUE) == 0);
   }
   else if (strcmp(token, STR_PRINT_AS_BIB) == 0) {
      optionsStatus[OPT_PRINT_AS_BIB] = 
			       (strcmp(strupr(value), STR_TRUE) == 0);
   }
   else if (strcmp(token, STR_DISPLAY_ERRWIN) == 0) {
      optionsStatus[OPT_DISPLAY_ERRWIN] = 
			       (strcmp(strupr(value), STR_TRUE) == 0);
   }
   else {
      if (prtToStd)
	 fprintf(stderr, "bibview: Illegal option %s in config file.\n", str);
   }
   return(OK);
}


/*********************************************************************/
/* procIndentLine:                                                   */
/*    Process line containing indentation information                */
/*********************************************************************/
static int
procIndentLine (char *str)
{
char token[MAX_TAGLEN+1] = "",
     value[MAX_CFGLINELEN+1] = "";
char *p;
int width, fieldnr;
   
   if ((p = strchr(str, ':')) == NULL) {
      if (prtToStd)
	 fprintf(stderr, "bibview: illegal [Indent] format: %s\n", str);
      return(OK);
   }

   *p = '\0';
   strcpy(token, str);
   glbTrimString(token);
   strcpy(value, p+1);
   glbTrimString(value);
   strlower(token);
   if (strcmp(token, STR_FLDINDENT) == 0) 
      fld_indent = atoi(value);
   else if (strcmp(token, STR_CONTINDENT) == 0) 
      cont_indent = atoi(value);
   else if (strcmp(token, STR_NEWLINEINDENT) == 0) 
      newline_indent = atoi(value);
   else if (strcmp(token, STR_MAXLINELEN) == 0) 
      max_linelen = atoi(value);
   else {
      if (prtToStd)
	 fprintf(stderr, 
	 "bibview: Illegal indentation information %s in config file.\n", str);
   }
   if (fld_indent < 0)
      fld_indent = 0;
   if (newline_indent < 0)
      newline_indent = 0;
   if (max_linelen < 20)
      max_linelen = 20;
   return(OK);
}


/*********************************************************************/
/* procPredefLine:                                                   */
/*    Process line containing predefined data for a field            */
/*********************************************************************/
static int
procPredefLine (char *str)
{
char field[MAX_TAGLEN+1] = "",
     data[MAX_CFGLINELEN+1] = "";
ListNode **lnp;
char *p;
int found, i;
   
   found = 0;
   if ((p = strchr(str, ':')) == NULL) {
      if (prtToStd)
	 fprintf(stderr, "bibview: illegal [Predef] format: %s\n", str);
      return(OK);
   }

   *p = '\0';
   strcpy(field, str);
   glbTrimString(field);
   strcpy(data, p+1);
   glbTrimString(data);
   if (strcmp(strlower(field), "allfields") == 0) {
      found = 1;
      lnp = &predefLst.allfields;
      }
   else if (strcmp(strlower(field), "cardtype") == 0) {
      found = 1;
      lnp = &predefLst.bibtype;
      }
   else if (strcmp(strlower(field), "mainkey") == 0) {
      found = 1;
      lnp = &predefLst.mainkey;
      }
   else 
     for (i=0; i<max_fields; i++)
       if ((!found) && strcmp(field, glbFldToName(i)) == 0){ 
	  found = 1;
	  lnp = &predefLst.field[i];
	  }
   if (!found) { 
      if (prtToStd)
	 fprintf(stderr, "bibview: illegal field %s in config file.\n", field);
      return(OK);
   }

   dbtListAppend(lnp, data);
   return(OK);
}


/*********************************************************************/
/* procUserFldLine:                                                  */
/*    Process line containing user defined field for a card type     */
/*********************************************************************/
static int
procUserFldLine (char *str)
{
char type[MAX_TAGLEN+1] = "",
     data[MAX_CFGLINELEN+1] = "";
CardType cardtype;
char *p;
int i;

   if ((p = strchr(str, ':')) == NULL) {
      if (prtToStd)
	 fprintf(stderr, "bibview: illegal [UserFields] format: %s\n", str);
      return(OK);
   }

   *p = '\0';
   strcpy(type, str);
   glbTrimString(type);
   strcpy(data, p+1);
   glbTrimString(data);
   strlower(type);
   strlower(data);
   i=0;
   while ((data[i] != '\0') && (!isspace(data[i])))
      i++;
   if (isspace(data[i])) 
      data[i] = '\0';
   if (strcmp(type, "all") == 0) {
      for (i = 0; i < MAX_BIBTEX_TYPES+1; i++)
	 dbtListAppend(&userDefFlds[i], data);
   }
   else if ((cardtype = glbNameToType(type)) != -1)
      dbtListAppend(&userDefFlds[cardtype], data);
   else {
      if (prtToStd)
	 fprintf(stderr, "bibview: illegal type %s in config file.\n", 
			 type);
   }

   return(OK);
}


/*********************************************************************/
/* procLatexHeadLine:                                                */
/*    Process line containing a line of LaTeX-Header                 */
/*********************************************************************/
static int
procLatexHeadLine (char *str)
{
int linelen;

   linelen = strlen(str);
   if (latexHeader) {
      latexHeaderLen += linelen + 1;
      latexHeader = (char *)XtRealloc(latexHeader, latexHeaderLen);
      strcat(latexHeader, str);
      strcat(latexHeader, "\n");
   }
   else {
      latexHeaderLen = linelen + 2;
      latexHeader = (char *)XtMalloc(latexHeaderLen);
      strcpy(latexHeader, str);
      strcat(latexHeader, "\n");
   }

   return(OK);
}


/*********************************************************************/
/* procLatexFootLine:                                                */
/*    Process line containing a line of LaTeX-Footer                 */
/*********************************************************************/
static int
procLatexFootLine (char *str)
{
int linelen;

   linelen = strlen(str);
   if (latexFooter) {
      latexFooterLen += linelen + 1;
      latexFooter = (char *)XtRealloc(latexFooter, latexFooterLen);
      strcat(latexFooter, str);
      strcat(latexFooter, "\n");
   }
   else {
      latexFooterLen = linelen + 2;
      latexFooter = (char *)XtMalloc(latexFooterLen);
      strcpy(latexFooter, str);
      strcat(latexFooter, "\n");
   }

   return(OK);
}


/*********************************************************************/
/* procDefaultDirLine:                                               */
/*    Process line containing the Default Directory                  */
/*********************************************************************/
Errcode
procDefaultDirLine (char *str)

{
struct stat fstats;
int status;
char defdir[MAX_TAGLEN+1] = "";
   
   strcpy(defdir, str);
   glbTrimString(defdir);

   status = stat(defdir, &fstats);

   if (status != -1 && fstats.st_mode & S_IFDIR)
      if  (access(defdir, R_OK) == 0)
        strcpy(actual_path, defdir);
   
   return(OK);
}

/*********************************************************************/
/* procStyleFileLine:                                                */
/*    Process line containing the Default Style File                 */
/*********************************************************************/
static int
procStyleFileLine (char *str)

{
char stfile[MAX_TAGLEN+1] = "";
  
   strcpy(stfile, str);
   glbTrimString(stfile);

   strcpy(style_file, stfile);
   
   return(OK);
}

/*********************************************************************/
/* procSortedByTags:                                                 */
/*    Process line containing Default how list is sorted	     */
/*********************************************************************/
static int
procSortedByLine (char *str)

{
char sortfield[MAX_TAGLEN+1] = "";
FieldName i;

   strcpy(sortfield,str);
   glbTrimString(sortfield);
  
   if (!strncmp(strlower(sortfield), "type", 4))
      sortedby = SORT_TYPE;
   else if (!strncmp(strlower(sortfield), "mainkey", 7))
      sortedby = SORT_MAINKEY;
   else if ((i=glbNameToField(strlower(sortfield))) != -1) 
      sortedby = i;
   else { 
      if (max_fields == MAX_FIELDS){
         fprintf(stderr,
	      "bibview: too many new fields in config file.\n");
         return(OK);
	 }
      fieldNames[max_fields] = XtCalloc(strlen(sortfield)+1, sizeof(char));
      strcpy(fieldNames[max_fields], sortfield);
      sortedby = max_fields;
      max_fields++;
      }
   return(OK);
}

/*********************************************************************/
/* procTypeLine:                                                     */
/*    Process line type definition                                   */
/*********************************************************************/
static int
procTypeLine (char *str)
{
char field[MAX_TAGLEN+1] = "",
     data[MAX_CFGLINELEN+1] = "";
char *p;
int found, i, type, fieldnr;
   
   found = 0;
   if ((p = strchr(str, ':')) == NULL) {
      if (prtToStd)
	 fprintf(stderr, "bibview: illegal [Types] format: %s\n", str);
      return(OK);
   }

   *p = '\0';
   strcpy(field, str);
   glbTrimString(field);
   strcpy(data, p+1);
   glbTrimString(data);
   strlower(field);
   strlower(data);
   i=0;
   while ((data[i] != '\0') && (!isspace(data[i])))
      i++;
   if (isspace(data[i])) 
      data[i] = '\0';
   if (field[0] == 't'){
      found = 1;
      if (strcmp(data, "all") == 0)
	 akttype = -1;
      else if ((type = glbNameToType(data)) != -1){
	 if (field[1] == 'c'){
	    for (i=0; i<MAX_FIELDS; i++){
	       standardfields[type][i] = '0';
	       requiredfields[type][i] = '0';
	       }
	    standardfields[type][nannote] = '1';
	    }
         akttype = type;
	 }
      else {
	 if (max_bibtex_types == MAX_BIBTEX_TYPES){
	    fprintf(stderr,
	      "bibview: too many type definitions in config file.\n");
            return(OK);
	    }
	 if (field[1] == 'c'){
	    for (i=0; i<MAX_FIELDS; i++){
	       standardfields[max_bibtex_types][i] = '0';
	       requiredfields[max_bibtex_types][i] = '0';
	       }
	    }
	 standardfields[max_bibtex_types][nannote] = '1';
	 cardNames[max_bibtex_types] = XtCalloc(strlen(data)+1, sizeof(char));
	 strcpy(cardNames[max_bibtex_types], data);
         akttype = max_bibtex_types;
	 max_bibtex_types++;
	 }
      }
   else if (strcmp(field, "f") == 0) {
      found = 1;
      if ((fieldnr = glbNameToField(data)) != -1){
	 if (akttype == -1){
	    for (i=0; i<max_bibtex_types; i++)
	       standardfields[i][fieldnr] = '1';
            }
         else
	    standardfields[akttype][fieldnr] = '1';
	 }
      else { 
	 if (max_fields == MAX_FIELDS){
	    fprintf(stderr,
	      "bibview: too many new fields in config file.\n");
            return(OK);
	    }
	 fieldNames[max_fields] = XtCalloc(strlen(data)+1, sizeof(char));
	 strcpy(fieldNames[max_fields], data);
	 if (akttype == -1){
	    for (i=0; i<max_bibtex_types; i++)
	       standardfields[i][max_fields] = '1';
            }
         else
	    standardfields[akttype][max_fields] = '1';
	 max_fields++;
	 }
      }
   else if (strcmp(strlower(field), "rf") == 0) {
      found = 1;
      if ((fieldnr = glbNameToField(data)) != -1){
	 if (akttype == -1){
	    for (i=0; i<max_bibtex_types; i++){
	       standardfields[i][fieldnr] = '1';
	       requiredfields[i][fieldnr] = '1';
	       }
            }
         else {
	    standardfields[akttype][fieldnr] = '1';
	    requiredfields[akttype][fieldnr] = '1';
	    }
	 }
      else {
	 if (max_fields == MAX_FIELDS){
	    fprintf(stderr,
	      "bibview: too many new fields in config file.\n");
            return(OK);
	    }
	 fieldNames[max_fields] = XtCalloc(strlen(data)+1, sizeof(char));
	 strcpy(fieldNames[max_fields], data);
	 if (akttype == -1){
	    for (i=0; i<max_bibtex_types; i++){
	       standardfields[i][max_fields] = '1';
	       requiredfields[i][max_fields] = '1';
	       }
            }
         else {
	    standardfields[akttype][max_fields] = '1';
	    requiredfields[akttype][max_fields] = '1';
	    }
	 max_fields++;
	 }
      }
   
   if (!found) { 
      if (prtToStd)
	 fprintf(stderr, "bibview: illegal type %s in config file.\n", field);
      return(OK);
   }

   return(OK);
}


/*********************************************************************/
/* procSortFieldLine:                                                */
/*    Process fields for sorting                                     */
/*********************************************************************/
static int
procSortFieldLine (char *str)
{ 
char field[MAX_TAGLEN+1] = "",
     data[MAX_CFGLINELEN+1] = "";
char *p;
int i, type, fieldnr;
   
   p = strchr(str, ':');
   if (p!=NULL){
      *p = '\0';
      strcpy(field, str);
      glbTrimString(field);
      strcpy(data, p+1);
      glbTrimString(data);
      strlower(field);
      strlower(data);
      }
   else{
      strcpy(field, strlower(str));
      strcpy(data, "");
      glbTrimString(field);
      }
   if (strcmp(field, "$clear$")==0)
      for (i=0; i<MAX_FIELDS; i++)
         sort_field[i] = '0';
   else if ((fieldnr = glbNameToField(field)) != -1){
      if (data[0] == 'n')
         sort_field[fieldnr] = 'n';
      else if (data[0] == 'd')
         sort_field[fieldnr] = 'd';
      else
         sort_field[fieldnr] = '1';
      }
   else { 
      if (max_fields == MAX_FIELDS){
	    fprintf(stderr,
	      "bibview: too many new fields in [SortField] part.\n");
            return(OK);
	    }
      fieldNames[max_fields] = XtCalloc(strlen(field)+1, sizeof(char));
      strcpy(fieldNames[max_fields], strlower(field));
      if (data[0] == 'n')
         sort_field[max_fields] = 'n';
      else if (data[0] == 'd')
         sort_field[max_fields] = 'd';
      else
         sort_field[max_fields] = '1';
      max_fields++;
   }
   
   return(OK);
}


/*********************************************************************/
/* procSearchFieldLine:                                              */
/*    Process fields for sorting                                     */
/*********************************************************************/
static int
procSearchFieldLine (char *str)
{ 
char field[MAX_TAGLEN+1] = ""; 
int i, fieldnr;

   strcpy(field, strlower(str));
   glbTrimString(field);
   i=0;
   while ((field[i] != '\0') && (!isspace(field[i])))
      i++;
   if (isspace(field[i])) 
      field[i] = '\0';
   if (strcmp(field, "$clear$")==0)
      for (i=0; i<MAX_FIELDS; i++)
         is_search_field[i] = '0';
   else if ((fieldnr = glbNameToField(field)) != -1)
      is_search_field[fieldnr] = '1';
   else { 
      if (max_fields == MAX_FIELDS){
	    fprintf(stderr,
	      "bibview: too many new fields in [SearchField] part.\n");
            return(OK);
	    }
      fieldNames[max_fields] = XtCalloc(strlen(field)+1, sizeof(char));
      strcpy(fieldNames[max_fields], strlower(field));
      is_search_field[max_fields] = '1';
      max_fields++;
   }
   
   return(OK);
}


/*********************************************************************/
/* procAnnoteFieldLine:                                              */
/*    Process line for name of annote field                          */
/*********************************************************************/
static int
procAnnoteFieldLine (char *str)
{ 
char field[MAX_TAGLEN+1] = ""; 
int fieldnr;

   strcpy(field, strlower(str));
   glbTrimString(field);
   if (fieldNames[nannote] != NULL){
      XtFree((char *) fieldNames[nannote]);
      }
   fieldNames[nannote] = XtCalloc(strlen(field)+1, sizeof(char));
   strcpy(fieldNames[nannote], field);
   
   return(OK);
}


/*********************************************************************/
/* procListFieldLine:                                                */
/*    Process fields for sorting                                     */
/*********************************************************************/
static int
procListFieldLine (char *str)
{ 
char field[MAX_TAGLEN+1] = "",
     data[MAX_CFGLINELEN+1] = "";
char *p;
int width, fieldnr;
   
   if ((p = strchr(str, ':')) == NULL) {
      if (prtToStd)
	 fprintf(stderr, "bibview: illegal [ListFields] format: %s\n", str);
      return(OK);
   }

   *p = '\0';
   strcpy(field, str);
   glbTrimString(field);
   strcpy(data, p+1);
   glbTrimString(data);
   strlower(field);
   strlower(data);
 
   if ((width = atoi(data)) <= 0){
      fprintf(stderr,
        "bibview: illegal width in field %s of [ListFields] part.\n", field);
      return(OK);
      }
   if (strcmp(field, "mainkey") == 0)
      list_layout.field[list_layout.number] = -1;
   else if (strcmp(field, "cardtype") == 0)
      list_layout.field[list_layout.number] = -2;
   else if ((fieldnr = glbNameToField(field)) != -1)
      list_layout.field[list_layout.number] = fieldnr;
   else { 
      if (max_fields == MAX_FIELDS){
	    fprintf(stderr,
	      "bibview: too many new fields in [ListFields] part.\n");
            return(OK);
	    }
      fieldNames[max_fields] = XtCalloc(strlen(field)+1, sizeof(char));
      strcpy(fieldNames[max_fields], strlower(field));
      list_layout.field[list_layout.number] = max_fields;
      max_fields++;
   }
   list_layout.width[list_layout.number] = width;
   list_layout.number++;
   
   return(OK);
}

