/* viDOOM - level editor for DOOM Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------------- Routines to read our version of an INI file */ static const char rcs_id[]="$Id$"; #include "config.h" #include #include #include #include "ini.h" #include "mem.h" #include "file.h" #include "vstring.h" #include "gfx.h" #define MAXLEN (PATH_MAX*2) #define ROOTVAR "%WADDED%" typedef struct Token { char *key; char *valkey; char *val; struct Token *next; struct Token *prev; } Token; static Token *ini=NULL; static char ini_dir[PATH_MAX]; static char ini_file[PATH_MAX]; /* Token tables to export */ TokenTable ini_yesno[]={{"yes",TRUE}, {"no",FALSE}, {"true",TRUE}, {"false",FALSE}, {"y",TRUE}, {"n",FALSE}, {"1",TRUE}, {"0",FALSE}, {NULL,0}}; /* ---------------------------------------- PRIVATE FUNCTIONS */ static int cmpstr(char *a,char *b) { if ((a)&&(b)) return(StrCaseCmp(a,b)); else if ((!a)&&(!b)) return(0); else if (!a) return(-1); else return(1); } static int CompareToken(Token *a, Token *b) { int n; if ((n=cmpstr(a->key,b->key))) return(n); return (cmpstr(a->valkey,b->valkey)); } static Token *FindToken(char *key, char *val) { Token *tok; tok=ini; while(tok) { if ((cmpstr(tok->key,key)==0)&& (cmpstr(tok->valkey,val)==0)) return(tok); tok=tok->next; } return(NULL); } static char *GetLine(FILE *fp, int len) { static char s[MAXLEN]; int l,f; fgets(s,len-1,fp); if (feof(fp)) return(FALSE); l=strlen(s)-1; if ((l>=0)&&(s[l]=='\n')) s[l]=0; l=strlen(s)-1; if ((l>=0)&&(s[l]=='\r')) s[l]=0; for(f=0;fkey=Strdup(key); tok->valkey=Strdup(valkey); tok->val=Strdup(val); tok->next=NULL; tok->prev=NULL; if (!ini) { ini=tok; return; } ins=ini; while(ins) { if (CompareToken(ins,tok)>0) if (ins->prev) { ins->prev->next=tok; tok->prev=ins->prev; tok->next=ins; ins->prev=tok; return; } else { tok->next=ins; ins->prev=tok; ini=tok; return; } if (ins->next) ins=ins->next; else { ins->next=tok; tok->prev=ins; return; } } } static int TokenToNum(char *val, TokenTable tokens[]) { int f; f=0; while(tokens[f].token) if (cmpstr(tokens[f].token,val)==0) return(tokens[f].val); else f++; return(0); } static char *NumToToken(int val, TokenTable tokens[]) { int f; f=0; while(tokens[f].token) if (tokens[f].val==val) return(tokens[f].token); else f++; return(""); } static char *Expand(char *p) { static char r[MAXLEN]; if (strncmp(p,ROOTVAR,strlen(ROOTVAR))==0) { strcpy(r,ini_dir); strcat(r,p+strlen(ROOTVAR)); return(r); } else return(p); } static char *Unexpand(char *p) { static char r[MAXLEN]; if (strncmp(p,ini_dir,strlen(ini_dir))==0) { strcpy(r,ROOTVAR); strcat(r,p+strlen(ini_dir)); return(r); } else return(p); } /* ---------------------------------------- EXPORTED FUNCTIONS */ int INI_ReadInt(char *key, char *val) { Token *tok; if ((tok=FindToken(key,val))) return((int)strtol(tok->val,(char **)NULL,0)); else return(0); } char *INI_ReadStr(char *key, char *val) { Token *tok; if ((tok=FindToken(key,val))) return(Expand(tok->val)); else return(""); } int INI_ReadToken(char *key, char *val, TokenTable tokens[]) { Token *tok; if ((tok=FindToken(key,val))) return(TokenToNum(tok->val,tokens)); else return(0); } double INI_ReadDouble(char *key, char *val) { Token *tok; char *dum; if ((tok=FindToken(key,val))) return(strtod(tok->val,&dum)); else return(0.0); } void INI_SaveInt(char *key, char *valkey, int val) { char s[MAXLEN]; Token *tok; sprintf(s,"%d",val); if ((tok=FindToken(key,valkey))) { Release(tok->val); tok->val=Strdup(s); } else { sprintf(s,"%s=%d",valkey,val); AddToken(key,s); } } void INI_SaveStr(char *key, char *valkey, char *val) { char s[MAXLEN]; Token *tok; if ((tok=FindToken(key,valkey))) { Release(tok->val); tok->val=Strdup(Unexpand(val)); } else { sprintf(s,"%s=%s",valkey,val); AddToken(key,s); } } void INI_SaveToken(char *key, char *valkey, int val, TokenTable tokens[]) { char s[MAXLEN]; Token *tok; if ((tok=FindToken(key,valkey))) { Release(tok->val); tok->val=Strdup(NumToToken(val,tokens)); } else { sprintf(s,"%s=%s",valkey,NumToToken(val,tokens)); AddToken(key,s); } } void INI_SaveDouble(char *key, char *valkey, double val) { char s[MAXLEN]; Token *tok; sprintf(s,"%f",val); if ((tok=FindToken(key,valkey))) { Release(tok->val); tok->val=Strdup(s); } else { sprintf(s,"%s=%f",valkey,val); AddToken(key,s); } } void INI_DeleteKey(char *key,char *valkey) { Token *tok; if ((tok=FindToken(key,valkey))) { if (tok->prev) tok->prev->next=tok->next; if (tok->next) tok->next->prev=tok->prev; if (ini==tok) ini=tok->next; Release(tok->key); Release(tok->valkey); Release(tok->val); Release(tok); } } void INI_Load(char *name) { FILE *fp; char *line; char token[32]; strcpy(ini_dir,Pwd()); strcpy(ini_file,ini_dir); strcat(ini_file,DIRSEP); strcat(ini_file,name); if ((fp=fopen(ini_file,"r"))) { while((line=GetLine(fp,MAXLEN))) if (line[0]=='[') { line[strlen(line)-1]=0; strcpy(token,line+1); } else AddToken(token,line); } else GFX_exit(EXIT_FAILURE,"Couldn't open INI file. " "Check doc/overview.htm for config details.\n"); } void INI_Save(void) { FILE *fp; Token *tok; char *last_key; int first=TRUE; if ((fp=fopen(ini_file,"w"))) { tok=ini; last_key=NULL; while(tok) { if (cmpstr(last_key,tok->key)) { if (first) fprintf(fp,"[%s]\n",tok->key); else fprintf(fp,"\n[%s]\n",tok->key); last_key=tok->key; first=FALSE; } fprintf(fp,"%s=%s\n",tok->valkey,tok->val); tok=tok->next; } fclose(fp); } } void INI_GetTable(INI_Table table[],int no) { int f; int *i; char *p; double *d; for(f=0;f