1 (*
2 * Hedgewars, a free turn based strategy game
3 * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
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; version 2 of the License
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *)
18
19 {$INCLUDE "options.inc"}
20
21 unit uLocale;
22 interface
23 uses uTypes;
24
25 const MAX_EVENT_STRINGS = 255;
26
27 procedure LoadLocale(FileName: shortstring);
GetEventStringnull28 function GetEventString(e: TEventId): ansistring;
29
Formatnull30 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: shortstring; argCount: Byte): shortstring;
Formatnull31 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: shortstring): shortstring;
Formatnull32 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8: shortstring): shortstring;
Formatnull33 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7: shortstring): shortstring;
Formatnull34 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6: shortstring): shortstring;
Formatnull35 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5: shortstring): shortstring;
Formatnull36 function Format(fmt: shortstring; arg1, arg2, arg3, arg4: shortstring): shortstring;
Formatnull37 function Format(fmt: shortstring; arg1, arg2, arg3: shortstring): shortstring;
Formatnull38 function Format(fmt: shortstring; arg1, arg2: shortstring): shortstring;
Formatnull39 function Format(fmt: shortstring; arg1: shortstring): shortstring;
FormatAnull40 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: ansistring; argCount: Byte): ansistring;
FormatAnull41 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: ansistring): ansistring;
FormatAnull42 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8: ansistring): ansistring;
FormatAnull43 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7: ansistring): ansistring;
FormatAnull44 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6: ansistring): ansistring;
FormatAnull45 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5: ansistring): ansistring;
FormatAnull46 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4: ansistring): ansistring;
FormatAnull47 function FormatA(fmt: ansistring; arg1, arg2, arg3: ansistring): ansistring;
FormatAnull48 function FormatA(fmt: ansistring; arg1, arg2: ansistring): ansistring;
FormatAnull49 function FormatA(fmt: ansistring; arg1: ansistring): ansistring;
50
51 {$IFDEF HWLIBRARY}
52 procedure LoadLocaleWrapper(path: pchar; userpath: pchar; filename: pchar); cdecl; export;
53 {$ENDIF}
54
55 implementation
56 uses SysUtils, uRandom, uUtils, uVariables, uDebug, uPhysFSLayer;
57
58 var trevt: array[TEventId] of array [0..Pred(MAX_EVENT_STRINGS)] of ansistring;
59 trevt_n: array[TEventId] of integer;
60
61 procedure LoadLocale(FileName: shortstring);
62 var s: ansistring;
63 f: pfsFile;
64 a, b, c: LongInt;
65 first: array[TEventId] of boolean;
66 e: TEventId;
67 begin
68 {- TODO: Add support for localized decimal separator in Pas2C -}
69 {$IFNDEF PAS2C}
70 lDecimalSeparator:= FormatSettings.DecimalSeparator;
71 {$ENDIF}
72
73 for e:= Low(TEventId) to High(TEventId) do
74 first[e]:= true;
75
76 f:= pfsOpenRead(FileName);
77 checkFails(f <> nil, 'Cannot load locale "' + FileName + '"', false);
78
79 s:= '';
80
81 if f <> nil then
82 begin
83 while not pfsEof(f) do
84 begin
85 pfsReadLnA(f, s);
86 if Length(s) = 0 then
87 continue;
88 if (s[1] < '0') or (s[1] > '9') then
89 continue;
90 checkFails(Length(s) > 6, 'Load locale: empty string', true);
91 {$IFNDEF PAS2C}
92 val(s[1]+s[2], a, c);
93 checkFails(c = 0, ansistring('Load locale: numbers should be two-digit: ') + s, true);
94 val(s[4]+s[5], b, c);
95 checkFails(c = 0, ansistring('Load locale: numbers should be two-digit: ') + s, true);
96 {$ELSE}
97 val(s[1]+s[2], a);
98 val(s[4]+s[5], b);
99 {$ENDIF}
100 checkFails(s[3] = ':', 'Load locale: ":" expected', true);
101 checkFails(s[6] = '=', 'Load locale: "=" expected', true);
102 if not allOK then exit;
103 Delete(s, 1, 6);
104 case a of
105 0: if (b >=0) and (b <= ord(High(TAmmoStrId))) then
106 trammo[TAmmoStrId(b)]:= s;
107 1: if (b >=0) and (b <= ord(High(TMsgStrId))) then
108 trmsg[TMsgStrId(b)]:= s;
109 2: if (b >=0) and (b <= ord(High(TEventId))) then
110 begin
111 checkFails(trevt_n[TEventId(b)] < MAX_EVENT_STRINGS, 'Too many event strings in ' + IntToStr(a) + ':' + IntToStr(b), false);
112 if first[TEventId(b)] then
113 begin
114 trevt_n[TEventId(b)]:= 0;
115 first[TEventId(b)]:= false;
116 end;
117 trevt[TEventId(b)][trevt_n[TEventId(b)]]:= s;
118 inc(trevt_n[TEventId(b)]);
119 end;
120 3: if (b >=0) and (b <= ord(High(TAmmoStrId))) then
121 trammoc[TAmmoStrId(b)]:= s;
122 4: if (b >=0) and (b <= ord(High(TAmmoStrId))) then
123 trammod[TAmmoStrId(b)]:= s;
124 5: if (b >=0) and (b <= ord(High(TGoalStrId))) then
125 trgoal[TGoalStrId(b)]:= s;
126 6: if (b >=0) and (b <= ord(High(TCmdHelpStrId))) then
127 trcmd[TCmdHelpStrId(b)]:= s;
128 end;
129 end;
130 pfsClose(f);
131 end;
132 end;
133
GetEventStringnull134 function GetEventString(e: TEventId): ansistring;
135 begin
136 if trevt_n[e] = 0 then // no messages for this event type?
137 GetEventString:= '*missing translation*'
138 else
139 GetEventString:= trevt[e][GetRandom(trevt_n[e])]; // Pick a random message and return it
140 end;
141
142 // Format the string fmt.
143 // Take a shortstring with placeholders %1, %2, %3, ... %9. and replace
144 // them with the corresponding elements of an array with up to
145 // argCount. ArgCount must not be larger than 9.
146 // Each placeholder must be used exactly once and numbers MUST NOT be
147 // skipped (e.g. using %1 and %3 but not %2.
Formatnull148 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: shortstring; argCount: Byte): shortstring;
149 var i, p: LongInt;
150 tempstr, curArg: shortstring;
151 begin
152 tempstr:= fmt;
153 for i:=0 to argCount - 1 do
154 begin
155 case i of
156 0: curArg:= arg1;
157 1: curArg:= arg2;
158 2: curArg:= arg3;
159 3: curArg:= arg4;
160 4: curArg:= arg5;
161 5: curArg:= arg6;
162 6: curArg:= arg7;
163 7: curArg:= arg8;
164 8: curArg:= arg9;
165 end;
166
167 repeat
168 p:= Pos('%'+IntToStr(i+1), tempstr);
169 if (p <> 0) then
170 begin
171 delete(tempstr, p, 2);
172 insert(curArg, tempstr, p);
173 end;
174 until (p = 0);
175 end;
176 Format:= tempstr;
177 end;
178
179 // Same as Format, but for ansistring
FormatAnull180 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: ansistring; argCount: Byte): ansistring;
181 var i, p: LongInt;
182 tempstr, curArg: ansistring;
183 begin
184 tempstr:= fmt;
185 for i:=0 to argCount - 1 do
186 begin
187 case i of
188 0: curArg:= arg1;
189 1: curArg:= arg2;
190 2: curArg:= arg3;
191 3: curArg:= arg4;
192 4: curArg:= arg5;
193 5: curArg:= arg6;
194 6: curArg:= arg7;
195 7: curArg:= arg8;
196 8: curArg:= arg9;
197 end;
198
199 repeat
200 p:= Pos('%'+IntToStr(i+1), tempstr);
201 if (p <> 0) then
202 begin
203 delete(tempstr, p, 2);
204 insert(curArg, tempstr, p);
205 end;
206 until (p = 0);
207 end;
208 FormatA:= tempstr;
209 end;
210
211 // The following functions are just shortcuts of Format/FormatA, with fewer argument counts
Formatnull212 function Format(fmt: shortstring; arg1: shortstring): shortstring;
213 begin
214 Format:= Format(fmt, arg1, '', '', '', '', '', '', '', '', 1);
215 end;
Formatnull216 function Format(fmt: shortstring; arg1, arg2: shortstring): shortstring;
217 begin
218 Format:= Format(fmt, arg1, arg2, '', '', '', '', '', '', '', 2);
219 end;
Formatnull220 function Format(fmt: shortstring; arg1, arg2, arg3: shortstring): shortstring;
221 begin
222 Format:= Format(fmt, arg1, arg2, arg3, '', '', '', '', '', '', 3);
223 end;
Formatnull224 function Format(fmt: shortstring; arg1, arg2, arg3, arg4: shortstring): shortstring;
225 begin
226 Format:= Format(fmt, arg1, arg2, arg3, arg4, '', '', '', '', '', 4);
227 end;
Formatnull228 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5: shortstring): shortstring;
229 begin
230 Format:= Format(fmt, arg1, arg2, arg3, arg4, arg5, '', '', '', '', 5);
231 end;
Formatnull232 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6: shortstring): shortstring;
233 begin
234 Format:= Format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, '', '', '', 6);
235 end;
Formatnull236 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7: shortstring): shortstring;
237 begin
238 Format:= Format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, '', '', 7);
239 end;
Formatnull240 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8: shortstring): shortstring;
241 begin
242 Format:= Format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, '', 8);
243 end;
Formatnull244 function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: shortstring): shortstring;
245 begin
246 Format:= Format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, 9);
247 end;
248
FormatAnull249 function FormatA(fmt: ansistring; arg1: ansistring): ansistring;
250 begin
251 FormatA:= FormatA(fmt, arg1, ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), 1);
252 end;
FormatAnull253 function FormatA(fmt: ansistring; arg1, arg2: ansistring): ansistring;
254 begin
255 FormatA:= FormatA(fmt, arg1, arg2, ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), 2);
256 end;
FormatAnull257 function FormatA(fmt: ansistring; arg1, arg2, arg3: ansistring): ansistring;
258 begin
259 FormatA:= FormatA(fmt, arg1, arg2, arg3, ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), 3);
260 end;
FormatAnull261 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4: ansistring): ansistring;
262 begin
263 FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), 4);
264 end;
FormatAnull265 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5: ansistring): ansistring;
266 begin
267 FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, arg5, ansistring(''), ansistring(''), ansistring(''), ansistring(''), 5);
268 end;
FormatAnull269 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6: ansistring): ansistring;
270 begin
271 FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, arg5, arg6, ansistring(''), ansistring(''), ansistring(''), 6);
272 end;
FormatAnull273 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7: ansistring): ansistring;
274 begin
275 FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ansistring(''), ansistring(''), 7);
276 end;
FormatAnull277 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8: ansistring): ansistring;
278 begin
279 FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ansistring(''), 8);
280 end;
FormatAnull281 function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: ansistring): ansistring;
282 begin
283 FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, 9);
284 end;
285
286 {$IFDEF HWLIBRARY}
287 procedure LoadLocaleWrapper(path: pchar; userpath: pchar; filename: pchar); cdecl; export;
288 begin
289 PathPrefix := Strpas(path);
290 UserPathPrefix := Strpas(userpath);
291
292 //normally this var set in preInit of engine
293 allOK := true;
294
295 uVariables.initModule;
296
297 PathPrefix:= PathPrefix + #0;
298 UserPathPrefix:= UserPathPrefix + #0;
299 uPhysFSLayer.initModule(@PathPrefix[1], @UserPathPrefix[1]);
300 PathPrefix:= copy(PathPrefix, 1, length(PathPrefix) - 1);
301 UserPathPrefix:= copy(UserPathPrefix, 1, length(UserPathPrefix) - 1);
302
303 LoadLocale(Strpas(filename));
304
305 uPhysFSLayer.freeModule;
306 uVariables.freeModule;
307 end;
308 {$ENDIF}
309
310 end.
311