Skip to content

Commit 2c8fd3c

Browse files
committed
vgui: initial add of vgui localization code
1 parent 3bbd6e5 commit 2c8fd3c

File tree

4 files changed

+219
-4
lines changed

4 files changed

+219
-4
lines changed

MenuStrings.cpp

+211-3
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1313
GNU General Public License for more details.
1414
*/
1515

16-
16+
#include <ctype.h>
1717
#include "extdll_menu.h"
1818
#include "BaseMenu.h"
1919
#include "Utils.h"
2020
#include "MenuStrings.h"
21+
#include "unicode_strtools.h"
2122

2223
#define EMPTY_STRINGS_1 ""
2324
#define EMPTY_STRINGS_2 EMPTY_STRINGS_1, EMPTY_STRINGS_1
@@ -27,6 +28,14 @@ GNU General Public License for more details.
2728
#define EMPTY_STRINGS_50 EMPTY_STRINGS_20, EMPTY_STRINGS_20, EMPTY_STRINGS_10
2829
#define EMPTY_STRINGS_100 EMPTY_STRINGS_50, EMPTY_STRINGS_50
2930

31+
#define HASH_SIZE 256 // 256 * 4 * 4 == 4096 bytes
32+
static struct dictionary_t
33+
{
34+
const char *name;
35+
const char *value;
36+
dictionary_t *next;
37+
} *hashed_cmds[HASH_SIZE];
38+
3039
const char *MenuStrings[IDS_LAST] =
3140
{
3241
EMPTY_STRINGS_100, // 0..9
@@ -79,7 +88,52 @@ EMPTY_STRINGS_50, // 540..589
7988
EMPTY_STRINGS_10, // 590..599
8089
};
8190

82-
void UI_InitAliasStrings( void )
91+
/*
92+
=================
93+
Com_HashKey
94+
95+
returns hash key for string
96+
=================
97+
*/
98+
static uint Com_HashKey( const char *string, uint hashSize )
99+
{
100+
uint i, hashKey = 0;
101+
102+
for( i = 0; string[i]; i++ )
103+
{
104+
hashKey = (hashKey + i) * 37 + tolower( string[i] );
105+
}
106+
107+
return (hashKey % hashSize);
108+
}
109+
110+
static inline dictionary_t *Dictionary_FindInBucket( dictionary_t *bucket, const char *name )
111+
{
112+
dictionary_t *i = bucket;
113+
for( ; i && strcasecmp( name, i->name ); // filter out
114+
i = i->next );
115+
116+
return i;
117+
}
118+
119+
static void Dictionary_Insert( const char *name, const char *second )
120+
{
121+
uint hash = Com_HashKey( name, HASH_SIZE );
122+
dictionary_t *elem;
123+
124+
elem = new dictionary_t;
125+
elem->name = StringCopy(name);
126+
elem->value = StringCopy(second);
127+
elem->next = hashed_cmds[hash];
128+
hashed_cmds[hash] = elem;
129+
}
130+
131+
static inline dictionary_t *Dictionary_GetBucket( const char *name )
132+
{
133+
return hashed_cmds[ Com_HashKey( name, HASH_SIZE ) ];
134+
}
135+
136+
static void UI_InitAliasStrings( void )
83137
{
84138
char token[1024];
85139

@@ -106,6 +160,137 @@ void UI_InitAliasStrings( void )
106160
MenuStrings[IDS_MAIN_MULTIPLAYERHELP] = StringCopy( token );
107161
}
108162

163+
static void Localize_AddToDictionary( const char *name, const char *lang )
164+
{
165+
char filename[64];
166+
snprintf( filename, sizeof( filename ), "resource/%s_%s.txt", name, lang );
167+
168+
int unicodeLength;
169+
uchar16 *unicodeBuf = (uchar16*)EngFuncs::COM_LoadFile( filename, &unicodeLength );
170+
171+
if( unicodeBuf ) // no problem, so read it.
172+
{
173+
int ansiLength = unicodeLength / 2;
174+
char *afile = new char[ansiLength]; // save original pointer, so we can free it later
175+
char *pfile = afile;
176+
char token[4096];
177+
int i = 0;
178+
179+
Q_UTF16ToUTF8( unicodeBuf + 1, afile, ansiLength, STRINGCONVERT_ASSERT_REPLACE );
180+
181+
pfile = EngFuncs::COM_ParseFile( pfile, token );
182+
183+
if( stricmp( token, "lang" ))
184+
{
185+
Con_Printf( "Localize_AddToDict( %s, %s ): invalid header, got %s", name, lang, token );
186+
goto error;
187+
}
188+
189+
pfile = EngFuncs::COM_ParseFile( pfile, token );
190+
191+
if( strcmp( token, "{" ))
192+
{
193+
Con_Printf( "Localize_AddToDict( %s, %s ): want {, got %s", name, lang, token );
194+
goto error;
195+
}
196+
197+
pfile = EngFuncs::COM_ParseFile( pfile, token );
198+
199+
if( stricmp( token, "Language" ))
200+
{
201+
Con_Printf( "Localize_AddToDict( %s, %s ): want Language, got %s", name, lang, token );
202+
goto error;
203+
}
204+
205+
// skip language actual name
206+
pfile = EngFuncs::COM_ParseFile( pfile, token );
207+
208+
pfile = EngFuncs::COM_ParseFile( pfile, token );
209+
210+
if( stricmp( token, "Tokens" ))
211+
{
212+
Con_Printf( "Localize_AddToDict( %s, %s ): want Tokens, got %s", name, lang, token );
213+
goto error;
214+
}
215+
216+
pfile = EngFuncs::COM_ParseFile( pfile, token );
217+
218+
if( strcmp( token, "{" ))
219+
{
220+
Con_Printf( "Localize_AddToDict( %s, %s ): want { after Tokens, got %s", name, lang, token );
221+
goto error;
222+
}
223+
224+
while( (pfile = EngFuncs::COM_ParseFile( pfile, token )))
225+
{
226+
if( !strcmp( token, "}" ))
227+
break;
228+
229+
char szLocString[4096];
230+
pfile = EngFuncs::COM_ParseFile( pfile, szLocString );
231+
232+
if( !strcmp( szLocString, "}" ))
233+
break;
234+
235+
236+
if( pfile )
237+
{
238+
Dictionary_Insert( token, szLocString );
239+
i++;
240+
}
241+
}
242+
243+
Con_Printf( "Localize_AddToDict: loaded %i words from %s\n", i, filename );
244+
245+
error:
246+
delete[] afile;
247+
248+
EngFuncs::COM_FreeFile( unicodeBuf );
249+
}
250+
else
251+
{
252+
Con_Printf( "Couldn't open file %s. Strings will not be localized!.\n", filename );
253+
}
254+
}
255+
256+
static void Localize_Init( void )
257+
{
258+
char gamedir[256];
259+
260+
EngFuncs::GetGameDir( gamedir );
261+
262+
memset( hashed_cmds, 0, sizeof( hashed_cmds ) );
263+
264+
// first is lowest in priority
265+
if( strcmp( gamedir, "gameui" )) // just for case
266+
Localize_AddToDictionary( "gameui", "english" );
267+
268+
Localize_AddToDictionary( "valve", "english" );
269+
270+
if( strcmp( gamedir, "valve" ))
271+
Localize_AddToDictionary( gamedir, "english" );
272+
}
273+
274+
static void Localize_Free( void )
275+
{
276+
for( int i = 0; i < HASH_SIZE; i++ )
277+
{
278+
dictionary_t *base = hashed_cmds[i];
279+
while( base )
280+
{
281+
dictionary_t *next = base->next;
282+
283+
delete [] base->value;
284+
delete [] base->name;
285+
delete base;
286+
287+
base = next;
288+
}
289+
}
290+
291+
return;
292+
}
293+
109294
void UI_LoadCustomStrings( void )
110295
{
111296
char *afile = (char *)EngFuncs::COM_LoadFile( "gfx/shell/strings.lst", NULL );
@@ -114,6 +299,7 @@ void UI_LoadCustomStrings( void )
114299
int string_num;
115300

116301
UI_InitAliasStrings ();
302+
Localize_Init();
117303

118304
if( !afile )
119305
return;
@@ -131,10 +317,32 @@ void UI_LoadCustomStrings( void )
131317
}
132318
else continue; // invalid declaration ?
133319

134-
// parse new string
320+
// parse new string
135321
pfile = EngFuncs::COM_ParseFile( pfile, token );
136322
MenuStrings[string_num] = StringCopy( token ); // replace default string with custom
137323
}
138324

139325
EngFuncs::COM_FreeFile( afile );
140326
}
327+
328+
const char *L( const char *szStr ) // L means Localize!
329+
{
330+
if( szStr )
331+
{
332+
if( *szStr == '#' )
333+
szStr++;
334+
335+
dictionary_t *base = Dictionary_GetBucket( szStr );
336+
dictionary_t *found = Dictionary_FindInBucket( base, szStr );
337+
338+
if( found )
339+
return found->value;
340+
}
341+
342+
return szStr;
343+
}
344+
345+
void UI_FreeCustomStrings( void )
346+
{
347+
Localize_Free();
348+
}

MenuStrings.h

+2
Original file line numberDiff line numberDiff line change
@@ -615,3 +615,5 @@ GNU General Public License for more details.
615615
#define IDS_LAST 600
616616

617617
extern const char *MenuStrings[IDS_LAST];
618+
619+

Utils.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,12 @@ extern int KEY_GetKey( const char *binding ); // ripped out from engine
139139
extern char *StringCopy( const char *input ); // copy string into new memory
140140
extern int COM_CompareSaves( const void **a, const void **b );
141141
extern void Com_EscapeCommand( char *newCommand, const char *oldCommand, int len );
142-
extern void UI_LoadCustomStrings( void );
143142
extern void UI_EnableTextInput( bool enable );
144143

144+
void UI_LoadCustomStrings( void );
145+
const char *L( const char *szStr ); // L means Localize!
146+
void UI_FreeCustomStrings( void );
147+
145148
#ifdef __APPLE__
146149
#define register
147150
#endif // __APPLE__

extdll_menu.h

+2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@ GNU General Public License for more details.
6969

7070
typedef int (*cmpfunc)( const void *a, const void *b );
7171
typedef int BOOL;
72+
typedef int qboolean;
7273
typedef unsigned char byte;
7374
typedef unsigned int uint;
75+
typedef unsigned int uint32; //!!!
7476

7577
#include "menu_int.h"
7678

0 commit comments

Comments
 (0)