/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ #include "stdh.h" #include #include #include #include #include #include #include #include #include // table of translations static CNameTable_CTranslationPair _nttpPairs; static CDynamicArray _atpPairs; static int _iLine; #define CHAR_EOF -1 #define CHAR_SRC -2 #define CHAR_DST -3 static int ReadOneChar_t(CTStream &strm) { // skip line breaks and count them unsigned char c; do { strm>>c; if (c=='\n') { _iLine++; } } while (c=='\n' || c=='\r'); // if start of control token if (c=='\\') { // read next char strm>>c; // decode token switch (c) { case '\\': return '\\'; // eol case 'n': return '\n'; // string end case '0': return 0; // source string case '<': return CHAR_SRC; // destination string case '>': return CHAR_DST; // file end case '$': return CHAR_EOF; // other default: if (isprint(c)) { ThrowF_t(TRANS("%d: unknown token '%c'"), _iLine, c); } else { ThrowF_t(TRANS("%d: unknown token ascii: 0x%02x"), _iLine, c); } } } return c; } // read one translation string from file static CTString ReadOneString_t(CTStream &strm) { // start with empty string CTString str; // read characters FOREVER{ int i = ReadOneChar_t(strm); if (i==0) { return str; } else { char c[2]; c[1] = 0; c[0] = i; str+=c; } } } // init translation routines with given translation table ENGINE_API void InitTranslation(void) { // init tables _atpPairs.Clear(); _nttpPairs.Clear(); _nttpPairs.SetAllocationParameters(100, 5, 5); } ENGINE_API void ReadTranslationTable_t( CDynamicArray &atpPairs, const CTFileName &fnmTable) // throw char * { _iLine = 0; CTFileStream strm; strm.Open_t(fnmTable); // read number of pairs INDEX ctPairs; CTString strPairs = ReadOneString_t(strm); strPairs.ScanF("%d", &ctPairs); // instance that much CTranslationPair *atp = atpPairs.New(ctPairs); // for each pair for(INDEX iPair=0; iPair, premature EOF in line #%d!"), (const char *)fnmTable, _iLine); } else { ThrowF_t(TRANS("error in file <%s>, line #%d (pair #%d): expected '<' but found '%c'"), (const char *)fnmTable, _iLine, iPair, iToken); } } // read source tp.tp_strSrc = ReadOneString_t(strm); // next token must be destination if (ReadOneChar_t(strm)!=CHAR_DST) { if (iToken==CHAR_EOF) { ThrowF_t(TRANS("error in file <%s>, premature EOF in line #%d!"), (const char *)fnmTable, _iLine); } else { ThrowF_t(TRANS("error in file <%s>, line #%d (pair #%d): expected '>' but found '%c'"), (const char *)fnmTable, _iLine, iPair, iToken); } } // read destination tp.tp_strDst = ReadOneString_t(strm); }; // last token must be eof if (ReadOneChar_t(strm)!=CHAR_EOF) { ThrowF_t(TRANS("error in file <%s>: end of file marker not found in line #%d!"), (const char *)fnmTable, _iLine); } } // finish translation table building ENGINE_API void FinishTranslationTable(void) { INDEX ctPairs = _atpPairs.Count(); // for each pair _atpPairs.Lock(); for(INDEX iPair=0; iPairSetKeyNames(); } // add given translation table ENGINE_API void AddTranslationTable_t(const CTFileName &fnmTable) // throw char * { // just read it to global array ReadTranslationTable_t(_atpPairs, fnmTable); } // add several tables from a directory using wildcards ENGINE_API void AddTranslationTablesDir_t(const CTFileName &fnmDir, const CTFileName &fnmPattern) // throw char * { // list the translation tables matching given pattern CDynamicStackArray afnmTables; MakeDirList(afnmTables, fnmDir, fnmPattern, 0); for(INDEX i=0; i=iOffset) { str+=iOffset; } else { ASSERT(FALSE); } // find translation pair CTranslationPair *ptp = NULL; if (_atpPairs.Count()>0) { ptp = _nttpPairs.Find(str); } // if not found if (ptp==NULL) { // return original string return str; // if found } else { // return translation return ptp->tp_strDst; } }