📄 snd_gus.c
字号:
/*
Copyright (C) 1996-1997 Id Software, Inc.
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 for GUS support in QUAKE
//
// Author(s): Jayeson Lee-Steere
//=============================================================================
#include "quakedef.h"
#include "dosisms.h"
//=============================================================================
// Author(s): Jayeson Lee-Steere
#define INI_STRING_SIZE 0x100
FILE *ini_fopen(const char *filename, const char *modes);
int ini_fclose(FILE *f);
void ini_fgets(FILE *f, const char *section, const char *field, char *s);
// Routines for reading from .INI files
// The read routines are fairly efficient.
//
// Author(s): Jayeson Lee-Steere
#define MAX_SECTION_WIDTH 20
#define MAX_FIELD_WIDTH 20
#define NUM_SECTION_BUFFERS 10
#define NUM_FIELD_BUFFERS 20
struct section_buffer
{
long offset;
char name[MAX_SECTION_WIDTH+1];
};
struct field_buffer
{
long offset;
int section;
char name[MAX_FIELD_WIDTH+1];
};
static FILE *current_file=NULL;
static int current_section;
static int current_section_buffer=0;
static int current_field_buffer=0;
static struct section_buffer section_buffers[NUM_SECTION_BUFFERS];
static struct field_buffer field_buffers[NUM_FIELD_BUFFERS];
//***************************************************************************
// Internal routines
//***************************************************************************
static char toupper(char c)
{
if (c>='a' && c<='z')
c-=('a'-'A');
return(c);
}
static void reset_buffer(FILE *f)
{
int i;
for (i=0;i<NUM_SECTION_BUFFERS;i++)
section_buffers[i].name[0]=0;
for (i=0;i<NUM_FIELD_BUFFERS;i++)
field_buffers[i].name[0]=0;
current_file=f;
}
// Sees if the current string is section "name" (i.e. ["name"]).
// If "name"=="*", sees if the current string is any section
// (i.e. [....]). Returns 1 if true else 0 if false.
static int is_section(char *s,const char *name)
{
int wild=0;
// See if wild search
if (strcmp("*",name)==0)
wild=1;
// Skip leading spaces
while (s[0]==' ')
s++;
// Look for leading "["
if (s[0]!='[')
return(0);
s++;
// Make sure name matches
while (s[0]!=']' && s[0]!=13 && s[0]!=10 && s[0]!=0 && name[0]!=0)
{
if (!wild)
if (toupper(s[0])!=toupper(name[0]))
return(0);
s++;
if (!wild)
name++;
}
if (!wild)
if (name[0]!=0)
return(0);
// Skip trailing spaces
while (s[0]==' ')
s++;
// Make sure we have trailing "]"
if (s[0]!=']')
return(0);
return(1);
}
// Sees if the current string is field "name" (i.e. "name"=...).
// If "name"=="*", sees if the current string is any field
// (i.e. ...=...). Returns 1 if true else 0 if false.
static int is_field(char *s,const char *name)
{
int wild=0;
// See if wild search
if (strcmp("*",name)==0)
wild=1;
// Skip leading spaces
while (s[0]==' ')
s++;
// Make sure name matches
while (s[0]!='=' && s[0]!=13 && s[0]!=10 && s[0]!=0 && name[0]!=0)
{
if (!wild)
if (toupper(s[0])!=toupper(name[0]))
return(0);
s++;
if (!wild)
name++;
}
if (!wild)
if (name[0]!=0)
return(0);
// Skip trailing spaces
while (s[0]==' ')
s++;
// Make sure we have an "="
if (s[0]!='=')
return(0);
return(1);
}
// Extracts the section name from a section heading
// e.g. in="[hey man]" gives out="hey man"
static void get_section_name(char *out, char *in)
{
int i=0;
// Skip spaces before '['
while (in[0]==' ')
in++;
// Make sure there is a '['
if (in[0]!='[')
{
out[0]=0;
return;
}
// Skip past '['
in++;
// Copy string if any to output string.
while (in[0]!=']' && in[0]!=13 && in[0]!=10 && in[0]!=0)
{
if (i<MAX_SECTION_WIDTH)
{
out[i]=in[0];
i++;
}
in++;
}
// Make sure string was terminated with ']'
if (in[0]!=']')
{
out[0]=0;
return;
}
// Remove trailing spaces
while (i>0 && out[i-1]==' ')
i--;
// Null terminate the output string.
out[i]=0;
}
// Extracts the field name from a field line
// e.g. in="sooty=life be in it" gives out="sooty"
static void get_field_name(char *out, char *in)
{
int i=0;
// Skip leading spaces
while (in[0]==' ')
in++;
// Copy name to output string
while (in[0]!='=' && in[0]!=13 && in[0]!=10 && in[0]!=0)
{
if (i<MAX_FIELD_WIDTH)
{
out[i]=in[0];
i++;
}
in++;
}
// Make sure we stopped on "="
if (in[0]!='=')
{
out[0]=0;
return;
}
// Remove trailing spaces
while (i>0 && out[i-1]==' ')
i--;
// Null terminate the output string.
out[i]=0;
}
// Returns the field data from string s.
// e.g. in="wally = golly man" gives out="golly man"
static void get_field_string(char *out, char *in)
{
int i=0;
// Find '=' if it exists
while (in[0]!='=' && in[0]!=13 && in[0]!=10 && in[0]!=0)
in++;
// If there is an '=', skip past it.
if (in[0]=='=')
in++;
// Skip any spaces between the '=' and string.
while (in[0]==' ' || in[0]=='[')
in++;
// Copy string, if there is one, to the output string.
while (in[0]!=13 && in[0]!=10 && in[0]!=0 && i<(INI_STRING_SIZE-1))
{
out[i]=in[0];
in++;
i++;
}
// Null terminate the output string.
out[i]=0;
}
// Adds a section to the buffer
static int add_section(char *instring, long offset)
{
int i;
char section[MAX_SECTION_WIDTH+1];
// Extract section name
get_section_name(section,instring);
// See if section already exists.
for (i=0;i<NUM_SECTION_BUFFERS;i++)
if (stricmp(section,section_buffers[i].name)==0)
return(i);
// Increment current_section_buffer
current_section_buffer++;
if (current_section_buffer>NUM_SECTION_BUFFERS)
current_section_buffer=0;
// Delete any field buffers that correspond to this section
for (i=0;i<NUM_FIELD_BUFFERS;i++)
if (field_buffers[i].section==current_section_buffer)
field_buffers[i].name[0]=0;
// Set buffer information
strcpy(section_buffers[current_section_buffer].name,section);
section_buffers[current_section_buffer].offset=offset;
return(current_section_buffer);
}
// Adds a field to the buffer
static void add_field(char *instring, int section, long offset)
{
int i;
char field[MAX_FIELD_WIDTH+1];
// Extract field name
get_field_name(field,instring);
// See if field already exists
for (i=0;i<NUM_FIELD_BUFFERS;i++)
if (field_buffers[i].section==section)
if (stricmp(field_buffers[i].name,field)==0)
return;
// Increment current_field_buffer
current_field_buffer++;
if (current_field_buffer>NUM_FIELD_BUFFERS)
current_field_buffer=0;
// Set buffer information
strcpy(field_buffers[current_field_buffer].name,field);
field_buffers[current_field_buffer].section=section;
field_buffers[current_field_buffer].offset=offset;
}
// Identical to fgets except the string is trucated at the first ';',
// carriage return or line feed.
static char *stripped_fgets(char *s, int n, FILE *f)
{
int i=0;
if (fgets(s,n,f)==NULL)
return(NULL);
while (s[i]!=';' && s[i]!=13 && s[i]!=10 && s[i]!=0)
i++;
s[i]=0;
return(s);
}
//***************************************************************************
// Externally accessable routines
//***************************************************************************
// Opens an .INI file. Works like fopen
FILE *ini_fopen(const char *filename, const char *modes)
{
return(fopen(filename,modes));
}
// Closes a .INI file. Works like fclose
int ini_fclose(FILE *f)
{
if (f==current_file)
reset_buffer(NULL);
return(fclose(f));
}
// Puts "field" from "section" from .ini file "f" into "s".
// If "section" does not exist or "field" does not exist in
// section then s="";
void ini_fgets(FILE *f, const char *section, const char *field, char *s)
{
int i;
long start_pos,string_start_pos;
char ts[INI_STRING_SIZE*2];
if (f!=current_file)
reset_buffer(f);
// Default to "Not found"
s[0]=0;
// See if section is in buffer
for (i=0;i<NUM_SECTION_BUFFERS;i++)
if (strnicmp(section_buffers[i].name,section,MAX_SECTION_WIDTH)==0)
break;
// If section is in buffer, seek to it if necessary
if (i<NUM_SECTION_BUFFERS)
{
if (i!=current_section)
{
current_section=i;
fseek(f,section_buffers[i].offset,SEEK_SET);
}
}
// else look through .ini file for it.
else
{
// Make sure we are not at eof or this will cause trouble.
if (feof(f))
rewind(f);
start_pos=ftell(f);
while (1)
{
stripped_fgets(ts,INI_STRING_SIZE*2,f);
// If it is a section, add it to the section buffer
if (is_section(ts,"*"))
current_section=add_section(ts,ftell(f));
// If it is the section we are looking for, break.
if (is_section(ts,section))
break;
// If we reach the end of the file, rewind to the start.
if (feof(f))
rewind(f);
if (ftell(f)==start_pos)
return;
}
}
// See if field is in buffer
for (i=0;i<NUM_FIELD_BUFFERS;i++)
if (field_buffers[i].section==current_section)
if (strnicmp(field_buffers[i].name,field,MAX_FIELD_WIDTH)==0)
break;
// If field is in buffer, seek to it and read it
if (i<NUM_FIELD_BUFFERS)
{
fseek(f,field_buffers[i].offset,SEEK_SET);
stripped_fgets(ts,INI_STRING_SIZE*2,f);
get_field_string(s,ts);
}
else
// else search through section for field.
{
// Make sure we do not start at eof or this will cause problems.
if (feof(f))
fseek(f,section_buffers[current_section].offset,SEEK_SET);
start_pos=ftell(f);
while (1)
{
string_start_pos=ftell(f);
stripped_fgets(ts,INI_STRING_SIZE*2,f);
// If it is a field, add it to the buffer
if (is_field(ts,"*"))
add_field(ts,current_section,string_start_pos);
// If it is the field we are looking for, save it
if (is_field(ts,field))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -