jedioutcast/CODE-mp/qcommon/strip.cpp
2013-04-04 15:49:50 -05:00

1747 lines
32 KiB
C++

// this include must remain at the top of every CPP file
#include "../server/server.h"
#include "../game/q_shared.h"
#include "qcommon.h"
//#ifdef _DEBUG
//#include <windows.h>
//#endif
/*
#if !defined(G_LOCAL_H_INC)
#include "..\game\g_local.h"
#endif
*/
//#include "stdafx.h"
#ifndef _STRIPED_
// #include "parental.h"
#include "strip.h"
// #include "../qcommon/palette.h"
#endif
#ifdef _STRIPED_
#include "resource.h" // main symbols
#include "SP_ConfigFile.h"
cStringPackageED *StringPackage = NULL;
char LanguageList[LANGUAGELIST_MAX][LANGUAGE_LENGTH];
char FlagList[FLAGLIST_MAX][FLAG_LENGTH];
#else
/*static*/ cvar_t *sp_language;
static cvar_t *sp_show_strip;
#endif
/*
void LogFile(char *Text, ...)
{
char Buffer[16384];
va_list argptr;
FILE *FH;
va_start (argptr,Text);
vsprintf (Buffer,Text,argptr);
va_end (argptr);
FH = fopen("c:\\striped.log", "r+");
if (!FH)
{
FH = fopen("c:\\striped.log", "w");
}
else
{
fseek(FH, 0, SEEK_END);
}
fprintf(FH, "%s", Buffer);
fclose(FH);
}
*/
enum
{
TK_INVALID = -1,
TK_VERSION = 0,
TK_ID,
TK_REFERENCE,
TK_DESCRIPTION,
TK_COUNT,
TK_FLAGS,
TK_SP_FLAG1,
TK_SP_FLAG2,
TK_SP_FLAG3,
TK_SP_FLAG4,
TK_SP_FLAG5,
TK_SP_FLAG6,
TK_SP_FLAG7,
TK_SP_FLAG8,
TK_SP_FLAG9,
TK_SP_FLAG_ORIGINAL,
TK_LEFT_BRACE,
TK_RIGHT_BRACE,
TK_INDEX,
TK_NOTES,
TK_CONFIG,
TK_TEXT_LANGUAGE1,
TK_TEXT_LANGUAGE2,
TK_TEXT_LANGUAGE3,
TK_TEXT_LANGUAGE4,
TK_TEXT_LANGUAGE5,
TK_TEXT_LANGUAGE6,
TK_TEXT_LANGUAGE7,
TK_TEXT_LANGUAGE8,
TK_TEXT_LANGUAGE9,
TK_TEXT_LANGUAGE10,
TK_END
};
char *Tokens[TK_END] =
{
"VERSION",
"ID",
"REFERENCE",
"DESCRIPTION",
"COUNT",
"FLAGS",
"SP_FLAG1",
"SP_FLAG2",
"SP_FLAG3",
"SP_FLAG4",
"SP_FLAG5",
"SP_FLAG6",
"SP_FLAG7",
"SP_FLAG8",
"SP_FLAG9",
"SP_FLAG_ORIGINAL",
"{",
"}",
"INDEX",
"NOTES",
"CONFIG",
"TEXT_LANGUAGE1",
"TEXT_LANGUAGE2",
"TEXT_LANGUAGE3",
"TEXT_LANGUAGE4",
"TEXT_LANGUAGE5",
"TEXT_LANGUAGE6",
"TEXT_LANGUAGE7",
"TEXT_LANGUAGE8",
"TEXT_LANGUAGE9",
"TEXT_LANGUAGE10"
};
sFlagPair FlagPairs[] =
{
{ TK_SP_FLAG1, SP_FLAG1 },
{ TK_SP_FLAG2, SP_FLAG2 },
{ TK_SP_FLAG3, SP_FLAG3 },
{ TK_SP_FLAG4, SP_FLAG4 },
{ TK_SP_FLAG5, SP_FLAG5 },
{ TK_SP_FLAG6, SP_FLAG6 },
{ TK_SP_FLAG7, SP_FLAG7 },
{ TK_SP_FLAG8, SP_FLAG8 },
{ TK_SP_FLAG9, SP_FLAG9 },
{ TK_SP_FLAG_ORIGINAL, SP_FLAG_ORIGINAL },
{ TK_INVALID, 0 }
};
sFlagPair LanguagePairs[] =
{
{ TK_TEXT_LANGUAGE1, SP_LANGUAGE_ENGLISH },
{ TK_TEXT_LANGUAGE2, SP_LANGUAGE_FRENCH },
{ TK_TEXT_LANGUAGE3, SP_LANGUAGE_GERMAN },
{ TK_TEXT_LANGUAGE4, SP_LANGUAGE_BRITISH },
{ TK_TEXT_LANGUAGE5, SP_LANGUAGE_KOREAN },
{ TK_TEXT_LANGUAGE6, SP_LANGUAGE_TAIWANESE },
{ TK_TEXT_LANGUAGE7, SP_LANGUAGE_ITALIAN },
{ TK_TEXT_LANGUAGE8, SP_LANGUAGE_SPANISH },
{ TK_TEXT_LANGUAGE9, SP_LANGUAGE_JAPANESE },
{ TK_TEXT_LANGUAGE10, SP_LANGUAGE_10},
{ TK_INVALID, 0 }
};
/************************************************************************************************
* FindToken
*
* inputs:
* token string
* flag indicating if token string is partial or not
*
* return:
* token enum
*
************************************************************************************************/
int FindToken(char *token, bool whole)
{
int token_value;
int i;
for(token_value = 0; token_value != TK_END; token_value++)
{
if (whole)
{
if (Q_stricmp(token, Tokens[token_value]) == 0)
{
return token_value;
}
}
else
{
if (Q_stricmpn(token, Tokens[token_value], strlen(Tokens[token_value])) == 0)
{
i = strlen(Tokens[token_value]);
while(token[i] == ' ')
{
i++;
}
memmove(token, &token[i], strlen(token)-i+1);
return token_value;
}
}
}
return TK_INVALID;
}
/************************************************************************************************
* ReadData
*
* inputs:
*
* return:
*
************************************************************************************************/
bool ReadData(char *&Data, int &Size, char *Result, int Result_Size)
{
char *pos;
Result[0] = 0;
if (Size <= 0)
{
return false;
}
pos = Result;
do
{
*pos = *Data;
pos++;
Data++;
Size--;
Result_Size--;
} while(Size > 0 && Result_Size > 0 && *(Data-1) != '\n');
*pos = 0;
return true;
}
/************************************************************************************************
* GetLine
*
* inputs:
*
* return:
*
************************************************************************************************/
void GetLine(char *&Data, int &Size, int &token, char *&data)
{
static char save_data[8192];
char temp_data[8192];
char *test_token, *pos;
save_data[0] = 0;
token = TK_INVALID;
data = save_data;
if (!ReadData(Data, Size, temp_data, sizeof(temp_data)))
{
return;
}
// strcpy(temp_data, " DATA \"test of the data\ntest test\ndfa dfd");
// strcpy(temp_data, " DATA");
pos = temp_data;
while((*pos) && strchr(" \n\r", *pos))
{ // remove white space
pos++;
}
test_token = pos;
while((*pos) && !strchr(" \n\r", *pos))
{ // scan until end of white space
pos++;
}
if ((*pos))
{
*pos = 0;
pos++;
}
token = FindToken(test_token, true);
while((*pos) && strchr(" \n\r", *pos))
{ // remove white space
pos++;
}
if ((*pos) == '\"')
{
pos++;
test_token = save_data;
memset(save_data, 0, sizeof(save_data));
while(((*pos) != '\"' || !strchr("\n\r", (*(pos+1)))) && (*pos))
{
if ((*pos) == '\\' && (*(pos+1)) == 'n')
{
#ifdef _STRIPED_
*test_token = '\r';
test_token++;
#endif
*test_token = '\n';
test_token++;
pos+=2;
continue;
}
*test_token = *pos;
test_token++;
pos++;
}
if ((*pos) == '\"')
{
*pos = 0;
}
}
else
{
test_token = pos;
while((*pos) && !strchr("\n\r", *pos))
{ // scan until end of white space
pos++;
}
*pos = 0;
strcpy(save_data, test_token);
}
}
#ifdef _STRIPED_
/************************************************************************************************
* SaveString
*
* inputs:
*
* return:
*
************************************************************************************************/
void SaveString(FILE *FH, char *data)
{
fputc('\"', FH);
if (data)
{
for(;*data;data++)
{
if ((*data) == '\r')
{
}
else if ((*data) == '\n')
{
fputc('\\', FH);
fputc('n', FH);
}
else
{
fputc(*data, FH);
}
}
}
fputc('\"', FH);
}
#endif
//======================================================================
/************************************************************************************************
* cCriteria
*
* inputs:
*
* return:
*
************************************************************************************************/
cCriteria::cCriteria(int initWhichLanguage)
{
WhichLanguage = initWhichLanguage;
}
#ifdef _STRIPED_
/************************************************************************************************
* cCriteriaED
*
* inputs:
*
* return:
*
************************************************************************************************/
cCriteriaED::cCriteriaED(int initWhichLanguage, cStringPackageED *initMerge)
:cCriteria(initWhichLanguage)
{
Merge = initMerge;
}
#endif
//======================================================================
/************************************************************************************************
* cStrings
*
* inputs:
*
* return:
*
************************************************************************************************/
cStrings::cStrings(unsigned int initFlags, char *initReference)
{
Flags = initFlags;
Reference = NULL;
SetReference(initReference);
}
/************************************************************************************************
* ~cStrings
*
* inputs:
*
* return:
*
************************************************************************************************/
cStrings::~cStrings(void)
{
Clear();
}
/************************************************************************************************
* Clear
*
* inputs:
*
* return:
*
************************************************************************************************/
void cStrings::Clear(void)
{
Flags = 0;
if (Reference)
{
delete Reference;
Reference = NULL;
}
}
/************************************************************************************************
* SetFlags
*
* inputs:
*
* return:
*
************************************************************************************************/
void cStrings::SetFlags(unsigned int newFlags)
{
Flags = newFlags;
}
void cStrings::SetReference(char *newReference)
{
if (Reference)
{
delete Reference;
Reference = NULL;
}
if (!newReference || !newReference[0])
{
return;
}
Reference = new char[strlen(newReference)+1];
strcpy(Reference, newReference);
}
bool cStrings::UnderstandToken(int token, char *data)
{
sFlagPair *FlagPair;
switch(token)
{
case TK_FLAGS:
while(token != TK_INVALID)
{
token = FindToken(data, false);
for(FlagPair = FlagPairs; FlagPair->Name != TK_INVALID; FlagPair++)
{
if (FlagPair->Name == token)
{
Flags |= FlagPair->Value;
break;
}
}
}
return true;
case TK_REFERENCE:
SetReference(data);
return true;
case TK_RIGHT_BRACE:
return false;
}
if (token == TK_INVALID)
{
return false;
}
return true;
}
bool cStrings::SubSave(FILE *FH)
{
sFlagPair *FlagPair;
if (Flags)
{
fprintf(FH, " %s", Tokens[TK_FLAGS]);
for(FlagPair = FlagPairs; FlagPair->Name != TK_INVALID; FlagPair++)
{
if (Flags & FlagPair->Value)
{
fprintf(FH, " %s", Tokens[FlagPair->Name]);
}
}
fprintf(FH,"\n");
}
if (Reference)
{
fprintf(FH, " %s %s\n", Tokens[TK_REFERENCE], Reference);
}
return true;
}
bool cStrings::Save(FILE *FH)
{
fprintf(FH,"%s\n", Tokens[TK_LEFT_BRACE]);
SubSave(FH);
fprintf(FH,"%s\n", Tokens[TK_RIGHT_BRACE]);
return true;
}
bool cStrings::Load(char *&Data, int &Size)
{
int token;
char *data;
Clear();
GetLine(Data, Size, token, data);
if (token != TK_LEFT_BRACE)
{
return false;
}
GetLine(Data, Size, token, data);
while (UnderstandToken(token, data))
{
GetLine(Data, Size, token, data);
}
if (token != TK_RIGHT_BRACE)
{
return false;
}
return true;
}
#ifdef _STRIPED_
cStringsED::cStringsED(unsigned int initFlags, char *initReference, char *initNotes)
:cStrings(initFlags, initReference)
{
int i;
Used = false;
Notes = NULL;
for(i=0;i<MAX_LANGUAGES;i++)
{
Text[i] = NULL;
}
SetNotes(initNotes);
}
cStringsED::~cStringsED()
{
Clear();
}
void cStringsED::Clear(void)
{
int i;
cStrings::Clear();
Used = false;
for(i=0;i<MAX_LANGUAGES;i++)
{
if (Text[i])
{
delete Text[i];
Text[i] = NULL;
}
}
if (Notes)
{
delete Notes;
Notes = NULL;
}
}
void cStringsED::SetText(int index, char *newText)
{
if (Text[index])
{
delete Text[index];
Text[index] = NULL;
}
if (!newText || !newText[0])
{
return;
}
Text[index] = new char[strlen(newText)+1];
strcpy(Text[index], newText);
}
void cStringsED::SetNotes(char *newNotes)
{
if (Notes)
{
delete Notes;
Notes = NULL;
}
if (!newNotes || !newNotes[0])
{
return;
}
Notes = new char[strlen(newNotes)+1];
strcpy(Notes, newNotes);
}
bool cStringsED::UnderstandToken(int token, char *data, cCriteria &Criteria)
{
sFlagPair *LanguagePair;
switch(token)
{
case TK_NOTES:
SetNotes(data);
return true;
default:
for(LanguagePair = LanguagePairs; LanguagePair->Name != TK_INVALID; LanguagePair++)
{
if (LanguagePair->Name == token)
{
SetText(LanguagePair->Value, data);
return true;
}
}
return cStrings::UnderstandToken(token, data, Criteria);
}
}
bool cStringsED::SubSave(FILE *FH, cCriteria &Criteria)
{
int i;
sFlagPair *LanguagePair;
cStrings::SubSave(FH, Criteria);
if (Notes)
{
fprintf(FH, " %s ", Tokens[TK_NOTES]);
SaveString(FH, Notes);
fprintf(FH, "\n");
}
for(i=0;i<MAX_LANGUAGES;i++)
{
if (Criteria.WhichLanguage != TEXT_ALL && Criteria.WhichLanguage != i && i != TEXT_LANGUAGE1)
{ // we aren't saving everything, and this isn't the matching text or english
continue;
}
if (Text[i])
{
for(LanguagePair = LanguagePairs; LanguagePair->Name != TK_INVALID; LanguagePair++)
{
if (i == (int)LanguagePair->Value)
{
fprintf(FH, " %s ",Tokens[LanguagePair->Name]);
SaveString(FH, Text[i]);
fprintf(FH, "\n");
}
}
}
}
return true;
}
bool cStringsED::Load(char *&Data, int &Size, cCriteria &Criteria)
{
if (cStrings::Load(Data, Size, Criteria))
{
Used = true;
return true;
}
return false;
}
#endif
#ifndef _STRIPED_
cStringsSingle::cStringsSingle(unsigned int initFlags, char *initReference)
:cStrings(initFlags, initReference)
{
Text = NULL;
}
cStringsSingle::~cStringsSingle()
{
Clear();
}
void cStringsSingle::Clear(void)
{
cStrings::Clear();
if (Text)
{
delete Text;
Text = NULL;
}
}
void cStringsSingle::SetText(const char *newText)
{
int length;
char *Dest;
if (Text)
{
delete Text;
Text = NULL;
}
if (!newText || !newText[0])
{
return;
}
length = strlen(newText)+1;
#ifndef _STRIPED_
// Following is for TESTING for SOF.
if(sp_show_strip->value)
{
Dest = Text = new char[length + 6];
strcpy(Dest,"SP:");
Dest += strlen(Dest);
}
else
#endif
{
Dest = Text = new char[length];
}
strcpy(Dest, newText);
}
// fix problems caused by fucking morons entering clever "rich" chars in to new text files *after* the auto-stripper
// removed them all in the first place...
//
// ONLY DO THIS FOR ENGLISH, OR IT BREAKS ASIAN STRINGS!!!!!!!!!!!!!!!!!!!!!
//
static void FixIllegalChars(char *psText)
{
char *p;
// strXLS_Speech.Replace(va("%c",0x92),va("%c",0x27)); // "'"
while ((p=strchr(psText,0x92))!=NULL) // "rich" (and illegal) apostrophe
{
*p = 0x27;
}
// strXLS_Speech.Replace(va("%c",0x93),"\""); // smart quotes -> '"'
while ((p=strchr(psText,0x93))!=NULL) // "rich" (and illegal) apostrophe
{
*p = '"';
}
// strXLS_Speech.Replace(va("%c",0x94),"\""); // smart quotes -> '"'
while ((p=strchr(psText,0x94))!=NULL) // "rich" (and illegal) apostrophe
{
*p = '"';
}
// strXLS_Speech.Replace(va("%c",0x0B),"."); // full stop
while ((p=strchr(psText,0x0B))!=NULL) // "rich" (and illegal) apostrophe
{
*p = '.';
}
// strXLS_Speech.Replace(va("%c",0x85),"..."); // "..."-char -> 3-char "..."
while ((p=strchr(psText,0x85))!=NULL) // "rich" (and illegal) apostrophe
{
*p = '.'; // can't do in-string replace of "." with "...", so just forget it
}
// strXLS_Speech.Replace(va("%c",0x91),va("%c",0x27)); // "'"
while ((p=strchr(psText,0x91))!=NULL) // "rich" (and illegal) apostrophe
{
*p = 0x27;
}
// strXLS_Speech.Replace(va("%c",0x96),va("%c",0x2D)); // "-"
while ((p=strchr(psText,0x96))!=NULL)
{
*p = 0x2D;
}
// strXLS_Speech.Replace(va("%c",0x97),va("%c",0x2D)); // "-"
while ((p=strchr(psText,0x97))!=NULL)
{
*p = 0x2D;
}
// StripEd and our print code don't support tabs...
//
while ((p=strchr(psText,0x09))!=NULL)
{
*p = ' ';
}
}
bool cStringsSingle::UnderstandToken(int token, char *data)
{
sFlagPair *LanguagePair;
// switch(token)
// {
// default:
for(LanguagePair = LanguagePairs; LanguagePair->Name != TK_INVALID; LanguagePair++)
{
if (LanguagePair->Name == TK_TEXT_LANGUAGE1 && token == TK_TEXT_LANGUAGE1 && !Text)
{ // default to english in case there is no foreign
if (LanguagePair->Name == TK_TEXT_LANGUAGE1 ||
LanguagePair->Name == TK_TEXT_LANGUAGE2 ||
LanguagePair->Name == TK_TEXT_LANGUAGE3
)
{
FixIllegalChars(data);
}
SetText(data);
return true;
}
else if (LanguagePair->Name == token && LanguagePair->Value == (int)sp_language->value)
{
if (LanguagePair->Name == TK_TEXT_LANGUAGE1 ||
LanguagePair->Name == TK_TEXT_LANGUAGE2 ||
LanguagePair->Name == TK_TEXT_LANGUAGE3
)
{
FixIllegalChars(data);
}
SetText(data);
return true;
}
}
return cStrings::UnderstandToken(token, data);
// }
}
#endif
cStringPackage::cStringPackage(const char *in, unsigned char initID, char *initDescription, char *initReference)
{
ID = initID;
Registration = 0;
name = in;
Reference = NULL;
SetReference(initReference);
}
cStringPackage::~cStringPackage(void)
{
if (Reference)
{
delete Reference;
Reference = NULL;
}
}
void cStringPackage::SetReference(char *newReference)
{
if (Reference)
{
delete Reference;
Reference = NULL;
}
if (!newReference || !newReference[0])
{
return;
}
Reference = new char[strlen(newReference)+1];
strcpy(Reference, newReference);
}
#ifndef _STRIPED_
bool cStringPackage::UnderstandToken(char *&Data, int &Size, int token, char *data )
{
cCriteria FullCriteria;
switch(token)
{
case TK_ID:
ID = (unsigned char)atol(data);
return true;
case TK_CONFIG:
#ifdef _STRIPED_
ConfigFile.Load(data,FullCriteria);
#endif
return true;
case TK_REFERENCE:
#ifdef _STRIPED_
if (Reference)
{
char temp[1024];
sprintf(temp, "Please get RJ about this error! Do NOT save or do anything! OldRefeence: %s, New: %s", Reference, data);
MessageBox(NULL, temp, "RJ Error!", MB_OK);
}
#endif
SetReference(data);
return true;
}
if (token == TK_INVALID)
{
return false;
}
return true;
}
#endif
bool cStringPackage::SubSave(FILE *FH )
{
fprintf(FH,"%s %d\n",Tokens[TK_ID], ID);
if (Reference)
{
fprintf(FH,"%s %s\n", Tokens[TK_REFERENCE], Reference);
}
return true;
}
#ifdef _STRIPED_
bool cStringPackage::Save(char *FileName)
{
FILE *FH;
FH = fopen(FileName,"w");
if (!FH)
{
return false;
}
fprintf(FH,"%s %d\n",Tokens[TK_VERSION], STRIP_VERSION);
fprintf(FH,"%s %s\n",Tokens[TK_CONFIG], ConfigFile.fileName);
SubSave(FH);
fclose(FH);
return true;
}
#endif
bool cStringPackage::Load(char *FileName)
{
FILE *FH;
int Size;
char *buffer;
FH = fopen(FileName,"rb");
if (!FH)
{
return false;
}
fseek(FH, 0, SEEK_END);
Size = ftell(FH);
fseek(FH, 0, SEEK_SET);
buffer = new char[Size];
fread(buffer, 1, Size, FH);
fclose(FH);
Load(buffer, Size);
delete buffer;
return true;
}
bool cStringPackage::Load(char *Data, int &Size)
{
char *token_data;
int token;
GetLine(Data, Size, token, token_data);
if (token != TK_VERSION || atol(token_data) != STRIP_VERSION)
{
return false;
}
GetLine(Data, Size, token, token_data);
while (UnderstandToken(Data, Size, token, token_data ))
{
GetLine(Data, Size, token, token_data);
}
return true;
}
#ifdef _STRIPED_
cStringPackageED::cStringPackageED(unsigned char initID, char *initDescription, char *initReference)
:cStringPackage("", initID, initReference)
{
Description = NULL;
SetDescription(initDescription);
}
cStringPackageED::~cStringPackageED(void)
{
if (Description)
{
delete Description;
Description = NULL;
}
}
void cStringPackageED::SetDescription(char *newDescription)
{
if (Description)
{
delete Description;
Description = NULL;
}
if (!newDescription || !newDescription[0])
{
return;
}
Description = new char[strlen(newDescription)+1];
strcpy(Description, newDescription);
}
cStringsED *cStringPackageED::FindString(int &index)
{
if (index == -1)
{
for(index=0;index<MAX_STRINGS;index++)
{
if (!Strings[index].GetUsed())
{
return &Strings[index];
}
}
return NULL;
}
else
{
return &Strings[index];
}
}
void cStringPackageED::ClearString(int index)
{
Strings[index].Clear();
}
bool cStringPackageED::UnderstandToken(char *&Data, int &Size, int token, char *data )
{
int count, i, pos;
switch(token)
{
case TK_DESCRIPTION:
SetDescription(data);
return true;
case TK_COUNT:
count = atol(data);
for(i=0;i<count;i++)
{
GetLine(Data, Size, token, data);
if (token != TK_INDEX)
{
return false;
}
pos = atol(data);
if (!Strings[pos].Load(Data, Size ))
{
return false;
}
}
return true;
default:
return cStringPackage::UnderstandToken(Data, Size, token, data );
}
}
bool cStringPackageED::SubSave(FILE *FH, cCriteria )
{
int i, count;
cStringPackage::SubSave(FH);
if (Description)
{
fprintf(FH,"%s \"%s\"\n", Tokens[TK_DESCRIPTION], Description);
}
for(i=count=0;i<MAX_STRINGS;i++)
{
if (Strings[i].GetUsed())
{
count++;
}
}
fprintf(FH, "%s %d\n",Tokens[TK_COUNT], count);
for(i=count=0;i<MAX_STRINGS;i++)
{
if (Strings[i].GetUsed())
{
fprintf(FH, "%s %d\n", Tokens[TK_INDEX], i);
Strings[i].Save(FH );
}
}
return true;
}
bool cStringPackageED::GenerateCHeader(char *FileName)
{
FILE *FH;
char FilePath[MAX_PATH], *FileNamePos, *Test;
int i;
bool NeedComma = false;;
if (!Reference)
{
return false;
}
FH = fopen(FileName, "w");
if (!FH)
{
return false;
}
GetFullPathName(FileName, sizeof(FilePath), FilePath, &FileNamePos);
for(Test = FilePath; (*Test); Test++)
{
if (strchr(" .", *Test))
{
*Test = '_';
}
}
fprintf(FH, "#ifndef __%s\n",FileNamePos);
fprintf(FH, "#define __%s\n",FileNamePos);
fprintf(FH, "\n\n");
if (Description && Description[0])
{
fprintf(FH, "/********************************************************************************\n");
fprintf(FH, "\n");
fprintf(FH, "%s\n", Description);
fprintf(FH, "\n");
fprintf(FH, "********************************************************************************/\n");
fprintf(FH, "\n\n");
}
fprintf(FH, "#define PACKAGE_%s\t\t0x%02x\n", Reference, (unsigned int)ID);
fprintf(FH, "\n");
fprintf(FH, "enum\n");
fprintf(FH, "{\n");
for(i=0;i<MAX_STRINGS;i++)
{
if (Strings[i].GetUsed())
{
Test = Strings[i].GetReference();
if (Test && Test[0])
{
if (NeedComma)
{
fprintf(FH, ",\n");
}
else
{
NeedComma = true;
}
fprintf(FH, "\t%s_%s = 0x%02x%02x", Reference, Test, (unsigned int)ID, i);
}
}
}
if (NeedComma)
{
fprintf(FH, "\n");
}
fprintf(FH, "};\n");
fprintf(FH, "\n\n");
fprintf(FH, "#endif // __%s\n", FileNamePos);
fclose(FH);
return true;
}
bool cStringPackageED::GenerateDSHeader(char *FileName)
{
FILE *FH;
char FilePath[MAX_PATH], *FileNamePos, *Test;
int i;
if (!Reference)
{
return false;
}
FH = fopen(FileName, "w");
if (!FH)
{
return false;
}
GetFullPathName(FileName, sizeof(FilePath), FilePath, &FileNamePos);
for(Test = FilePath; (*Test); Test++)
{
if (strchr(" .", *Test))
{
*Test = '_';
}
}
fprintf(FH, "// __%s\n",FileNamePos);
fprintf(FH, "//\n");
fprintf(FH, "\n\n");
if (Description && Description[0])
{
fprintf(FH, "/********************************************************************************\n");
fprintf(FH, "\n");
fprintf(FH, "%s\n", Description);
fprintf(FH, "\n");
fprintf(FH, "********************************************************************************/\n");
fprintf(FH, "\n\n");
}
fprintf(FH, "#define PACKAGE_%s\t\t0x%02x\n", Reference, (unsigned int)ID);
fprintf(FH, "\n");
for(i=0;i<MAX_STRINGS;i++)
{
if (Strings[i].GetUsed())
{
Test = Strings[i].GetReference();
if (Test && Test[0])
{
fprintf(FH, "#define %s_%s\t\t\t0x%02x%02x\n", Reference, Test, (unsigned int)ID, i);
}
}
}
fprintf(FH, "\n\n");
fprintf(FH, "// __%s\n", FileNamePos);
fclose(FH);
return true;
}
#endif
#ifndef _STRIPED_
cStringPackageSingle::cStringPackageSingle(const char *in, unsigned char initID, char *initReference)
:cStringPackage(in, initID, initReference)
{
}
cStringPackageSingle::~cStringPackageSingle(void)
{
ReferenceTable.clear();
}
cStringsSingle *cStringPackageSingle::FindString(char *ReferenceLookup)
{
int index;
index = FindStringID(ReferenceLookup);
if (index == -1)
{
return NULL;
}
return FindString(index & SP_STRING);
}
int cStringPackageSingle::FindStringID(const char *ReferenceLookup)
{
map<string, int>::iterator i;
int size;
if (!Reference)
{
return -1;
}
size = strlen(Reference);
if (strlen(ReferenceLookup) < size+2)
{
return -1;
}
if (strncmp(ReferenceLookup, Reference, size))
{
return -1;
}
i = ReferenceTable.find(string(ReferenceLookup + size + 1));
if (i != ReferenceTable.end())
{
return (*i).second;
}
//#ifdef _DEBUG
// // findmeste
// for (map<string, int>::iterator it = ReferenceTable.begin(); it != ReferenceTable.end(); ++it)
// {
// OutputDebugString(va("%s\n",(*it).first.c_str()));
// }
//#endif
return -1;
}
bool cStringPackageSingle::UnderstandToken(char *&Data, int &Size, int token, char *data )
{
int count, i, pos;
char *ReferenceLookup;
switch(token)
{
case TK_COUNT:
count = atol(data);
for(i=0;i<count;i++)
{
GetLine(Data, Size, token, data);
if (token != TK_INDEX)
{
return false;
}
pos = atol(data);
if (!Strings[pos].Load(Data, Size))
{
return false;
}
ReferenceLookup = Strings[pos].GetReference();
if (ReferenceLookup)
{
ReferenceTable[string(ReferenceLookup)] = pos;
}
}
return true;
default:
return cStringPackage::UnderstandToken(Data, Size, token, data);
}
}
#endif
#ifndef _STRIPED_
// A map of loaded string packages
map<string, cStringPackageSingle *> SP_ListByName;
map<byte, cStringPackageSingle *> SP_ListByID;
// Registration
cStringPackageSingle *SP_Register(const char *inPackage, unsigned char Registration)
{
char *buffer;
char Package[MAX_QPATH];
int size;
cStringPackageSingle *new_sp;
map<string, cStringPackageSingle *>::iterator i;
assert(SP_ListByName.size() == SP_ListByID.size());
Q_strncpyz(Package, inPackage, MAX_QPATH);
Q_strupr(Package);
i = SP_ListByName.find(Package);
if (i != SP_ListByName.end())
{
new_sp = (*i).second;
}
else
{
size = FS_ReadFile(va("strip/%s.sp", Package), (void **)&buffer);
if (size == -1)
{
if ( Registration & SP_REGISTER_REQUIRED )
{
Com_Error(ERR_FATAL, "Could not open string package '%s'", Package);
}
return NULL;
}
// Create the new string package
new_sp = new cStringPackageSingle(Package);
new_sp->Load(buffer, size );
FS_FreeFile(buffer);
if (Registration & SP_REGISTER_CLIENT)
{
Com_DPrintf(S_COLOR_YELLOW "SP_Register: Registered client string package '%s' with ID %02x\n", Package, (int)new_sp->GetID());
}
else
{
Com_DPrintf(S_COLOR_YELLOW "SP_Register: Registered string package '%s' with ID %02x\n", Package, (int)new_sp->GetID());
}
// Insert into the name vs package map
SP_ListByName[Package] = new_sp;
// Insert into the id vs package map
SP_ListByID[new_sp->GetID()] = new_sp;
}
// Or in the new registration data
new_sp->Register(Registration);
return new_sp;
}
// Update configstrings array on clients and server
qboolean SP_RegisterServer(const char *Package)
{
cStringPackageSingle *sp;
sp = SP_Register(Package, SP_REGISTER_SERVER);
if (sp)
{
SV_AddConfigstring(Package,CS_STRING_PACKAGES,MAX_STRING_PACKAGES);
return qtrue;
}
return qfalse;
}
// Unload all packages with the relevant registration bits
void SP_Unload(unsigned char Registration)
{
map<string, cStringPackageSingle *>::iterator i, next;
map<byte, cStringPackageSingle *>::iterator id;
assert(SP_ListByName.size() == SP_ListByID.size());
for(i = SP_ListByName.begin(); i != SP_ListByName.end(); i = next)
{
next = i;
next++;
if ((*i).second->UnRegister(Registration))
{
Com_DPrintf(S_COLOR_YELLOW "SP_UnRegister: Package '%s' with ID %02x\n", (*i).first.c_str(), (int)(*i).second->GetID());
id = SP_ListByID.find((*i).second->GetID());
SP_ListByID.erase(id);
delete (*i).second;
SP_ListByName.erase(i);
}
}
}
// Direct string functions
int SP_GetStringID(const char *inReference)
{
map<unsigned char,cStringPackageSingle *>::iterator i;
int ID;
char Reference[MAX_QPATH];
Q_strncpyz(Reference, inReference, MAX_QPATH);
strupr(Reference);
for(i = SP_ListByID.begin(); i != SP_ListByID.end(); i++)
{
ID = (*i).second->FindStringID(Reference);
if (ID >= 0)
{
ID |= ((int)(*i).first) << 8;
return ID;
}
}
return -1;
}
/************************************************************************************************
* SP_GetString
*
* inputs:
* ID of the string package
*
* return:
* pointer to desired String Package
*
************************************************************************************************/
cStringsSingle *SP_GetString(unsigned short ID)
{
cStringPackageSingle *sp;
cStringsSingle *string;
map<unsigned char,cStringPackageSingle *>::iterator i;
i = SP_ListByID.find(SP_GET_PACKAGE(ID));
if (i == SP_ListByID.end())
{
Com_Error(ERR_DROP, "String package not registered for ID %04x", ID);
return NULL;
}
sp = (*i).second;
string = sp->FindString(ID & SP_STRING);
if (!string)
{
Com_Error(ERR_DROP, "String ID %04x not defined\n", ID);
}
return string;
}
cStringsSingle *SP_GetString(const char *Reference)
{
int index;
index = SP_GetStringID(Reference);
if (index == -1)
{
return NULL;
}
return SP_GetString(index);
}
const char *SP_GetStringText(unsigned short ID)
{
cStringsSingle *string;
char *value;
string = SP_GetString(ID);
value = string->GetText();
if (!value)
{
value = "";
}
return value;
}
const char *SP_GetStringTextString(const char *Reference)
{
int index;
index = SP_GetStringID(Reference);
if (index == -1)
{
return "";
}
return SP_GetStringText(index);
}
static void SP_UpdateLanguage(void)
{
map<unsigned char, cStringPackageSingle *>::iterator it;
list<cStringPackageID> sps;
list<cStringPackageID>::iterator spit;
// Grab all SP ids
for(it = SP_ListByID.begin(); it != SP_ListByID.end(); it++)
{
sps.push_back(cStringPackageID((*it).second->GetName(), (*it).second->GetRegistration()));
}
// Clear out all pointers
SP_Unload(SP_REGISTER_CLIENT | SP_REGISTER_SERVER | SP_REGISTER_MENU | SP_REGISTER_REQUIRED);
// Reinitialise with new language
for(spit = sps.begin(); spit != sps.end(); spit++)
{
SP_Register((*spit).GetName(), (*spit).GetReg());
}
sps.clear();
}
void SP_Init(void)
{
sp_language = Cvar_Get("sp_language", va("%d", SP_LANGUAGE_ENGLISH), CVAR_ARCHIVE);
sp_show_strip = Cvar_Get ("sp_show_strip", "0", 0);
SP_UpdateLanguage();
sp_language->modified = qfalse;
}
// called in Com_Frame, so don't take up any time! (can also be called during dedicated)
//
void SP_CheckForLanguageUpdates(void)
{
if (sp_language && sp_language->modified)
{
SP_Init(); // force language package to reload
sp_language->modified = qfalse;
}
}
int Language_GetIntegerValue(void)
{
if (sp_language)
{
return sp_language->integer;
}
return 0;
}
#endif