/// unit obsahujuci funkcie na vratenie lokalizovaneho stringu
/// z .dll subora, alebo s hasovacej tabulky definujucej tieto stringy
unit langres;

interface

uses constants;

function GetLangString(const Index: integer) : xString;
procedure SetCurrentLang(i: Integer);
function GetCurrentLang: Integer;
function WideStringToString(const ws: WideString; codePage: Word): AnsiString;
function StringToWideString(const s: AnsiString; codePage: Word): WideString;

implementation

uses Windows,SysUtils,hashmap,langstrings;

var stringSet: TStrIntHashMap;
    hLangLib: THandle;
    iCurrentLang: Integer;

/// funkcia transformujuca widestring an ansistring
function WideStringToString(const ws: WideString; codePage: Word): AnsiString;
var
  l: integer;
begin
  if ws = '' then
    Result := ''
  else begin
    l := WideCharToMultiByte(codePage,WC_COMPOSITECHECK or WC_DISCARDNS or WC_SEPCHARS or WC_DEFAULTCHAR,@ws[1],-1,nil,0,nil,nil);
    SetLength(Result, l - 1);
    if l > 1 then
      WideCharToMultiByte(codePage,WC_COMPOSITECHECK or WC_DISCARDNS or WC_SEPCHARS or WC_DEFAULTCHAR,@ws[1],-1,@Result[1],l-1,nil,nil);
  end;
end;

/// funkcia transformujuca ansistring an widestring
function StringToWideString(const s: AnsiString; codePage: Word): WideString;
var
  l: integer;
begin
  if s = '' then
    Result := ''
  else begin
    l := MultiByteToWideChar(codePage,MB_PRECOMPOSED,PChar(@s[1]),-1,nil,0);
    SetLength(Result, l - 1);
    if l > 1 then
      MultiByteToWideChar(CodePage,MB_PRECOMPOSED,PChar(@s[1]),-1,PWideChar(@Result[1]),l-1);
  end;
end;

/// procedura na nastavenie jazyka
procedure SetCurrentLang(i: Integer);
begin
  iCurrentLang := i;
end;

/// funkcia zistujuca momentalne nastaveny jazyk
function GetCurrentLang: Integer;
begin
  result := iCurrentLang;
end;

/// funkcia vracajuca lokalizovany string na zaklade vstupneho indexu a nastaveneho jazyka
function GetLangString(const Index: Integer) : xString;
var bufferW : array[0..255] of Widechar;
    strTemp: WideString;
    ls : Integer;
    S: xString;
    p: Integer;
begin
{$IFDEF LANGDLL}
  Result := '';
  begin
    ls := LoadStringW(hLangLib, LANG_RES_OFFSET + iCurrentLang * LANG_RES_SIZE + Index, bufferW, sizeof(bufferW) div sizeof(Widechar)); // / sizeof(TCHAR));
    if ls <> 0 then begin
      strTemp := bufferW;
      result := UTF8Decode(strTemp);
    end
    else begin
      ls := LoadStringW(hLangLib, LANG_RES_OFFSET + iCurrentLang * LANG_RES_SIZE + LANG_RES_SIZE shr 1, bufferW, sizeof(bufferW) div sizeof(Widechar)); // / sizeof(TCHAR));
      if ls <> 0 then begin
        strTemp := bufferW;
        result := UTF8Decode(strTemp);
      end
      else
        result := '!!!lang.dll - corrupted!!! ' + '[' + IntToStr(iCurrentLang) + ':' + IntToStr(Index) + ']' + '(%1%) (%2%)';
    end;
  end;
{$ELSE}
  if stringSet.getByValue(LANG_RES_OFFSET + iCurrentLang * LANG_RES_SIZE + Index,S,p) then begin
    result := S
  end
  else begin
    if stringSet.getByValue(LANG_RES_OFFSET + iCurrentLang * LANG_RES_SIZE + LANG_RES_SIZE shr 1,S,p) then begin
      result := S;
    end
    else begin
      result := '!!!unsupported language!!! ' + '[' + IntToStr(iCurrentLang) + ':' + IntToStr(Index) + ']' + '(%1%) (%2%)';
    end;
  end;

{$ENDIF}
  result := StringReplace(result,'%L%',IntToStr(iCurrentLang),[rfReplaceAll]);
  result := StringReplace(result,'%I%',IntToStr(Index),[rfReplaceAll]);
end;

initialization
{$IFDEF LANGDLL}
  hLangLib := LoadLibrary('lang.dll');
  iCurrentLang := 0;
{$ELSE}
  stringSet := TStrIntHashMap.create;
  fillWithStrings(stringSet);
{$ENDIF}

finalization
{$IFDEF LANGDLL}
  FreeLibrary(hLangLib);
{$ELSE}
  stringSet.Free;
{$ENDIF}

end.
