Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
locale.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/* Copyright (C) Electronic Arts Canada Inc. 1998-1999. All rights reserved. */
20
21#include <string.h>
22#include <assert.h>
23#include "gimex.h" /* for file and memory IO only */
24#include "locale.h"
25#include "wnd_file.h"
26
27/*************************************************************************/
28/* File Format Structures */
29/*************************************************************************/
30
31#define LOCALEFILE_HEADERCHUNKID 0x48434f4c /* 'LOCH' */
32#define LOCALEFILE_INDEXCHUNKID 0x49434f4c /* 'LOCI' */
33#define LOCALEFILE_LANGUAGECHUNKID 0x4c434f4c /* 'LOCL' */
34
35typedef struct
36{
37 unsigned int ChunkID; /* 'LOCH' LOCALEFILE_HEADERCHUNKID */
38 unsigned int ChunkSize; /* size of chunk in bytes */
39 unsigned int Flags; /* 0=no index chunk present,1=index chunk present */
40 unsigned int LanguageCount; /* number of language chunks in this file */
41/* unsigned int LanguageOffset[LanguageCount]; \\ offsets in bytes from start of file to language chunk */
43
44/* offset LOCALEFILE_HEADERCHUNK_LANGUAGE_OFFSET bytes from the start of the chunk to the language offset table */
45#define LOCALEFILE_HEADERCHUNK_LANGUAGE_OFFSET sizeof(LOCALEFILE_HEADERCHUNK)
46
47
48typedef struct
49{
50 unsigned int ChunkID; /* 'LOCI' LOCALEFILE_INDEXCHUNKID */
51 unsigned int ChunkSize; /* size of chunk in bytes */
52 unsigned int StringCount; /* number of string ids in this chunk (same value in all language chunks) */
53 unsigned int pad; /* must be zero */
54/* STRINGID StringID[StringCount]; */
55/* { */
56/* unsigned short ID; \\ id that user gives to look up value */
57/* unsigned short Index; \\ index to look up value in language chunks */
58/* } */
60
61/* offset LOCALEFILE_INDEXCHUNK_STRINGID_OFFSET bytes from the start of the chunk to the string id table */
62#define LOCALEFILE_INDEXCHUNK_STRINGID_OFFSET sizeof(LOCALEFILE_INDEXCHUNK)
63
64
65typedef struct
66{
67 unsigned int ChunkID; /* 'LOCL' LOCALEFILE_LANGUAGECHUNKID */
68 unsigned int ChunkSize; /* size of chunk in bytes including this header and all string data */
69 unsigned int LanguageID; /* language strings are in for this bank */
70 unsigned int StringCount; /* number of strings in this chunk */
71/* unsigned int StringOffset[StringCount]; \\ offsets in bytes from start of chunk to string */
72/* const char* Data[StringCount]; \\ StringCount null terminated strings */
74
75/* offset LOCALEFILE_LANGUAGECHUNK_STRING_OFFSETbytes from the start of the chunk to the string offset table */
76#define LOCALEFILE_LANGUAGECHUNK_STRING_OFFSET sizeof(LOCALEFILE_LANGUAGECHUNK)
77
78
79/*************************************************************************/
80/* LOCALE_INSTANCE declaration */
81/*************************************************************************/
82
86
87typedef struct
88{
89 int BankIndex; /* current language bank set (0..BANK_COUNT-1) */
90 BANK* pBank[LOCALE_BANK_COUNT]; /* array of string banks */
91 INDEX* pIndex[LOCALE_BANK_COUNT]; /* array of string indices */
93
94static LOCALE_INSTANCE *lx = NULL;
95
96/*************************************************************************/
97/* initialization/restore */
98/*************************************************************************/
99
100/* helper function to make assertions for initialization clearer */
102{
103 if ( lx == NULL ) {
104// TRACE("LOCALE API is not initialized - call LOCALE_init before calling LOCALE functions\n");
105 }
106 return( lx != NULL );
107}
108
109/*
110;
111; ABSTRACT
112;
113; LOCALE_init - Init the localization module
114;
115;
116; SUMMARY
117;
118; #include "realfont.h"
119;
120; int LOCALE_init(void)
121;
122; DESCRIPTION
123;
124; Initilizes everything needed to use the locale API. Can only be called
125; once until LOCALE_restore is called.
126;
127; Returns non-zero if everything went ok.
128;
129; SEE ALSO
130;
131; LOCALE_restore
132;
133;
134; EXAMPLE
135;
136; locale_eg.c
137;
138; <HTML A HREF="locale_eg.c">Download the source<HTML /A>
139; <HTML A HREF="locale_eg.csv">locale_eg.csv<HTML /A> (example data)
140;
141;
142; END ABSTRACT
143;
144*/
145
146int LOCALE_init(void)
147{
148 int ok = 0;
149
150 /* ensure locale module is NOT already initialized */
151 ASSERT(lx == NULL); /* can only call LOCALE_init after a restore or once, cannot double init locale API */
152
153 /* allocate instance */
154 lx = (LOCALE_INSTANCE*)galloc(sizeof(LOCALE_INSTANCE));
155 if (lx != NULL) {
156 memset(lx, 0, sizeof(LOCALE_INSTANCE));
157 ok = 1;
158 }
159 return ok;
160}
161
162/*
163;
164; ABSTRACT
165;
166; LOCALE_restore - Free resources used by the locale module
167;
168;
169; SUMMARY
170;
171; #include "realfont.h"
172;
173; void LOCALE_restore(void)
174;
175; DESCRIPTION
176;
177; Restores all resources used by the locale API. Can only be called after
178; LOCALE_init, and only once.
179;
180; SEE ALSO
181;
182; LOCALE_init
183;
184;
185; EXAMPLE
186;
187; locale_eg.c
188;
189; <HTML A HREF="locale_eg.c">Download the source<HTML /A>
190; <HTML A HREF="locale_eg.csv">locale_eg.csv<HTML /A> (example data)
191;
192;
193; END ABSTRACT
194;
195*/
196
198{
199 int i;
200
201 if( lx != NULL ) {
202
203 ASSERT(LOCALE_isinitialized()); /* must call LOCALE_init before calling this function */
204 ASSERT(lx != NULL);
205
206 /* free any language tables */
207 for (i = 0; i < LOCALE_BANK_COUNT; i++) {
208 if (lx->pBank[i]) {
211 }
212 }
213
214 /* free instance */
215 gfree(lx);
216 lx = NULL;
217 }
218}
219
220/*************************************************************************/
221/* attributes */
222/*************************************************************************/
223
224/*
225;
226; ABSTRACT
227;
228; LOCALE_setbank - Set the current bank
229;
230;
231; SUMMARY
232;
233; #include "realfont.h"
234;
235; void LOCALE_setbank(BankIndex)
236; int BankIndex; Number between 0 and LOCALE_BANK_COUNT - 1
237;
238; DESCRIPTION
239;
240; Sets the current bank to be active. All functions will now use this
241; bank for strings. A bank is slot where a string table is loaded.
242; More than one bank can have a table loaded but the locale functions
243; only work on one bank at a time, the active bank set by this function.
244;
245; SEE ALSO
246;
247; LOCALE_getbank
248;
249;
250; EXAMPLE
251;
252; locale_eg.c
253;
254; <HTML A HREF="locale_eg.c">Download the source<HTML /A>
255; <HTML A HREF="locale_eg.csv">locale_eg.csv<HTML /A> (example data)
256;
257;
258; END ABSTRACT
259;
260*/
261
262void LOCALE_setbank(int BankIndex)
263{
264 ASSERT(LOCALE_isinitialized()); /* must call LOCALE_init before calling this function */
265 lx->BankIndex = BankIndex;
266}
267
268/*
269;
270; ABSTRACT
271;
272; LOCALE_getbank - Get the current bank
273;
274;
275; SUMMARY
276;
277; #include "realfont.h"
278;
279; int LOCALE_getbank(void)
280;
281; DESCRIPTION
282;
283; Returns the bank index of the current bank.
284;
285; SEE ALSO
286;
287; LOCALE_setbank
288;
289;
290; EXAMPLE
291;
292; locale_eg.c
293;
294; <HTML A HREF="locale_eg.c">Download the source<HTML /A>
295; <HTML A HREF="locale_eg.csv">locale_eg.csv<HTML /A> (example data)
296;
297;
298; END ABSTRACT
299;
300*/
301
303{
304 ASSERT(LOCALE_isinitialized()); /* must call LOCALE_init before calling this function */
305 return lx->BankIndex;
306}
307
308
309/*
310;
311; ABSTRACT
312;
313; LOCALE_getbanklanguageid - Get the language id for the current bank
314;
315;
316; SUMMARY
317;
318; #include "realfont.h"
319;
320; int LOCALE_getbanklanguageid(void)
321;
322; DESCRIPTION
323;
324; Returns the language id of the current bank. This id will match
325; the lanugage id in the header file generated by Locomoto
326;
327; SEE ALSO
328;
329; LOCALE_loadtable
330;
331; EXAMPLE
332;
333; locale_eg.c
334;
335; <HTML A HREF="locale_eg.c">Download the source<HTML /A>
336; <HTML A HREF="locale_eg.csv">locale_eg.csv<HTML /A> (example data)
337;
338;
339; END ABSTRACT
340;
341*/
342
344{
345 ASSERT(LOCALE_isinitialized()); /* must call LOCALE_init before calling this function */
346 ASSERT(lx->pBank[lx->BankIndex]); /* must load a table into bank before calling this function */
347 return (int)(lx->pBank[lx->BankIndex]->LanguageID);
348}
349
350/*
351;
352; ABSTRACT
353;
354; LOCALE_getbankstringcount - Get the string count for the current bank
355;
356;
357; SUMMARY
358;
359; #include "realfont.h"
360;
361; int LOCALE_getbankstringcount(void)
362;
363; DESCRIPTION
364;
365; Returns the number of strings in the current bank. If zero is
366; returned then this bank is empty.
367;
368; SEE ALSO
369;
370; LOCALE_loadtable
371;
372; EXAMPLE
373;
374; locale_eg.c
375;
376; <HTML A HREF="locale_eg.c">Download the source<HTML /A>
377; <HTML A HREF="locale_eg.csv">locale_eg.csv<HTML /A> (example data)
378;
379;
380; END ABSTRACT
381;
382*/
383
385{
386 int StringCount = 0;
387
388 ASSERT(LOCALE_isinitialized()); /* must call LOCALE_init before calling this function */
389 if (lx->pBank[lx->BankIndex]) {
390 StringCount = lx->pBank[lx->BankIndex]->StringCount;
391 }
392 return StringCount;
393}
394
395/*************************************************************************/
396/* operations */
397/*************************************************************************/
398
399/*
400;
401; ABSTRACT
402;
403; LOCALE_loadtable - Load a string table into the current bank
404;
405;
406; SUMMARY
407;
408; #include "realfont.h"
409;
410; int LOCALE_loadtable(pathname, languageid)
411;
412; const char* pathname; // pathname of .loc file to load
413; int languageid; // language id to load (from .h file)
414;
415; DESCRIPTION
416;
417; Loads the specified language from the string file into the
418; current bank. Returns non zero if the operation was succesful.
419; The bank must be free before you can call LOCALE_loadtable. To
420; free a bank use the LOCALE_freetable function. To determine
421; if the bank is free use the LOCALE_getbankstringcount function.
422;
423; The languageid value is available in the .h file created by
424; locomoto.
425;
426; Returns non-zero if everthing is ok.
427;
428; SEE ALSO
429;
430; LOCALE_freetable, LOCALE_getbankstringcount
431;
432; EXAMPLE
433;
434; locale_eg.c
435;
436; <HTML A HREF="locale_eg.c">Download the source<HTML /A>
437; <HTML A HREF="locale_eg.csv">locale_eg.csv<HTML /A> (example data)
438;
439;
440; END ABSTRACT
441;
442*/
443
444static int readheader( GSTREAM* g )
445{
446 int ok = 0;
447
448 /* read file header */
450 int HeaderChunkSize = sizeof(LOCALEFILE_HEADERCHUNK);
451
452// VERIFY(gread(g, &header, HeaderChunkSize) == HeaderChunkSize);
453 if( gread(g, &header, HeaderChunkSize) != HeaderChunkSize ) {
454 return ok;
455 }
456
457 Msg( __LINE__, __FILE__, "readheader - HeaderChunkSize = %d.", HeaderChunkSize );
458 Msg( __LINE__, __FILE__, "readheader - header.LanguageCount = %d.", header.LanguageCount );
459 Msg( __LINE__, __FILE__, "readheader - header.Flags = %d.", header.Flags );
460
461 ASSERT( header.ChunkID == LOCALEFILE_HEADERCHUNKID ); /* ensure that this is a valid .loc file */
462
463 /* read index chunk if present */
464 if ( header.Flags == 1 ) {
465
466 int IndexChunkSize;
467 int IndexChunkPos = header.ChunkSize;
468
469 /* read index chunk size */
470// VERIFY(gseek(g, IndexChunkPos + 4));
471 if( !gseek( g, IndexChunkPos + 4)) {
472 return ok;
473 }
474
475 Msg( __LINE__, __FILE__, "readheader - seek to = %d.", IndexChunkPos + 4 );
476
477// VERIFY(gread(g, &IndexChunkSize, 4) == 4);
478 if( gread( g, &IndexChunkSize, 4) != 4 ) {
479 return ok;
480 }
481
482 Msg( __LINE__, __FILE__, "readheader - IndexChunkSize = %d.", IndexChunkSize );
483
484 /* alloc and read index chunk */
485 lx->pIndex[lx->BankIndex] = (LOCALEFILE_INDEXCHUNK *)galloc((long)IndexChunkSize );
486 if (lx->pIndex[lx->BankIndex]) {
487
488// VERIFY(gseek(g, IndexChunkPos));
489 gseek( g, IndexChunkPos );
490
491 Msg( __LINE__, __FILE__, "readheader - seek to = %d.", IndexChunkPos );
492
493// VERIFY(gread(g, lx->pIndex[lx->BankIndex], IndexChunkSize) == IndexChunkSize);
494 if ( gread(g, lx->pIndex[lx->BankIndex], IndexChunkSize ) != IndexChunkSize ) {
495 return ok;
496 }
497 Msg( __LINE__, __FILE__, "readheader - IndexChunkSize = %d.", IndexChunkSize );
498
499 ASSERT( lx->pIndex[lx->BankIndex]->ChunkID == LOCALEFILE_INDEXCHUNKID );
500
501 ok = 1;
502 }
503 }
504 Msg( __LINE__, __FILE__, "readheader - exiting." );
505
506 return ok;
507}
508
509static int readstrings( GSTREAM* g, int LanguageID )
510{
511 Msg( __LINE__, __FILE__, "readstrings:: g ok? %d.", ((g!= NULL)?1:0));
512
513 int ok = 0;
514
515 int LanguageChunkOffsetPos = 16 + LanguageID*4;
516 int LanguageChunkPos = 0;
517 int LanguageChunkSize = -1;
518
519 /* read offset to language chunk */
520// VERIFY(gseek(g, (int)LanguageChunkOffsetPos));
521// VERIFY(gread(g, &LanguageChunkPos, 4) == 4);
522 if( !gseek( g, (int)LanguageChunkOffsetPos )) {
523 return ok;
524 }
525 if( gread( g, &LanguageChunkPos, 4 ) != 4 ) {
526 return ok;
527 }
528
529 /* read language chunk size */
530// VERIFY(gseek(g, LanguageChunkPos + 4));
531// VERIFY(gread(g, &LanguageChunkSize, 4) == 4);
532 if( !gseek( g, LanguageChunkPos + 4 )) {
533 return ok;
534 }
535 if( gread( g, &LanguageChunkSize, 4 ) != 4 ) {
536 return ok;
537 }
538
539 Msg( __LINE__, __FILE__, "readstrings::LanguageChunkOffsetPos = %d.", LanguageChunkOffsetPos );
540 Msg( __LINE__, __FILE__, "readstrings::LanguageChunkPos = %d.", LanguageChunkPos );
541 Msg( __LINE__, __FILE__, "readstrings::LanguageChunkSize = %d.", LanguageChunkSize );
542
543 /* alloc and read language chunk */
544 lx->pBank[lx->BankIndex] = (LOCALEFILE_LANGUAGECHUNK *)galloc((long)LanguageChunkSize);
545 if (lx->pBank[lx->BankIndex]) {
546
547 Msg( __LINE__, __FILE__, "readstrings:: A." );
548
549// VERIFY(gseek(g, LanguageChunkPos));
550// VERIFY(gread(g, lx->pBank[lx->BankIndex], LanguageChunkSize) == LanguageChunkSize);
551 if( !gseek( g, LanguageChunkPos )) {
552 return ok;
553 }
554 if( gread( g, lx->pBank[lx->BankIndex], LanguageChunkSize ) != LanguageChunkSize ) {
555 return ok;
556 }
557
558 ASSERT(lx->pBank[lx->BankIndex]->ChunkID == LOCALEFILE_LANGUAGECHUNKID);
559 ok = 1;
560 }
561 return ok;
562}
563
564int LOCALE_loadtable(const char* PathName, int LanguageID)
565{
566 int ok = 0;
567 GSTREAM* g;
568
569 ASSERT(LOCALE_isinitialized()); /* must call LOCALE_init before calling this function */
570 ASSERT(lx->pBank[lx->BankIndex] == NULL); /* bank must be empty before loading a new table */
571 ASSERT(lx->pIndex[lx->BankIndex] == NULL); /* bank must be empty before loading a new table */
572
573 g = gopen( PathName );
574 if( g != NULL ) {
575
576 Msg( __LINE__, __FILE__, "LOCALE_loadtable-- file opened." );
577
578 if( readheader(g)) {
579
580 Msg( __LINE__, __FILE__, "LOCALE_loadtable-- readstrings." );
581
582 ok = readstrings( g, LanguageID );
583
584 Msg( __LINE__, __FILE__, "LOCALE_loadtable-- ok = %d ).", ok );
585 }
586 gclose(g);
587 }
588 return ok;
589}
590
591/*
592;
593; ABSTRACT
594;
595; LOCALE_purgetable - OBSOLETE
596;
597; Make all references to LOCALE_freetable
598;
599; END ABSTRACT
600;
601*/
602
603/*
604;
605; ABSTRACT
606;
607; LOCALE_freetable - Free the string table in the current bank
608;
609;
610; SUMMARY
611;
612; #include "realfont.h"
613;
614; void LOCALE_freetable(void)
615;
616; DESCRIPTION
617;
618; Frees the table loaded in the current bank. There must be a
619; table loaded in the current bank. Use LOCALE_getbankstringcount
620; to determine if the bank is free or not.
621;
622; SEE ALSO
623;
624; LOCALE_loadtable, LOCALE_getbankstringcount
625;
626; EXAMPLE
627;
628; locale_eg.c
629;
630; <HTML A HREF="locale_eg.c">Download the source<HTML /A>
631; <HTML A HREF="locale_eg.csv">locale_eg.csv<HTML /A> (example data)
632;
633;
634; END ABSTRACT
635;
636*/
637
639{
640 if( lx != NULL ) {
641
642 ASSERT(LOCALE_isinitialized()); /* must call LOCALE_init before calling this function */
643 ASSERT(lx->pBank[lx->BankIndex]); /* table must be loaded before calling this function */
644
645 /* free string bank */
646 gfree(lx->pBank[lx->BankIndex]);
647 lx->pBank[lx->BankIndex] = NULL;
648
649 /* if the bank has an index loaded, free that as well */
650 if (lx->pIndex[lx->BankIndex]) {
651 gfree(lx->pIndex[lx->BankIndex]);
652 lx->pIndex[lx->BankIndex] = NULL;
653 }
654 }
655}
656
657/*
658;
659; ABSTRACT
660;
661; LOCALE_getstring - Return the specified string from the current bank
662;
663; SUMMARY
664;
665; #include "realfont.h"
666;
667; const char* LOCALE_getstring( StringID )
668; int StringID; ID of string to return
669;
670; DESCRIPTION
671;
672; Returns the string specified from the current bank. There must
673; be a string table loaded into the current bank. Use the String
674; ID specified in the header file created by Locomoto. Note that
675; the string pointer is a const pointer. Do not modify the string
676; or the Locale library may return invalid results.
677;
678; If the .loc file was created with an index StringID can be any
679; valid integer in the range 0..65535. If no index was created
680; with the .loc file StringID will be a zero based array index.
681;
682; String is returned by const for a reason. Bad things will happen
683; if you modify it. You have been warned.
684;
685; SEE ALSO
686;
687; LOCALE_loadtable, LOCALE_getbankstringcount
688;
689; EXAMPLE
690;
691; locale_eg.c
692;
693; <HTML A HREF="locale_eg.c">Download the source<HTML /A>
694; <HTML A HREF="locale_eg.csv">locale_eg.csv<HTML /A> (example data)
695;
696;
697; END ABSTRACT
698;
699*/
700
701#include <stdlib.h> // for bsearch function
702
703static int compare ( const void* arg1, const void* arg2 )
704{
705 const unsigned short* s1 = (const unsigned short*)(arg1);
706 const unsigned short* s2 = (const unsigned short*)(arg2);
707 return (*s1) - (*s2);
708}
709
710static int getstringbyindex( unsigned short key, const INDEX* pIndex )
711{
712 int index = 0;
713 unsigned short* result;
714 unsigned char* base; /* pointer to base of string id table */
715
716 ASSERT(LOCALE_isinitialized()); /* must call LOCALE_init before calling this function */
717 ASSERT(pIndex != NULL); /* index not loaded - .loc file must have index created (use -i option) */
718
719 base = ((unsigned char*)pIndex) + LOCALEFILE_INDEXCHUNK_STRINGID_OFFSET;
720 result = (unsigned short*)bsearch((unsigned char *)&key, base, pIndex->StringCount, 4, compare);
721
722 if (result != NULL) {
723 /* index is the second unsigned short */
724 ++result;
725 index = *result;
726 } else {
727 index = -1;
728 }
729 return index;
730}
731
732const char* LOCALE_getstring( int StringID )
733{
734 const char* p; /* pointer to string, NULL if string cannot be found */
735
736 Msg( __LINE__, __FILE__, "Locale_getstring::( %d ).", StringID );
737
738 ASSERT( LOCALE_isinitialized()); /* must call LOCALE_init before calling this function */
739
740 /* get string array index from the index if it exists */
741 if ( lx->pIndex[ lx->BankIndex ] != NULL ) {
742 StringID = getstringbyindex((unsigned short)StringID, lx->pIndex[lx->BankIndex]);
743 }
744
745 Msg( __LINE__, __FILE__, "Locale_getstring::( %d ).", StringID );
746 Msg( __LINE__, __FILE__, "Locale_getstring::( lx->BankIndex = %d ).", lx->BankIndex );
747 Msg( __LINE__, __FILE__, "Locale_getstring::( lx->pBank[lx->BankIndex]->StringCount = %d ).", lx->pBank[lx->BankIndex]->StringCount );
748
749 if ((StringID >= 0) && (StringID < (int)(lx->pBank[lx->BankIndex]->StringCount ))) {
750
751 Msg( __LINE__, __FILE__, "Locale_getstring:: A" );
752
753 unsigned int offset;
754
755 p = (const char*)(lx->pBank[lx->BankIndex]);
756
757 Msg( __LINE__, __FILE__, "Locale_getstring:: B" );
758
759 offset = *(unsigned int*)(p + LOCALEFILE_LANGUAGECHUNK_STRING_OFFSET + StringID*4);
760
761 Msg( __LINE__, __FILE__, "Locale_getstring:: C" );
762
763 p += offset;
764
765 Msg( __LINE__, __FILE__, "Locale_getstring:: D" );
766
767
768 } else {
769 p = NULL;
770 }
771
772 Msg( __LINE__, __FILE__, L"%s", 1252, (wchar_t *)p );
773
774 return p;
775}
776
777
778/*
779;
780; ABSTRACT
781;
782; LOCALE_getstr - return selected string from the specified .loc file
783;
784;
785; SUMMARY
786;
787; #include "realfont.h"
788;
789; const char* LOCALE_getstr(stringid)
790;
791; int stringid; // string id to return
792;
793; DESCRIPTION
794;
795; Returns the string identified by stringid from the specified
796; .loc file. Use the string ID specified in the header file created
797; by Locomoto. Note that the string pointer is a const pointer. Do
798; not modify the string or the Locale library may return invalid results.
799;
800; If your strings are Unicode strings, cast the result to a const USTR *.
801;
802; If the .loc file was created with an index stringid can be any
803; valid integer in the range 0..65535. If no index was created
804; with the .loc file stringid will be a zero based array index.
805;
806; String is returned by const for a reason. Bad things will happen
807; if you modify it. You have been warned.
808;
809; SEE ALSO
810;
811; EXAMPLE
812;
813; locale_eg.c
814;
815; <HTML A HREF="locale_eg.c">Download the source<HTML /A>
816; <HTML A HREF="locale_eg.csv">locale_eg.csv<HTML /A> (example data)
817;
818; END ABSTRACT
819;
820*/
821
823
824const char* LOCALE_getstr( const void* pLocFile, int StringID )
825{
826 const char* p; /* pointer to string, NULL if string cannot be found */
827
828 HEADER* pHeader;
829 BANK* pBank;
830
831 ASSERT(pLocFile != NULL);
832
833 pHeader = (LOCALEFILE_HEADERCHUNK*)(pLocFile);
835 ASSERT(pHeader->LanguageCount >= 1);
836
837 if( pHeader->Flags == 1 ) {
838
839 /* file has an index */
840 INDEX* pIndex = (INDEX*)((unsigned char*)(pLocFile) + pHeader->ChunkSize);
841 StringID = getstringbyindex((unsigned short)StringID, pIndex);
842 }
843
844 /* get pointer to string bank */
845 {
846 int offset = *((int*)(pLocFile) + 4 + LOCALElanguageid);
847 pBank = (BANK*)((unsigned char*)(pLocFile) + offset);
848 }
849
850 if ((StringID >= 0) && (StringID < (int)(pBank->StringCount))) {
851
852 unsigned int offset;
853
854 p = (const char*)(pBank);
855 offset = *(unsigned int*)(p + LOCALEFILE_LANGUAGECHUNK_STRING_OFFSET + StringID*4);
856 p += offset;
857
858 } else {
859 p = NULL;
860 }
861
862 return p;
863}
864
#define NULL
Definition BaseType.h:92
LanguageID
Definition Language.h:63
int GCALL gread(GSTREAM *g, void *buf, int size)
bool GCALL gclose(GSTREAM *g)
Definition EZGIMEX.cpp:176
bool GCALL gseek(GSTREAM *g, GPOS offset)
#define gfree
Definition gimex.h:360
GSTREAM *GCALL gopen(const char *pathname)
Definition EZGIMEX.cpp:146
#define galloc
Definition gimex.h:356
struct GSTREAM GSTREAM
Definition gimex.h:173
#define Msg
Definition Wnd_File.h:102
#define ASSERT(x)
Definition Wnd_File.h:58
LOCALEFILE_LANGUAGECHUNK BANK
Definition locale.cpp:85
void LOCALE_setbank(int BankIndex)
Definition locale.cpp:262
#define LOCALEFILE_LANGUAGECHUNK_STRING_OFFSET
Definition locale.cpp:76
const char * LOCALE_getstr(const void *pLocFile, int StringID)
Definition locale.cpp:824
#define LOCALEFILE_LANGUAGECHUNKID
Definition locale.cpp:33
#define LOCALEFILE_HEADERCHUNKID
Definition locale.cpp:31
#define LOCALEFILE_INDEXCHUNK_STRINGID_OFFSET
Definition locale.cpp:62
int LOCALE_isinitialized(void)
Definition locale.cpp:101
int LOCALElanguageid
Definition locale.cpp:822
int LOCALE_getbankstringcount(void)
Definition locale.cpp:384
void LOCALE_freetable(void)
Definition locale.cpp:638
int LOCALE_getbank(void)
Definition locale.cpp:302
void LOCALE_restore(void)
Definition locale.cpp:197
LOCALEFILE_INDEXCHUNK INDEX
Definition locale.cpp:84
const char * LOCALE_getstring(int StringID)
Definition locale.cpp:732
int LOCALE_init(void)
Definition locale.cpp:146
int LOCALE_loadtable(const char *PathName, int LanguageID)
Definition locale.cpp:564
LOCALEFILE_HEADERCHUNK HEADER
Definition locale.cpp:83
int LOCALE_getbanklanguageid(void)
Definition locale.cpp:343
#define LOCALEFILE_INDEXCHUNKID
Definition locale.cpp:32
#define LOCALE_BANK_COUNT
Definition locale.h:45
BANK * pBank[LOCALE_BANK_COUNT]
Definition locale.cpp:90
INDEX * pIndex[LOCALE_BANK_COUNT]
Definition locale.cpp:91
unsigned int ChunkSize
Definition locale.cpp:38
unsigned int ChunkID
Definition locale.cpp:37
unsigned int Flags
Definition locale.cpp:39
unsigned int LanguageCount
Definition locale.cpp:40
unsigned int ChunkID
Definition locale.cpp:50
unsigned int pad
Definition locale.cpp:53
unsigned int StringCount
Definition locale.cpp:52
unsigned int ChunkSize
Definition locale.cpp:51
unsigned int LanguageID
Definition locale.cpp:69
unsigned int ChunkID
Definition locale.cpp:67
unsigned int StringCount
Definition locale.cpp:70
unsigned int ChunkSize
Definition locale.cpp:68