/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
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, see .
===========================================================================
*/
#include "qcommon/sstring.h" // stl string class won't compile in here (MS shite), so use Gil's.
#include "tr_local.h"
#include "tr_font.h"
#include "qcommon/stringed_ingame.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This file is shared in the single and multiplayer codebases, so be CAREFUL WHAT YOU ADD/CHANGE!!!!!
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef enum
{
eWestern, // ( I only care about asian languages in here at the moment )
eRussian, // .. but now I need to care about this, since it uses a different TP
ePolish, // ditto
eKorean,
eTaiwanese, // 15x15 glyphs tucked against BR of 16x16 space
eJapanese, // 15x15 glyphs tucked against TL of 16x16 space
eChinese, // 15x15 glyphs tucked against TL of 16x16 space
eThai, // 16x16 cells with glyphs against left edge, special file (tha_widths.dat) for variable widths
} Language_e;
// this is to cut down on all the stupid string compares I've been doing, and convert asian stuff to switch-case
//
Language_e GetLanguageEnum()
{
static int iSE_Language_ModificationCount = -1234; // any old silly value that won't match the cvar mod count
static Language_e eLanguage = eWestern;
// only re-strcmp() when language string has changed from what we knew it as...
//
if (iSE_Language_ModificationCount != se_language->modificationCount )
{
iSE_Language_ModificationCount = se_language->modificationCount;
if ( Language_IsRussian() ) eLanguage = eRussian;
else if ( Language_IsPolish() ) eLanguage = ePolish;
else if ( Language_IsKorean() ) eLanguage = eKorean;
else if ( Language_IsTaiwanese() ) eLanguage = eTaiwanese;
else if ( Language_IsJapanese() ) eLanguage = eJapanese;
else if ( Language_IsChinese() ) eLanguage = eChinese;
else if ( Language_IsThai() ) eLanguage = eThai;
else eLanguage = eWestern;
}
return eLanguage;
}
struct SBCSOverrideLanguages_t
{
const char *m_psName;
Language_e m_eLanguage;
};
// so I can do some stuff with for-next loops when I add polish etc...
//
SBCSOverrideLanguages_t g_SBCSOverrideLanguages[]=
{
{"russian", eRussian},
{"polish", ePolish},
{NULL, eWestern}
};
//================================================
//
#define sFILENAME_THAI_WIDTHS "fonts/tha_widths.dat"
#define sFILENAME_THAI_CODES "fonts/tha_codes.dat"
struct ThaiCodes_t
{
std::map m_mapValidCodes;
std::vector m_viGlyphWidths;
sstring_t m_strInitFailureReason; // so we don't have to keep retrying to work this out
void Clear( void )
{
m_mapValidCodes.clear();
m_viGlyphWidths.clear();
m_strInitFailureReason = ""; // if blank, never failed, else says don't bother re-trying
}
ThaiCodes_t()
{
Clear();
}
// convert a supplied 1,2 or 3-byte multiplied-up integer into a valid 0..n index, else -1...
//
int GetValidIndex( int iCode )
{
std::map ::iterator it = m_mapValidCodes.find( iCode );
if (it != m_mapValidCodes.end())
{
return (*it).second;
}
return -1;
}
int GetWidth( int iGlyphIndex )
{
if (iGlyphIndex < (int)m_viGlyphWidths.size())
{
return m_viGlyphWidths[ iGlyphIndex ];
}
assert(0);
return 0;
}
// return is error message to display, or NULL for success
const char *Init(void)
{
if (m_mapValidCodes.empty() && m_viGlyphWidths.empty())
{
if (m_strInitFailureReason.empty()) // never tried and failed already?
{
int *piData = NULL; // note , not , for []-access
//
// read the valid-codes table in...
//
int iBytesRead = ri.FS_ReadFile( sFILENAME_THAI_CODES, (void **) &piData );
if (iBytesRead > 0 && !(iBytesRead&3)) // valid length and multiple of 4 bytes long
{
int iTableEntries = iBytesRead / sizeof(int);
for (int i=0; i < iTableEntries; i++)
{
m_mapValidCodes[ piData[i] ] = i; // convert MBCS code to sequential index...
}
ri.FS_FreeFile( piData ); // dispose of original
// now read in the widths... (I'll keep these in a simple STL vector, so they'all disappear when the