hedgewars/uLocale.pas
branchhedgeroid
changeset 15515 7030706266df
parent 14866 acb0526bf458
--- a/hedgewars/uLocale.pas	Sun Oct 28 15:18:26 2012 +0100
+++ b/hedgewars/uLocale.pas	Fri Dec 06 22:20:53 2019 +0100
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -13,7 +13,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *)
 
 {$INCLUDE "options.inc"}
@@ -22,58 +22,84 @@
 interface
 uses uTypes;
 
-const MAX_EVENT_STRINGS = 100;
+const MAX_EVENT_STRINGS = 255;
 
 procedure LoadLocale(FileName: shortstring);
-function  Format(fmt: shortstring; var arg: shortstring): shortstring;
-function  FormatA(fmt: ansistring; var arg: ansistring): ansistring;
 function  GetEventString(e: TEventId): ansistring;
 
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: shortstring; argCount: Byte): shortstring;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: shortstring): shortstring;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8: shortstring): shortstring;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7: shortstring): shortstring;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6: shortstring): shortstring;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5: shortstring): shortstring;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4: shortstring): shortstring;
+function Format(fmt: shortstring; arg1, arg2, arg3: shortstring): shortstring;
+function Format(fmt: shortstring; arg1, arg2: shortstring): shortstring;
+function Format(fmt: shortstring; arg1: shortstring): shortstring;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: ansistring; argCount: Byte): ansistring;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: ansistring): ansistring;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8: ansistring): ansistring;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7: ansistring): ansistring;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6: ansistring): ansistring;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5: ansistring): ansistring;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4: ansistring): ansistring;
+function FormatA(fmt: ansistring; arg1, arg2, arg3: ansistring): ansistring;
+function FormatA(fmt: ansistring; arg1, arg2: ansistring): ansistring;
+function FormatA(fmt: ansistring; arg1: ansistring): ansistring;
+
 {$IFDEF HWLIBRARY}
-procedure LoadLocaleWrapper(str: pchar); cdecl; export;
+procedure LoadLocaleWrapper(path: pchar; userpath: pchar; filename: pchar); cdecl; export;
 {$ENDIF}
 
 implementation
-uses uRandom, uUtils, uVariables, uDebug;
+uses SysUtils, uRandom, uUtils, uVariables, uDebug, uPhysFSLayer;
 
 var trevt: array[TEventId] of array [0..Pred(MAX_EVENT_STRINGS)] of ansistring;
     trevt_n: array[TEventId] of integer;
 
 procedure LoadLocale(FileName: shortstring);
 var s: ansistring;
-    f: textfile;
+    f: pfsFile;
     a, b, c: LongInt;
     first: array[TEventId] of boolean;
     e: TEventId;
-    loaded: boolean;
 begin
-loaded:= false;
+{- TODO: Add support for localized decimal separator in Pas2C -}
+{$IFNDEF PAS2C}
+lDecimalSeparator:= FormatSettings.DecimalSeparator;
+{$ENDIF}
+
 for e:= Low(TEventId) to High(TEventId) do
     first[e]:= true;
 
-{$I-} // iochecks off
-Assign(f, FileName);
-filemode:= 0; // readonly
-Reset(f);
-if IOResult = 0 then
-    loaded:= true;
-TryDo(loaded, 'Cannot load locale "' + FileName + '"', false);
-if loaded then
+f:= pfsOpenRead(FileName);
+checkFails(f <> nil, 'Cannot load locale "' + FileName + '"', false);
+
+s:= '';
+
+if f <> nil then
     begin
-    while not eof(f) do
+    while not pfsEof(f) do
         begin
-        readln(f, s);
+        pfsReadLnA(f, s);
         if Length(s) = 0 then
             continue;
         if (s[1] < '0') or (s[1] > '9') then
             continue;
-        TryDo(Length(s) > 6, 'Load locale: empty string', true);
+        checkFails(Length(s) > 6, 'Load locale: empty string', true);
+        {$IFNDEF PAS2C}
         val(s[1]+s[2], a, c);
-        TryDo(c = 0, 'Load locale: numbers should be two-digit: ' + s, true);
-        TryDo(s[3] = ':', 'Load locale: ":" expected', true);
+        checkFails(c = 0, ansistring('Load locale: numbers should be two-digit: ') + s, true);
         val(s[4]+s[5], b, c);
-        TryDo(c = 0, 'Load locale: numbers should be two-digit' + s, true);
-        TryDo(s[6] = '=', 'Load locale: "=" expected', true);
+        checkFails(c = 0, ansistring('Load locale: numbers should be two-digit: ') + s, true);
+        {$ELSE}
+        val(s[1]+s[2], a);
+        val(s[4]+s[5], b);
+        {$ENDIF}
+        checkFails(s[3] = ':', 'Load locale: ":" expected', true);
+        checkFails(s[6] = '=', 'Load locale: "=" expected', true);
+        if not allOK then exit;
         Delete(s, 1, 6);
         case a of
             0: if (b >=0) and (b <= ord(High(TAmmoStrId))) then
@@ -82,7 +108,7 @@
                 trmsg[TMsgStrId(b)]:= s;
             2: if (b >=0) and (b <= ord(High(TEventId))) then
                 begin
-                TryDo(trevt_n[TEventId(b)] < MAX_EVENT_STRINGS, 'Too many event strings in ' + IntToStr(a) + ':' + IntToStr(b), false);
+                checkFails(trevt_n[TEventId(b)] < MAX_EVENT_STRINGS, 'Too many event strings in ' + IntToStr(a) + ':' + IntToStr(b), false);
                 if first[TEventId(b)] then
                     begin
                     trevt_n[TEventId(b)]:= 0;
@@ -97,11 +123,12 @@
                 trammod[TAmmoStrId(b)]:= s;
             5: if (b >=0) and (b <= ord(High(TGoalStrId))) then
                 trgoal[TGoalStrId(b)]:= s;
+            6: if (b >=0) and (b <= ord(High(TCmdHelpStrId))) then
+                trcmd[TCmdHelpStrId(b)]:= s;
            end;
        end;
-   Close(f);
+   pfsClose(f);
    end;
-{$I+}
 end;
 
 function GetEventString(e: TEventId): ansistring;
@@ -112,30 +139,171 @@
         GetEventString:= trevt[e][GetRandom(trevt_n[e])]; // Pick a random message and return it
 end;
 
-function Format(fmt: shortstring; var arg: shortstring): shortstring;
-var i: LongInt;
+// Format the string fmt.
+// Take a shortstring with placeholders %1, %2, %3, ... %9. and replace
+// them with the corresponding elements of an array with up to
+// argCount. ArgCount must not be larger than 9.
+// Each placeholder must be used exactly once and numbers MUST NOT be
+// skipped (e.g. using %1 and %3 but not %2.
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: shortstring; argCount: Byte): shortstring;
+var i, p: LongInt;
+tempstr, curArg: shortstring;
 begin
-i:= Pos('%1', fmt);
-if i = 0 then
-    Format:= fmt
-else
-    Format:= copy(fmt, 1, i - 1) + arg + Format(copy(fmt, i + 2, Length(fmt) - i - 1), arg)
+tempstr:= fmt;
+for i:=0 to argCount - 1 do
+    begin
+        case i of
+            0: curArg:= arg1;
+            1: curArg:= arg2;
+            2: curArg:= arg3;
+            3: curArg:= arg4;
+            4: curArg:= arg5;
+            5: curArg:= arg6;
+            6: curArg:= arg7;
+            7: curArg:= arg8;
+            8: curArg:= arg9;
+        end;
+
+        repeat
+        p:= Pos('%'+IntToStr(i+1), tempstr);
+        if (p <> 0) then
+            begin
+            delete(tempstr, p, 2);
+            insert(curArg, tempstr, p);
+            end;
+        until (p = 0);
+    end;
+Format:= tempstr;
+end;
+
+// Same as Format, but for ansistring
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: ansistring; argCount: Byte): ansistring;
+var i, p: LongInt;
+tempstr, curArg: ansistring;
+begin
+tempstr:= fmt;
+for i:=0 to argCount - 1 do
+    begin
+        case i of
+            0: curArg:= arg1;
+            1: curArg:= arg2;
+            2: curArg:= arg3;
+            3: curArg:= arg4;
+            4: curArg:= arg5;
+            5: curArg:= arg6;
+            6: curArg:= arg7;
+            7: curArg:= arg8;
+            8: curArg:= arg9;
+        end;
+
+        repeat
+        p:= Pos('%'+IntToStr(i+1), tempstr);
+        if (p <> 0) then
+            begin
+            delete(tempstr, p, 2);
+            insert(curArg, tempstr, p);
+            end;
+        until (p = 0);
+    end;
+FormatA:= tempstr;
 end;
 
-function FormatA(fmt: ansistring; var arg: ansistring): ansistring;
-var i: LongInt;
+// The following functions are just shortcuts of Format/FormatA, with fewer argument counts
+function Format(fmt: shortstring; arg1: shortstring): shortstring;
+begin
+    Format:= Format(fmt, arg1, '', '', '', '', '', '', '', '', 1);
+end;
+function Format(fmt: shortstring; arg1, arg2: shortstring): shortstring;
+begin
+    Format:= Format(fmt, arg1, arg2, '', '', '', '', '', '', '', 2);
+end;
+function Format(fmt: shortstring; arg1, arg2, arg3: shortstring): shortstring;
+begin
+    Format:= Format(fmt, arg1, arg2, arg3, '', '', '', '', '', '', 3);
+end;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4: shortstring): shortstring;
+begin
+    Format:= Format(fmt, arg1, arg2, arg3, arg4, '', '', '', '', '', 4);
+end;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5: shortstring): shortstring;
+begin
+    Format:= Format(fmt, arg1, arg2, arg3, arg4, arg5, '', '', '', '', 5);
+end;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6: shortstring): shortstring;
+begin
+    Format:= Format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, '', '', '', 6);
+end;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7: shortstring): shortstring;
+begin
+    Format:= Format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, '', '', 7);
+end;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8: shortstring): shortstring;
+begin
+    Format:= Format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, '', 8);
+end;
+function Format(fmt: shortstring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: shortstring): shortstring;
 begin
-i:= Pos('%1', fmt);
-if i = 0 then
-    FormatA:= fmt
-else
-    FormatA:= copy(fmt, 1, i - 1) + arg + FormatA(copy(fmt, i + 2, Length(fmt) - i - 1), arg)
+    Format:= Format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, 9);
+end;
+
+function FormatA(fmt: ansistring; arg1: ansistring): ansistring;
+begin
+    FormatA:= FormatA(fmt, arg1, ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), 1);
+end;
+function FormatA(fmt: ansistring; arg1, arg2: ansistring): ansistring;
+begin
+    FormatA:= FormatA(fmt, arg1, arg2, ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), 2);
+end;
+function FormatA(fmt: ansistring; arg1, arg2, arg3: ansistring): ansistring;
+begin
+    FormatA:= FormatA(fmt, arg1, arg2, arg3, ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), 3);
+end;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4: ansistring): ansistring;
+begin
+    FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, ansistring(''), ansistring(''), ansistring(''), ansistring(''), ansistring(''), 4);
+end;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5: ansistring): ansistring;
+begin
+    FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, arg5, ansistring(''), ansistring(''), ansistring(''), ansistring(''), 5);
+end;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6: ansistring): ansistring;
+begin
+    FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, arg5, arg6, ansistring(''), ansistring(''), ansistring(''), 6);
+end;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7: ansistring): ansistring;
+begin
+    FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ansistring(''), ansistring(''), 7);
+end;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8: ansistring): ansistring;
+begin
+    FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ansistring(''), 8);
+end;
+function FormatA(fmt: ansistring; arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9: ansistring): ansistring;
+begin
+    FormatA:= FormatA(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, 9);
 end;
 
 {$IFDEF HWLIBRARY}
-procedure LoadLocaleWrapper(str: pchar); cdecl; export;
+procedure LoadLocaleWrapper(path: pchar; userpath: pchar; filename: pchar); cdecl; export;
 begin
-    LoadLocale(Strpas(str));
+    PathPrefix := Strpas(path);
+    UserPathPrefix := Strpas(userpath);
+ 
+    //normally this var set in preInit of engine
+    allOK := true;
+    
+    uVariables.initModule;
+ 
+    PathPrefix:= PathPrefix + #0;
+    UserPathPrefix:= UserPathPrefix + #0;
+    uPhysFSLayer.initModule(@PathPrefix[1], @UserPathPrefix[1]);
+    PathPrefix:= copy(PathPrefix, 1, length(PathPrefix) - 1);
+    UserPathPrefix:= copy(UserPathPrefix, 1, length(UserPathPrefix) - 1);
+ 
+    LoadLocale(Strpas(filename));
+ 
+    uPhysFSLayer.freeModule;
+    uVariables.freeModule;
 end;
 {$ENDIF}