Merge branch 'master' into jgrpp

# Conflicts:
#	projects/openttd_vs140.vcxproj.filters
#	projects/openttd_vs141.vcxproj.filters
#	projects/openttd_vs142.vcxproj.filters
#	src/base_consist.h
#	src/company_base.h
#	src/newgrf_config.cpp
#	src/newgrf_config.h
#	src/openttd.cpp
#	src/saveload/saveload.cpp
#	src/saveload/saveload.h
#	src/saveload/station_sl.cpp
#	src/settings.cpp
#	src/signs_base.h
#	src/string.cpp
#	src/string_func.h
#	src/table/misc_settings.ini
#	src/table/settings.h.preamble
#	src/town_cmd.cpp
#	src/vehicle.cpp
#	src/vehicle_cmd.cpp
#	src/video/cocoa/cocoa_v.mm
#	src/video/null_v.cpp
pull/175/head
Jonathan G Rennison 4 years ago
commit f8d6e781ba

@ -528,6 +528,9 @@ See the comments in the source files in `src/3rdparty/md5` for the complete lice
The implementations of Posix `getaddrinfo` and `getnameinfo` for OS/2 in `src/3rdparty/os2` are distributed partly under the GNU Lesser General Public License 2.1, and partly under the (3-clause) BSD license.
The exact licensing terms can be found in `src/3rdparty/os2/getaddrinfo.c` resp. `src/3rdparty/os2/getnameinfo.c`.
The implementation of C++17 `std::optional` in `src/3rdparty/optional` is licensed under the Boost Software License - Version 1.0.
See `src/3rdparty/optional/LICENSE_1_0.txt` for the complete license text.
## 4.0 Credits

@ -65,6 +65,7 @@ output_files() {
if [ ! -e ${FOLDER}/${filename}.md5sum ] || [ ! -e ${FOLDER}/${filename}.sha1sum ] || [ ! -e ${FOLDER}/${filename}.sha256sum ]; then
echo "ERROR: missing checksum file for ${filename}" 1>&2
error="y"
shift
continue
fi

@ -63,10 +63,14 @@ Sub Lookup(ini_key, str_id, outfile)
For Each file In folder.Files
If UCase(FSO.GetExtensionName(file.Name)) = "TXT" Then
Dim f
Set f = FSO.OpenTextFile(file.Path)
Set f = CreateObject("ADODB.Stream")
f.Charset = "utf-8"
f.LineSeparator = 10 ' Assume lines end with \n even for \r\n files
f.Open
f.LoadFromFile(file.Path)
Do Until f.atEndOfStream
line = f.ReadLine()
Do Until f.EOS
line = Replace(f.ReadText(-2), Chr(13), "") ' Read a line and remove any \r
If InStr(1, line, "##isocode ") = 1 Then
p = Split(line)
@ -80,8 +84,9 @@ Sub Lookup(ini_key, str_id, outfile)
End If
i = i + 1
End If
Loop
f.Close
End If
Next
@ -89,7 +94,7 @@ Sub Lookup(ini_key, str_id, outfile)
ISort output
For Each line In output
outfile.Write line & vbCrLf
outfile.WriteText line, 1
Next
End Sub
@ -100,7 +105,9 @@ Dim infile
Set infile = FSO.OpenTextFile(inputfile)
Dim outfile
Set outfile = FSO.CreateTextFile(outputfile, True)
Set outfile = CreateObject("ADODB.Stream")
outfile.Charset = "utf-8"
outfile.Open
Do Until infile.atEndOfStream
@ -109,15 +116,30 @@ Do Until infile.atEndOfStream
If InStr(1, line, "ORIG_EXTRA.GRF ") = 1 Then
p = Split(line, "=")
If Trim(p(1)) = "" Then
outfile.Write("ORIG_EXTRA.GRF = " & GetExtraGrfHash() & vbCrLf)
outfile.WriteText "ORIG_EXTRA.GRF = " & GetExtraGrfHash(), 1
Else
outfile.Write(line & vbCrLf)
outfile.WriteText line, 1
End If
ElseIf InStr(1, line, "!! ") = 1 Then
p = Split(line)
Lookup p(1), p(2), outfile
Else
outfile.Write(line & vbCrLf)
outfile.WriteText line, 1
End If
Loop
' UTF-8 Text ADO Stream includes BOM, so we need to remove it
Dim outfile_noBOM
Set outfile_noBOM = CreateObject("ADODB.Stream")
outfile_noBOM.Type = 1
outfile_noBOM.Open
' Copy Text stream to Binary stream, skiping the BOM
outfile.Position = 3
outfile.CopyTo outfile_noBOM
outfile.Close
' Write the Binary stream
outfile_noBOM.SaveToFile outputfile, 2
outfile_noBOM.Close

@ -1029,6 +1029,8 @@
<ClInclude Include="..\src\table\water_land.h" />
<ClCompile Include="..\src\3rdparty\md5\md5.cpp" />
<ClInclude Include="..\src\3rdparty\md5\md5.h" />
<ClInclude Include="..\src\3rdparty\optional\optional.hpp" />
<ClInclude Include="..\src\3rdparty\optional\ottd_optional.h" />
<ClCompile Include="..\src\script\script_config.cpp" />
<ClInclude Include="..\src\script\script_config.hpp" />
<ClInclude Include="..\src\script\script_fatalerror.hpp" />

@ -28,84 +28,87 @@
<Filter Include="MD5">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000008}</UniqueIdentifier>
</Filter>
<Filter Include="Script">
<Filter Include="Compat">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000009}</UniqueIdentifier>
</Filter>
<Filter Include="Squirrel">
<Filter Include="Script">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000010}</UniqueIdentifier>
</Filter>
<Filter Include="Squirrel headers">
<Filter Include="Squirrel">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000011}</UniqueIdentifier>
</Filter>
<Filter Include="AI Core">
<Filter Include="Squirrel headers">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000012}</UniqueIdentifier>
</Filter>
<Filter Include="AI API">
<Filter Include="AI Core">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000013}</UniqueIdentifier>
</Filter>
<Filter Include="Game API">
<Filter Include="AI API">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000014}</UniqueIdentifier>
</Filter>
<Filter Include="Game Core">
<Filter Include="Game API">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000015}</UniqueIdentifier>
</Filter>
<Filter Include="Script API">
<Filter Include="Game Core">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000016}</UniqueIdentifier>
</Filter>
<Filter Include="Script API Implementation">
<Filter Include="Script API">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000017}</UniqueIdentifier>
</Filter>
<Filter Include="Blitters">
<Filter Include="Script API Implementation">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000018}</UniqueIdentifier>
</Filter>
<Filter Include="Drivers">
<Filter Include="Blitters">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000019}</UniqueIdentifier>
</Filter>
<Filter Include="Sprite loaders">
<Filter Include="Drivers">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000020}</UniqueIdentifier>
</Filter>
<Filter Include="NewGRF">
<Filter Include="Sprite loaders">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000021}</UniqueIdentifier>
</Filter>
<Filter Include="Map Accessors">
<Filter Include="NewGRF">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000022}</UniqueIdentifier>
</Filter>
<Filter Include="Misc">
<Filter Include="Map Accessors">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000023}</UniqueIdentifier>
</Filter>
<Filter Include="Network Core">
<Filter Include="Misc">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000024}</UniqueIdentifier>
</Filter>
<Filter Include="Pathfinder">
<Filter Include="Network Core">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000025}</UniqueIdentifier>
</Filter>
<Filter Include="NPF">
<Filter Include="Pathfinder">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000026}</UniqueIdentifier>
</Filter>
<Filter Include="YAPF">
<Filter Include="NPF">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000027}</UniqueIdentifier>
</Filter>
<Filter Include="Video">
<Filter Include="YAPF">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000028}</UniqueIdentifier>
</Filter>
<Filter Include="Music">
<Filter Include="Video">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000029}</UniqueIdentifier>
</Filter>
<Filter Include="Sound">
<Filter Include="Music">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000030}</UniqueIdentifier>
</Filter>
<Filter Include="Windows files">
<Filter Include="Sound">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000031}</UniqueIdentifier>
</Filter>
<Filter Include="Threading">
<Filter Include="Windows files">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000032}</UniqueIdentifier>
</Filter>
<Filter Include="Btree containers">
<Filter Include="Threading">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000033}</UniqueIdentifier>
</Filter>
<Filter Include="MinGW threading">
<Filter Include="Btree containers">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000034}</UniqueIdentifier>
</Filter>
<Filter Include="MinGW threading">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000035}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\tbtr_template_gui_main.cpp">
@ -2181,6 +2184,12 @@
<ClInclude Include="..\src\3rdparty\md5\md5.h">
<Filter>MD5</Filter>
</ClInclude>
<ClInclude Include="..\src\3rdparty\optional\optional.hpp">
<Filter>Compat</Filter>
</ClInclude>
<ClInclude Include="..\src\3rdparty\optional\ottd_optional.h">
<Filter>Compat</Filter>
</ClInclude>
<ClCompile Include="..\src\script\script_config.cpp">
<Filter>Script</Filter>
</ClCompile>

@ -1029,6 +1029,8 @@
<ClInclude Include="..\src\table\water_land.h" />
<ClCompile Include="..\src\3rdparty\md5\md5.cpp" />
<ClInclude Include="..\src\3rdparty\md5\md5.h" />
<ClInclude Include="..\src\3rdparty\optional\optional.hpp" />
<ClInclude Include="..\src\3rdparty\optional\ottd_optional.h" />
<ClCompile Include="..\src\script\script_config.cpp" />
<ClInclude Include="..\src\script\script_config.hpp" />
<ClInclude Include="..\src\script\script_fatalerror.hpp" />

@ -28,84 +28,87 @@
<Filter Include="MD5">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000008}</UniqueIdentifier>
</Filter>
<Filter Include="Script">
<Filter Include="Compat">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000009}</UniqueIdentifier>
</Filter>
<Filter Include="Squirrel">
<Filter Include="Script">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000010}</UniqueIdentifier>
</Filter>
<Filter Include="Squirrel headers">
<Filter Include="Squirrel">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000011}</UniqueIdentifier>
</Filter>
<Filter Include="AI Core">
<Filter Include="Squirrel headers">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000012}</UniqueIdentifier>
</Filter>
<Filter Include="AI API">
<Filter Include="AI Core">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000013}</UniqueIdentifier>
</Filter>
<Filter Include="Game API">
<Filter Include="AI API">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000014}</UniqueIdentifier>
</Filter>
<Filter Include="Game Core">
<Filter Include="Game API">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000015}</UniqueIdentifier>
</Filter>
<Filter Include="Script API">
<Filter Include="Game Core">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000016}</UniqueIdentifier>
</Filter>
<Filter Include="Script API Implementation">
<Filter Include="Script API">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000017}</UniqueIdentifier>
</Filter>
<Filter Include="Blitters">
<Filter Include="Script API Implementation">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000018}</UniqueIdentifier>
</Filter>
<Filter Include="Drivers">
<Filter Include="Blitters">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000019}</UniqueIdentifier>
</Filter>
<Filter Include="Sprite loaders">
<Filter Include="Drivers">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000020}</UniqueIdentifier>
</Filter>
<Filter Include="NewGRF">
<Filter Include="Sprite loaders">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000021}</UniqueIdentifier>
</Filter>
<Filter Include="Map Accessors">
<Filter Include="NewGRF">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000022}</UniqueIdentifier>
</Filter>
<Filter Include="Misc">
<Filter Include="Map Accessors">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000023}</UniqueIdentifier>
</Filter>
<Filter Include="Network Core">
<Filter Include="Misc">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000024}</UniqueIdentifier>
</Filter>
<Filter Include="Pathfinder">
<Filter Include="Network Core">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000025}</UniqueIdentifier>
</Filter>
<Filter Include="NPF">
<Filter Include="Pathfinder">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000026}</UniqueIdentifier>
</Filter>
<Filter Include="YAPF">
<Filter Include="NPF">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000027}</UniqueIdentifier>
</Filter>
<Filter Include="Video">
<Filter Include="YAPF">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000028}</UniqueIdentifier>
</Filter>
<Filter Include="Music">
<Filter Include="Video">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000029}</UniqueIdentifier>
</Filter>
<Filter Include="Sound">
<Filter Include="Music">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000030}</UniqueIdentifier>
</Filter>
<Filter Include="Windows files">
<Filter Include="Sound">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000031}</UniqueIdentifier>
</Filter>
<Filter Include="Threading">
<Filter Include="Windows files">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000032}</UniqueIdentifier>
</Filter>
<Filter Include="Btree containers">
<Filter Include="Threading">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000033}</UniqueIdentifier>
</Filter>
<Filter Include="MinGW threading">
<Filter Include="Btree containers">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000034}</UniqueIdentifier>
</Filter>
<Filter Include="MinGW threading">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000035}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\tbtr_template_gui_main.cpp">
@ -2181,6 +2184,12 @@
<ClInclude Include="..\src\3rdparty\md5\md5.h">
<Filter>MD5</Filter>
</ClInclude>
<ClInclude Include="..\src\3rdparty\optional\optional.hpp">
<Filter>Compat</Filter>
</ClInclude>
<ClInclude Include="..\src\3rdparty\optional\ottd_optional.h">
<Filter>Compat</Filter>
</ClInclude>
<ClCompile Include="..\src\script\script_config.cpp">
<Filter>Script</Filter>
</ClCompile>

@ -100,7 +100,7 @@
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<Optimization>Full</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
@ -168,7 +168,7 @@
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@ -223,7 +223,7 @@
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<Optimization>Full</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
@ -289,7 +289,7 @@
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@ -1029,6 +1029,8 @@
<ClInclude Include="..\src\table\water_land.h" />
<ClCompile Include="..\src\3rdparty\md5\md5.cpp" />
<ClInclude Include="..\src\3rdparty\md5\md5.h" />
<ClInclude Include="..\src\3rdparty\optional\optional.hpp" />
<ClInclude Include="..\src\3rdparty\optional\ottd_optional.h" />
<ClCompile Include="..\src\script\script_config.cpp" />
<ClInclude Include="..\src\script\script_config.hpp" />
<ClInclude Include="..\src\script\script_fatalerror.hpp" />

@ -28,84 +28,87 @@
<Filter Include="MD5">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000008}</UniqueIdentifier>
</Filter>
<Filter Include="Script">
<Filter Include="Compat">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000009}</UniqueIdentifier>
</Filter>
<Filter Include="Squirrel">
<Filter Include="Script">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000010}</UniqueIdentifier>
</Filter>
<Filter Include="Squirrel headers">
<Filter Include="Squirrel">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000011}</UniqueIdentifier>
</Filter>
<Filter Include="AI Core">
<Filter Include="Squirrel headers">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000012}</UniqueIdentifier>
</Filter>
<Filter Include="AI API">
<Filter Include="AI Core">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000013}</UniqueIdentifier>
</Filter>
<Filter Include="Game API">
<Filter Include="AI API">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000014}</UniqueIdentifier>
</Filter>
<Filter Include="Game Core">
<Filter Include="Game API">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000015}</UniqueIdentifier>
</Filter>
<Filter Include="Script API">
<Filter Include="Game Core">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000016}</UniqueIdentifier>
</Filter>
<Filter Include="Script API Implementation">
<Filter Include="Script API">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000017}</UniqueIdentifier>
</Filter>
<Filter Include="Blitters">
<Filter Include="Script API Implementation">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000018}</UniqueIdentifier>
</Filter>
<Filter Include="Drivers">
<Filter Include="Blitters">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000019}</UniqueIdentifier>
</Filter>
<Filter Include="Sprite loaders">
<Filter Include="Drivers">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000020}</UniqueIdentifier>
</Filter>
<Filter Include="NewGRF">
<Filter Include="Sprite loaders">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000021}</UniqueIdentifier>
</Filter>
<Filter Include="Map Accessors">
<Filter Include="NewGRF">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000022}</UniqueIdentifier>
</Filter>
<Filter Include="Misc">
<Filter Include="Map Accessors">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000023}</UniqueIdentifier>
</Filter>
<Filter Include="Network Core">
<Filter Include="Misc">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000024}</UniqueIdentifier>
</Filter>
<Filter Include="Pathfinder">
<Filter Include="Network Core">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000025}</UniqueIdentifier>
</Filter>
<Filter Include="NPF">
<Filter Include="Pathfinder">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000026}</UniqueIdentifier>
</Filter>
<Filter Include="YAPF">
<Filter Include="NPF">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000027}</UniqueIdentifier>
</Filter>
<Filter Include="Video">
<Filter Include="YAPF">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000028}</UniqueIdentifier>
</Filter>
<Filter Include="Music">
<Filter Include="Video">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000029}</UniqueIdentifier>
</Filter>
<Filter Include="Sound">
<Filter Include="Music">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000030}</UniqueIdentifier>
</Filter>
<Filter Include="Windows files">
<Filter Include="Sound">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000031}</UniqueIdentifier>
</Filter>
<Filter Include="Threading">
<Filter Include="Windows files">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000032}</UniqueIdentifier>
</Filter>
<Filter Include="Btree containers">
<Filter Include="Threading">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000033}</UniqueIdentifier>
</Filter>
<Filter Include="MinGW threading">
<Filter Include="Btree containers">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000034}</UniqueIdentifier>
</Filter>
<Filter Include="MinGW threading">
<UniqueIdentifier>{c76ff9f1-1e62-46d8-8d55-000000000035}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\tbtr_template_gui_main.cpp">
@ -2181,6 +2184,12 @@
<ClInclude Include="..\src\3rdparty\md5\md5.h">
<Filter>MD5</Filter>
</ClInclude>
<ClInclude Include="..\src\3rdparty\optional\optional.hpp">
<Filter>Compat</Filter>
</ClInclude>
<ClInclude Include="..\src\3rdparty\optional\ottd_optional.h">
<Filter>Compat</Filter>
</ClInclude>
<ClCompile Include="..\src\script\script_config.cpp">
<Filter>Script</Filter>
</ClCompile>

@ -100,7 +100,7 @@
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<Optimization>Full</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
@ -168,7 +168,7 @@
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@ -223,7 +223,7 @@
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<Optimization>Full</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
@ -289,7 +289,7 @@
</HeaderFileName>
</Midl>
<ClCompile>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

@ -39,6 +39,7 @@
<Inputs>%(Inputs)</Inputs>
</CustomBuildStep>
<ClCompile>
<AdditionalOptions>/std:c++latest /Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<PreprocessorDefinitions>SETTINGSGEN;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

@ -747,6 +747,10 @@ table/water_land.h
3rdparty/md5/md5.cpp
3rdparty/md5/md5.h
# Compat
3rdparty/optional/optional.hpp
3rdparty/optional/ottd_optional.h
# Script
script/script_config.cpp
script/script_config.hpp

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

File diff suppressed because it is too large Load Diff

@ -0,0 +1,33 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ottd_optional.h Header to select between native. */
#ifndef OTTD_OPTIONAL_H
#define OTTD_OPTIONAL_H
#if defined(__has_include)
# if __has_include(<version>)
# include <version>
# endif
#endif
#if (__cplusplus >= 201703L) || (defined(__cpp_lib_optional) && __cpp_lib_optional >= 201606L)
/* Native std::optional. */
#include <optional>
namespace opt = std;
#else
/* No std::optional, use local copy instead. */
#include "optional.hpp"
namespace opt = std::experimental;
#endif
#endif /* OTTD_OPTIONAL_H */

@ -309,7 +309,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
v->cargo_type = e->GetDefaultCargoType();
u->cargo_type = CT_MAIL;
v->name = nullptr;
v->name.clear();
v->last_station_visited = INVALID_STATION;
v->last_loading_station = INVALID_STATION;

@ -14,10 +14,6 @@
#include "safeguards.h"
BaseConsist::~BaseConsist()
{
free(this->name);
}
/**
* Copy properties of other BaseConsist.
@ -27,8 +23,7 @@ void BaseConsist::CopyConsistPropertiesFrom(const BaseConsist *src)
{
if (this == src) return;
free(this->name);
this->name = src->name != nullptr ? stredup(src->name) : nullptr;
this->name = src->name;
this->current_order_time = src->current_order_time;
this->lateness_counter = src->lateness_counter;

@ -13,10 +13,11 @@
#include "order_type.h"
#include "date_type.h"
#include "timetable.h"
#include <string>
/** Various front vehicle properties that are preserved when autoreplacing, using order-backup or switching front engines within a consist. */
struct BaseConsist {
char *name; ///< Name of vehicle
std::string name; ///< Name of vehicle
/* Used for timetabling. */
uint32 current_order_time; ///< How many ticks have passed since this order started.
@ -32,8 +33,7 @@ struct BaseConsist {
uint16 vehicle_flags; ///< Used for gradual loading and other miscellaneous things (@see VehicleFlags enum)
BaseConsist() : name(nullptr) {}
virtual ~BaseConsist();
virtual ~BaseConsist() {}
void CopyConsistPropertiesFrom(const BaseConsist *src);
};

@ -15,6 +15,7 @@
#include "gfx_type.h"
#include "textfile_type.h"
#include "textfile_gui.h"
#include <unordered_map>
/* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
struct IniFile;
@ -46,7 +47,7 @@ struct MD5File {
*/
template <class T, size_t Tnum_files, bool Tsearch_in_tars>
struct BaseSet {
typedef SmallMap<const char *, const char *> TranslatedStrings;
typedef std::unordered_map<std::string, std::string> TranslatedStrings;
/** Number of files in this set */
static const size_t NUM_FILES = Tnum_files;
@ -57,7 +58,7 @@ struct BaseSet {
/** Internal names of the files in this set. */
static const char * const *file_names;
const char *name; ///< The name of the base set
std::string name; ///< The name of the base set
TranslatedStrings description; ///< Description of the base set
uint32 shortname; ///< Four letter short variant of the name
uint32 version; ///< The version of this base set
@ -72,13 +73,6 @@ struct BaseSet {
/** Free everything we allocated */
~BaseSet()
{
free(this->name);
for (auto &pair : this->description) {
free(pair.first);
free(pair.second);
}
for (uint i = 0; i < NUM_FILES; i++) {
free(this->files[i].filename);
free(this->files[i].missing_warning);
@ -116,20 +110,19 @@ struct BaseSet {
* @param isocode the isocode to search for
* @return the description
*/
const char *GetDescription(const char *isocode = nullptr) const
const char *GetDescription(const std::string &isocode) const
{
if (isocode != nullptr) {
if (!isocode.empty()) {
/* First the full ISO code */
for (const auto &pair : this->description) {
if (strcmp(pair.first, isocode) == 0) return pair.second;
}
auto desc = this->description.find(isocode);
if (desc != this->description.end()) return desc->second.c_str();
/* Then the first two characters */
for (const auto &pair : this->description) {
if (strncmp(pair.first, isocode, 2) == 0) return pair.second;
}
desc = this->description.find(isocode.substr(0, 2));
if (desc != this->description.end()) return desc->second.c_str();
}
/* Then fall back */
return this->description.front().second;
return this->description.at(std::string{}).c_str();
}
/**
@ -183,7 +176,7 @@ protected:
static const char *GetExtension();
public:
/** The set as saved in the config file. */
static const char *ini_set;
static std::string ini_set;
/**
* Determine the graphics pack that has to be used.
@ -203,7 +196,7 @@ public:
static Tbase_set *GetAvailableSets();
static bool SetSet(const char *name);
static bool SetSet(const std::string &name);
static char *GetSetsList(char *p, const char *last);
static int GetNumSets();
static int GetIndexOfUsedSet();
@ -219,7 +212,7 @@ public:
static bool HasSet(const ContentInfo *ci, bool md5sum);
};
template <class Tbase_set> /* static */ const char *BaseMedia<Tbase_set>::ini_set;
template <class Tbase_set> /* static */ std::string BaseMedia<Tbase_set>::ini_set;
template <class Tbase_set> /* static */ const Tbase_set *BaseMedia<Tbase_set>::used_set;
template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::available_sets;
template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::duplicate_sets;

@ -21,7 +21,7 @@
*/
#define fetch_metadata(name) \
item = metadata->GetItem(name, false); \
if (item == nullptr || StrEmpty(item->value)) { \
if (item == nullptr || !item->value.has_value() || item->value->empty()) { \
DEBUG(grf, 0, "Base " SET_TYPE "set detail loading: %s field missing.", name); \
DEBUG(grf, 0, " Is %s readable for the user running OpenTTD?", full_filename); \
return false; \
@ -42,28 +42,28 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
IniItem *item;
fetch_metadata("name");
this->name = stredup(item->value);
this->name = *item->value;
fetch_metadata("description");
this->description[stredup("")] = stredup(item->value);
this->description[std::string{}] = *item->value;
/* Add the translations of the descriptions too. */
for (const IniItem *item = metadata->item; item != nullptr; item = item->next) {
if (strncmp("description.", item->name, 12) != 0) continue;
if (item->name.compare(0, 12, "description.") != 0) continue;
this->description[stredup(item->name + 12)] = stredup(item->value);
this->description[item->name.substr(12)] = item->value.value_or("");
}
fetch_metadata("shortname");
for (uint i = 0; item->value[i] != '\0' && i < 4; i++) {
this->shortname |= ((uint8)item->value[i]) << (i * 8);
for (uint i = 0; item->value.value()[i] != '\0' && i < 4; i++) {
this->shortname |= ((uint8)item->value.value()[i]) << (i * 8);
}
fetch_metadata("version");
this->version = atoi(item->value);
this->version = atoi(item->value->c_str());
item = metadata->GetItem("fallback", false);
this->fallback = (item != nullptr && strcmp(item->value, "0") != 0 && strcmp(item->value, "false") != 0);
this->fallback = (item != nullptr && item->value && item->value.value() != "0" && item->value.value() != "false");
/* For each of the file types we want to find the file, MD5 checksums and warning messages. */
IniGroup *files = ini->GetGroup("files");
@ -73,13 +73,12 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
MD5File *file = &this->files[i];
/* Find the filename first. */
item = files->GetItem(BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i], false);
if (item == nullptr || (item->value == nullptr && !allow_empty_filename)) {
if (item == nullptr || (!item->value.has_value() && !allow_empty_filename)) {
DEBUG(grf, 0, "No " SET_TYPE " file for: %s (in %s)", BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i], full_filename);
return false;
}
const char *filename = item->value;
if (filename == nullptr) {
if (!item->value.has_value()) {
file->filename = nullptr;
/* If we list no file, that file must be valid */
this->valid_files++;
@ -87,15 +86,16 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
continue;
}
const char *filename = item->value->c_str();
file->filename = str_fmt("%s%s", path, filename);
/* Then find the MD5 checksum */
item = md5s->GetItem(filename, false);
if (item == nullptr || item->value == nullptr) {
if (item == nullptr || !item->value.has_value()) {
DEBUG(grf, 0, "No MD5 checksum specified for: %s (in %s)", filename, full_filename);
return false;
}
char *c = item->value;
const char *c = item->value->c_str();
for (uint i = 0; i < sizeof(file->hash) * 2; i++, c++) {
uint j;
if ('0' <= *c && *c <= '9') {
@ -118,11 +118,11 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
/* Then find the warning message when the file's missing */
item = origin->GetItem(filename, false);
if (item == nullptr) item = origin->GetItem("default", false);
if (item == nullptr) {
if (item == nullptr || !item->value.has_value()) {
DEBUG(grf, 1, "No origin warning message specified for: %s", filename);
file->missing_warning = stredup("");
} else {
file->missing_warning = stredup(item->value);
file->missing_warning = stredup(item->value->c_str());
}
file->check_result = T::CheckMD5(file, BASESET_DIR);
@ -170,7 +170,7 @@ bool BaseMedia<Tbase_set>::AddFile(const char *filename, size_t basepath_length,
if (set->FillSetDetails(ini, path, filename)) {
Tbase_set *duplicate = nullptr;
for (Tbase_set *c = BaseMedia<Tbase_set>::available_sets; c != nullptr; c = c->next) {
if (strcmp(c->name, set->name) == 0 || c->shortname == set->shortname) {
if (c->name == set->name || c->shortname == set->shortname) {
duplicate = c;
break;
}
@ -179,7 +179,7 @@ bool BaseMedia<Tbase_set>::AddFile(const char *filename, size_t basepath_length,
/* The more complete set takes precedence over the version number. */
if ((duplicate->valid_files == set->valid_files && duplicate->version >= set->version) ||
duplicate->valid_files > set->valid_files) {
DEBUG(grf, 1, "Not adding %s (%i) as base " SET_TYPE " set (duplicate, %s)", set->name, set->version,
DEBUG(grf, 1, "Not adding %s (%i) as base " SET_TYPE " set (duplicate, %s)", set->name.c_str(), set->version,
duplicate->valid_files > set->valid_files ? "less valid files" : "lower version");
set->next = BaseMedia<Tbase_set>::duplicate_sets;
BaseMedia<Tbase_set>::duplicate_sets = set;
@ -195,7 +195,7 @@ bool BaseMedia<Tbase_set>::AddFile(const char *filename, size_t basepath_length,
* version number until a new game is started which isn't a big problem */
if (BaseMedia<Tbase_set>::used_set == duplicate) BaseMedia<Tbase_set>::used_set = set;
DEBUG(grf, 1, "Removing %s (%i) as base " SET_TYPE " set (duplicate, %s)", duplicate->name, duplicate->version,
DEBUG(grf, 1, "Removing %s (%i) as base " SET_TYPE " set (duplicate, %s)", duplicate->name.c_str(), duplicate->version,
duplicate->valid_files < set->valid_files ? "less valid files" : "lower version");
duplicate->next = BaseMedia<Tbase_set>::duplicate_sets;
BaseMedia<Tbase_set>::duplicate_sets = duplicate;
@ -209,7 +209,7 @@ bool BaseMedia<Tbase_set>::AddFile(const char *filename, size_t basepath_length,
ret = true;
}
if (ret) {
DEBUG(grf, 1, "Adding %s (%i) as base " SET_TYPE " set", set->name, set->version);
DEBUG(grf, 1, "Adding %s (%i) as base " SET_TYPE " set", set->name.c_str(), set->version);
}
} else {
delete set;
@ -226,18 +226,18 @@ bool BaseMedia<Tbase_set>::AddFile(const char *filename, size_t basepath_length,
* @return true if it could be loaded
*/
template <class Tbase_set>
/* static */ bool BaseMedia<Tbase_set>::SetSet(const char *name)
/* static */ bool BaseMedia<Tbase_set>::SetSet(const std::string &name)
{
extern void CheckExternalFiles();
if (StrEmpty(name)) {
if (name.empty()) {
if (!BaseMedia<Tbase_set>::DetermineBestSet()) return false;
CheckExternalFiles();
return true;
}
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
if (strcmp(name, s->name) == 0) {
if (name == s->name) {
BaseMedia<Tbase_set>::used_set = s;
CheckExternalFiles();
return true;
@ -257,7 +257,7 @@ template <class Tbase_set>
{
p += seprintf(p, last, "List of " SET_TYPE " sets:\n");
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
p += seprintf(p, last, "%18s: %s", s->name, s->GetDescription());
p += seprintf(p, last, "%18s: %s", s->name.c_str(), s->GetDescription({}));
int invalid = s->GetNumInvalid();
if (invalid != 0) {
int missing = s->GetNumMissing();
@ -376,11 +376,11 @@ template <class Tbase_set>
* @param set_type the type of the BaseSet to instantiate
*/
#define INSTANTIATE_BASE_MEDIA_METHODS(repl_type, set_type) \
template const char *repl_type::ini_set; \
template std::string repl_type::ini_set; \
template const char *repl_type::GetExtension(); \
template bool repl_type::AddFile(const char *filename, size_t pathlength, const char *tar_filename); \
template bool repl_type::HasSet(const struct ContentInfo *ci, bool md5sum); \
template bool repl_type::SetSet(const char *name); \
template bool repl_type::SetSet(const std::string &name); \
template char *repl_type::GetSetsList(char *p, const char *last); \
template int repl_type::GetNumSets(); \
template int repl_type::GetIndexOfUsedSet(); \

@ -56,7 +56,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
TrackedViewportSign sign; ///< NOSAVE: Dimensions of sign
byte delete_ctr; ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted.
char *name; ///< Custom name
std::string name; ///< Custom name
StringID string_id; ///< Default name (town area) of station
mutable std::string cached_name; ///< NOSAVE: Cache of the resolved name of the station, if not using a custom name
@ -113,7 +113,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
inline const char *GetCachedName() const
{
if (this->name != nullptr) return this->name;
if (!this->name.empty()) return this->name.c_str();
if (this->cached_name.empty()) this->FillCachedName();
return this->cached_name.c_str();
}

@ -22,10 +22,10 @@
*/
class BlitterFactory {
private:
const char *name; ///< The name of the blitter factory.
const char *description; ///< The description of the blitter.
const std::string name; ///< The name of the blitter factory.
const std::string description; ///< The description of the blitter.
typedef std::map<const char *, BlitterFactory *, StringCompare> Blitters; ///< Map of blitter factories.
typedef std::map<std::string, BlitterFactory *> Blitters; ///< Map of blitter factories.
/**
* Get the map with currently known blitters.
@ -58,7 +58,7 @@ protected:
* @pre There is no blitter registered with this name.
*/
BlitterFactory(const char *name, const char *description, bool usable = true) :
name(stredup(name)), description(stredup(description))
name(name), description(description)
{
if (usable) {
/*
@ -78,9 +78,6 @@ public:
{
GetBlitters().erase(this->name);
if (GetBlitters().empty()) delete &GetBlitters();
free(this->name);
free(this->description);
}
/**
@ -88,7 +85,7 @@ public:
* @param name the blitter to select.
* @post Sets the blitter so GetCurrentBlitter() returns it too.
*/
static Blitter *SelectBlitter(const char *name)
static Blitter *SelectBlitter(const std::string &name)
{
BlitterFactory *b = GetBlitterFactory(name);
if (b == nullptr) return nullptr;
@ -97,7 +94,7 @@ public:
delete *GetActiveBlitter();
*GetActiveBlitter() = newb;
DEBUG(driver, 1, "Successfully %s blitter '%s'", StrEmpty(name) ? "probed" : "loaded", newb->GetName());
DEBUG(driver, 1, "Successfully %s blitter '%s'", name.empty() ? "probed" : "loaded", newb->GetName());
return newb;
}
@ -106,7 +103,7 @@ public:
* @param name the blitter factory to select.
* @return The blitter factory, or nullptr when there isn't one with the wanted name.
*/
static BlitterFactory *GetBlitterFactory(const char *name)
static BlitterFactory *GetBlitterFactory(const std::string &name)
{
#if defined(DEDICATED)
const char *default_blitter = "null";
@ -116,12 +113,12 @@ public:
const char *default_blitter = "8bpp-optimized";
#endif
if (GetBlitters().size() == 0) return nullptr;
const char *bname = (StrEmpty(name)) ? default_blitter : name;
const char *bname = name.empty() ? default_blitter : name.c_str();
Blitters::iterator it = GetBlitters().begin();
for (; it != GetBlitters().end(); it++) {
BlitterFactory *b = (*it).second;
if (strcasecmp(bname, b->name) == 0) {
if (strcasecmp(bname, b->name.c_str()) == 0) {
return b;
}
}
@ -148,7 +145,7 @@ public:
Blitters::iterator it = GetBlitters().begin();
for (; it != GetBlitters().end(); it++) {
BlitterFactory *b = (*it).second;
p += seprintf(p, last, "%18s: %s\n", b->name, b->GetDescription());
p += seprintf(p, last, "%18s: %s\n", b->name.c_str(), b->GetDescription().c_str());
}
p += seprintf(p, last, "\n");
@ -158,7 +155,7 @@ public:
/**
* Get the long, human readable, name for the Blitter-class.
*/
const char *GetName() const
const std::string &GetName() const
{
return this->name;
}
@ -166,7 +163,7 @@ public:
/**
* Get a nice description of the blitter-class.
*/
const char *GetDescription() const
const std::string &GetDescription() const
{
return this->description;
}
@ -177,7 +174,7 @@ public:
virtual Blitter *CreateInstance() = 0;
};
extern char *_ini_blitter;
extern std::string _ini_blitter;
extern bool _blitter_autodetected;
#endif /* BLITTER_FACTORY_HPP */

@ -16,6 +16,7 @@
#include "tile_type.h"
#include "settings_type.h"
#include "group.h"
#include <string>
/** Statistics about the economy. */
struct CompanyEconomyEntry {
@ -56,11 +57,11 @@ extern CompanyPool _company_pool;
struct CompanyProperties {
uint32 name_2; ///< Parameter of #name_1.
StringID name_1; ///< Name of the company if the user did not change it.
char *name; ///< Name of the company if the user changed it.
std::string name; ///< Name of the company if the user changed it.
StringID president_name_1; ///< Name of the president if the user did not change it.
uint32 president_name_2; ///< Parameter of #president_name_1
char *president_name; ///< Name of the president if the user changed it.
std::string president_name; ///< Name of the president if the user changed it.
CompanyManagerFace face; ///< Face description of the president.
@ -102,17 +103,11 @@ struct CompanyProperties {
// TODO: Change some of these member variables to use relevant INVALID_xxx constants
CompanyProperties()
: name_2(0), name_1(0), name(nullptr), president_name_1(0), president_name_2(0), president_name(nullptr),
: name_2(0), name_1(0), president_name_1(0), president_name_2(0),
face(0), money(0), money_fraction(0), current_loan(0), colour(0), block_preview(0),
location_of_HQ(0), last_build_coordinate(0), share_owners(), inaugurated_year(0),
months_of_bankruptcy(0), bankrupt_asked(0), bankrupt_timeout(0), bankrupt_value(0),
terraform_limit(0), clear_limit(0), tree_limit(0), purchase_land_limit(0), is_ai(false) {}
~CompanyProperties()
{
free(this->name);
free(this->president_name);
}
};
struct Company : CompanyPool::PoolItem<&_company_pool>, CompanyProperties {

@ -359,7 +359,7 @@ static void GenerateCompanyName(Company *c)
StringID str;
uint32 strp;
if (t->name == nullptr && IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1)) {
if (t->name.empty() && IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1)) {
str = t->townnametype - SPECSTR_TOWNNAME_START + SPECSTR_COMPANY_NAME_START;
strp = t->townnameparts;
@ -1062,7 +1062,7 @@ CommandCost CmdSetCompanyColour(TileIndex tile, DoCommandFlag flags, uint32 p1,
static bool IsUniqueCompanyName(const char *name)
{
for (const Company *c : Company::Iterate()) {
if (c->name != nullptr && strcmp(c->name, name) == 0) return false;
if (!c->name.empty() && c->name == name) return false;
}
return true;
@ -1088,8 +1088,11 @@ CommandCost CmdRenameCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
if (flags & DC_EXEC) {
Company *c = Company::Get(_current_company);
free(c->name);
c->name = reset ? nullptr : stredup(text);
if (reset) {
c->name.clear();
} else {
c->name = text;
}
MarkWholeScreenDirty();
CompanyAdminUpdate(c);
}
@ -1105,7 +1108,7 @@ CommandCost CmdRenameCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
static bool IsUniquePresidentName(const char *name)
{
for (const Company *c : Company::Iterate()) {
if (c->president_name != nullptr && strcmp(c->president_name, name) == 0) return false;
if (!c->president_name.empty() && c->president_name == name) return false;
}
return true;
@ -1131,14 +1134,13 @@ CommandCost CmdRenamePresident(TileIndex tile, DoCommandFlag flags, uint32 p1, u
if (flags & DC_EXEC) {
Company *c = Company::Get(_current_company);
free(c->president_name);
if (reset) {
c->president_name = nullptr;
c->president_name.clear();
} else {
c->president_name = stredup(text);
c->president_name = text;
if (c->name_1 == STR_SV_UNNAMED && c->name == nullptr) {
if (c->name_1 == STR_SV_UNNAMED && c->name.empty()) {
char buf[80];
seprintf(buf, lastof(buf), "%s Transport", text);

@ -11,40 +11,26 @@
#define SMALLMAP_TYPE_HPP
#include "smallvec_type.hpp"
#include <utility>
/**
* Simple pair of data. Both types have to be POD ("Plain Old Data")!
* @tparam T Key type.
* @tparam U Value type.
*/
template <typename T, typename U>
struct SmallPair {
T first;
U second;
/** Initializes this Pair with data */
inline SmallPair(const T &first, const U &second) : first(first), second(second) { }
SmallPair() = default;
};
/**
* Implementation of simple mapping class. Both types have to be POD ("Plain Old Data")!
* It has inherited accessors from SmallVector().
* Implementation of simple mapping class.
* It has inherited accessors from std::vector().
* @tparam T Key type.
* @tparam U Value type.
* @tparam S Unit of allocation.
*
* @see SmallVector
* @see std::vector
*/
template <typename T, typename U>
struct SmallMap : std::vector<SmallPair<T, U> > {
typedef ::SmallPair<T, U> Pair;
struct SmallMap : std::vector<std::pair<T, U> > {
typedef std::pair<T, U> Pair;
typedef Pair *iterator;
typedef const Pair *const_iterator;
/** Creates new SmallMap. Data are initialized in SmallVector constructor */
/** Creates new SmallMap. Data are initialized in std::vector constructor */
inline SmallMap() { }
/** Data are freed in SmallVector destructor */
/** Data are freed in std::vector destructor */
inline ~SmallMap() { }
/**

@ -199,15 +199,15 @@ char *CrashLog::LogConfiguration(char *buffer, const char *last) const
" Video driver: %s\n"
" Pathfinder: %s %s %s\n\n",
BlitterFactory::GetCurrentBlitter() == nullptr ? "none" : BlitterFactory::GetCurrentBlitter()->GetName(),
BaseGraphics::GetUsedSet() == nullptr ? "none" : BaseGraphics::GetUsedSet()->name,
BaseGraphics::GetUsedSet() == nullptr ? "none" : BaseGraphics::GetUsedSet()->name.c_str(),
BaseGraphics::GetUsedSet() == nullptr ? UINT32_MAX : BaseGraphics::GetUsedSet()->version,
_current_language == nullptr ? "none" : _current_language->file,
MusicDriver::GetInstance() == nullptr ? "none" : MusicDriver::GetInstance()->GetName(),
BaseMusic::GetUsedSet() == nullptr ? "none" : BaseMusic::GetUsedSet()->name,
BaseMusic::GetUsedSet() == nullptr ? "none" : BaseMusic::GetUsedSet()->name.c_str(),
BaseMusic::GetUsedSet() == nullptr ? UINT32_MAX : BaseMusic::GetUsedSet()->version,
_networking ? (_network_server ? "server" : "client") : "no",
SoundDriver::GetInstance() == nullptr ? "none" : SoundDriver::GetInstance()->GetName(),
BaseSounds::GetUsedSet() == nullptr ? "none" : BaseSounds::GetUsedSet()->name,
BaseSounds::GetUsedSet() == nullptr ? "none" : BaseSounds::GetUsedSet()->name.c_str(),
BaseSounds::GetUsedSet() == nullptr ? UINT32_MAX : BaseSounds::GetUsedSet()->version,
VideoDriver::GetInstance() == nullptr ? "none" : VideoDriver::GetInstance()->GetName(),
pathfinder_name(_settings_game.pf.pathfinder_for_trains), pathfinder_name(_settings_game.pf.pathfinder_for_roadvehs), pathfinder_name(_settings_game.pf.pathfinder_for_ships)

@ -8,9 +8,11 @@
/** @file dedicated.cpp Forking support for dedicated servers. */
#include "stdafx.h"
#include "fileio_func.h"
#include <string>
char *_log_file = nullptr; ///< File to reroute output of a forked OpenTTD to
FILE *_log_fd = nullptr; ///< File to reroute output of a forked OpenTTD to
std::string _log_file; ///< File to reroute output of a forked OpenTTD to
std::unique_ptr<FILE, FileDeleter> _log_fd; ///< File to reroute output of a forked OpenTTD to
#if defined(UNIX)
@ -38,17 +40,17 @@ void DedicatedFork()
case 0: { // We're the child
/* Open the log-file to log all stuff too */
_log_fd = fopen(_log_file, "a");
if (_log_fd == nullptr) {
_log_fd.reset(fopen(_log_file.c_str(), "a"));
if (!_log_fd) {
perror("Unable to open logfile");
exit(1);
}
/* Redirect stdout and stderr to log-file */
if (dup2(fileno(_log_fd), fileno(stdout)) == -1) {
if (dup2(fileno(_log_fd.get()), fileno(stdout)) == -1) {
perror("Rerouting stdout");
exit(1);
}
if (dup2(fileno(_log_fd), fileno(stderr)) == -1) {
if (dup2(fileno(_log_fd.get()), fileno(stderr)) == -1) {
perror("Rerouting stderr");
exit(1);
}

@ -154,7 +154,7 @@ protected:
&& order->GetDestination() == this->station) {
this->vehicles.push_back(v);
if (v->name == nullptr) {
if (v->name.empty()) {
if (v->unitnumber > unitnumber_max[v->type]) unitnumber_max[v->type] = v->unitnumber;
} else {
SetDParam(0, (uint64)(v->index));

@ -28,8 +28,6 @@ INSTANTIATE_POOL_METHODS(Depot)
*/
Depot::~Depot()
{
free(this->name);
if (CleaningPool()) return;
if (!IsDepotTile(this->xy) || GetDepotIndex(this->xy) != this->index) {

@ -18,7 +18,7 @@ extern DepotPool _depot_pool;
struct Depot : DepotPool::PoolItem<&_depot_pool> {
Town *town;
char *name;
std::string name;
TileIndex xy;
uint16 town_cn; ///< The N-1th depot for this town (consecutive number)

@ -29,7 +29,7 @@
static bool IsUniqueDepotName(const char *name)
{
for (const Depot *d : Depot::Iterate()) {
if (d->name != nullptr && strcmp(d->name, name) == 0) return false;
if (!d->name.empty() && d->name == name) return false;
}
return true;
@ -60,13 +60,11 @@ CommandCost CmdRenameDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
}
if (flags & DC_EXEC) {
free(d->name);
if (reset) {
d->name = nullptr;
d->name.clear();
MakeDefaultName(d);
} else {
d->name = stredup(text);
d->name = text;
}
/* Update the orders and depot */

@ -13,19 +13,21 @@
#include "music/music_driver.hpp"
#include "video/video_driver.hpp"
#include "string_func.h"
#include <string>
#include <sstream>
#include "safeguards.h"
char *_ini_videodriver; ///< The video driver a stored in the configuration file.
std::string _ini_videodriver; ///< The video driver a stored in the configuration file.
std::vector<Dimension> _resolutions; ///< List of resolutions.
Dimension _cur_resolution; ///< The current resolution.
bool _rightclick_emulate; ///< Whether right clicking is emulated.
char *_ini_sounddriver; ///< The sound driver a stored in the configuration file.
std::string _ini_sounddriver; ///< The sound driver a stored in the configuration file.
char *_ini_musicdriver; ///< The music driver a stored in the configuration file.
std::string _ini_musicdriver; ///< The music driver a stored in the configuration file.
char *_ini_blitter; ///< The blitter as stored in the configuration file.
std::string _ini_blitter; ///< The blitter as stored in the configuration file.
bool _blitter_autodetected; ///< Was the blitter autodetected or specified by the user?
/**
@ -34,19 +36,15 @@ bool _blitter_autodetected; ///< Was the blitter autodetected or specif
* @param name The parameter name we're looking for.
* @return The parameter value.
*/
const char *GetDriverParam(const char * const *parm, const char *name)
const char *GetDriverParam(const StringList &parm, const char *name)
{
size_t len;
if (parm.empty()) return nullptr;
if (parm == nullptr) return nullptr;
len = strlen(name);
for (; *parm != nullptr; parm++) {
const char *p = *parm;
if (strncmp(p, name, len) == 0) {
if (p[len] == '=') return p + len + 1;
if (p[len] == '\0') return p + len;
size_t len = strlen(name);
for (auto &p : parm) {
if (p.compare(0, len, name) == 0) {
if (p.length() == len) return "";
if (p[len] == '=') return p.c_str() + len + 1;
}
}
return nullptr;
@ -58,7 +56,7 @@ const char *GetDriverParam(const char * const *parm, const char *name)
* @param name The parameter name we're looking for.
* @return The parameter value.
*/
bool GetDriverParamBool(const char * const *parm, const char *name)
bool GetDriverParamBool(const StringList &parm, const char *name)
{
return GetDriverParam(parm, name) != nullptr;
}
@ -70,7 +68,7 @@ bool GetDriverParamBool(const char * const *parm, const char *name)
* @param def The default value if the parameter doesn't exist.
* @return The parameter value.
*/
int GetDriverParamInt(const char * const *parm, const char *name, int def)
int GetDriverParamInt(const StringList &parm, const char *name, int def)
{
const char *p = GetDriverParam(parm, name);
return p != nullptr ? atoi(p) : def;
@ -82,12 +80,12 @@ int GetDriverParamInt(const char * const *parm, const char *name, int def)
* @param type the type of driver to select
* @post Sets the driver so GetCurrentDriver() returns it too.
*/
void DriverFactoryBase::SelectDriver(const char *name, Driver::Type type)
void DriverFactoryBase::SelectDriver(const std::string &name, Driver::Type type)
{
if (!DriverFactoryBase::SelectDriverImpl(name, type)) {
StrEmpty(name) ?
name.empty() ?
usererror("Failed to autoprobe %s driver", GetDriverTypeName(type)) :
usererror("Failed to select requested %s driver '%s'", GetDriverTypeName(type), name);
usererror("Failed to select requested %s driver '%s'", GetDriverTypeName(type), name.c_str());
}
}
@ -98,11 +96,11 @@ void DriverFactoryBase::SelectDriver(const char *name, Driver::Type type)
* @post Sets the driver so GetCurrentDriver() returns it too.
* @return True upon success, otherwise false.
*/
bool DriverFactoryBase::SelectDriverImpl(const char *name, Driver::Type type)
bool DriverFactoryBase::SelectDriverImpl(const std::string &name, Driver::Type type)
{
if (GetDrivers().size() == 0) return false;
if (StrEmpty(name)) {
if (name.empty()) {
/* Probe for this driver, but do not fall back to dedicated/null! */
for (int priority = 10; priority > 0; priority--) {
Drivers::iterator it = GetDrivers().begin();
@ -117,7 +115,7 @@ bool DriverFactoryBase::SelectDriverImpl(const char *name, Driver::Type type)
Driver *newd = d->CreateInstance();
*GetActiveDriver(type) = newd;
const char *err = newd->Start(nullptr);
const char *err = newd->Start({});
if (err == nullptr) {
DEBUG(driver, 1, "Successfully probed %s driver '%s'", GetDriverTypeName(type), d->name);
delete oldd;
@ -131,23 +129,15 @@ bool DriverFactoryBase::SelectDriverImpl(const char *name, Driver::Type type)
}
usererror("Couldn't find any suitable %s driver", GetDriverTypeName(type));
} else {
char *parm;
char buffer[256];
const char *parms[32];
/* Extract the driver name and put parameter list in parm */
strecpy(buffer, name, lastof(buffer));
parm = strchr(buffer, ':');
parms[0] = nullptr;
if (parm != nullptr) {
uint np = 0;
/* Tokenize the parm. */
do {
*parm++ = '\0';
if (np < lengthof(parms) - 1) parms[np++] = parm;
while (*parm != '\0' && *parm != ',') parm++;
} while (*parm == ',');
parms[np] = nullptr;
std::istringstream buffer(name);
std::string dname;
std::getline(buffer, dname, ':');
std::string param;
std::vector<std::string> parms;
while (std::getline(buffer, param, ',')) {
parms.push_back(param);
}
/* Find this driver */
@ -159,7 +149,7 @@ bool DriverFactoryBase::SelectDriverImpl(const char *name, Driver::Type type)
if (d->type != type) continue;
/* Check driver name */
if (strcasecmp(buffer, d->name) != 0) continue;
if (strcasecmp(dname.c_str(), d->name) != 0) continue;
/* Found our driver, let's try it */
Driver *newd = d->CreateInstance();
@ -175,7 +165,7 @@ bool DriverFactoryBase::SelectDriverImpl(const char *name, Driver::Type type)
*GetActiveDriver(type) = newd;
return true;
}
usererror("No such %s driver: %s\n", GetDriverTypeName(type), buffer);
usererror("No such %s driver: %s\n", GetDriverTypeName(type), dname.c_str());
}
}
@ -221,9 +211,7 @@ DriverFactoryBase::DriverFactoryBase(Driver::Type type, int priority, const char
strecpy(buf, GetDriverTypeName(type), lastof(buf));
strecpy(buf + 5, name, lastof(buf));
const char *longname = stredup(buf);
std::pair<Drivers::iterator, bool> P = GetDrivers().insert(Drivers::value_type(longname, this));
std::pair<Drivers::iterator, bool> P = GetDrivers().insert(Drivers::value_type(buf, this));
assert(P.second);
}
@ -240,10 +228,6 @@ DriverFactoryBase::~DriverFactoryBase()
Drivers::iterator it = GetDrivers().find(buf);
assert(it != GetDrivers().end());
const char *longname = (*it).first;
GetDrivers().erase(it);
free(longname);
if (GetDrivers().empty()) delete &GetDrivers();
}

@ -12,11 +12,12 @@
#include "core/enum_type.hpp"
#include "core/string_compare_type.hpp"
#include "string_type.h"
#include <map>
const char *GetDriverParam(const char * const *parm, const char *name);
bool GetDriverParamBool(const char * const *parm, const char *name);
int GetDriverParamInt(const char * const *parm, const char *name, int def);
const char *GetDriverParam(const StringList &parm, const char *name);
bool GetDriverParamBool(const StringList &parm, const char *name);
int GetDriverParamInt(const StringList &parm, const char *name, int def);
/** A driver for communicating with the user. */
class Driver {
@ -26,7 +27,7 @@ public:
* @param parm Parameters passed to the driver.
* @return nullptr if everything went okay, otherwise an error message.
*/
virtual const char *Start(const char * const *parm) = 0;
virtual const char *Start(const StringList &parm) = 0;
/**
* Stop this driver.
@ -66,7 +67,7 @@ private:
const char *name; ///< The name of the drivers of this factory.
const char *description; ///< The description of this driver.
typedef std::map<const char *, DriverFactoryBase *, StringCompare> Drivers; ///< Type for a map of drivers.
typedef std::map<std::string, DriverFactoryBase *> Drivers; ///< Type for a map of drivers.
/**
* Get the map with drivers.
@ -99,7 +100,7 @@ private:
return driver_type_name[type];
}
static bool SelectDriverImpl(const char *name, Driver::Type type);
static bool SelectDriverImpl(const std::string &name, Driver::Type type);
protected:
DriverFactoryBase(Driver::Type type, int priority, const char *name, const char *description);
@ -118,7 +119,7 @@ public:
}
}
static void SelectDriver(const char *name, Driver::Type type);
static void SelectDriver(const std::string &name, Driver::Type type);
static char *GetDriversInfo(char *p, const char *last);
/**

@ -68,7 +68,6 @@ assert_compile(lengthof(_orig_rail_vehicle_info) + lengthof(_orig_road_vehicle_i
const uint EngineOverrideManager::NUM_DEFAULT_ENGINES = _engine_counts[VEH_TRAIN] + _engine_counts[VEH_ROAD] + _engine_counts[VEH_SHIP] + _engine_counts[VEH_AIRCRAFT];
Engine::Engine() :
name(nullptr),
overrides_count(0),
overrides(nullptr)
{
@ -141,7 +140,6 @@ Engine::Engine(VehicleType type, EngineID base)
Engine::~Engine()
{
UnloadWagonOverrides(this);
free(this->name);
}
/**
@ -1079,7 +1077,7 @@ void EnginesMonthlyLoop()
static bool IsUniqueEngineName(const char *name)
{
for (const Engine *e : Engine::Iterate()) {
if (e->name != nullptr && strcmp(e->name, name) == 0) return false;
if (!e->name.empty() && e->name == name) return false;
}
return true;
@ -1107,12 +1105,10 @@ CommandCost CmdRenameEngine(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
}
if (flags & DC_EXEC) {
free(e->name);
if (reset) {
e->name = nullptr;
e->name.clear();
} else {
e->name = stredup(text);
e->name = text;
}
MarkWholeScreenDirty();

@ -19,7 +19,7 @@ typedef Pool<Engine, EngineID, 64, 64000> EnginePool;
extern EnginePool _engine_pool;
struct Engine : EnginePool::PoolItem<&_engine_pool> {
char *name; ///< Custom name of engine.
std::string name; ///< Custom name of engine.
Date intro_date; ///< Date of introduction of the engine.
Date age;
uint16 reliability; ///< Current reliability of the engine.

@ -1251,8 +1251,9 @@ void DeterminePaths(const char *exe)
free(tmp);
}
extern char *_log_file;
_log_file = str_fmt("%sopenttd.log", _personal_dir);
extern std::string _log_file;
_log_file = _personal_dir;
_log_file += "openttd.log";
}
/**

@ -159,4 +159,12 @@ public:
}
};
/** Helper to manage a FILE with a \c std::unique_ptr. */
struct FileDeleter {
void operator()(FILE *f)
{
if (f) fclose(f);
}
};
#endif /* FILEIO_FUNC_H */

@ -548,9 +548,9 @@ public:
for (auto &pair : _load_check_data.companies) {
SetDParam(0, pair.first + 1);
const CompanyProperties &c = *pair.second;
if (c.name != nullptr) {
if (!c.name.empty()) {
SetDParam(1, STR_JUST_RAW_STRING);
SetDParamStr(2, c.name);
SetDParamStr(2, c.name.c_str());
} else {
SetDParam(1, c.name_1);
SetDParam(2, c.name_2);

@ -94,13 +94,13 @@ SpriteFontCache::~SpriteFontCache()
this->ClearGlyphToSpriteMap();
}
SpriteID SpriteFontCache::GetUnicodeGlyph(GlyphID key)
SpriteID SpriteFontCache::GetUnicodeGlyph(WChar key)
{
if (this->glyph_to_spriteid_map[GB(key, 8, 8)] == nullptr) return 0;
return this->glyph_to_spriteid_map[GB(key, 8, 8)][GB(key, 0, 8)];
}
void SpriteFontCache::SetUnicodeGlyph(GlyphID key, SpriteID sprite)
void SpriteFontCache::SetUnicodeGlyph(WChar key, SpriteID sprite)
{
if (this->glyph_to_spriteid_map == nullptr) this->glyph_to_spriteid_map = CallocT<SpriteID*>(256);
if (this->glyph_to_spriteid_map[GB(key, 8, 8)] == nullptr) this->glyph_to_spriteid_map[GB(key, 8, 8)] = CallocT<SpriteID>(256);
@ -209,7 +209,7 @@ protected:
int req_size; ///< Requested font size.
int used_size; ///< Used font size.
typedef SmallMap<uint32, SmallPair<size_t, const void*> > FontTable; ///< Table with font table cache
typedef SmallMap<uint32, std::pair<size_t, const void*> > FontTable; ///< Table with font table cache
FontTable font_tables; ///< Cached font tables.
/** Container for information about a glyph. */
@ -438,7 +438,7 @@ const void *TrueTypeFontCache::GetFontTable(uint32 tag, size_t &length)
const void *result = this->InternalGetFontTable(tag, length);
this->font_tables.Insert(tag, SmallPair<size_t, const void *>(length, result));
this->font_tables.Insert(tag, std::pair<size_t, const void *>(length, result));
return result;
}

@ -58,70 +58,47 @@ void NORETURN CDECL strgen_fatal(const char *s, ...)
throw std::exception();
}
/**
* Create a new container for language strings.
* @param language The language name.
* @param end If not nullptr, terminate \a language at this position.
*/
LanguageStrings::LanguageStrings(const char *language, const char *end)
{
this->language = stredup(language, end != nullptr ? end - 1 : nullptr);
}
/** Free everything. */
LanguageStrings::~LanguageStrings()
{
free(this->language);
}
/**
* Read all the raw language strings from the given file.
* @param file The file to read from.
* @return The raw strings, or nullptr upon error.
*/
std::unique_ptr<LanguageStrings> ReadRawLanguageStrings(const char *file)
LanguageStrings ReadRawLanguageStrings(const std::string &file)
{
try {
size_t to_read;
FILE *fh = FioFOpenFile(file, "rb", GAME_DIR, &to_read);
if (fh == nullptr) return nullptr;
size_t to_read;
FILE *fh = FioFOpenFile(file.c_str(), "rb", GAME_DIR, &to_read);
if (fh == nullptr) return LanguageStrings();
FileCloser fhClose(fh);
FileCloser fhClose(fh);
const char *langname = strrchr(file, PATHSEPCHAR);
if (langname == nullptr) {
langname = file;
} else {
langname++;
}
auto pos = file.rfind(PATHSEPCHAR);
if (pos == std::string::npos) return LanguageStrings();
std::string langname = file.substr(pos + 1);
/* Check for invalid empty filename */
if (*langname == '.' || *langname == 0) return nullptr;
/* Check for invalid empty filename */
if (langname.empty() || langname.front() == '.') return LanguageStrings();
std::unique_ptr<LanguageStrings> ret(new LanguageStrings(langname, strchr(langname, '.')));
LanguageStrings ret(langname.substr(0, langname.find('.')));
char buffer[2048];
while (to_read != 0 && fgets(buffer, sizeof(buffer), fh) != nullptr) {
size_t len = strlen(buffer);
char buffer[2048];
while (to_read != 0 && fgets(buffer, sizeof(buffer), fh) != nullptr) {
size_t len = strlen(buffer);
/* Remove trailing spaces/newlines from the string. */
size_t i = len;
while (i > 0 && (buffer[i - 1] == '\r' || buffer[i - 1] == '\n' || buffer[i - 1] == ' ')) i--;
buffer[i] = '\0';
/* Remove trailing spaces/newlines from the string. */
size_t i = len;
while (i > 0 && (buffer[i - 1] == '\r' || buffer[i - 1] == '\n' || buffer[i - 1] == ' ')) i--;
buffer[i] = '\0';
ret->lines.emplace_back(buffer, i);
ret.lines.emplace_back(buffer, i);
if (len > to_read) {
to_read = 0;
} else {
to_read -= len;
}
if (len > to_read) {
to_read = 0;
} else {
to_read -= len;
}
return ret;
} catch (...) {
return nullptr;
}
return ret;
}
@ -138,7 +115,7 @@ struct StringListReader : StringReader {
* @param translation Are we reading a translation?
*/
StringListReader(StringData &data, const LanguageStrings &strings, bool master, bool translation) :
StringReader(data, strings.language, master, translation), p(strings.lines.begin()), end(strings.lines.end())
StringReader(data, strings.language.c_str(), master, translation), p(strings.lines.begin()), end(strings.lines.end())
{
}
@ -215,12 +192,11 @@ struct StringNameWriter : HeaderWriter {
class LanguageScanner : protected FileScanner {
private:
GameStrings *gs;
char *exclude;
std::string exclude;
public:
/** Initialise */
LanguageScanner(GameStrings *gs, const char *exclude) : gs(gs), exclude(stredup(exclude)) {}
~LanguageScanner() { free(exclude); }
LanguageScanner(GameStrings *gs, const std::string &exclude) : gs(gs), exclude(exclude) {}
/**
* Scan.
@ -232,10 +208,10 @@ public:
bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename) override
{
if (strcmp(filename, exclude) == 0) return true;
if (exclude == filename) return true;
auto ls = ReadRawLanguageStrings(filename);
if (ls == nullptr) return false;
if (!ls.IsValid()) return false;
gs->raw_strings.push_back(std::move(ls));
return true;
@ -249,17 +225,16 @@ public:
GameStrings *LoadTranslations()
{
const GameInfo *info = Game::GetInfo();
char filename[512];
strecpy(filename, info->GetMainScript(), lastof(filename));
char *e = strrchr(filename, PATHSEPCHAR);
if (e == nullptr) return nullptr;
e++; // Make 'e' point after the PATHSEPCHAR
std::string basename(info->GetMainScript());
auto e = basename.rfind(PATHSEPCHAR);
if (e == std::string::npos) return nullptr;
basename.erase(e + 1);
strecpy(e, "lang" PATHSEP "english.txt", lastof(filename));
if (!FioCheckFileExists(filename, GAME_DIR)) return nullptr;
std::string filename = basename + "lang" PATHSEP "english.txt";
if (!FioCheckFileExists(filename.c_str() , GAME_DIR)) return nullptr;
auto ls = ReadRawLanguageStrings(filename);
if (ls == nullptr) return nullptr;
if (!ls.IsValid()) return nullptr;
GameStrings *gs = new GameStrings();
try {
@ -267,8 +242,7 @@ GameStrings *LoadTranslations()
/* Scan for other language files */
LanguageScanner scanner(gs, filename);
strecpy(e, "lang" PATHSEP, lastof(filename));
size_t len = strlen(filename);
std::string ldir = basename + "lang" PATHSEP;
const char *tar_filename = info->GetTarFile();
TarList::iterator iter;
@ -281,14 +255,14 @@ GameStrings *LoadTranslations()
if (tar->second.tar_filename != iter->first) continue;
/* Check the path and extension. */
if (tar->first.size() <= len || tar->first.compare(0, len, filename) != 0) continue;
if (tar->first.size() <= ldir.size() || tar->first.compare(0, ldir.size(), ldir) != 0) continue;
if (tar->first.compare(tar->first.size() - 4, 4, ".txt") != 0) continue;
scanner.AddFile(tar->first.c_str(), 0, tar_filename);
}
} else {
/* Scan filesystem */
scanner.Scan(filename);
scanner.Scan(ldir.c_str());
}
gs->Compile();
@ -303,7 +277,7 @@ GameStrings *LoadTranslations()
void GameStrings::Compile()
{
StringData data(32);
StringListReader master_reader(data, *this->raw_strings[0], true, false);
StringListReader master_reader(data, this->raw_strings[0], true, false);
master_reader.ParseFile();
if (_errors != 0) throw std::exception();
@ -314,12 +288,12 @@ void GameStrings::Compile()
for (const auto &p : this->raw_strings) {
data.FreeTranslation();
StringListReader translation_reader(data, *p, false, strcmp(p->language, "english") != 0);
StringListReader translation_reader(data, p, false, p.language != "english");
translation_reader.ParseFile();
if (_errors != 0) throw std::exception();
this->compiled_strings.emplace_back(new LanguageStrings(p->language));
TranslationWriter writer(this->compiled_strings.back()->lines);
this->compiled_strings.emplace_back(p.language);
TranslationWriter writer(this->compiled_strings.back().lines);
writer.WriteLang(data);
}
}
@ -387,11 +361,11 @@ void ReconsiderGameScriptLanguage()
language++;
for (auto &p : _current_data->compiled_strings) {
if (strcmp(p->language, language) == 0) {
_current_data->cur_language = p;
if (p.language == language) {
_current_data->cur_language = &p;
return;
}
}
_current_data->cur_language = _current_data->compiled_strings[0];
_current_data->cur_language = &_current_data->compiled_strings[0];
}

@ -18,23 +18,34 @@ void ReconsiderGameScriptLanguage();
/** Container for the raw (unencoded) language strings of a language. */
struct LanguageStrings {
const char *language; ///< Name of the language (base filename).
StringList lines; ///< The lines of the file to pass into the parser/encoder.
std::string language; ///< Name of the language (base filename). Empty string if invalid.
StringList lines; ///< The lines of the file to pass into the parser/encoder.
LanguageStrings(const char *language, const char *end = nullptr);
~LanguageStrings();
LanguageStrings() {}
LanguageStrings(const std::string &lang) : language(lang) {}
LanguageStrings(const LanguageStrings &other) : language(other.language), lines(other.lines) {}
LanguageStrings(LanguageStrings &&other) : language(std::move(other.language)), lines(std::move(other.lines)) {}
bool IsValid() const { return !this->language.empty(); }
};
/** Container for all the game strings. */
struct GameStrings {
uint version; ///< The version of the language strings.
std::shared_ptr<LanguageStrings> cur_language; ///< The current (compiled) language.
uint version; ///< The version of the language strings.
LanguageStrings *cur_language; ///< The current (compiled) language.
std::vector<std::unique_ptr<LanguageStrings>> raw_strings; ///< The raw strings per language, first must be English/the master language!.
std::vector<std::shared_ptr<LanguageStrings>> compiled_strings; ///< The compiled strings per language, first must be English/the master language!.
StringList string_names; ///< The names of the compiled strings.
std::vector<LanguageStrings> raw_strings; ///< The raw strings per language, first must be English/the master language!.
std::vector<LanguageStrings> compiled_strings; ///< The compiled strings per language, first must be English/the master language!.
StringList string_names; ///< The names of the compiled strings.
void Compile();
GameStrings() = default;
GameStrings(const GameStrings &) = delete;
GameStrings(GameStrings &&) = delete;
GameStrings &operator=(const GameStrings &) = delete;
GameStrings &operator=(GameStrings &&) = delete;
};
#endif /* GAME_TEXT_HPP */

@ -114,7 +114,7 @@ int DrawString(int left, int right, int top, StringID str, TextColour colour = T
int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL);
int DrawStringMultiLine(int left, int right, int top, int bottom, StringID str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL);
void DrawCharCentered(uint32 c, int x, int y, TextColour colour);
void DrawCharCentered(WChar c, int x, int y, TextColour colour);
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode = FILLRECT_OPAQUE);
void GfxFillPolygon(const std::vector<Point> &shape, int colour, FillRectMode mode = FILLRECT_OPAQUE);
@ -168,7 +168,7 @@ void SortResolutions();
bool ToggleFullScreen(bool fs);
/* gfx.cpp */
byte GetCharacterWidth(FontSize size, uint32 key);
byte GetCharacterWidth(FontSize size, WChar key);
byte GetDigitWidth(FontSize size = FS_NORMAL);
void GetBroadestDigit(uint *front, uint *next, FontSize size = FS_NORMAL);

@ -134,7 +134,7 @@ void CheckExternalFiles()
const GraphicsSet *used_set = BaseGraphics::GetUsedSet();
DEBUG(grf, 1, "Using the %s base graphics set", used_set->name);
DEBUG(grf, 1, "Using the %s base graphics set", used_set->name.c_str());
static const size_t ERROR_MESSAGE_LENGTH = 256;
static const size_t MISSING_FILE_MESSAGE_LENGTH = 128;
@ -149,7 +149,7 @@ void CheckExternalFiles()
if (used_set->GetNumInvalid() != 0) {
/* Not all files were loaded successfully, see which ones */
add_pos += seprintf(add_pos, last, "Trying to load graphics set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of README.md.\n\nThe following files are corrupted or missing:\n", used_set->name);
add_pos += seprintf(add_pos, last, "Trying to load graphics set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of README.md.\n\nThe following files are corrupted or missing:\n", used_set->name.c_str());
for (uint i = 0; i < GraphicsSet::NUM_FILES; i++) {
MD5File::ChecksumResult res = GraphicsSet::CheckMD5(&used_set->files[i], BASESET_DIR);
if (res != MD5File::CR_MATCH) add_pos += seprintf(add_pos, last, "\t%s is %s (%s)\n", used_set->files[i].filename, res == MD5File::CR_MISMATCH ? "corrupt" : "missing", used_set->files[i].missing_warning);
@ -159,7 +159,7 @@ void CheckExternalFiles()
const SoundsSet *sounds_set = BaseSounds::GetUsedSet();
if (sounds_set->GetNumInvalid() != 0) {
add_pos += seprintf(add_pos, last, "Trying to load sound set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of README.md.\n\nThe following files are corrupted or missing:\n", sounds_set->name);
add_pos += seprintf(add_pos, last, "Trying to load sound set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of README.md.\n\nThe following files are corrupted or missing:\n", sounds_set->name.c_str());
assert_compile(SoundsSet::NUM_FILES == 1);
/* No need to loop each file, as long as there is only a single
@ -503,11 +503,11 @@ bool GraphicsSet::FillSetDetails(IniFile *ini, const char *path, const char *ful
IniItem *item;
fetch_metadata("palette");
this->palette = (*item->value == 'D' || *item->value == 'd') ? PAL_DOS : PAL_WINDOWS;
this->palette = (item->value.value()[0] == 'D' || item->value.value()[0] == 'd') ? PAL_DOS : PAL_WINDOWS;
/* Get optional blitter information. */
item = metadata->GetItem("blitter", false);
this->blitter = (item != nullptr && *item->value == '3') ? BLT_32BPP : BLT_8BPP;
this->blitter = (item != nullptr && item->value.value()[0] == '3') ? BLT_32BPP : BLT_8BPP;
}
return ret;
}

@ -16,6 +16,7 @@
#include "vehicle_type.h"
#include "engine_type.h"
#include "livery.h"
#include <string>
typedef Pool<Group, GroupID, 16, 64000> GroupPool;
extern GroupPool _group_pool; ///< Pool of groups.
@ -63,7 +64,7 @@ struct GroupStatistics {
/** Group data. */
struct Group : GroupPool::PoolItem<&_group_pool> {
char *name; ///< Group Name
std::string name; ///< Group Name
Owner owner; ///< Group Owner
VehicleType vehicle_type; ///< Vehicle type of the group
@ -76,7 +77,6 @@ struct Group : GroupPool::PoolItem<&_group_pool> {
GroupID parent; ///< Parent group
Group(CompanyID owner = INVALID_COMPANY);
~Group();
};

@ -298,11 +298,6 @@ Group::Group(Owner owner)
this->folded = false;
}
Group::~Group()
{
free(this->name);
}
/**
* Create a new vehicle group.
@ -436,10 +431,12 @@ CommandCost CmdAlterGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
}
if (flags & DC_EXEC) {
/* Delete the old name */
free(g->name);
/* Assign the new one */
g->name = reset ? nullptr : stredup(text);
if (reset) {
g->name.clear();
} else {
g->name = text;
}
}
} else {
/* Set group parent */

@ -292,7 +292,7 @@ void HotkeyList::Load(IniFile *ini)
IniItem *item = group->GetItem(hotkey->name, false);
if (item != nullptr) {
hotkey->keycodes.clear();
if (item->value != nullptr) ParseHotkeys(hotkey, item->value);
if (item->value.has_value()) ParseHotkeys(hotkey, item->value->c_str());
}
}
}

@ -12,9 +12,11 @@
#include "ini_type.h"
#include "string_func.h"
#include "fileio_func.h"
#include <fstream>
#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500)
# include <unistd.h>
# include <fcntl.h>
#endif
#ifdef _WIN32
@ -45,31 +47,33 @@ bool IniFile::SaveToDisk(const char *filename)
* that file. This to prevent that when OpenTTD crashes during the save
* you end up with a truncated configuration file.
*/
char file_new[MAX_PATH];
std::string file_new{ filename };
file_new.append(".new");
strecpy(file_new, filename, lastof(file_new));
strecat(file_new, ".new", lastof(file_new));
FILE *f = fopen(file_new, "w");
if (f == nullptr) return false;
std::ofstream os(OTTD2FS(file_new.c_str()));
if (os.fail()) return false;
for (const IniGroup *group = this->group; group != nullptr; group = group->next) {
if (group->comment) fputs(group->comment, f);
fprintf(f, "[%s]\n", group->name);
os << group->comment << "[" << group->name << "]\n";
for (const IniItem *item = group->item; item != nullptr; item = item->next) {
if (item->comment != nullptr) fputs(item->comment, f);
os << item->comment;
/* protect item->name with quotes if needed */
if (strchr(item->name, ' ') != nullptr ||
item->name[0] == '[') {
fprintf(f, "\"%s\"", item->name);
if (item->name.find(' ') != std::string::npos ||
item->name[0] == '[') {
os << "\"" << item->name << "\"";
} else {
fprintf(f, "%s", item->name);
os << item->name;
}
fprintf(f, " = %s\n", item->value == nullptr ? "" : item->value);
os << " = " << item->value.value_or("") << "\n";
}
}
if (this->comment) fputs(this->comment, f);
os << this->comment;
os.flush();
os.close();
if (os.fail()) return false;
/*
* POSIX (and friends) do not guarantee that when a file is closed it is
@ -78,11 +82,10 @@ bool IniFile::SaveToDisk(const char *filename)
* (modification date etc.) is not important to us; only the real data is.
*/
#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
int ret = fdatasync(fileno(f));
fclose(f);
int f = open(file_new.c_str(), O_RDWR);
int ret = fdatasync(f);
close(f);
if (ret != 0) return false;
#else
fclose(f);
#endif
#if defined(_WIN32)
@ -91,7 +94,7 @@ bool IniFile::SaveToDisk(const char *filename)
/* Allocate space for one more \0 character. */
TCHAR tfilename[MAX_PATH + 1], tfile_new[MAX_PATH + 1];
_tcsncpy(tfilename, OTTD2FS(filename), MAX_PATH);
_tcsncpy(tfile_new, OTTD2FS(file_new), MAX_PATH);
_tcsncpy(tfile_new, OTTD2FS(file_new.c_str()), MAX_PATH);
/* SHFileOperation wants a double '\0' terminated string. */
tfilename[MAX_PATH - 1] = '\0';
tfile_new[MAX_PATH - 1] = '\0';
@ -107,8 +110,8 @@ bool IniFile::SaveToDisk(const char *filename)
shfopt.pTo = tfilename;
SHFileOperation(&shfopt);
#else
if (rename(file_new, filename) < 0) {
DEBUG(misc, 0, "Renaming %s to %s failed; configuration not saved", file_new, filename);
if (rename(file_new.c_str(), filename) < 0) {
DEBUG(misc, 0, "Renaming %s to %s failed; configuration not saved", file_new.c_str(), filename);
}
#endif

@ -19,12 +19,10 @@
* Construct a new in-memory item of an Ini file.
* @param parent the group we belong to
* @param name the name of the item
* @param last the last element of the name of the item
*/
IniItem::IniItem(IniGroup *parent, const char *name, const char *last) : next(nullptr), value(nullptr), comment(nullptr)
IniItem::IniItem(IniGroup *parent, const std::string &name) : next(nullptr)
{
this->name = stredup(name, last);
str_validate(this->name, this->name + strlen(this->name));
this->name = str_validate(name);
*parent->last_item = this;
parent->last_item = &this->next;
@ -33,10 +31,6 @@ IniItem::IniItem(IniGroup *parent, const char *name, const char *last) : next(nu
/** Free everything we loaded. */
IniItem::~IniItem()
{
free(this->name);
free(this->value);
free(this->comment);
delete this->next;
}
@ -46,20 +40,21 @@ IniItem::~IniItem()
*/
void IniItem::SetValue(const char *value)
{
free(this->value);
this->value = stredup(value);
if (value == nullptr) {
this->value.reset();
} else {
this->value.emplace(value);
}
}
/**
* Construct a new in-memory group of an Ini file.
* @param parent the file we belong to
* @param name the name of the group
* @param last the last element of the name of the group
*/
IniGroup::IniGroup(IniLoadFile *parent, const char *name, const char *last) : next(nullptr), type(IGT_VARIABLES), item(nullptr), comment(nullptr)
IniGroup::IniGroup(IniLoadFile *parent, const std::string &name) : next(nullptr), type(IGT_VARIABLES), item(nullptr)
{
this->name = stredup(name, last);
str_validate(this->name, this->name + strlen(this->name));
this->name = str_validate(name);
this->last_item = &this->item;
*parent->last_group = this;
@ -67,7 +62,7 @@ IniGroup::IniGroup(IniLoadFile *parent, const char *name, const char *last) : ne
if (parent->list_group_names != nullptr) {
for (uint i = 0; parent->list_group_names[i] != nullptr; i++) {
if (strcmp(this->name, parent->list_group_names[i]) == 0) {
if (this->name == parent->list_group_names[i]) {
this->type = IGT_LIST;
return;
}
@ -75,7 +70,7 @@ IniGroup::IniGroup(IniLoadFile *parent, const char *name, const char *last) : ne
}
if (parent->seq_group_names != nullptr) {
for (uint i = 0; parent->seq_group_names[i] != nullptr; i++) {
if (strcmp(this->name, parent->seq_group_names[i]) == 0) {
if (this->name == parent->seq_group_names[i]) {
this->type = IGT_SEQUENCE;
return;
}
@ -86,9 +81,6 @@ IniGroup::IniGroup(IniLoadFile *parent, const char *name, const char *last) : ne
/** Free everything we loaded. */
IniGroup::~IniGroup()
{
free(this->name);
free(this->comment);
delete this->item;
delete this->next;
}
@ -100,16 +92,16 @@ IniGroup::~IniGroup()
* @param create whether to create an item when not found or not.
* @return the requested item or nullptr if not found.
*/
IniItem *IniGroup::GetItem(const char *name, bool create)
IniItem *IniGroup::GetItem(const std::string &name, bool create)
{
for (IniItem *item = this->item; item != nullptr; item = item->next) {
if (strcmp(item->name, name) == 0) return item;
if (item->name == name) return item;
}
if (!create) return nullptr;
/* otherwise make a new one */
return new IniItem(this, name, nullptr);
return new IniItem(this, name);
}
/**
@ -129,7 +121,6 @@ void IniGroup::Clear()
*/
IniLoadFile::IniLoadFile(const char * const *list_group_names, const char * const *seq_group_names) :
group(nullptr),
comment(nullptr),
list_group_names(list_group_names),
seq_group_names(seq_group_names)
{
@ -139,7 +130,6 @@ IniLoadFile::IniLoadFile(const char * const *list_group_names, const char * cons
/** Free everything we loaded. */
IniLoadFile::~IniLoadFile()
{
free(this->comment);
delete this->group;
}
@ -147,26 +137,21 @@ IniLoadFile::~IniLoadFile()
* Get the group with the given name. If it doesn't exist
* and \a create_new is \c true create a new group.
* @param name name of the group to find.
* @param len the maximum length of said name (\c 0 means length of the string).
* @param create_new Allow creation of group if it does not exist.
* @return The requested group if it exists or was created, else \c nullptr.
*/
IniGroup *IniLoadFile::GetGroup(const char *name, size_t len, bool create_new)
IniGroup *IniLoadFile::GetGroup(const std::string &name, bool create_new)
{
if (len == 0) len = strlen(name);
/* does it exist already? */
for (IniGroup *group = this->group; group != nullptr; group = group->next) {
if (!strncmp(group->name, name, len) && group->name[len] == 0) {
return group;
}
if (group->name == name) return group;
}
if (!create_new) return nullptr;
/* otherwise make a new one */
IniGroup *group = new IniGroup(this, name, name + len - 1);
group->comment = stredup("\n");
IniGroup *group = new IniGroup(this, name);
group->comment = "\n";
return group;
}
@ -182,7 +167,7 @@ void IniLoadFile::RemoveGroup(const char *name)
/* does it exist already? */
for (group = this->group; group != nullptr; prev = group, group = group->next) {
if (strncmp(group->name, name, len) == 0) {
if (group->name.compare(0, len, name) == 0) {
break;
}
}
@ -266,17 +251,17 @@ void IniLoadFile::LoadFromDisk(const char *filename, Subdirectory subdir, std::s
e--;
}
s++; // skip [
group = new IniGroup(this, s, e - 1);
group = new IniGroup(this, std::string(s, e - s));
if (comment_size != 0) {
group->comment = stredup(comment, comment + comment_size - 1);
group->comment.assign(comment, comment_size);
comment_size = 0;
}
} else if (group != nullptr) {
if (group->type == IGT_SEQUENCE) {
/* A sequence group, use the line as item name without further interpretation. */
IniItem *item = new IniItem(group, buffer, e - 1);
IniItem *item = new IniItem(group, std::string(buffer, e - buffer));
if (comment_size) {
item->comment = stredup(comment, comment + comment_size - 1);
item->comment.assign(comment, comment_size);
comment_size = 0;
}
continue;
@ -292,9 +277,9 @@ void IniLoadFile::LoadFromDisk(const char *filename, Subdirectory subdir, std::s
}
/* it's an item in an existing group */
IniItem *item = new IniItem(group, s, t - 1);
IniItem *item = new IniItem(group, std::string(s, t - s));
if (comment_size != 0) {
item->comment = stredup(comment, comment + comment_size - 1);
item->comment.assign(comment, comment_size);
comment_size = 0;
}
@ -310,8 +295,11 @@ void IniLoadFile::LoadFromDisk(const char *filename, Subdirectory subdir, std::s
*e = '\0';
/* If the value was not quoted and empty, it must be nullptr */
item->value = (!quoted && e == t) ? nullptr : stredup(t);
if (item->value != nullptr) str_validate(item->value, item->value + strlen(item->value));
if (!quoted && e == t) {
item->value.reset();
} else {
item->value = str_validate(std::string(t));
}
} else {
/* it's an orphan item */
this->ReportFileError("ini: '", buffer, "' outside of group");
@ -319,7 +307,7 @@ void IniLoadFile::LoadFromDisk(const char *filename, Subdirectory subdir, std::s
}
if (comment_size > 0) {
this->comment = stredup(comment, comment + comment_size - 1);
this->comment.assign(comment, comment_size);
comment_size = 0;
}

@ -11,6 +11,8 @@
#define INI_TYPE_H
#include "fileio_type.h"
#include <string>
#include "3rdparty/optional/ottd_optional.h"
#include <string>
@ -23,12 +25,12 @@ enum IniGroupType {
/** A single "line" in an ini file. */
struct IniItem {
IniItem *next; ///< The next item in this group
char *name; ///< The name of this item
char *value; ///< The value of this item
char *comment; ///< The comment associated with this item
IniItem *next; ///< The next item in this group
std::string name; ///< The name of this item
opt::optional<std::string> value; ///< The value of this item
std::string comment; ///< The comment associated with this item
IniItem(struct IniGroup *parent, const char *name, const char *last = nullptr);
IniItem(struct IniGroup *parent, const std::string &name);
~IniItem();
void SetValue(const char *value);
@ -40,13 +42,13 @@ struct IniGroup {
IniGroupType type; ///< type of group
IniItem *item; ///< the first item in the group
IniItem **last_item; ///< the last item in the group
char *name; ///< name of group
char *comment; ///< comment for group
std::string name; ///< name of group
std::string comment; ///< comment for group
IniGroup(struct IniLoadFile *parent, const char *name, const char *last = nullptr);
IniGroup(struct IniLoadFile *parent, const std::string &name);
~IniGroup();
IniItem *GetItem(const char *name, bool create);
IniItem *GetItem(const std::string &name, bool create);
void Clear();
};
@ -54,14 +56,14 @@ struct IniGroup {
struct IniLoadFile {
IniGroup *group; ///< the first group in the ini
IniGroup **last_group; ///< the last group in the ini
char *comment; ///< last comment in file
std::string comment; ///< last comment in file
const char * const *list_group_names; ///< nullptr terminated list with group names that are lists
const char * const *seq_group_names; ///< nullptr terminated list with group names that are sequences.
IniLoadFile(const char * const *list_group_names = nullptr, const char * const *seq_group_names = nullptr);
virtual ~IniLoadFile();
IniGroup *GetGroup(const char *name, size_t len = 0, bool create_new = true);
IniGroup *GetGroup(const std::string &name, bool create_new = true);
void RemoveGroup(const char *name);
void LoadFromDisk(const char *filename, Subdirectory subdir, std::string *save = nullptr);

@ -935,6 +935,7 @@ STR_GAME_OPTIONS_CURRENCY_MXN :Mexicaanse peso
STR_GAME_OPTIONS_CURRENCY_NTD :Nieuwe Taiwanse dollar (NTD)
STR_GAME_OPTIONS_CURRENCY_CNY :Chinese Renminbi (CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :Hong Kong Dollar (HKD)
STR_GAME_OPTIONS_CURRENCY_INR :Indiase rupee (INR)
############ end of currency region
STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME :{BLACK}Wegvoertuigen

@ -3605,6 +3605,7 @@ STR_REPLACE_WAGONS :Gerbong
STR_REPLACE_ALL_RAILTYPE :Semua kereta
STR_REPLACE_HELP_RAILTYPE :{BLACK}Pilih jenis kereta yang anda inginkan untuk diganti
STR_REPLACE_HELP_ROADTYPE :{BLACK}Pilih jenis jalan yang anda inginkan untuk diganti
STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}Menampilkan kendaraan terpilih di sisi kiri yang akan diganti, jika ada
STR_REPLACE_RAIL_VEHICLES :Kereta
STR_REPLACE_ELRAIL_VEHICLES :Kereta Listrik

@ -244,6 +244,7 @@ STR_TOOLTIP_CLOSE_WINDOW :{BLACK}Aizvērt
STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS :{BLACK}Loga virsraksts - vilkt to, lai pārvietotu logu
STR_TOOLTIP_SHADE :{BLACK}Aizēnot logu - rādīt tikai virsrakstu
STR_TOOLTIP_DEBUG :{BLACK}Rādīt NewGRF atkļūdošanas informāciju
STR_TOOLTIP_DEFSIZE :{BLACK}Mainīt loga izmēru uz tā noklusējuma izmēru. Ctrl+klikšķis, lai saglabātu esošo izmēru kā noklusējuma
STR_TOOLTIP_STICKY :{BLACK}Atzīmēt šo logu kā neaizveramu ar "Aizvērt visus logus" taustiņu. Ctrl+klikšķis, lai saglabātu stāvokli kā noklusējumu
STR_TOOLTIP_RESIZE :{BLACK}Klikšķināt un vilkt, lai mainītu šī loga lielumu
STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Pārslēgties starp lielu/mazu loga izmēru
@ -361,6 +362,7 @@ STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION :{BLACK}Ainavas
STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}Pilsētu radīšana
STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION :{BLACK}Ražotņu radīšana
STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}Ceļu būvēšana
STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION :{BLACK}Tramvaju sliežu ceļu būvniecība
STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}Stādīt kokus. Shift pārslēdz būvēšanu/izmaksu tāmes rādīšanu
STR_SCENEDIT_TOOLBAR_PLACE_SIGN :{BLACK}Novietot zīmi
STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}Novietot objektu. Shift pārslēdz būvēšanu/izmaksu tāmes rādīšanu
@ -651,6 +653,7 @@ STR_MUSIC_EFFECTS_VOLUME :{TINY_FONT}{BLA
STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}--
STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM}
STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------
STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Mūzika nav pieejama
STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}"
STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Celiņš
STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Nosaukums
@ -884,10 +887,10 @@ STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLAC
# Extra view window
STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Skatvieta {COMMA}
STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Kopēt uz skatvietu
STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN :{BLACK}Mainīt skatvietu
STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT :{BLACK}Kopēt galvenā skata atrašanās vietu uz šo skatvietu
STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Kopēt no skatvietas
STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Ielīmēt šīs skatvietas atrašanās vietu uz galveno skatu
STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW :{BLACK}Mainīt galveno skatu
STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT :{BLACK}Kopēt šīs skatvietas atrašanās vietu uz galveno skatu
# Game options window
STR_GAME_OPTIONS_CAPTION :{WHITE}Spēles opcijas
@ -933,6 +936,7 @@ STR_GAME_OPTIONS_CURRENCY_RUB :Jaunais Krievij
STR_GAME_OPTIONS_CURRENCY_MXN :Meksikas peso (MXN)
STR_GAME_OPTIONS_CURRENCY_NTD :Jaunais Taivānas dolārs (NTD)
STR_GAME_OPTIONS_CURRENCY_CNY :Ķīnas juaņa (CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :Honkongas dolārs (HKD)
STR_GAME_OPTIONS_CURRENCY_INR :Indijas rūpija (INR)
############ end of currency region
@ -997,6 +1001,7 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :Divkāršs
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Četrkāršs
STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}Fonta izmērs
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Izvēlieties saskarnes fonta izmēru
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :Normāls
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :Divkāršs izmērs
@ -1016,6 +1021,7 @@ STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP :{BLACK}Atlasīt
STR_GAME_OPTIONS_BASE_MUSIC_STATUS :{RED}{NUM} bojāt{P s i u} fail{P s i u}
STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :{BLACK}Papildinformācija par pamata mūzikas kopu
STR_ERROR_RESOLUTION_LIST_FAILED :{WHITE}Neizdevās saņemt sarakstu ar atbalstītajām izšķirtspējām
STR_ERROR_FULLSCREEN_FAILED :{WHITE}Pilnekrāna spēles iestatīšana neizdevās
# Custom currency window
@ -1133,6 +1139,7 @@ STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME :Spēles iestat
STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU :Uzņēmuma iestatījumi (tiek iekļauti saglabājumos, ietekmē tikai jaunās spēles)
STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME :Uzņēmuma iestatījumi (tiek iekļauti saglabājumā, ietekmē tikai pašreizējo uzņēmumu)
STR_CONFIG_SETTING_CATEGORY_HIDES :{BLACK}Rādīt visus meklēšanas rezultātus, iestatot{}{SILVER}Kategoriju {BLACK}uz {WHITE}{STRING}
STR_CONFIG_SETTING_TYPE_HIDES :{BLACK}Rādīt visus meklēšanas rezultātus, iestatot{}{SILVER}Veidu {BLACK}uz {WHITE}Visi iestatījumu veidi
STR_CONFIG_SETTING_CATEGORY_AND_TYPE_HIDES :{BLACK}Rādīt visus meklēšanas rezultātus, iestatot{}{SILVER}Kategorija {BLACK}uz {WHITE}{STRING} {BLACK}un {SILVER}Tips {BLACK}uz {WHITE}Visi iestatījumu veidi
STR_CONFIG_SETTINGS_NONE :{WHITE}-Nav-
@ -1157,17 +1164,21 @@ STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_HELPTEXT :Maksimālais ai
STR_CONFIG_SETTING_INTEREST_RATE :Procentu likme: {STRING}
STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :Aizdevumu procentu likme; ja ieslēgts, ietekmē arī inflāciju
STR_CONFIG_SETTING_RUNNING_COSTS :Kārtējās izmaksas: {STRING}
STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Iestaties uzturēšanas un ekspluatācijas izmaksu līmeni transportlīdzekļiem un infrastruktūrai
STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Būvēšanas ātrums: {STRING}
STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :MI (mākslīgā intelekta) būvniecības darbību daudzuma ierobežošana
STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Transportlīdzekļu bojāšanās: {STRING}
STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Nosaka, cik bieži var salūzt nepietiekami apkalpoti transportlīdzekļi
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Subsīdiju reizinātājs: {STRING}
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Iestatīt, cik daudz maksāt par subsidētajiem savienojumiem
STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Būvēšanas izmaksas: {STRING}
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Iestatīt būvēšanas un pirkumu izmaksas
STR_CONFIG_SETTING_RECESSIONS :Lejupslīde: {STRING}
STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :Ja ieslēgts, ik pa laikam var gadīties recesijas. To laikā visa ražošana būtiski samazinās (tā atgriežas sākotnējā līmenī pēc recesijas beigām).
STR_CONFIG_SETTING_TRAIN_REVERSING :Neatļaut vilcienu apgriešanos stacijās: {STRING}
STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT :Ja ieslēgts, stacijās vilcieni negriezīsies pretējā virzienā, pat ja braucot tādā veidā tie atrastu īsāku ceļu un nākamo pieturu; izņēmums ir gala stacijas
STR_CONFIG_SETTING_DISASTERS :Katastrofas: {STRING}
STR_CONFIG_SETTING_DISASTERS_HELPTEXT :Pārslēgt katastrofas, kas laiku pa laikam var bloķēt vai iznīcināt transportlīdzekļus un infrastruktūru
STR_CONFIG_SETTING_CITY_APPROVAL :Pilsētu domju attieksme pret platības pārstrukturēšanu: {STRING}
STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :Izvēlieties, cik lielā mērā trokšņi un vides bojājumi ietekmē uzņēmuma reitingu un turpmākās būvniecības darbības viņu teritorijā
@ -1178,6 +1189,8 @@ STR_CONFIG_SETTING_AUTOSLOPE :Atļaut ainavas
STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Atļauj ainavas veidošanu zem ekām un ceļiem bez to nojaukšanas
STR_CONFIG_SETTING_CATCHMENT :Atļaut realistiskākas, palielinātas apkalpojamās platības: {STRING}
STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :Atšķirīga lieluma apkalpojamās platības dažādu veidu stacijām un lidostām
STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES :Uzņēmumu stacijas var apkalpot industrijas, kurām ir pievienotas neitrālas stacijas: {STRING}
STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT :Ja ieslēgts, industrijas ar pievienotām stacijām (piemēram, naftas ieguves platformas) var apkalpot arī netālu esošās uzņēmumumam piederošās stacijas. Ja izslēgts, šīs industrijas var apkalpot tikai to pašu stacijas. Tuvumā esošās uzņēmumu stacijas nevarēs tās apkalpot, un pievienotās stacijas neapkalpos preču veidus, kas nav atbilstošas attiecīgajai industrijai.
STR_CONFIG_SETTING_EXTRADYNAMITE :Atļaut pilsētai piederošo ceļu, tiltu un tuneļu nojaukšanu: {STRING}
STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :Padara vieglāku pilsētai piederošas infrastruktūras un ēku nojaukšanu
STR_CONFIG_SETTING_TRAIN_LENGTH :Maksimālais vilcienu garums: {STRING}
@ -1194,8 +1207,8 @@ STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS_HELPTEXT :Slīpu lauciņu
STR_CONFIG_SETTING_PERCENTAGE :{COMMA}%
STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS :Nogāžu stāvums autotransporta līdzekļiem: {STRING}
STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS_HELPTEXT :Slīpu lauciņu nogāžu stāvums autotransporta līdzekļiem. Augstākas vērtības apgrūtina uzbraukšanu uzkalnā
STR_CONFIG_SETTING_FORBID_90_DEG :Aizliegt vilcieniem un kuģiem veikt 90 grādu pagriezienus: {STRING}
STR_CONFIG_SETTING_FORBID_90_DEG_HELPTEXT :90 grādu pagriezieni rodas, ja horizontālam sliežu ceļa posmam tieši seko vertikāls sliežu ceļa posms uz blakus esošā lauciņa. Tādējādi vilciens, šķērsojot lauciņu malas, veic 90 grādu pagriezienu, nevis parasto 45 grādu kā citām sliežu ceļu kombinācijām. Tas attiecas arī uz kuģu pagrieziena lenķiem
STR_CONFIG_SETTING_FORBID_90_DEG :Aizliegt vilcieniem veikt 90° pagriezienus: {STRING}
STR_CONFIG_SETTING_FORBID_90_DEG_HELPTEXT :90 grādu pagriezieni rodas, ja horizontālam sliežu ceļa posmam tieši seko vertikāls sliežu ceļa posms uz blakus esošā lauciņa. Tādējādi vilciens, šķērsojot lauciņu malas, veic 90 grādu pagriezienu, nevis parasto 45 grādu kā citām sliežu ceļu kombinācijām. Tas attiecas arī uz kuģu pagrieziena leņķiem. Tas arī attiecas uz kuģu pagriešanās rādiusu.
STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS :Atļaut savienot stacijas, kas neatrodas tieši blakus: {STRING}
STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS_HELPTEXT :Atļaut pievienot staciju daļas, tām nesaskaroties ar jau esošajām. Novietojot jaunās daļas, ir nepieciešams nospiest Ctrl+klikšķis
STR_CONFIG_SETTING_INFLATION :Inflācija: {STRING}
@ -1240,7 +1253,7 @@ STR_CONFIG_SETTING_BRIBE_HELPTEXT :Lauj uzņēmumi
STR_CONFIG_SETTING_ALLOW_EXCLUSIVE :Atļaut pirkt pārvadājumu izņēmuma tiesības: {STRING}
STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT :Ja uzņēmums pērk pārvadājumu izņēmuma tiesības pilsētā, pretinieku stacijas (pasažieru un kravas) veselu gadu nesaņems nekādu kravu
STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS :Atļaut ēku finansēšanu: {STRING}
STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT :Atļauj uzņēmumiem dot naudu pilsētām jaunu ēku finansēšanai
STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT :Atļauj uzņēmumiem dot naudu apdzīvotām vietām jaunu ēku finansēšanai
STR_CONFIG_SETTING_ALLOW_FUND_ROAD :Atļaut finansēt vietējo ceļu atjaunošanu: {STRING}
STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT :Atļaut uzņēmumiem dot pilsētām naudu ceļu rekonstrukcijai, lai kaitētu ceļu pakalpojumiem pilsētās
STR_CONFIG_SETTING_ALLOW_GIVE_MONEY :Atļaut pārsūtīt naudu citiem uzņēmumiem: {STRING}
@ -1251,8 +1264,8 @@ STR_CONFIG_SETTING_PLANE_SPEED :Lidmašīnu āt
STR_CONFIG_SETTING_PLANE_SPEED_HELPTEXT :Iestatīt lidmašīnu nosacīto ātrumu salīdzinājumā ar citu veidu transportlīdzekļiem, lai samazinātu lidaparātu ienākumus
STR_CONFIG_SETTING_PLANE_SPEED_VALUE :1 / {COMMA}
STR_CONFIG_SETTING_PLANE_CRASHES :Lidmašīnu avāriju daudzums: {STRING}
STR_CONFIG_SETTING_PLANE_CRASHES_HELPTEXT :Iestatīt lidaparātu avāriju notikšanas iespējamību
STR_CONFIG_SETTING_PLANE_CRASHES_NONE :neviena
STR_CONFIG_SETTING_PLANE_CRASHES_HELPTEXT :Iestatīt nejaušu lidaparātu avāriju iespējamību.{}* Lielām lidmašīnām vienmēr ir risks avarēt, kad piezemējas mazās lidostās
STR_CONFIG_SETTING_PLANE_CRASHES_NONE :Nav*
STR_CONFIG_SETTING_PLANE_CRASHES_REDUCED :samazināts
STR_CONFIG_SETTING_PLANE_CRASHES_NORMAL :parasts
STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD :Atļaut caurbraucamas pieturvietas uz pilsētai piederošiem ceļiem: {STRING}
@ -1308,11 +1321,12 @@ STR_CONFIG_SETTING_LAND_GENERATOR :Zemes radītāj
STR_CONFIG_SETTING_LAND_GENERATOR_HELPTEXT :Sākotnējais ģenerators ir atkarīgs no bāzes grafikas kopas, un veido fiksētas ainavas formas. TerraGenesis ir uz Perlina trokšņa balstīts ģenerators ar smalkākiem vadības iestatījumiem.
STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :Sākotnējais
STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis
STR_CONFIG_SETTING_TERRAIN_TYPE :Reljefa veids: {STRING}
STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :(Tikai TerraGenesis) Ainavas kalnainība
STR_CONFIG_SETTING_INDUSTRY_DENSITY :Industriju blīvums: {STRING}
STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Iestatiet, cik industrijas jāģenerē un kāds līmenis jāuztur spēles laikā
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Maksimālais attālums no kartes malas naftas pārstrādes rūpnīcām: {STRING}
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Naftas pārstrādes rūpnīcas ir būvējamas tikai kartes malu tuvumā, salu kartēm tas ir pie krasta
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Naftas industriju maksimālais attālums no kartes malas: {STRING}
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Limits, cik tālu no kartes malām drīkst taisīt naftas pārstrādes rūpnīcas un un naftas ieguves platformas. Uz salu kartēm tas nodrošina, ka šīs konstrukcijas tiek būvētas piekrastēs. Uz kartēm, kas ir lielākas par 256 lauciņiem šī vērtība tiek palielināta.
STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Sniega līnijas augstums: {STRING}
STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Noteikt, kādā augstumā sākas subarktiskā ainava. Sniegs arī ietekmē industriju rašanos un apdzīvoto vietu pieaugšanas prasības
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Apvidus nelīdzenums: {STRING}
@ -1331,6 +1345,7 @@ STR_CONFIG_SETTING_TREE_PLACER_NONE :Nav
STR_CONFIG_SETTING_TREE_PLACER_ORIGINAL :Sākotnējais
STR_CONFIG_SETTING_TREE_PLACER_IMPROVED :Uzlabotais
STR_CONFIG_SETTING_ROAD_SIDE :Autotransporta līdzekļi: {STRING}
STR_CONFIG_SETTING_ROAD_SIDE_HELPTEXT :Izvēlieties braukšanas pusi
STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :Augstumu kartes pagriešana: {STRING}
STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE :Pret pulksteņa rādītāja virzienu
STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_CLOCKWISE :Pulksteņa rādītāja virzienā
@ -1353,8 +1368,10 @@ STR_CONFIG_SETTING_SCROLLMODE :Skatvietas riti
STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Uzvedība, kad ritina karti
STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :Pārvietot skatvietu ar labo peles pogu, peles pozīcija ir fiksēta
STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Pārvietot karti ar labo peles pogu, peles pozīcija ir fiksēta
STR_CONFIG_SETTING_SCROLLMODE_RMB :Pārvietot karti ar labo peles pogu
STR_CONFIG_SETTING_SCROLLMODE_LMB :Pārvietot karti ar kreiso peles pogu
STR_CONFIG_SETTING_SMOOTH_SCROLLING :Plūdena skatvietas ritināšana: {STRING}
STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Noteikt, kā galvenais skats ritina uz norādīto pozīciju, kad klikšķina uz mazās kartes vai kad dod komandu ritināt uz noteiktu kartes objektu. Ja ieslēgs, skatvieta ritinās gludi. Ja izslēgts, skats pārlec uz izvēlēto punktu.
STR_CONFIG_SETTING_MEASURE_TOOLTIP :Rādīt mērījumu rīkjoslu, izmantojot dažādus būvniecības rīkus: {STRING}
STR_CONFIG_SETTING_MEASURE_TOOLTIP_HELPTEXT :Rāda lauciņu attālumus un augstuma starpības, ar vilkšanu veicot būvniecības darbības
STR_CONFIG_SETTING_LIVERIES :Rādīt uzņēmuma identitātes krāsas: {STRING}
@ -1384,6 +1401,7 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Komanda+klikš
STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+klikšķis
STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Izslēgta
STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Aizvērt logu ar labo klikšķi: {STRING}
STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Labais klikšķis logā aizver logu. Izslēdz paskaidres parādīšanu ar labo klikšķi!
STR_CONFIG_SETTING_AUTOSAVE :Automātiskā saglabāšana: {STRING}
@ -1477,6 +1495,7 @@ STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_HELPTEXT :Cik daudz atmi
STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_VALUE :{COMMA} MiB
STR_CONFIG_SETTING_SERVINT_ISPERCENT :Apkopju starplaiki procentos: {STRING}
STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT :Izvēlieties, vai transportlīdzekļu apkopi veikt pēc fiksēta laika kopš iepriekšējās apkopes vai, kad uzticamība nokrīt zem kāda noteiktas daļas no maksimālās uzticamības
STR_CONFIG_SETTING_SERVINT_TRAINS :Vilcienu apkopju noklusējuma starplaiks: {STRING}
STR_CONFIG_SETTING_SERVINT_TRAINS_HELPTEXT :Izvēlēties jaunajiem sliežu transportlīdzekļiem apkopju noklusējuma starplaiku, ja tiem tas nav noteikts
STR_CONFIG_SETTING_SERVINT_VALUE :{COMMA}{NBSP}dien{P 0 a as u}/%
@ -1533,6 +1552,7 @@ STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :Krāsaini avī
STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :Gads kad sāk drukāt krāsainas avīzes. Pirms šā gada tās ir melnbaltas
STR_CONFIG_SETTING_STARTING_YEAR :Sākuma gads: {STRING}
STR_CONFIG_SETTING_ENDING_YEAR :Vērtēšanas beigu gads: {STRING}
STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :Spēles beigas gads (tiek izmantots rezultāta noteikšanai). Šī gada beigās uzņēmuma rezultāti tiek ierakstīti un uz ekrāna tiek parādīti labākie rezultāti, bet spēlētāji var turpināt spēlēt arī pēc šī datuma.{}Ja tas ir norādīts pirms spēles sākuma datuma, labākie rezultāti nekad netiek parādīti.
STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM}
STR_CONFIG_SETTING_ENDING_YEAR_ZERO :Nekad
STR_CONFIG_SETTING_SMOOTH_ECONOMY :Atļaut vienmērīgas izmaiņas ekonomikā: {STRING}
@ -1621,12 +1641,12 @@ STR_CONFIG_SETTING_TOWN_GROWTH_SLOW :mazs
STR_CONFIG_SETTING_TOWN_GROWTH_NORMAL :vidējs
STR_CONFIG_SETTING_TOWN_GROWTH_FAST :liels
STR_CONFIG_SETTING_TOWN_GROWTH_VERY_FAST :ļoti liels
STR_CONFIG_SETTING_LARGER_TOWNS :Pilsētu daļa kas kļūs par lielpilsētām: {STRING}
STR_CONFIG_SETTING_LARGER_TOWNS_HELPTEXT :Pilsētu daudzums kas kļūs par lielpilsētām, tādēļ tās sākumā ir lielākas un attīstās ātrāk
STR_CONFIG_SETTING_LARGER_TOWNS :Apdzīvotu vietu proporcija, kas kļūs par pilsētām: {STRING}
STR_CONFIG_SETTING_LARGER_TOWNS_HELPTEXT :Apdzīvotu vietu daudzums kas kļūs par pilsētām; tādēļ apdzīvota vieta, kas sākumā ir lielāka, augs straujāk
STR_CONFIG_SETTING_LARGER_TOWNS_VALUE :1 pret {COMMA}
STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED :neviena
STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :Lielpilsētu sākuma lieluma reizinātājs: {STRING}
STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :Lielpilsētu vidējais lielums attiecībā pret parastām pilsētām spēles sākumā
STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :Pilsētu sākuma lieluma reizinātājs: {STRING}
STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :Pilsētu vidējais lielums attiecībā pret parastām apdzīvotām vietām spēles sākumā
STR_CONFIG_SETTING_LINKGRAPH_INTERVAL :Atjaunināt sadales grafu ik pa {STRING}{NBSP}dien{P 0:2 ai ām ām}
STR_CONFIG_SETTING_LINKGRAPH_INTERVAL_HELPTEXT :Laiks starp secīgām saišu grafa pārrēķināšanām. Katra pārrēķināšana izskaitļo plānos vienai grafa komponentei. Tas nozīmē, ka šim iestatījumam vērtība X nenozīmē, ka viss grafs tiks atjaunināts ir pēc X dienām. Tikai dažas komponentes tiks pārrēķinātas. Jo mazāka iestatītā vērtība, jo vairāk laika CPU pavadīs rēķinot. Jo lielāka iestatītā vērtība, jo ilgāk nevarēs sākties kravu izplatīšana jaunos maršrutos.
@ -1644,10 +1664,12 @@ STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :APSARGĀJAMĀ k
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Izplatīšanas modelis citām kravu klasēm: {STRING}
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :"asimetriska" nozīmē, ka patvaļīgu kravas daudzumu var nosūtīt abos virzienos."manuāli" nozīmē, ka šīm kravām netiks veikta automātiska izplatīšana.
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Sadales precizitāte: {STRING}
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :Jo lielāku vērtību iestatīsiet, jo vairāk CPU laika aizies saišu grafa aprēķināšanai. Ja tas aizņem pārāk daudz laika, jūs varētu pamanīt spēles iebremzēšanos. Ja iestatīsiet pārāk mazu, izplatīšana būs neprecīza un jūs varētu pamanīt, ka krava tiek nosūtīta uz negaidītām vietām.
STR_CONFIG_SETTING_DEMAND_DISTANCE :Attāluma ietekme uz pieprasījumu: {STRING}
STR_CONFIG_SETTING_DEMAND_DISTANCE_HELPTEXT :Ja iestatīsiet šo vērtību lielāku kā 0, attālums starp kravas izcelsmes staciju A un iespējamo galastaciju B ietekmēs sūtāmās kravas apjomu. Jo tālāk no stacijas A ir stacija B, jo mazāk kravas tiks nosūtīts. Jo augstāka vērtība, jo mazāk kravas tiks nosūtīts uz tālo staciju un vairāk kravu uz tuvo staciju.
STR_CONFIG_SETTING_DEMAND_SIZE :Atpakaļceļa kravas daudzums simetriskajā režīmā: {STRING}
STR_CONFIG_SETTING_DEMAND_SIZE_HELPTEXT :Uzstādod šo mazāk par 100% liks simetriskajai sadalei izturēties vairāk kā asimetriskajai. Mazāk kravas ar varu tiks sūtīts atpakaļ ja noteikts daudzums tiks sūtīts uz piestātni. Ja jūs uzstādīsiet to uz 0% simetriskā sadale izturēsies tā pat kā asimetriskā.
STR_CONFIG_SETTING_SHORT_PATH_SATURATION :Īso ceļu piesātinājums pirms sākt izmantot augstas ietilpības ceļus: {STRING}
STR_CONFIG_SETTING_SHORT_PATH_SATURATION_HELPTEXT :Nereti starp divām stacijām ir vairāki ceļi. Kravu sadale vispirms piesātinās īsāko maršrutu, pēc tam izmantos nākamo īsāko maršrutu līdz tas būs piesātināts, un tā tālāk. Piesātinājumu nosaka novērtējot ietilpību un plānoto izmantojumu. Kad visi ceļi ir piesātināti un vēl ir palicis pieprasījumus, tas pārslogos visus ceļus, dodot priekšroku ceļiem ar lielāko ietilpību. Algoritms visbiežāk nepareizi novērtēs ietilpību. Šis iestatījums jums atļaus norādīt, līdz cik procentiem īsākais ceļš ir jāpiesātina pirmajā piegājienā pirms izvēlēties garāku ceļu. Iestatiet to uz mazāk kā 100%, lai izvairītos no pārpildītām stacijām, ja kapacitāte ir pārvērtēta.
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY :Ātruma mērvienības: {STRING}
@ -1803,8 +1825,8 @@ STR_OSNAME_SUNOS :SunOS
# Abandon game
STR_ABANDON_GAME_CAPTION :{WHITE}Pamest spēli
STR_ABANDON_GAME_QUERY :{YELLOW}Vai jūs tiešām vēlaties pamest šo spēli?
STR_ABANDON_SCENARIO_QUERY :{YELLOW}Vai esat pārliecināts, ka vēlaties pamest šo scenāriju?
STR_ABANDON_GAME_QUERY :{YELLOW}Vai tiešām vēlaties pamest šo spēli?
STR_ABANDON_SCENARIO_QUERY :{YELLOW}Vai tiešām vēlaties pamest šo scenāriju?
# Cheat window
STR_CHEATS :{WHITE}Blēdības
@ -2132,7 +2154,7 @@ STR_NETWORK_CHAT_ALL :[Visiem] {STRIN
STR_NETWORK_CHAT_OSKTITLE :{BLACK}Ievadīt tekstu tīkla tērzēšanai
# Network messages
STR_NETWORK_ERROR_NOTAVAILABLE :{WHITE}Neviena tīkla iekārta nav atrasta vai kompilēta bez ENABLE_NETWORK
STR_NETWORK_ERROR_NOTAVAILABLE :{WHITE}Nav atrasta neviena tīkla ierīce
STR_NETWORK_ERROR_NOSERVER :{WHITE}Nevar atrast nevienu tīkla spēli
STR_NETWORK_ERROR_NOCONNECTION :{WHITE}Serveris neatbild uz pieprasījumu
STR_NETWORK_ERROR_NEWGRF_MISMATCH :{WHITE}Nevar pieslēgties sakarā ar NewGRF neatbilstību
@ -2386,9 +2408,9 @@ STR_BUILD_SIGNAL_ELECTRIC_COMBO_TOOLTIP :{BLACK}Kombinē
STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP :{BLACK}Ceļa signāls (luksofors){}Ceļa signāls ļauj vairāk kā vienam vilcienam iebraukt signāla blokā vienlaicīgi, ja vien vilciens var rezervēt drošu apstāšanās punktu. Parastiem ceļa signāliem var pabraukt garām no aizmugures
STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP :{BLACK}Vienvirziena ceļa signālierīce (elektriska){}Ceļa signāls ļauj iebraukt signāla blokā vairāk kā vienam vilcienam vienlaicīgi, ja vien vilciens var rezervēt drošu apstāšanās punktu. Vienvirziena ceļa signālierīcēm nevar pabraukt garām no aizmugures
STR_BUILD_SIGNAL_CONVERT_TOOLTIP :{BLACK}Signālierīču pārveidotājs{}Kad ieslēgts, klikšķis uz jau esošas signālierīces pārveidos to uz norādīto signāla tipu un variantu. Ctrl+klikšķis pārslēgs pašreizējo variantu. Shift+klikšķis rāda pārveidošanas tāmes vērtību
STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP :{BLACK}Vilkt signālu biežumu
STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP :{BLACK}Vilkto signālu attālums
STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP :{BLACK}Samazināt signālierīču attālumu
STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP :{BLACK}Palielināt signālierīču biežumu
STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP :{BLACK}Palielināt signālierīču atstatumu
# Bridge selection window
STR_SELECT_RAIL_BRIDGE_CAPTION :{WHITE}Izvēlēties dzelzceļa tiltu
@ -2426,6 +2448,7 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL :{BLACK}Būvēt
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}Būvēt tramvaju tuneli. Shift pārslēdz būvēšanu/izmaksu tāmes rādīšanu
STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}Pārslēgties starp ceļa būvēšanas/nojaukšanas režīmiem
STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}Pārslēgt būvēt/novākt tramvaju būvei
STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}Pārveidot/uzlabot ceļa veidu. Shift pārslēdz būvēšanu/izmaksu novērtējumu rādīšanu
STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM :{BLACK}Pārveidot/uzlabot tramvaju veidu. Shift pārslēdz būvēšanu/izmaksu novērtējumu rādīšanu
STR_ROAD_NAME_ROAD :Ceļš
@ -2477,7 +2500,7 @@ STR_STATION_BUILD_AIRPORT_CLASS_LABEL :{BLACK}Lidostas
STR_STATION_BUILD_AIRPORT_LAYOUT_NAME :{BLACK}{NUM}. izkārtojums
STR_AIRPORT_SMALL :Maza
STR_AIRPORT_CITY :Lielpilsēta
STR_AIRPORT_CITY :Pilsēta
STR_AIRPORT_METRO :Metropolitēns
STR_AIRPORT_INTERNATIONAL :Starptautiskā lidosta
STR_AIRPORT_COMMUTER :Ikdienas satiksme
@ -2553,8 +2576,8 @@ STR_FOUND_TOWN_INITIAL_SIZE_MEDIUM_BUTTON :{BLACK}Vidējs
STR_FOUND_TOWN_INITIAL_SIZE_LARGE_BUTTON :{BLACK}Liels
STR_FOUND_TOWN_SIZE_RANDOM :{BLACK}Nejaušs
STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP :{BLACK}Izvēlēties pilsētas izmērus
STR_FOUND_TOWN_CITY :{BLACK}Lielpilsēta
STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Lielpilsētas attīstās ātrāk kā pilsētas{}Atkarībā no iestatījumiem, dibināšanas brīdī tās ir lielākas
STR_FOUND_TOWN_CITY :{BLACK}Pilsēta
STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Pilsētas aug straujāk kā parastas apdzīvotās vietas{}Atkarībā no iestatījumiem, dibināšanas brīdī pilsētas ir lielākas
STR_FOUND_TOWN_ROAD_LAYOUT :{YELLOW}Pilsētas ceļu izskats:
STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT :{BLACK}Atlasīt šajā pilsētā lietojamo ceļu izkārtojumu
@ -2616,6 +2639,7 @@ STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED :{BLACK}Pieņem
STR_LAND_AREA_INFORMATION_CARGO_EIGHTS :({COMMA}/8 {STRING})
STR_LANG_AREA_INFORMATION_RAIL_TYPE :{BLACK}Sliežu veids: {LTBLUE}{STRING}
STR_LANG_AREA_INFORMATION_ROAD_TYPE :{BLACK}Ceļu tips: {LTBLUE}{STRING}
STR_LANG_AREA_INFORMATION_TRAM_TYPE :{BLACK}Tramvaja veids: {LTBLUE}{STRING}
STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT :{BLACK}Sliežu ātruma ierobežojums: {LTBLUE}{VELOCITY}
STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT :{BLACK}Ceļa ātruma ierobežojums: {LTBLUE}{VELOCITY}
STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT :{BLACK}Tramvaja ātruma ierobežojums: {LTBLUE}{VELOCITY}
@ -2629,29 +2653,29 @@ STR_LAI_CLEAR_DESCRIPTION_FIELDS :Lauki
STR_LAI_CLEAR_DESCRIPTION_SNOW_COVERED_LAND :Apsnigusi zeme
STR_LAI_CLEAR_DESCRIPTION_DESERT :Tuksnesis
STR_LAI_RAIL_DESCRIPTION_TRACK :Dzelzceļš sliedes
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SIGNALS :Dzelzceļš ceļš ar bloķēšanas signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRESIGNALS :Dzelzceļš sliedes ar pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXITSIGNALS :Dzelzceļš sliedes ar izejas signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBOSIGNALS :Dzelzceļš sliedes ar kombinētajām signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBSSIGNALS :Dzelzceļš sliedes ar ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRYSIGNALS :Dzelzceļš sliedes ar vienvirziena ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PRESIGNALS :Dzelzceļš sliedes ar bloka un pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_EXITSIGNALS :Dzelzceļš sliedes ar bloka un izejas signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_COMBOSIGNALS :Dzelzceļš sliedes ar bloka un kombinētajām signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PBSSIGNALS :Dzelzceļš sliedes ar bloka un ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_NOENTRYSIGNALS :Dzelzceļš sliedes ar bloka un vienvirziena ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_EXITSIGNALS :Dzelzceļš sliedes ar izejas un pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_COMBOSIGNALS :Dzelzceļš sliedes ar kombinētajām un pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PBSSIGNALS :Dzelzceļš sliedes ar ceļu un pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_NOENTRYSIGNALS :Dzelzceļš sliedes ar vienvirziena ceļu un pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_COMBOSIGNALS :Dzelzceļš sliedes ar izejas un kombinētajām signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PBSSIGNALS :Dzelzceļš sliedes ar izejas un ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS :Dzelzceļš sliedes ar izejas un vienvirziena ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PBSSIGNALS :Dzelzceļš sliedes ar kombinētajām un ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS :Dzelzceļš sliedes ar kombinētajām un vienvirziena ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS :Dzelzceļš sliedes ar ceļa un vienvirziena ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT :Dzelzceļš vilcienu depo
STR_LAI_RAIL_DESCRIPTION_TRACK :Dzelzceļa sliedes
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SIGNALS :Dzelzceļa sliedes ar bloku signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRESIGNALS :Dzelzceļa sliedes ar pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXITSIGNALS :Dzelzceļa sliedes ar izejas signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBOSIGNALS :Dzelzceļa sliedes ar kombinētajām signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBSSIGNALS :Dzelzceļa sliedes ar ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRYSIGNALS :Dzelzceļa sliedes ar vienvirziena ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PRESIGNALS :Dzelzceļa sliedes ar bloku un pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_EXITSIGNALS :Dzelzceļa sliedes ar bloku un izejas signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_COMBOSIGNALS :Dzelzceļa sliedes ar bloku un kombinētajām signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PBSSIGNALS :Dzelzceļa sliedes ar bloku un ceļu signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_NOENTRYSIGNALS :Dzelzceļa sliedes ar bloka un vienvirziena ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_EXITSIGNALS :Dzelzceļa sliedes ar izejas un pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_COMBOSIGNALS :Dzelzceļa sliedes ar kombinētajām un pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PBSSIGNALS :Dzelzceļa sliedes ar ceļu un pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_NOENTRYSIGNALS :Dzelzceļa sliedes ar vienvirziena un pirmssignālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_COMBOSIGNALS :Dzelzceļa sliedes ar izejas un kombinētajām signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PBSSIGNALS :Dzelzceļa sliedes ar izejas un ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS :Dzelzceļa sliedes ar izejas un vienvirziena ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PBSSIGNALS :Dzelzceļa sliedes ar kombinētajām un ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS :Dzelzceļa sliedes ar kombinētajām un vienvirziena ceļa signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS :Dzelzceļa sliedes ar ceļu un vienvirziena ceļu signālierīcēm
STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT :Dzelzceļa vilcienu depo
STR_LAI_ROAD_DESCRIPTION_ROAD :Ceļš
STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS :Ceļš ar ielu apgaismojumu
@ -2723,7 +2747,8 @@ STR_FRAMERATE_CAPTION_SMALL :{STRING}{WHITE}
STR_FRAMERATE_RATE_GAMELOOP :{BLACK}Simulācijas ātrums: {STRING}
STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}Spēles tikšķu skaits, ko simulēt vienā sekundē.
STR_FRAMERATE_RATE_BLITTER :{BLACK}Grafikas kadru ātrums: {STRING}
STR_FRAMERATE_SPEED_FACTOR :{WHITE}pašreizējās spēles ātruma pakāpe: {DECIMAL}x
STR_FRAMERATE_RATE_BLITTER_TOOLTIP :{BLACK}Sekundē renderēto video kadru skaits.
STR_FRAMERATE_SPEED_FACTOR :{BLACK}Pašreizējās spēles ātruma pakāpe: {DECIMAL}×
STR_FRAMERATE_SPEED_FACTOR_TOOLTIP :{BLACK}Cik ātri spēle šobrīd iet salīdzinot ar standarta ātrumu.
STR_FRAMERATE_CURRENT :{WHITE}Pašreizējais
STR_FRAMERATE_AVERAGE :{WHITE}Vidējais
@ -2749,6 +2774,7 @@ STR_FRAMERATE_GL_SHIPS :{BLACK} Kuģu
STR_FRAMERATE_GL_AIRCRAFT :{BLACK} Lidaparātu tikšķi:
STR_FRAMERATE_GL_LANDSCAPE :{BLACK} Pasaules tikšķi:
STR_FRAMERATE_GL_LINKGRAPH :{BLACK} Saišu grafika aizture:
STR_FRAMERATE_DRAWING :{BLACK}Grafikas renderēšana:
STR_FRAMERATE_DRAWING_VIEWPORTS :{BLACK} Pasaules skatvietas:
STR_FRAMERATE_VIDEO :{BLACK}Video izvade:
STR_FRAMERATE_SOUND :{BLACK}Skaņas miksēšana:
@ -2761,6 +2787,7 @@ STR_FRAMETIME_CAPTION_GAMELOOP :Spēles cikls
STR_FRAMETIME_CAPTION_GL_ECONOMY : Kravu iekraušana un izkraušana
STR_FRAMETIME_CAPTION_GL_TRAINS :Vilcienu tikšķi
STR_FRAMETIME_CAPTION_GL_ROADVEHS :Autotransporta tikšķi
STR_FRAMETIME_CAPTION_GL_SHIPS :Kuģu tikšķi
STR_FRAMETIME_CAPTION_GL_AIRCRAFT :Lidaparātu tikšķi
STR_FRAMETIME_CAPTION_GL_LANDSCAPE :Pasaules tikšķi
STR_FRAMETIME_CAPTION_GL_LINKGRAPH :Saišu grafa aizture
@ -2918,6 +2945,8 @@ STR_NEWGRF_SETTINGS_MD5SUM :{BLACK}MD5sum:
STR_NEWGRF_SETTINGS_PALETTE :{BLACK}Palete: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_PALETTE_DEFAULT :Noklusējuma (D)
STR_NEWGRF_SETTINGS_PALETTE_DEFAULT_32BPP :Noklusējuma (D) / 32 bpp
STR_NEWGRF_SETTINGS_PALETTE_LEGACY :Mantotais (W)
STR_NEWGRF_SETTINGS_PALETTE_LEGACY_32BPP :Mantotais (W) / 32 bpp
STR_NEWGRF_SETTINGS_PARAMETER :{BLACK}Parametri: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_PARAMETER_NONE :Nav
@ -2965,9 +2994,11 @@ STR_SPRITE_ALIGNER_GOTO_TOOLTIP :{BLACK}Iet pie
STR_SPRITE_ALIGNER_PREVIOUS_BUTTON :{BLACK}Iepriekšējais gariņš
STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP :{BLACK}Iet pie iepriekšējā parastā gariņa, izlaižot visus pseido/pārkrāsotos/fonta gariņus
STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Atlasītā gariņa attēlojums. To attēlojot, izkārtojums netiek ievērots
STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Pārvietot gariņu, lai mainītu X un Y vērtības
STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Pārvietot gariņu, lai mainītu X un Y vērtības. Ctrl+klikšķis, lai vienā piegājienā pārvietotu gariņu par astoņām vienībām
STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Atiestatīt relatīvi
STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Pāriestatīt paršreizējo relatīvo nobīdi
STR_SPRITE_ALIGNER_OFFSETS_ABS :{BLACK}X nobīde: {NUM}, Y nobīde: {NUM} (absolūta)
STR_SPRITE_ALIGNER_OFFSETS_REL :{BLACK}X nobīde: {NUM}, Y nobīde: {NUM} (relatīvi)
STR_SPRITE_ALIGNER_PICKER_BUTTON :{BLACK}Paņemt gariņu
STR_SPRITE_ALIGNER_PICKER_TOOLTIP :{BLACK}Paņemt gariņu no jebkuras vietas ekrānā
@ -3033,6 +3064,7 @@ STR_NEWGRF_BUGGY :{WHITE}NewGRF '
STR_NEWGRF_BUGGY_ARTICULATED_CARGO :{WHITE}'{1:ENGINE}' kravas pielāgošanas informācija pēc izbūves atšķiras no pārdošanas sarakstā norādītās. Tas var liegt automātiskai atjaunošanai/aizvietošanai pareizi pielāgot kravas
STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK :{WHITE}'{1:STRING}' izraisīja bezgalīgu ražošanas izsaukumu ciklu
STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT :{WHITE}Izsaukums {1:HEX} atgrieza nezināmu vai nederīgu rezultātu {2:HEX}
STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK :{WHITE}“{1:STRING}” atgrieza nederīgu kravas veidu ražošanas atgriezeniskajā funkcijā punktā {2:HEX}
# 'User removed essential NewGRFs'-placeholders for stuff without specs
STR_NEWGRF_INVALID_CARGO :<nederīga krava>
@ -3073,7 +3105,7 @@ STR_TOWN_POPULATION :{BLACK}Pasaules
# Town view window
STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN}
STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (lielpilsēta)
STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (pilsēta)
STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Iedzīvotāji: {ORANGE}{COMMA}{BLACK} Mājas: {ORANGE}{COMMA}
STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} iepriekšējā mēnesī: {ORANGE}{COMMA}{BLACK} maks.: {ORANGE}{COMMA}
STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Krava nepieciešama pilsētas attīstībai:
@ -3101,6 +3133,7 @@ STR_TOWN_VIEW_RENAME_TOWN_BUTTON :Pārdēvēt pil
# Town local authority window
STR_LOCAL_AUTHORITY_CAPTION :{WHITE}{TOWN} pašvaldība
STR_LOCAL_AUTHORITY_ZONE :{BLACK}Zona
STR_LOCAL_AUTHORITY_ZONE_TOOLTIP :{BLACK}Rādīt zonu pašvaldības robežās
STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}Transporta uzņēmumu vērtējumi:
STR_LOCAL_AUTHORITY_COMPANY_RATING :{YELLOW}{COMPANY} {COMPANY_NUM}: {ORANGE}{STRING}
STR_LOCAL_AUTHORITY_ACTIONS_TITLE :{BLACK}Pieejamās darbības:
@ -3180,6 +3213,7 @@ STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klikšķ
# Story book window
STR_STORY_BOOK_CAPTION :{WHITE}{COMPANY} Stāstu grāmata
STR_STORY_BOOK_SPECTATOR_CAPTION :{WHITE}Globālā stāstu grāmata
STR_STORY_BOOK_SPECTATOR :Globālā stāstu grāmata
STR_STORY_BOOK_TITLE :{YELLOW}{STRING}
STR_STORY_BOOK_GENERIC_PAGE_ITEM :{NUM} lapa
STR_STORY_BOOK_SEL_PAGE_TOOLTIP :{BLACK}Pārlēkt uz specifisku lapu spiežot to zemāk esošajā sarakstā.
@ -3373,6 +3407,7 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENC
STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}Ražotnes
STR_INDUSTRY_DIRECTORY_NONE :{G=m}{ORANGE}- Neviens -
STR_INDUSTRY_DIRECTORY_NONE.kas :{ORANGE}- Neviena -
STR_INDUSTRY_DIRECTORY_ITEM_INFO :{BLACK}{CARGO_LONG}{STRING}{YELLOW} (pārvadāti {COMMA}%){BLACK}
STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY}
STR_INDUSTRY_DIRECTORY_ITEM_PROD1 :{ORANGE}{INDUSTRY} {STRING}
STR_INDUSTRY_DIRECTORY_ITEM_PROD2 :{ORANGE}{INDUSTRY} {STRING}, {STRING}
@ -3387,7 +3422,7 @@ STR_INDUSTRY_DIRECTORY_FILTER_NONE :Nav
# Industry view
STR_INDUSTRY_VIEW_CAPTION :{WHITE}{INDUSTRY}
STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE :{BLACK}Iepriekšējā mēnesī saražots:
STR_INDUSTRY_VIEW_TRANSPORTED :{YELLOW}{CARGO_LONG}{STRING}{BLACK} (aizvests {COMMA}%)
STR_INDUSTRY_VIEW_TRANSPORTED :{YELLOW}{CARGO_LONG}{STRING}{BLACK} (pārvadāti {COMMA}%)
STR_INDUSTRY_VIEW_LOCATION_TOOLTIP :{BLACK}Centrēt galveno skatu uz ražotni. Ctrl+klikšķis atvērs skatu uz ražotni jaunā skatlaukā
STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Ražošanas līmenis: {YELLOW}{COMMA}%
STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}Nozare ir paziņojusi par nenovēršamu slēgšanu!
@ -3396,6 +3431,7 @@ STR_INDUSTRY_VIEW_REQUIRES_N_CARGO :{BLACK}Pieprasa
STR_INDUSTRY_VIEW_PRODUCES_N_CARGO :{BLACK}Ražo: {YELLOW}{STRING}{STRING}
STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :, {STRING}{STRING}
STR_INDUSTRY_VIEW_REQUIRES :{BLACK}Pieprasa:
STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{STRING}{BLACK}{3:STRING}
STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW}{STRING}{BLACK}: {CARGO_SHORT} gaida{STRING}
@ -3466,6 +3502,7 @@ STR_GROUP_RENAME_CAPTION :{BLACK}Pārdēv
STR_GROUP_PROFIT_THIS_YEAR :Ienākumi šajā gadā:
STR_GROUP_PROFIT_LAST_YEAR :Peļņa pērn:
STR_GROUP_OCCUPANCY :Pašreizējais lietojums:
STR_GROUP_OCCUPANCY_VALUE :{NUM}%
# Build vehicle window
@ -3485,6 +3522,7 @@ STR_BUY_VEHICLE_AIRCRAFT_CAPTION :Jauns lidaparā
############ range for vehicle availability ends
STR_PURCHASE_INFO_COST_WEIGHT :{BLACK}Cena: {GOLD}{CURRENCY_LONG}{BLACK} Svars: {GOLD}{WEIGHT_SHORT}
STR_PURCHASE_INFO_COST_REFIT_WEIGHT :{BLACK}Cena: {GOLD}{CURRENCY_LONG}{BLACK} (Pielāgošanas izmaksas: {GOLD}{CURRENCY_LONG}{BLACK}) Svars: {GOLD}{WEIGHT_SHORT}
STR_PURCHASE_INFO_SPEED_POWER :{BLACK}Ātrums: {GOLD}{VELOCITY}{BLACK} Jauda: {GOLD}{POWER}
STR_PURCHASE_INFO_SPEED :{BLACK}Ātrums: {GOLD}{VELOCITY}
STR_PURCHASE_INFO_SPEED_OCEAN :{BLACK}Ātrums okeānā: {GOLD}{VELOCITY}
@ -3657,6 +3695,7 @@ STR_ENGINE_PREVIEW_SHIP :kuģis
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}Cena: {CURRENCY_LONG} Svars: {WEIGHT_SHORT}{}Ātrums: {VELOCITY} Jauda: {POWER}{}Kārtējās izmaksas: {CURRENCY_LONG} gadā{}Ietilpība: {CARGO_LONG}
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Cena: {CURRENCY_LONG} Svars: {WEIGHT_SHORT}{}Ātrums: {VELOCITY} Jauda: {POWER} Maks. spēks: {6:FORCE}{}Kārtējās izmaksas: {4:CURRENCY_LONG} gadā{}Ietilpība: {5:CARGO_LONG}
STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}Cena: {CURRENCY_LONG} Maks. ātrums: {VELOCITY}{}Ietilpība: {CARGO_LONG}{}Kārtējās izmaksas: {CURRENCY_LONG} gadā
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST :{BLACK}Cena: {CURRENCY_LONG} Maks. ātrums: {VELOCITY}{}Lidaparāta veids: {STRING}{}Ietilpība: {CARGO_LONG}, {CARGO_LONG}{}Izmaksas: {CURRENCY_LONG} gadā
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST :{BLACK}Cena: {CURRENCY_LONG} Maks. ātrums: {VELOCITY}{}Lidaparāta veids: {STRING}{}Ietilpība: {CARGO_LONG}{}Izmaksas: {CURRENCY_LONG}/gadā
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}Cena: {CURRENCY_LONG} Maks. ātrums: {VELOCITY}{}Lidaparāta veids: {STRING} Attālums: {COMMA} lauciņi{}Ietilpība: {CARGO_LONG}, {CARGO_LONG}{}Izmaksas: {CURRENCY_LONG}/gadā
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST :{BLACK}Cena: {CURRENCY_LONG} Maks. ātrums: {VELOCITY}{}Lidaparāta veids: {STRING} Attālums: {COMMA} lauciņi{}Ietilpība: {CARGO_LONG}{}Izmaksas: {CURRENCY_LONG}/gadā
@ -3669,7 +3708,9 @@ STR_REPLACE_VEHICLE_SHIP :Kuģis
STR_REPLACE_VEHICLE_AIRCRAFT :Lidaparāts
STR_REPLACE_VEHICLE_VEHICLES_IN_USE :{YELLOW}Lietošanā esošie transportlīdzekļi
STR_REPLACE_VEHICLE_VEHICLES_IN_USE_TOOLTIP :{BLACK}Kolonna ar jums piederošajiem transportlīdzekļiem
STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES :{YELLOW}Pieejamie transportlīdzekļi
STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES_TOOLTIP :{BLACK}Kolonna ar transportlīdzekļiem, kurus var aizvietot
STR_REPLACE_HELP_LEFT_ARRAY :{BLACK}Izvēlēties lokomotīves veidu, kuru vēlaties mainīt
STR_REPLACE_HELP_RIGHT_ARRAY :{BLACK}Izvēlēties jaunu lokomotīves veidu, kuru vēlaties lietot kreisajā pusē atlasītās lokomotīves vietā
@ -3691,6 +3732,7 @@ STR_REPLACE_ALL_RAILTYPE :Visi dzelzceļa
STR_REPLACE_ALL_ROADTYPE :Visi ceļu transportlīdzekļi
STR_REPLACE_HELP_RAILTYPE :{BLACK}Izvēlēties sliežu veidu, kuram vēlaties nomainīt lokomotīves
STR_REPLACE_HELP_ROADTYPE :{BLACK}Izvēlēties ceļu veidu, kuram vēlaties nomainīt dzinējus
STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}Parāda kura lokomotīve no kreisajā pusē atlasītajām tiek nomainīta, ja vien kāda ir
STR_REPLACE_RAIL_VEHICLES :Sliežu transportlīdzekļi
STR_REPLACE_ELRAIL_VEHICLES :Elektrificētā dzelzceļa transportlīdzekļi
@ -3784,6 +3826,8 @@ STR_VEHICLE_INFO_AGE :{COMMA} gad{P s
STR_VEHICLE_INFO_AGE_RED :{RED}{COMMA} gad{P s i u} ({COMMA})
STR_VEHICLE_INFO_MAX_SPEED :{BLACK}Maks. ātrums: {LTBLUE}{VELOCITY}
STR_VEHICLE_INFO_MAX_SPEED_TYPE :{BLACK}Maks. ātrums: {LTBLUE}{VELOCITY} {BLACK}Lidaparāta veids: {LTBLUE}{STRING}
STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE :{BLACK}Maks. ātrums: {LTBLUE}{VELOCITY} {BLACK}Lidaparāta veids: {LTBLUE}{STRING} {BLACK}Attālums: {LTBLUE}{COMMA} lauciņi
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Svars: {LTBLUE}{WEIGHT_SHORT} {BLACK}Jauda: {LTBLUE}{POWER}{BLACK} Maks. ātrums: {LTBLUE}{VELOCITY}
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Svars: {LTBLUE}{WEIGHT_SHORT} {BLACK}Jauda: {LTBLUE}{POWER}{BLACK} Maks. ātrums: {LTBLUE}{VELOCITY} {BLACK}Maks. spēks: {LTBLUE}{FORCE}
@ -4197,6 +4241,7 @@ STR_FEEDER :{YELLOW}Pārska
STR_FEEDER_INCOME_TINY :{TINY_FONT}{YELLOW}Pārkraušana: {CURRENCY_LONG}{WHITE} / {GREEN}Ienākumi: {CURRENCY_LONG}
STR_FEEDER_INCOME :{YELLOW}Pārkraušana: {CURRENCY_LONG}{WHITE} / {GREEN}Ienākumi: {CURRENCY_LONG}
STR_FEEDER_COST_TINY :{TINY_FONT}{YELLOW}Pārkraušana: {CURRENCY_LONG}{WHITE} / {RED}Izmaksas: {CURRENCY_LONG}
STR_FEEDER_COST :{YELLOW}Pārkraušana: {CURRENCY_LONG}{WHITE} / {RED}Izmaksas: {CURRENCY_LONG}
STR_MESSAGE_ESTIMATED_COST :{WHITE}Plānotās izmaksas: {CURRENCY_LONG}
STR_MESSAGE_ESTIMATED_INCOME :{WHITE}Plānotie ienākumi: {CURRENCY_LONG}
@ -4448,6 +4493,7 @@ STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}Šeit ne
STR_ERROR_THERE_IS_NO_ROAD :{WHITE}... tur nav ceļa
STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}... tur nav tramvaju sliežu ceļa
STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}Šeit nevar mainīt ceļa veidu...
STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}Šeit nevar pārveidot tramvaja veidu...
STR_ERROR_NO_SUITABLE_ROAD :{WHITE}Nav piemērota ceļa
STR_ERROR_NO_SUITABLE_TRAMWAY :{WHITE}Nav piemērotu tramvaju
STR_ERROR_INCOMPATIBLE_ROAD :{WHITE}... nesavietojams ceļš
@ -4504,6 +4550,7 @@ STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}Nevar iz
STR_ERROR_GROUP_CAN_T_DELETE :{WHITE}Nevar izdzēst šo grupu...
STR_ERROR_GROUP_CAN_T_RENAME :{WHITE}Nevar pārdēvēt grupu...
STR_ERROR_GROUP_CAN_T_SET_PARENT :nevar iestatīt vecāku grupu...
STR_ERROR_GROUP_CAN_T_SET_PARENT_RECURSION :{WHITE}... grupu hierarhijās cikli nav atļauti
STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES :{WHITE}Nevar noņemt no šīs grupas visus transportlīdzekļus...
STR_ERROR_GROUP_CAN_T_ADD_VEHICLE :{WHITE}Nevar pievienot transportlīdzekļus šai grupai...
STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE :{WHITE}Nevar pievienot koplietojamos transportlīdzekļus šai grupai...

@ -1063,7 +1063,7 @@ STR_GAME_OPTIONS_CURRENCY_NLG :Нидерла
STR_GAME_OPTIONS_CURRENCY_NOK :Норвежская крона (NOK)
STR_GAME_OPTIONS_CURRENCY_PLN :Польский злотый (PLN)
STR_GAME_OPTIONS_CURRENCY_RON :Румынский лей (RON)
STR_GAME_OPTIONS_CURRENCY_RUR :Российский рубль (RUR)
STR_GAME_OPTIONS_CURRENCY_RUR :Российский рубль (старый) (RUR)
STR_GAME_OPTIONS_CURRENCY_SIT :Словенский толар (SIT)
STR_GAME_OPTIONS_CURRENCY_SEK :Шведская крона (SEK)
STR_GAME_OPTIONS_CURRENCY_TRY :Турецкая лира (TRY)
@ -1076,11 +1076,12 @@ STR_GAME_OPTIONS_CURRENCY_ZAR :Южноафр
STR_GAME_OPTIONS_CURRENCY_CUSTOM :Своя...
STR_GAME_OPTIONS_CURRENCY_GEL :Грузинский лари (GEL)
STR_GAME_OPTIONS_CURRENCY_IRR :Иранский риал (IRR)
STR_GAME_OPTIONS_CURRENCY_RUB :Российский новый рубль (RUR)
STR_GAME_OPTIONS_CURRENCY_RUB :Российский рубль (RUR)
STR_GAME_OPTIONS_CURRENCY_MXN :Мексиканский песо (MXN)
STR_GAME_OPTIONS_CURRENCY_NTD :Новый тайваньский доллар (NTD)
STR_GAME_OPTIONS_CURRENCY_CNY :Китайский юань (CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :Гонконгский доллар (HKD)
STR_GAME_OPTIONS_CURRENCY_INR :Индийская рупия (INR)
############ end of currency region
STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME :{BLACK}Движение автомобилей

@ -225,9 +225,9 @@ STR_UNITS_HEIGHT_METRIC :{COMMA}{NBSP}m
STR_UNITS_HEIGHT_SI :{COMMA}{NBSP}m
# Common window strings
STR_LIST_FILTER_TITLE :{BLACK}Filtrar palabras:
STR_LIST_FILTER_OSKTITLE :{BLACK}Indicar una palabra a filtrar
STR_LIST_FILTER_TOOLTIP :{BLACK}Indicar una palabra clave para filtrar la lista
STR_LIST_FILTER_TITLE :{BLACK}Filtrar texto:
STR_LIST_FILTER_OSKTITLE :{BLACK}Indicar texto a filtrar
STR_LIST_FILTER_TOOLTIP :{BLACK}Indicar un texto clave para filtrar la lista
STR_TOOLTIP_GROUP_ORDER :{BLACK}Elegir orden de grupo
STR_TOOLTIP_SORT_ORDER :{BLACK}Elegir orden descendiente o ascendiente
@ -1109,7 +1109,7 @@ STR_WARNING_NO_SUITABLE_AI :{WHITE}No se en
# Settings tree window
STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Configuración
STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filtrar palabras:
STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filtrar texto:
STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Desplegar todo
STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Plegar todo
STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(sin explicación disponible)
@ -1163,7 +1163,7 @@ STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_HELPTEXT :Máxima cantida
STR_CONFIG_SETTING_INTEREST_RATE :Porcentaje de interés: {STRING}
STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :Porcentaje de interés de los préstamos; controla también la inflación, en caso de estar activada
STR_CONFIG_SETTING_RUNNING_COSTS :Costos de operación: {STRING}
STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Nivel de los costos de mantenimiento y operación de vehículos e infraestructura
STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Nivel de costos de mantenimiento y operación de vehículos e infraestructura
STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Velocidad de construcción: {STRING}
STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Restringir la velocidad de las acciones de construcción de jugadores no humanos
STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Averías de vehículos: {STRING}
@ -1173,9 +1173,9 @@ STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Establecer cuá
STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Costos de construcción: {STRING}
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Nivel de costos de construcción y adquisición
STR_CONFIG_SETTING_RECESSIONS :Recesiones: {STRING}
STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :Si se activa, habrá recesiones cada cierto año. Durante una recesión, toda la producción decaerá considerablemente (se restablecerá al final de la recesión)
STR_CONFIG_SETTING_TRAIN_REVERSING :Prohibir a los trenes que cambien de dirección en las estaciones: {STRING}
STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT :Si se activa, los trenes no podrán girar al lado opuesto en estaciones intermedias, ni siquiera si al girar hay una ruta más corta a su próximo destino
STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :Al activarse, habrá recesiones cada cierto año en las que toda la producción decaerá considerablemente, restableciéndose al final de cada recesión
STR_CONFIG_SETTING_TRAIN_REVERSING :Prohibir a los trenes que den reversa en estaciones: {STRING}
STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT :Al activarse, los trenes no podrán dar reversa en estaciones intermedias, aun si detrás hay una ruta más corta a su próximo destino
STR_CONFIG_SETTING_DISASTERS :Desastres: {STRING}
STR_CONFIG_SETTING_DISASTERS_HELPTEXT :Desastres que ocasionalmente pueden bloquear o destruir vehículos o infraestructura
STR_CONFIG_SETTING_CITY_APPROVAL :Actitud de los ayuntamientos ante restructuraciones hechas en sus zonas: {STRING}
@ -1189,7 +1189,7 @@ STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Modificar el te
STR_CONFIG_SETTING_CATCHMENT :Permitir cambiar el tamaño del área de recolección a una forma más real: {STRING}
STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :Las áreas de recolección se adecúan a diferentes tamaños, según los tipos de estaciones y aeropuertos
STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES :Las estaciones privadas pueden dar servicio a industrias con estaciones neutrales: {STRING}
STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT :Si se activa, las industrias con estaciones integradas (ej. plataformas petrolíferas) podrán aceptar cargamento de estaciones privadas construidas cerca. Si se desactiva, tales industrias solo recibirán cargamento en sus propias estaciones. No aceptarán cargamento de estaciones de compañías, y la estación integrada no brindará servicio a nada más que su industria
STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT :Al activarse, las industrias con estaciones integradas (ej. plataformas petrolíferas) podrán aceptar carga de estaciones aledañas. Al desactivarse, tales industrias solo recibirán carga en sus propias estaciones y no aceptarán de otras estaciones, ni la estación integrada brindará servicio a nada más que su industria
STR_CONFIG_SETTING_EXTRADYNAMITE :Permitir quitar mayor cantidad de carreteras, puentes y túneles de los pueblos: {STRING}
STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :Hacer más fácil eliminar infraestructura y edificios que sean propiedad de los pueblos
STR_CONFIG_SETTING_TRAIN_LENGTH :Longitud máxima de trenes: {STRING}
@ -1242,7 +1242,7 @@ STR_CONFIG_SETTING_STOP_LOCATION_NEAR_END :principio
STR_CONFIG_SETTING_STOP_LOCATION_MIDDLE :centro
STR_CONFIG_SETTING_STOP_LOCATION_FAR_END :fondo
STR_CONFIG_SETTING_AUTOSCROLL :Recorrer vista cuando se mueva el cursor a los bordes: {STRING}
STR_CONFIG_SETTING_AUTOSCROLL_HELPTEXT :Si se activa esta opción, las vistas se recorrerán cuando el ratón esté cerca de los bordes de la ventana
STR_CONFIG_SETTING_AUTOSCROLL_HELPTEXT :Al activarse, las vistas se desplazarán cuando el ratón se acarque a los bordes de la ventana
STR_CONFIG_SETTING_AUTOSCROLL_DISABLED :Desactivado
STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT_FULLSCREEN :Vista principal, solo en pantalla completa
STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT :Vista principal
@ -1273,7 +1273,7 @@ STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD :Permitir la con
STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD_HELPTEXT :Construir paradas de autobuses intermedias en carreteras que sean propiedad de otras empresas
STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}No se puede cambiar esta opción si ya existen vehículos
STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE :Mantenimiento de infraestructura: {STRING}
STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT :Cuando se activa, la infraestructura tiene costo de mantenimiento, el cual aumenta en relación con el tamaño de la red de transporte. Esto afecta en mayor medida a las empresas grandes que a las pequeñas
STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT :Al activarse, la infraestructura tiene costo de mantenimiento que aumenta según el tamaño de la red de transporte, de modo que las empresas grandes se afectan más que las pequeñas
STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR :Color inicial de la empresa: {STRING}
STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR_HELPTEXT :Elegir el color inicial de la empresa
@ -1284,7 +1284,7 @@ STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS_HELPTEXT :Los tipos de ae
STR_CONFIG_SETTING_WARN_LOST_VEHICLE :Avisar si un vehículo se ha perdido: {STRING}
STR_CONFIG_SETTING_WARN_LOST_VEHICLE_HELPTEXT :Mostrar mensajes indicando aquellos vehículos que no puedan encontrar una ruta a su destino
STR_CONFIG_SETTING_ORDER_REVIEW :Analizar órdenes de vehículos: {STRING}
STR_CONFIG_SETTING_ORDER_REVIEW_HELPTEXT :Cuando se activa, las órdenes de los vehículos se analizan regularmente y los problemas que se encuentren se informan en una noticia
STR_CONFIG_SETTING_ORDER_REVIEW_HELPTEXT :Al activarse, se analizan regularmente las órdenes de los vehículos y los problemas obvios que se detecten se informan en una noticia
STR_CONFIG_SETTING_ORDER_REVIEW_OFF :No
STR_CONFIG_SETTING_ORDER_REVIEW_EXDEPOT :Sí, excepto los vehículos detenidos
STR_CONFIG_SETTING_ORDER_REVIEW_ON :Todos los vehículos
@ -1294,8 +1294,8 @@ STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES :Vehículos siem
STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT :Todos los modelos de vehículos estarán disponibles para siempre tras haber sido introducidos
STR_CONFIG_SETTING_AUTORENEW_VEHICLE :Renovar automáticamente vehículos que se hagan viejos: {STRING}
STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT :Los vehículos próximos al final de su vida útil serán renovados automáticamente, siempre y cuando se cumplan las condiciones de renovación
STR_CONFIG_SETTING_AUTORENEW_MONTHS :Renovar automáticamente el vehículo a {STRING} de su edad máxima
STR_CONFIG_SETTING_AUTORENEW_MONTHS_HELPTEXT :Edad relativa en la que un vehículo es considerado para renovarse
STR_CONFIG_SETTING_AUTORENEW_MONTHS :Renovar automáticamente el vehículo cumpla {STRING}
STR_CONFIG_SETTING_AUTORENEW_MONTHS_HELPTEXT :Edad relativa en que un vehículo se considera para renovación
STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_BEFORE :{COMMA} mes{P 0 "" es} antes
STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_AFTER :{COMMA} mes{P 0 "" es} después
STR_CONFIG_SETTING_AUTORENEW_MONEY :Costo mínimo requerido para renovación automática: {STRING}
@ -1370,7 +1370,7 @@ STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :Recorrer mapa c
STR_CONFIG_SETTING_SCROLLMODE_RMB :Recorrer mapa con clic derecho
STR_CONFIG_SETTING_SCROLLMODE_LMB :Recorrer mapa con clic izquierdo
STR_CONFIG_SETTING_SMOOTH_SCROLLING :Desplazamiento de vista suavizado: {STRING}
STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Forma en la que la vista principal se mueve a una ubicación específica al hacer clic en el minimapa o tras una orden de moverse a un objeto determinado del mapa. Si se activa, la vista se mueve de forma suave. Si se desactiva, la vista se mueve instantáneamente al sitio indicado
STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Forma en que la vista principal cambia a una ubicación desde el minimapa o tras una orden de ver un objeto determinado del mapa. Al activarse, la vista se mueve suavemente, y al desactivarse, la vista se mueve instantáneamente al sitio indicado
STR_CONFIG_SETTING_MEASURE_TOOLTIP :Mostrar información de medidas al usar las herramientas de construcción: {STRING}
STR_CONFIG_SETTING_MEASURE_TOOLTIP_HELPTEXT :Mostrar distancias en número de casillas y las diferencias de altura cuando se realicen labores de construcción
STR_CONFIG_SETTING_LIVERIES :Mostrar cromáticas por tipo de vehículo: {STRING}
@ -1413,7 +1413,7 @@ STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_SHORT :corto (31-12-20
STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_ISO :ISO (2008-12-31)
STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME :Poner el juego en pausa al comenzar una partida: {STRING}
STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME_HELPTEXT :Si se activa, el juego se detendrá automáticamente al comenzar nuevas partidas para permitir revisar el mapa
STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME_HELPTEXT :Al activarse, el juego se detendrá automáticamente al comenzar nuevas partidas para permitir revisar el mapa
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL :Al pausar el juego, permitir: {STRING}
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_HELPTEXT :Qué acciones se pueden realizar mientras el juego está en pausa.
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_NO_ACTIONS :Ninguna acción
@ -1460,7 +1460,7 @@ STR_CONFIG_SETTING_SOUND_AMBIENT :Ambiente: {STRI
STR_CONFIG_SETTING_SOUND_AMBIENT_HELPTEXT :Reproducir sonidos ambientales de terreno, industrias y pueblos
STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING :Deshabilitar construcción de infraestructura cuando no haya vehículos apropiados disponibles: {STRING}
STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING_HELPTEXT :Cuando se activa, solamente se puede construir infraestructura si hay vehículos apropiados disponibles, previniendo un gasto innecesario de tiempo y dinero
STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING_HELPTEXT :Al activarse, hay infraestructura disponible solo si hay vehículos adecuados, evitando gastos de tiempo y dinero en infraestructura inservible
STR_CONFIG_SETTING_MAX_TRAINS :Número máximo de trenes por empresa: {STRING}
STR_CONFIG_SETTING_MAX_TRAINS_HELPTEXT :Número máximo de trenes que una empresa puede tener
STR_CONFIG_SETTING_MAX_ROAD_VEHICLES :Número máximo de vehículos de carretera por empresa: {STRING}
@ -1510,7 +1510,7 @@ STR_CONFIG_SETTING_NOSERVICE_HELPTEXT :Al activarse, l
STR_CONFIG_SETTING_WAGONSPEEDLIMITS :Activar límites de velocidad para vagones: {STRING}
STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT :Al activarse, se tienen en cuenta los límites de velocidad de los vagones para decidir la máxima velocidad de un tren
STR_CONFIG_SETTING_DISABLE_ELRAILS :Desactivar ferrocarriles eléctricos: {STRING}
STR_CONFIG_SETTING_DISABLE_ELRAILS_HELPTEXT :Si se activa, no es necesario electrificar las vías férreas para hacer que los trenes eléctricos puedan recorrerlas
STR_CONFIG_SETTING_DISABLE_ELRAILS_HELPTEXT :Al activarse, no es necesario electrificar las vías para que los trenes eléctricos las usen
STR_CONFIG_SETTING_NEWS_ARRIVAL_FIRST_VEHICLE_OWN :Llegada del primer vehículo a una estación del jugador: {STRING}
STR_CONFIG_SETTING_NEWS_ARRIVAL_FIRST_VEHICLE_OWN_HELPTEXT :Mostrar noticia cuando el primer vehículo llegue a una estación del jugador
@ -1566,11 +1566,11 @@ STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY :Al arrastrar, c
STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_HELPTEXT :Distancia de separación entre señales hasta topar con algún obstáculo (otra señal, un desvío, etc.) al instalarlas mediante arrastre con el ratón
STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_VALUE :{COMMA} casilla{P 0 "" s}
STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE :Al arrastrar, mantener distancia fija entre señales: {STRING}
STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE_HELPTEXT :Forma en que se instalan las señales cuando se usa Ctrl+Arrastrar. Si se desactiva, se instalan señales a la entrada de túneles y puentes para evitar tramos largas de vías férreas sin señales. Si se activa, se colocan señales cada cierto número de casillas, haciendo que el alineamiento de señales en vías paralelas sea más sencillo
STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE_HELPTEXT :Forma en que se instalan señales con Ctrl+Arrastrar. Al desactivarse, se colocan señales cerca de túneles y puentes para evitar tramos largos de vías sin señales. Al activarse, se colocan señales cada tanto de casillas, con lo que alinear señales en vías paralelas es más fácil
STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE :Señales mecánicas por defecto antes de: {STRING}
STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE_HELPTEXT :Año a partir del cual se usarán señales eléctricas. Antes de ese año se usarán señales mecánicas, las cuales funcionan igual pero tienen distinto aspecto
STR_CONFIG_SETTING_ENABLE_SIGNAL_GUI :Activar interfaz de señales: {STRING}
STR_CONFIG_SETTING_ENABLE_SIGNAL_GUI_HELPTEXT :Mostrar una ventana para elegir los tipos de señales a instalar. Si no se activa, se instalan las señales y se selecciona un tipo determinado mediante Ctrl+Clic, sin que aparezca ninguna interfaz
STR_CONFIG_SETTING_ENABLE_SIGNAL_GUI_HELPTEXT :Mostrar una ventana para elegir qué tipo de señales instalar en lugar de solo ir rotando los tipos mediante Ctrl+Clic y sin ventana
STR_CONFIG_SETTING_DEFAULT_SIGNAL_TYPE :Tipo de señal a instalar por defecto: {STRING}
STR_CONFIG_SETTING_DEFAULT_SIGNAL_TYPE_HELPTEXT :Tipo de señal por defecto
STR_CONFIG_SETTING_DEFAULT_SIGNAL_NORMAL :Señales de tramo
@ -2246,7 +2246,7 @@ STR_CONTENT_SEARCH_EXTERNAL :{BLACK}Buscar e
STR_CONTENT_SEARCH_EXTERNAL_TOOLTIP :{BLACK}Buscar contenido no disponible en el servicio de contenido del juego en sitios web externos no asociados con OpenTTD
STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER_CAPTION :{WHITE}¡Estás saliendo de OpenTTD!
STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER :{WHITE}Los términos y condiciones para descargar contenido de sitios web externos varían.{}Será necesario referirse a tales sitios para saber cómo instalar el contenido en OpenTTD.{}¿Continuar?
STR_CONTENT_FILTER_TITLE :{BLACK}Etiqueta o palabras claves
STR_CONTENT_FILTER_TITLE :{BLACK}Etiqueta o nombre:
STR_CONTENT_OPEN_URL :{BLACK}Visitar sitio web
STR_CONTENT_OPEN_URL_TOOLTIP :{BLACK}Visitar el sitio web de este contenido
STR_CONTENT_DOWNLOAD_CAPTION :{BLACK}Descargar
@ -2819,7 +2819,7 @@ STR_SAVELOAD_DETAIL_CAPTION :{BLACK}Detalles
STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}No hay información disponible
STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING}
STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: {WHITE}{STRING}
STR_SAVELOAD_FILTER_TITLE :{BLACK}Filtrar palabras:
STR_SAVELOAD_FILTER_TITLE :{BLACK}Filtrar texto:
STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Sobrescribir archivo
STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}¿Estás seguro de sobrescribir el archivo?
@ -2903,7 +2903,7 @@ STR_NEWGRF_SETTINGS_INFO_TITLE :{WHITE}Informac
STR_NEWGRF_SETTINGS_ACTIVE_LIST :{WHITE}Archivos NewGRF activos
STR_NEWGRF_SETTINGS_INACTIVE_LIST :{WHITE}Archivos NewGRF inactivos
STR_NEWGRF_SETTINGS_SELECT_PRESET :{ORANGE}Seleccionar perfil:
STR_NEWGRF_FILTER_TITLE :{ORANGE}Filtrar palabras:
STR_NEWGRF_FILTER_TITLE :{ORANGE}Filtrar texto:
STR_NEWGRF_SETTINGS_PRESET_LIST_TOOLTIP :{BLACK}Cargar perfil
STR_NEWGRF_SETTINGS_PRESET_SAVE :{BLACK}Guardar
STR_NEWGRF_SETTINGS_PRESET_SAVE_TOOLTIP :{BLACK}Guardar lista actual como nuevo perfil

@ -18,6 +18,7 @@
#include "../cargotype.h"
#include "../date_func.h"
#include "linkgraph_type.h"
#include <utility>
struct SaveLoad;
class LinkGraph;
@ -189,20 +190,20 @@ public:
* to return something that implements operator->, but isn't a pointer
* from operator->. A fake pointer.
*/
class FakePointer : public SmallPair<NodeID, Tedge_wrapper> {
class FakePointer : public std::pair<NodeID, Tedge_wrapper> {
public:
/**
* Construct a fake pointer from a pair of NodeID and edge.
* @param pair Pair to be "pointed" to (in fact shallow-copied).
*/
FakePointer(const SmallPair<NodeID, Tedge_wrapper> &pair) : SmallPair<NodeID, Tedge_wrapper>(pair) {}
FakePointer(const std::pair<NodeID, Tedge_wrapper> &pair) : std::pair<NodeID, Tedge_wrapper>(pair) {}
/**
* Retrieve the pair by operator->.
* @return Pair being "pointed" to.
*/
SmallPair<NodeID, Tedge_wrapper> *operator->() { return this; }
std::pair<NodeID, Tedge_wrapper> *operator->() { return this; }
};
public:
@ -267,9 +268,9 @@ public:
* Dereference with operator*.
* @return Pair of current target NodeID and edge object.
*/
SmallPair<NodeID, Tedge_wrapper> operator*() const
std::pair<NodeID, Tedge_wrapper> operator*() const
{
return SmallPair<NodeID, Tedge_wrapper>(this->current, Tedge_wrapper(this->base[this->current]));
return std::pair<NodeID, Tedge_wrapper>(this->current, Tedge_wrapper(this->base[this->current]));
}
/**

@ -173,9 +173,9 @@ public:
* @return Pair of the edge currently pointed to and the ID of its
* other end.
*/
SmallPair<NodeID, Edge> operator*() const
std::pair<NodeID, Edge> operator*() const
{
return SmallPair<NodeID, Edge>(this->current, Edge(this->base[this->current], this->base_anno[this->current]));
return std::pair<NodeID, Edge>(this->current, Edge(this->base[this->current], this->base_anno[this->current]));
}
/**

@ -135,10 +135,10 @@ bool MusicSet::FillSetDetails(IniFile *ini, const char *path, const char *full_f
this->songinfo[i].filename = filename; // non-owned pointer
IniItem *item = catindex->GetItem(_music_file_names[i], false);
if (item != nullptr && !StrEmpty(item->value)) {
if (item != nullptr && item->value.has_value() && !item->value->empty()) {
/* Song has a CAT file index, assume it's MPS MIDI format */
this->songinfo[i].filetype = MTT_MPSMIDI;
this->songinfo[i].cat_index = atoi(item->value);
this->songinfo[i].cat_index = atoi(item->value->c_str());
char *songname = GetMusicCatEntryName(filename, this->songinfo[i].cat_index);
if (songname == nullptr) {
DEBUG(grf, 1, "Base music set song missing from CAT file: %s/%d", filename, this->songinfo[i].cat_index);
@ -161,12 +161,12 @@ bool MusicSet::FillSetDetails(IniFile *ini, const char *path, const char *full_f
while (*trimmed_filename == PATHSEPCHAR) trimmed_filename++;
item = names->GetItem(trimmed_filename, false);
if (item != nullptr && !StrEmpty(item->value)) break;
if (item != nullptr && item->value.has_value() && !item->value->empty()) break;
}
if (this->songinfo[i].filetype == MTT_STANDARDMIDI) {
if (item != nullptr && !StrEmpty(item->value)) {
strecpy(this->songinfo[i].songname, item->value, lastof(this->songinfo[i].songname));
if (item != nullptr && item->value.has_value() && !item->value->empty()) {
strecpy(this->songinfo[i].songname, item->value->c_str(), lastof(this->songinfo[i].songname));
} else {
DEBUG(grf, 0, "Base music set song name missing: %s", filename);
return false;
@ -181,12 +181,12 @@ bool MusicSet::FillSetDetails(IniFile *ini, const char *path, const char *full_f
this->songinfo[i].tracknr = tracknr++;
}
item = timingtrim->GetItem(trimmed_filename, false);
if (item != nullptr && !StrEmpty(item->value)) {
const char *endpos = strchr(item->value, ':');
if (endpos != nullptr) {
this->songinfo[i].override_start = atoi(item->value);
this->songinfo[i].override_end = atoi(endpos + 1);
item = trimmed_filename != nullptr ? timingtrim->GetItem(trimmed_filename, false) : nullptr;
if (item != nullptr && item->value.has_value() && !item->value->empty()) {
auto endpos = item->value->find(':');
if (endpos != std::string::npos) {
this->songinfo[i].override_start = atoi(item->value->c_str());
this->songinfo[i].override_end = atoi(item->value->c_str() + endpos + 1);
}
}
}

@ -26,7 +26,7 @@ static MIDI *_midi = nullptr;
*/
extern int _allegro_instance_count;
const char *MusicDriver_Allegro::Start(const char * const *param)
const char *MusicDriver_Allegro::Start(const StringList &param)
{
if (_allegro_instance_count == 0 && install_allegro(SYSTEM_AUTODETECT, &errno, nullptr)) {
DEBUG(driver, 0, "allegro: install_allegro failed '%s'", allegro_error);

@ -15,7 +15,7 @@
/** Allegro's music player. */
class MusicDriver_Allegro : public MusicDriver {
public:
const char *Start(const char * const *param) override;
const char *Start(const StringList &param) override;
void Stop() override;

@ -24,7 +24,7 @@ static BMidiSynthFile midiSynthFile;
/** Factory for BeOS' midi player. */
static FMusicDriver_BeMidi iFMusicDriver_BeMidi;
const char *MusicDriver_BeMidi::Start(const char * const *parm)
const char *MusicDriver_BeMidi::Start(const StringList &parm)
{
return nullptr;
}

@ -15,7 +15,7 @@
/** The midi player for BeOS. */
class MusicDriver_BeMidi : public MusicDriver {
public:
const char *Start(const char * const *param) override;
const char *Start(const StringList &param) override;
void Stop() override;

@ -79,7 +79,7 @@ static void DoSetVolume()
/**
* Initialized the MIDI player, including QuickTime initialization.
*/
const char *MusicDriver_Cocoa::Start(const char * const *parm)
const char *MusicDriver_Cocoa::Start(const StringList &parm)
{
if (NewMusicPlayer(&_player) != noErr) return "failed to create music player";

@ -14,7 +14,7 @@
class MusicDriver_Cocoa : public MusicDriver {
public:
const char *Start(const char * const *param) override;
const char *Start(const StringList &param) override;
void Stop() override;

@ -1074,7 +1074,7 @@ static const char *LoadDefaultDLSFile(const char *user_dls)
}
const char *MusicDriver_DMusic::Start(const char * const *parm)
const char *MusicDriver_DMusic::Start(const StringList &parm)
{
/* Initialize COM */
if (FAILED(CoInitializeEx(nullptr, COINITBASE_MULTITHREADED))) return "COM initialization failed";

@ -17,7 +17,7 @@ class MusicDriver_DMusic : public MusicDriver {
public:
virtual ~MusicDriver_DMusic();
const char *Start(const char * const *param) override;
const char *Start(const StringList &param) override;
void Stop() override;

@ -36,7 +36,7 @@
/** Factory for the midi player that uses external players. */
static FMusicDriver_ExtMidi iFMusicDriver_ExtMidi;
const char *MusicDriver_ExtMidi::Start(const char * const * parm)
const char *MusicDriver_ExtMidi::Start(const StringList &parm)
{
if (strcmp(VideoDriver::GetInstance()->GetName(), "allegro") == 0 ||
strcmp(SoundDriver::GetInstance()->GetName(), "allegro") == 0) {

@ -22,7 +22,7 @@ private:
void DoStop();
public:
const char *Start(const char * const *param) override;
const char *Start(const StringList &param) override;
void Stop() override;

@ -50,7 +50,7 @@ static void RenderMusicStream(int16 *buffer, size_t samples)
fluid_synth_write_s16(_midi.synth, samples, buffer, 0, 2, buffer, 1, 2);
}
const char *MusicDriver_FluidSynth::Start(const char * const *param)
const char *MusicDriver_FluidSynth::Start(const StringList &param)
{
std::lock_guard<std::mutex> lock{ _midi.synth_mutex };

@ -15,7 +15,7 @@
/** Music driver making use of FluidSynth. */
class MusicDriver_FluidSynth : public MusicDriver {
public:
const char *Start(const char * const *param) override;
const char *Start(const StringList &param) override;
void Stop() override;

@ -48,6 +48,6 @@ public:
}
};
extern char *_ini_musicdriver;
extern std::string _ini_musicdriver;
#endif /* MUSIC_MUSIC_DRIVER_HPP */

@ -15,7 +15,7 @@
/** The music player that does nothing. */
class MusicDriver_Null : public MusicDriver {
public:
const char *Start(const char * const *param) override { return nullptr; }
const char *Start(const StringList &param) override { return nullptr; }
void Stop() override { }

@ -80,7 +80,7 @@ bool MusicDriver_OS2::IsSongPlaying()
return strcmp(buf, "playing") == 0 || strcmp(buf, "seeking") == 0;
}
const char *MusicDriver_OS2::Start(const char * const *parm)
const char *MusicDriver_OS2::Start(const StringList &parm)
{
return 0;
}

@ -15,7 +15,7 @@
/** OS/2's music player. */
class MusicDriver_OS2 : public MusicDriver {
public:
const char *Start(const char * const *param) override;
const char *Start(const StringList &param) override;
void Stop() override;

@ -366,7 +366,7 @@ void MusicDriver_Win32::SetVolume(byte vol)
_midi.new_volume = vol;
}
const char *MusicDriver_Win32::Start(const char * const *parm)
const char *MusicDriver_Win32::Start(const StringList &parm)
{
DEBUG(driver, 2, "Win32-MIDI: Start: initializing");

@ -15,7 +15,7 @@
/** The Windows music player. */
class MusicDriver_Win32 : public MusicDriver {
public:
const char *Start(const char * const *param) override;
const char *Start(const StringList &param) override;
void Stop() override;

@ -65,7 +65,7 @@ struct MusicSystem {
void BuildPlaylists();
void ChangePlaylist(PlaylistChoices pl);
void ChangeMusicSet(const char *set_name);
void ChangeMusicSet(const std::string &set_name);
void Shuffle();
void Unshuffle();
@ -167,12 +167,10 @@ void MusicSystem::ChangePlaylist(PlaylistChoices pl)
* Change to named music set, and reset playback.
* @param set_name Name of music set to select
*/
void MusicSystem::ChangeMusicSet(const char *set_name)
void MusicSystem::ChangeMusicSet(const std::string &set_name)
{
BaseMusic::SetSet(set_name);
free(BaseMusic::ini_set);
BaseMusic::ini_set = stredup(set_name);
BaseMusic::ini_set = set_name;
this->BuildPlaylists();
this->ChangePlaylist(this->selected_playlist);
@ -433,8 +431,7 @@ void MusicLoop()
void ChangeMusicSet(int index)
{
if (BaseMusic::GetIndexOfUsedSet() == index) return;
const char *name = BaseMusic::GetSet(index)->name;
_music.ChangeMusicSet(name);
_music.ChangeMusicSet(BaseMusic::GetSet(index)->name);
}
/**
@ -464,7 +461,7 @@ struct MusicTrackSelectionWindow : public Window {
SetDParam(0, STR_MUSIC_PLAYLIST_ALL + _settings_client.music.playlist);
break;
case WID_MTS_CAPTION:
SetDParamStr(0, BaseMusic::GetUsedSet()->name);
SetDParamStr(0, BaseMusic::GetUsedSet()->name.c_str());
break;
}
}

@ -175,21 +175,15 @@ void NetworkAfterNewGRFScan()
/* Don't know the GRF, so mark game incompatible and the (possibly)
* already resolved name for this GRF (another server has sent the
* name of the GRF already. */
c->name->Release();
c->name = FindUnknownGRFName(c->ident.grfid, c->ident.md5sum, true);
c->name->AddRef();
c->status = GCS_NOT_FOUND;
/* If we miss a file, we're obviously incompatible. */
item->info.compatible = false;
} else {
c->filename = f->filename;
c->name->Release();
c->name = f->name;
c->name->AddRef();
c->info->Release();
c->info = f->info;
c->info->AddRef();
c->status = GCS_UNKNOWN;
}
}

@ -511,9 +511,9 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd
/* Try to find the GRFTextWrapper for the name of this GRF ID and MD5sum tuple.
* If it exists and not resolved yet, then name of the fake GRF is
* overwritten with the name from the reply. */
GRFTextWrapper *unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
if (unknown_name != nullptr && strcmp(GetGRFStringFromGRFText(unknown_name->text), UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
AddGRFTextToList(&unknown_name->text, name);
GRFTextWrapper unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
if (unknown_name && strcmp(GetGRFStringFromGRFText(unknown_name), UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
AddGRFTextToList(unknown_name, name);
}
}
}
@ -526,21 +526,13 @@ void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFCo
/* Don't know the GRF, so mark game incompatible and the (possibly)
* already resolved name for this GRF (another server has sent the
* name of the GRF already */
config->name->Release();
config->name = FindUnknownGRFName(config->ident.grfid, config->ident.md5sum, true);
config->name->AddRef();
config->status = GCS_NOT_FOUND;
} else {
config->filename = f->filename;
config->name->Release();
config->name = f->name;
config->name->AddRef();
config->info->Release();
config->info = f->info;
config->info->AddRef();
config->url->Release();
config->url = f->url;
config->url->AddRef();
}
SetBit(config->flags, GCF_COPY);
}

@ -5355,7 +5355,7 @@ static void NewSpriteGroup(ByteReader *buf)
group->num_input = buf->ReadByte();
if (group->num_input > lengthof(group->subtract_input)) {
GRFError *error = DisableGrf(STR_NEWGRF_ERROR_INDPROD_CALLBACK);
error->data = stredup("too many inputs (max 16)");
error->data = "too many inputs (max 16)";
return;
}
for (uint i = 0; i < group->num_input; i++) {
@ -5368,7 +5368,7 @@ static void NewSpriteGroup(ByteReader *buf)
group->version = 0xFF;
} else if (std::find(group->cargo_input, group->cargo_input + i, cargo) != group->cargo_input + i) {
GRFError *error = DisableGrf(STR_NEWGRF_ERROR_INDPROD_CALLBACK);
error->data = stredup("duplicate input cargo");
error->data = "duplicate input cargo";
return;
}
group->cargo_input[i] = cargo;
@ -5377,7 +5377,7 @@ static void NewSpriteGroup(ByteReader *buf)
group->num_output = buf->ReadByte();
if (group->num_output > lengthof(group->add_output)) {
GRFError *error = DisableGrf(STR_NEWGRF_ERROR_INDPROD_CALLBACK);
error->data = stredup("too many outputs (max 16)");
error->data = "too many outputs (max 16)";
return;
}
for (uint i = 0; i < group->num_output; i++) {
@ -5388,7 +5388,7 @@ static void NewSpriteGroup(ByteReader *buf)
group->version = 0xFF;
} else if (std::find(group->cargo_output, group->cargo_output + i, cargo) != group->cargo_output + i) {
GRFError *error = DisableGrf(STR_NEWGRF_ERROR_INDPROD_CALLBACK);
error->data = stredup("duplicate output cargo");
error->data = "duplicate output cargo";
return;
}
group->cargo_output[i] = cargo;
@ -6636,7 +6636,7 @@ static void CfgApply(ByteReader *buf)
static void DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig *c)
{
GRFError *error = DisableGrf(STR_NEWGRF_ERROR_STATIC_GRF_CAUSES_DESYNC, c);
error->data = stredup(_cur.grfconfig->GetName());
error->data = _cur.grfconfig->GetName();
}
/* Action 0x07
@ -6839,11 +6839,11 @@ static void ScanInfo(ByteReader *buf)
/* GRF IDs starting with 0xFF are reserved for internal TTDPatch use */
if (GB(grfid, 0, 8) == 0xFF) SetBit(_cur.grfconfig->flags, GCF_SYSTEM);
AddGRFTextToList(&_cur.grfconfig->name->text, 0x7F, grfid, false, name);
AddGRFTextToList(_cur.grfconfig->name, 0x7F, grfid, false, name);
if (buf->HasData()) {
const char *info = buf->ReadString();
AddGRFTextToList(&_cur.grfconfig->info->text, 0x7F, grfid, true, info);
AddGRFTextToList(_cur.grfconfig->info, 0x7F, grfid, true, info);
}
/* GLS_INFOSCAN only looks for the action 8, so we can skip the rest of the file */
@ -7014,10 +7014,10 @@ static void GRFLoadError(ByteReader *buf)
if (buf->HasData()) {
const char *message = buf->ReadString();
error->custom_message = TranslateTTDPatchCodes(_cur.grffile->grfid, lang, true, message, nullptr, SCC_RAW_STRING_POINTER);
error->custom_message = TranslateTTDPatchCodes(_cur.grffile->grfid, lang, true, message, SCC_RAW_STRING_POINTER);
} else {
grfmsg(7, "GRFLoadError: No custom message supplied.");
error->custom_message = stredup("");
error->custom_message.clear();
}
} else {
error->message = msgstr[message_id];
@ -7029,7 +7029,7 @@ static void GRFLoadError(ByteReader *buf)
error->data = TranslateTTDPatchCodes(_cur.grffile->grfid, lang, true, data);
} else {
grfmsg(7, "GRFLoadError: No message data supplied.");
error->data = stredup("");
error->data.clear();
}
/* Only two parameter numbers can be used in the string. */
@ -7575,9 +7575,8 @@ static void FeatureTownName(ByteReader *buf)
const char *name = buf->ReadString();
char *lang_name = TranslateTTDPatchCodes(grfid, lang, false, name);
grfmsg(6, "FeatureTownName: lang 0x%X -> '%s'", lang, lang_name);
free(lang_name);
std::string lang_name = TranslateTTDPatchCodes(grfid, lang, false, name);
grfmsg(6, "FeatureTownName: lang 0x%X -> '%s'", lang, lang_name.c_str());
townname->name[nb_gen] = AddGRFString(grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
@ -7619,7 +7618,7 @@ static void FeatureTownName(ByteReader *buf)
townname->partlist[id][i].parts[j].data.id = ref_id;
} else {
const char *text = buf->ReadString();
townname->partlist[id][i].parts[j].data.text = TranslateTTDPatchCodes(grfid, 0, false, text);
townname->partlist[id][i].parts[j].data.text = stredup(TranslateTTDPatchCodes(grfid, 0, false, text).c_str());
grfmsg(6, "FeatureTownName: part %d, text %d, '%s' (with probability %d)", i, j, townname->partlist[id][i].parts[j].data.text, prob);
}
townname->partlist[id][i].parts[j].prob = prob;
@ -7891,7 +7890,7 @@ static void TranslateGRFStrings(ByteReader *buf)
char tmp[256];
GetString(tmp, STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE, lastof(tmp));
error->data = stredup(tmp);
error->data = tmp;
return;
}
@ -7925,21 +7924,21 @@ static void TranslateGRFStrings(ByteReader *buf)
/** Callback function for 'INFO'->'NAME' to add a translation to the newgrf name. */
static bool ChangeGRFName(byte langid, const char *str)
{
AddGRFTextToList(&_cur.grfconfig->name->text, langid, _cur.grfconfig->ident.grfid, false, str);
AddGRFTextToList(_cur.grfconfig->name, langid, _cur.grfconfig->ident.grfid, false, str);
return true;
}
/** Callback function for 'INFO'->'DESC' to add a translation to the newgrf description. */
static bool ChangeGRFDescription(byte langid, const char *str)
{
AddGRFTextToList(&_cur.grfconfig->info->text, langid, _cur.grfconfig->ident.grfid, true, str);
AddGRFTextToList(_cur.grfconfig->info, langid, _cur.grfconfig->ident.grfid, true, str);
return true;
}
/** Callback function for 'INFO'->'URL_' to set the newgrf url. */
static bool ChangeGRFURL(byte langid, const char *str)
{
AddGRFTextToList(&_cur.grfconfig->url->text, langid, _cur.grfconfig->ident.grfid, false, str);
AddGRFTextToList(_cur.grfconfig->url, langid, _cur.grfconfig->ident.grfid, false, str);
return true;
}
@ -8041,14 +8040,14 @@ static GRFParameterInfo *_cur_parameter; ///< The parameter which info is curren
/** Callback function for 'INFO'->'PARAM'->param_num->'NAME' to set the name of a parameter. */
static bool ChangeGRFParamName(byte langid, const char *str)
{
AddGRFTextToList(&_cur_parameter->name, langid, _cur.grfconfig->ident.grfid, false, str);
AddGRFTextToList(_cur_parameter->name, langid, _cur.grfconfig->ident.grfid, false, str);
return true;
}
/** Callback function for 'INFO'->'PARAM'->param_num->'DESC' to set the description of a parameter. */
static bool ChangeGRFParamDescription(byte langid, const char *str)
{
AddGRFTextToList(&_cur_parameter->desc, langid, _cur.grfconfig->ident.grfid, true, str);
AddGRFTextToList(_cur_parameter->desc, langid, _cur.grfconfig->ident.grfid, true, str);
return true;
}
@ -8249,12 +8248,12 @@ static bool ChangeGRFParamValueNames(ByteReader *buf)
byte langid = buf->ReadByte();
const char *name_string = buf->ReadString();
SmallPair<uint32, GRFText *> *val_name = _cur_parameter->value_names.Find(id);
std::pair<uint32, GRFTextList> *val_name = _cur_parameter->value_names.Find(id);
if (val_name != _cur_parameter->value_names.End()) {
AddGRFTextToList(&val_name->second, langid, _cur.grfconfig->ident.grfid, false, name_string);
AddGRFTextToList(val_name->second, langid, _cur.grfconfig->ident.grfid, false, name_string);
} else {
GRFText *list = nullptr;
AddGRFTextToList(&list, langid, _cur.grfconfig->ident.grfid, false, name_string);
GRFTextList list;
AddGRFTextToList(list, langid, _cur.grfconfig->ident.grfid, false, name_string);
_cur_parameter->value_names.Insert(id, list);
}

@ -21,6 +21,7 @@
#include "textfile_gui.h"
#include "thread.h"
#include "newgrf_config.h"
#include "newgrf_text.h"
#include "fileio_func.h"
#include "fios.h"
@ -35,17 +36,6 @@
#include "safeguards.h"
/** Create a new GRFTextWrapper. */
GRFTextWrapper::GRFTextWrapper() :
text(nullptr)
{
}
/** Cleanup a GRFTextWrapper object. */
GRFTextWrapper::~GRFTextWrapper()
{
CleanUpGRFText(this->text);
}
/**
* Create a new GRFConfig.
@ -53,15 +43,9 @@ GRFTextWrapper::~GRFTextWrapper()
* is copied so the original string isn't needed after the constructor.
*/
GRFConfig::GRFConfig(const char *filename) :
name(new GRFTextWrapper()),
info(new GRFTextWrapper()),
url(new GRFTextWrapper()),
num_valid_params(lengthof(param))
{
if (filename != nullptr) this->filename = stredup(filename);
this->name->AddRef();
this->info->AddRef();
this->url->AddRef();
}
/**
@ -87,9 +71,6 @@ GRFConfig::GRFConfig(const GRFConfig &config) :
MemCpyT<uint8>(this->original_md5sum, config.original_md5sum, lengthof(this->original_md5sum));
MemCpyT<uint32>(this->param, config.param, lengthof(this->param));
if (config.filename != nullptr) this->filename = stredup(config.filename);
this->name->AddRef();
this->info->AddRef();
this->url->AddRef();
if (config.error != nullptr) this->error = new GRFError(*config.error);
for (uint i = 0; i < config.param_info.size(); i++) {
if (config.param_info[i] == nullptr) {
@ -109,9 +90,6 @@ GRFConfig::~GRFConfig()
delete this->error;
}
free(this->full_filename);
this->name->Release();
this->info->Release();
this->url->Release();
for (uint i = 0; i < this->param_info.size(); i++) delete this->param_info[i];
}
@ -134,7 +112,7 @@ void GRFConfig::CopyParams(const GRFConfig &src)
*/
const char *GRFConfig::GetName() const
{
const char *name = GetGRFStringFromGRFText(this->name->text);
const char *name = GetGRFStringFromGRFText(this->name);
return StrEmpty(name) ? this->filename : name;
}
@ -144,7 +122,7 @@ const char *GRFConfig::GetName() const
*/
const char *GRFConfig::GetDescription() const
{
return GetGRFStringFromGRFText(this->info->text);
return GetGRFStringFromGRFText(this->info);
}
/**
@ -153,7 +131,7 @@ const char *GRFConfig::GetDescription() const
*/
const char *GRFConfig::GetURL() const
{
return GetGRFStringFromGRFText(this->url->text);
return GetGRFStringFromGRFText(this->url);
}
/** Set the default value for all parameters as specified by action14. */
@ -212,7 +190,8 @@ bool _grf_bug_too_many_strings = false;
*/
GRFError::GRFError(StringID severity, StringID message) :
message(message),
severity(severity)
severity(severity),
param_value()
{
}
@ -221,30 +200,21 @@ GRFError::GRFError(StringID severity, StringID message) :
* @param error The GRFError object to make a copy of.
*/
GRFError::GRFError(const GRFError &error) :
ZeroedMemoryAllocator(),
custom_message(error.custom_message),
data(error.data),
message(error.message),
severity(error.severity)
{
if (error.custom_message != nullptr) this->custom_message = stredup(error.custom_message);
if (error.data != nullptr) this->data = stredup(error.data);
memcpy(this->param_value, error.param_value, sizeof(this->param_value));
}
GRFError::~GRFError()
{
free(this->custom_message);
free(this->data);
}
/**
* Create a new empty GRFParameterInfo object.
* @param nr The newgrf parameter that is changed.
*/
GRFParameterInfo::GRFParameterInfo(uint nr) :
name(nullptr),
desc(nullptr),
name(),
desc(),
type(PTYPE_UINT_ENUM),
min_value(0),
max_value(UINT32_MAX),
@ -252,6 +222,7 @@ GRFParameterInfo::GRFParameterInfo(uint nr) :
param_nr(nr),
first_bit(0),
num_bit(32),
value_names(),
complete_labels(false)
{}
@ -261,8 +232,8 @@ GRFParameterInfo::GRFParameterInfo(uint nr) :
* @param info The GRFParameterInfo object to make a copy of.
*/
GRFParameterInfo::GRFParameterInfo(GRFParameterInfo &info) :
name(DuplicateGRFText(info.name)),
desc(DuplicateGRFText(info.desc)),
name(info.name),
desc(info.desc),
type(info.type),
min_value(info.min_value),
max_value(info.max_value),
@ -270,23 +241,9 @@ GRFParameterInfo::GRFParameterInfo(GRFParameterInfo &info) :
param_nr(info.param_nr),
first_bit(info.first_bit),
num_bit(info.num_bit),
value_names(info.value_names),
complete_labels(info.complete_labels)
{
for (uint i = 0; i < info.value_names.size(); i++) {
SmallPair<uint32, GRFText *> *data = info.value_names.data() + i;
this->value_names.Insert(data->first, DuplicateGRFText(data->second));
}
}
/** Cleanup all parameter info. */
GRFParameterInfo::~GRFParameterInfo()
{
CleanUpGRFText(this->name);
CleanUpGRFText(this->desc);
for (uint i = 0; i < this->value_names.size(); i++) {
SmallPair<uint32, GRFText *> *data = this->value_names.data() + i;
CleanUpGRFText(data->second);
}
}
/**
@ -689,12 +646,8 @@ compatible_grf:
free(c->filename);
c->filename = stredup(f->filename);
memcpy(c->ident.md5sum, f->ident.md5sum, sizeof(c->ident.md5sum));
c->name->Release();
c->name = f->name;
c->name->AddRef();
c->info->Release();
c->info = f->name;
c->info->AddRef();
c->error = nullptr;
c->version = f->version;
c->min_loadable_version = f->min_loadable_version;
@ -798,7 +751,7 @@ bool GRFFileScanner::AddFile(const char *filename, size_t basepath_length, const
_modal_progress_paint_mutex.lock();
const char *name = nullptr;
if (c->name != nullptr) name = GetGRFStringFromGRFText(c->name->text);
if (c->name != nullptr) name = GetGRFStringFromGRFText(c->name);
if (name == nullptr) name = c->filename;
UpdateNewGRFScanStatus(this->num_scanned, name);
@ -932,8 +885,12 @@ const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8
/** Structure for UnknownGRFs; this is a lightweight variant of GRFConfig */
struct UnknownGRF : public GRFIdentifier {
UnknownGRF *next; ///< The next unknown GRF.
GRFTextWrapper *name; ///< Name of the GRF.
GRFTextWrapper name; ///< Name of the GRF.
UnknownGRF() = default;
UnknownGRF(const UnknownGRF &other) = default;
UnknownGRF(UnknownGRF &&other) = default;
UnknownGRF(uint32 grfid, const uint8 *_md5sum) : GRFIdentifier(grfid, _md5sum), name(new GRFTextList) {}
};
/**
@ -953,30 +910,24 @@ struct UnknownGRF : public GRFIdentifier {
* and MD5 checksum or nullptr when it does not exist and create is false.
* This value must NEVER be freed by the caller.
*/
GRFTextWrapper *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create)
GRFTextWrapper FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create)
{
UnknownGRF *grf;
static UnknownGRF *unknown_grfs = nullptr;
static std::vector<UnknownGRF> unknown_grfs;
for (grf = unknown_grfs; grf != nullptr; grf = grf->next) {
if (grf->grfid == grfid) {
if (memcmp(md5sum, grf->md5sum, sizeof(grf->md5sum)) == 0) return grf->name;
for (const auto &grf : unknown_grfs) {
if (grf.grfid == grfid) {
if (memcmp(md5sum, grf.md5sum, sizeof(grf.md5sum)) == 0) return grf.name;
}
}
if (!create) return nullptr;
grf = CallocT<UnknownGRF>(1);
grf->grfid = grfid;
grf->next = unknown_grfs;
grf->name = new GRFTextWrapper();
grf->name->AddRef();
unknown_grfs.emplace_back(grfid, md5sum);
UnknownGRF &grf = unknown_grfs.back();
AddGRFTextToList(&grf->name->text, UNKNOWN_GRF_NAME_PLACEHOLDER);
memcpy(grf->md5sum, md5sum, sizeof(grf->md5sum));
AddGRFTextToList(grf.name, UNKNOWN_GRF_NAME_PLACEHOLDER);
unknown_grfs = grf;
return grf->name;
return grf.name;
}
/**

@ -16,6 +16,7 @@
#include "misc/countedptr.hpp"
#include "fileio_type.h"
#include "textfile_type.h"
#include "newgrf_text.h"
/** GRF config bit flags */
enum GCF_Flags {
@ -83,6 +84,16 @@ struct GRFIdentifier {
uint32 grfid; ///< GRF ID (defined by Action 0x08)
uint8 md5sum[16]; ///< MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF)
GRFIdentifier() = default;
GRFIdentifier(const GRFIdentifier &other) = default;
GRFIdentifier(GRFIdentifier &&other) = default;
GRFIdentifier(uint32 grfid, const uint8 *md5sum) : grfid(grfid)
{
MemCpyT(this->md5sum, md5sum, lengthof(this->md5sum));
}
GRFIdentifier& operator =(const GRFIdentifier &other) = default;
/**
* Does the identification match the provided values?
* @param grfid Expected grfid.
@ -98,16 +109,15 @@ struct GRFIdentifier {
};
/** Information about why GRF had problems during initialisation */
struct GRFError : ZeroedMemoryAllocator {
struct GRFError {
GRFError(StringID severity, StringID message = 0);
GRFError(const GRFError &error);
~GRFError();
char *custom_message; ///< Custom message (if present)
char *data; ///< Additional data for message and custom_message
StringID message; ///< Default message
StringID severity; ///< Info / Warning / Error / Fatal
uint64 param_value[4]; ///< Values of GRF parameters to show for message and custom_message
std::string custom_message; ///< Custom message (if present)
std::string data; ///< Additional data for message and custom_message
StringID message; ///< Default message
StringID severity; ///< Info / Warning / Error / Fatal
uint64 param_value[4]; ///< Values of GRF parameters to show for message and custom_message
};
/** The possible types of a newgrf parameter. */
@ -121,9 +131,8 @@ enum GRFParameterType {
struct GRFParameterInfo {
GRFParameterInfo(uint nr);
GRFParameterInfo(GRFParameterInfo &info);
~GRFParameterInfo();
struct GRFText *name; ///< The name of this parameter
struct GRFText *desc; ///< The description of this parameter
GRFTextList name; ///< The name of this parameter
GRFTextList desc; ///< The description of this parameter
GRFParameterType type; ///< The type of this parameter
uint32 min_value; ///< The minimal value this parameter can have
uint32 max_value; ///< The maximal value of this parameter
@ -131,7 +140,7 @@ struct GRFParameterInfo {
byte param_nr; ///< GRF parameter to store content in
byte first_bit; ///< First bit to use in the GRF parameter
byte num_bit; ///< Number of bits to use for this parameter
SmallMap<uint32, struct GRFText *> value_names; ///< Names for each value.
SmallMap<uint32, GRFTextList> value_names; ///< Names for each value.
bool complete_labels; ///< True if all values have a label.
uint32 GetValue(struct GRFConfig *config) const;
@ -139,14 +148,6 @@ struct GRFParameterInfo {
void Finalize();
};
/** Reference counted wrapper around a GRFText pointer. */
struct GRFTextWrapper : public SimpleCountedObject {
struct GRFText *text; ///< The actual text
GRFTextWrapper();
~GRFTextWrapper();
};
/** Information about GRF, used in the game and (part of it) in savegames */
struct GRFConfig : ZeroedMemoryAllocator {
GRFConfig(const char *filename = nullptr);
@ -157,9 +158,9 @@ struct GRFConfig : ZeroedMemoryAllocator {
uint8 original_md5sum[16]; ///< MD5 checksum of original file if only a 'compatible' file was loaded
char *filename; ///< Filename - either with or without full path
char *full_filename; ///< NOSAVE: Full filename
GRFTextWrapper *name; ///< NOSAVE: GRF name (Action 0x08)
GRFTextWrapper *info; ///< NOSAVE: GRF info (author, copyright, ...) (Action 0x08)
GRFTextWrapper *url; ///< NOSAVE: URL belonging to this GRF.
GRFTextWrapper name; ///< NOSAVE: GRF name (Action 0x08)
GRFTextWrapper info; ///< NOSAVE: GRF info (author, copyright, ...) (Action 0x08)
GRFTextWrapper url; ///< NOSAVE: URL belonging to this GRF.
GRFError *error; ///< NOSAVE: Error/Warning during GRF loading (Action 0x0B)
uint32 version; ///< NOSAVE: Version a NewGRF can set so only the newest NewGRF is shown
@ -237,7 +238,7 @@ void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFC
/** For communication about GRFs over the network */
#define UNKNOWN_GRF_NAME_PLACEHOLDER "<Unknown>"
GRFTextWrapper *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create);
GRFTextWrapper FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create);
void UpdateNewGRFScanStatus(uint num, const char *name);
bool UpdateNewGRFConfigPalette(int32 p1 = 0);

@ -842,7 +842,7 @@ GrfSpecFeature GetGrfSpecFeature(VehicleType type)
/** Window used for aligning sprites. */
struct SpriteAlignerWindow : Window {
typedef SmallPair<int16, int16> XyOffs; ///< Pair for x and y offsets of the sprite before alignment. First value contains the x offset, second value y offset.
typedef std::pair<int16, int16> XyOffs; ///< Pair for x and y offsets of the sprite before alignment. First value contains the x offset, second value y offset.
SpriteID current_sprite; ///< The currently shown sprite.
Scrollbar *vscroll;

@ -50,10 +50,10 @@ void ShowNewGRFError()
/* We only want to show fatal errors */
if (c->error == nullptr || c->error->severity != STR_NEWGRF_ERROR_MSG_FATAL) continue;
SetDParam (0, c->error->custom_message == nullptr ? c->error->message : STR_JUST_RAW_STRING);
SetDParamStr(1, c->error->custom_message);
SetDParam (0, c->error->message != STR_NULL ? c->error->message : STR_JUST_RAW_STRING);
SetDParamStr(1, c->error->custom_message.c_str());
SetDParamStr(2, c->filename);
SetDParamStr(3, c->error->data);
SetDParamStr(3, c->error->data.c_str());
for (uint i = 0; i < lengthof(c->error->param_value); i++) {
SetDParam(4 + i, c->error->param_value[i]);
}
@ -66,13 +66,13 @@ static void ShowNewGRFInfo(const GRFConfig *c, uint x, uint y, uint right, uint
{
if (c->error != nullptr) {
char message[512];
SetDParamStr(0, c->error->custom_message); // is skipped by built-in messages
SetDParamStr(0, c->error->custom_message.c_str()); // is skipped by built-in messages
SetDParamStr(1, c->filename);
SetDParamStr(2, c->error->data);
SetDParamStr(2, c->error->data.c_str());
for (uint i = 0; i < lengthof(c->error->param_value); i++) {
SetDParam(3 + i, c->error->param_value[i]);
}
GetString(message, c->error->custom_message == nullptr ? c->error->message : STR_JUST_RAW_STRING, lastof(message));
GetString(message, c->error->message != STR_NULL ? c->error->message : STR_JUST_RAW_STRING, lastof(message));
SetDParamStr(0, message);
y = DrawStringMultiLine(x, right, y, bottom, c->error->severity);
@ -927,7 +927,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
list.emplace_back(new DropDownListStringItem(STR_NONE, -1, false));
for (uint i = 0; i < this->grf_presets.size(); i++) {
list.emplace_back(new DropDownListCharStringItem(this->grf_presets[i].c_str(), i, false));
list.emplace_back(new DropDownListCharStringItem(this->grf_presets[i], i, false));
}
this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window

@ -749,8 +749,6 @@ bool NewHouseTileLoop(TileIndex tile)
uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, 0, GetHouseType(tile), t, tile);
if (callback_res != CALLBACK_FAILED && Convert8bitBooleanCallback(hs->grf_prop.grffile, CBID_HOUSE_DESTRUCTION, callback_res)) {
ClearTownHouse(t, tile);
extern void RemoveNearbyStations(Town *t);
RemoveNearbyStations(t);
return false;
}
}

@ -32,6 +32,8 @@
#include "core/alloc_type.hpp"
#include "core/smallmap_type.hpp"
#include "language.h"
#include <sstream>
#include <map>
#include "table/strings.h"
#include "table/control_codes.h"
@ -64,89 +66,6 @@ enum GRFExtendedLanguages {
GRFLX_UNSPECIFIED = 0x7F,
};
/**
* Element of the linked list.
* Each of those elements represent the string,
* but according to a different lang.
*/
struct GRFText {
public:
/**
* Allocate, and assign a new GRFText with the given text.
* As these strings can have string terminations in them, e.g.
* due to "choice lists" we (sometimes) cannot rely on detecting
* the length by means of strlen. Also, if the length of already
* known not scanning the whole string is more efficient.
* @param langid The language of the text.
* @param text The text to store in the new GRFText.
* @param len The length of the text.
*/
static GRFText *New(byte langid, const char *text, size_t len)
{
return new (len) GRFText(langid, text, len);
}
/**
* Create a copy of this GRFText.
* @param orig the grftext to copy.
* @return an exact copy of the given text.
*/
static GRFText *Copy(GRFText *orig)
{
return GRFText::New(orig->langid, orig->text, orig->len);
}
/**
* Helper allocation function to disallow something.
* Don't allow simple 'news'; they wouldn't have enough memory.
* @param size the amount of space not to allocate.
*/
void *operator new(size_t size)
{
NOT_REACHED();
}
/**
* Free the memory we allocated.
* @param p memory to free.
*/
void operator delete(void *p)
{
free(p);
}
private:
/**
* Actually construct the GRFText.
* @param langid_ The language of the text.
* @param text_ The text to store in this GRFText.
* @param len_ The length of the text to store.
*/
GRFText(byte langid_, const char *text_, size_t len_) : next(nullptr), len(len_), langid(langid_)
{
/* We need to use memcpy instead of strcpy due to
* the possibility of "choice lists" and therefore
* intermediate string terminators. */
memcpy(this->text, text_, len);
}
/**
* Allocate memory for this class.
* @param size the size of the instance
* @param extra the extra memory for the text
* @return the requested amount of memory for both the instance and the text
*/
void *operator new(size_t size, size_t extra)
{
return MallocT<byte>(size + extra);
}
public:
GRFText *next; ///< The next GRFText in this chain.
size_t len; ///< The length of the stored string, used for copying.
byte langid; ///< The language associated with this GRFText.
char text[]; ///< The actual (translated) text.
};
/**
* Holder of the above structure.
@ -157,7 +76,7 @@ struct GRFTextEntry {
uint32 grfid;
uint16 stringid;
StringID def_string;
GRFText *textholder;
GRFTextList textholder;
};
@ -196,58 +115,48 @@ int LanguageMap::GetReverseMapping(int openttd_id, bool gender) const
}
/** Helper structure for mapping choice lists. */
struct UnmappedChoiceList : ZeroedMemoryAllocator {
/** Clean everything up. */
~UnmappedChoiceList()
{
for (SmallPair<byte, char *> p : this->strings) {
free(p.second);
}
}
struct UnmappedChoiceList {
/**
* Initialise the mapping.
* @param type The type of mapping.
* @param old_d The old begin of the string, i.e. from where to start writing again.
* @param offset The offset to get the plural/gender from.
*/
UnmappedChoiceList(StringControlCode type, char *old_d, int offset) :
type(type), old_d(old_d), offset(offset)
UnmappedChoiceList(StringControlCode type, int offset) :
type(type), offset(offset)
{
}
StringControlCode type; ///< The type of choice list.
char *old_d; ///< The old/original location of the "d" local variable.
int offset; ///< The offset for the plural/gender form.
/** Mapping of NewGRF supplied ID to the different strings in the choice list. */
SmallMap<byte, char *> strings;
std::map<byte, std::stringstream> strings;
/**
* Flush this choice list into the old d variable.
* @param lm The current language mapping.
* @return The new location of the output string.
* Flush this choice list into the destination string.
* @param lm The current language mapping.
* @param dest Target to write to.
*/
char *Flush(const LanguageMap *lm)
void Flush(const LanguageMap *lm, std::ostringstream &dest)
{
if (!this->strings.Contains(0)) {
if (this->strings.find(0) == this->strings.end()) {
/* In case of a (broken) NewGRF without a default,
* assume an empty string. */
grfmsg(1, "choice list misses default value");
this->strings[0] = stredup("");
this->strings[0] = std::stringstream();
}
char *d = old_d;
std::ostreambuf_iterator<char> d(dest);
if (lm == nullptr) {
/* In case there is no mapping, just ignore everything but the default.
* A probable cause for this happening is when the language file has
* been removed by the user and as such no mapping could be made. */
size_t len = strlen(this->strings[0]);
memcpy(d, this->strings[0], len);
return d + len;
dest << this->strings[0].rdbuf();
return;
}
d += Utf8Encode(d, this->type);
Utf8Encode(d, this->type);
if (this->type == SCC_SWITCH_CASE) {
/*
@ -260,33 +169,31 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator {
int count = 0;
for (uint8 i = 0; i < _current_language->num_cases; i++) {
/* Count the ones we have a mapped string for. */
if (this->strings.Contains(lm->GetReverseMapping(i, false))) count++;
if (this->strings.find(lm->GetReverseMapping(i, false)) != this->strings.end()) count++;
}
*d++ = count;
for (uint8 i = 0; i < _current_language->num_cases; i++) {
/* Resolve the string we're looking for. */
int idx = lm->GetReverseMapping(i, false);
if (!this->strings.Contains(idx)) continue;
char *str = this->strings[idx];
if (this->strings.find(idx) == this->strings.end()) continue;
auto str = this->strings[idx].str();
/* "<CASEn>" */
*d++ = i + 1;
/* "<LENn>" */
size_t len = strlen(str) + 1;
*d++ = GB(len, 8, 8);
*d++ = GB(len, 0, 8);
/* "<LENn>": Limit the length of the string to 0xFFFE to leave space for the '\0'. */
size_t len = min<size_t>(0xFFFE, str.size());
*d++ = GB(len + 1, 8, 8);
*d++ = GB(len + 1, 0, 8);
/* "<STRINGn>" */
memcpy(d, str, len);
d += len;
dest.write(str.c_str(), len);
*d++ = '\0';
}
/* "<STRINGDEFAULT>" */
size_t len = strlen(this->strings[0]) + 1;
memcpy(d, this->strings[0], len);
d += len;
dest << this->strings[0].rdbuf() << '\0';
} else {
if (this->type == SCC_PLURAL_LIST) {
*d++ = lm->plural_form;
@ -307,8 +214,8 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator {
/* "<LENs>" */
for (int i = 0; i < count; i++) {
int idx = (this->type == SCC_GENDER_LIST ? lm->GetReverseMapping(i, true) : i + 1);
const char *str = this->strings[this->strings.Contains(idx) ? idx : 0];
size_t len = strlen(str) + 1;
const auto &str = this->strings[this->strings.find(idx) != this->strings.end() ? idx : 0].str();
size_t len = str.size() + 1;
if (len > 0xFF) grfmsg(1, "choice list string is too long");
*d++ = GB(len, 0, 8);
}
@ -316,16 +223,14 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator {
/* "<STRINGs>" */
for (int i = 0; i < count; i++) {
int idx = (this->type == SCC_GENDER_LIST ? lm->GetReverseMapping(i, true) : i + 1);
const char *str = this->strings[this->strings.Contains(idx) ? idx : 0];
const auto &str = this->strings[this->strings.find(idx) != this->strings.end() ? idx : 0].str();
/* Limit the length of the string we copy to 0xFE. The length is written above
* as a byte and we need room for the final '\0'. */
size_t len = min<size_t>(0xFE, strlen(str));
memcpy(d, str, len);
d += len;
size_t len = min<size_t>(0xFE, str.size());
dest.write(str.c_str(), len);
*d++ = '\0';
}
}
return d;
}
};
@ -335,47 +240,55 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator {
* @param language_id The (NewGRF) language ID associated with this string.
* @param allow_newlines Whether newlines are allowed in the string or not.
* @param str The string to translate.
* @param[out] olen The length of the final string.
* @param byte80 The control code to use as replacement for the 0x80-value.
* @return The translated string.
*/
char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newlines, const char *str, int *olen, StringControlCode byte80)
std::string TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newlines, const std::string &str, StringControlCode byte80)
{
char *tmp = MallocT<char>(strlen(str) * 10 + 1); // Allocate space to allow for expansion
char *d = tmp;
/* Empty input string? Nothing to do here. */
if (str.empty()) return str;
std::string::const_iterator src = str.cbegin();
/* Is this an unicode string? */
bool unicode = false;
WChar c;
size_t len = Utf8Decode(&c, str);
WChar marker;
size_t len = Utf8Decode(&marker, &*src);
if (marker == NFO_UTF8_IDENTIFIER) {
unicode = true;
src += len;
}
/* Helper variable for a possible (string) mapping. */
UnmappedChoiceList *mapping = nullptr;
if (c == NFO_UTF8_IDENTIFIER) {
unicode = true;
str += len;
}
std::ostringstream dest;
std::ostreambuf_iterator<char> d(dest);
while (src != str.cend()) {
WChar c;
for (;;) {
if (unicode && Utf8EncodedCharLen(*str) != 0) {
c = Utf8Consume(&str);
if (unicode && Utf8EncodedCharLen(*src) != 0) {
c = Utf8Consume(src);
/* 'Magic' range of control codes. */
if (GB(c, 8, 8) == 0xE0) {
c = GB(c, 0, 8);
} else if (c >= 0x20) {
if (!IsValidChar(c, CS_ALPHANUMERAL)) c = '?';
d += Utf8Encode(d, c);
Utf8Encode(d, c);
continue;
}
} else {
c = (byte)*str++;
c = (byte)*src++;
}
if (c == '\0') break;
switch (c) {
case 0x01:
if (str[0] == '\0') goto string_end;
d += Utf8Encode(d, ' ');
str++;
if (*src == '\0') goto string_end;
Utf8Encode(d, ' ');
src++;
break;
case 0x0A: break;
case 0x0D:
@ -385,92 +298,96 @@ char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newline
grfmsg(1, "Detected newline in string that does not allow one");
}
break;
case 0x0E: d += Utf8Encode(d, SCC_TINYFONT); break;
case 0x0F: d += Utf8Encode(d, SCC_BIGFONT); break;
case 0x0E: Utf8Encode(d, SCC_TINYFONT); break;
case 0x0F: Utf8Encode(d, SCC_BIGFONT); break;
case 0x1F:
if (str[0] == '\0' || str[1] == '\0') goto string_end;
d += Utf8Encode(d, ' ');
str += 2;
if (src[0] == '\0' || src[1] == '\0') goto string_end;
Utf8Encode(d, ' ');
src += 2;
break;
case 0x7B:
case 0x7C:
case 0x7D:
case 0x7E:
case 0x7F: d += Utf8Encode(d, SCC_NEWGRF_PRINT_DWORD_SIGNED + c - 0x7B); break;
case 0x80: d += Utf8Encode(d, byte80); break;
case 0x81: {
if (str[0] == '\0' || str[1] == '\0') goto string_end;
case 0x7F: Utf8Encode(d, SCC_NEWGRF_PRINT_DWORD_SIGNED + c - 0x7B); break;
case 0x80: Utf8Encode(d, byte80); break;
case 0x81:
{
if (src[0] == '\0' || src[1] == '\0') goto string_end;
StringID string;
string = ((uint8)*str++);
string |= ((uint8)*str++) << 8;
d += Utf8Encode(d, SCC_NEWGRF_STRINL);
d += Utf8Encode(d, MapGRFStringID(grfid, string));
string = ((uint8)* src++);
string |= ((uint8)* src++) << 8;
Utf8Encode(d, SCC_NEWGRF_STRINL);
Utf8Encode(d, MapGRFStringID(grfid, string));
break;
}
case 0x82:
case 0x83:
case 0x84: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_DATE_LONG + c - 0x82); break;
case 0x85: d += Utf8Encode(d, SCC_NEWGRF_DISCARD_WORD); break;
case 0x86: d += Utf8Encode(d, SCC_NEWGRF_ROTATE_TOP_4_WORDS); break;
case 0x87: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_VOLUME_LONG); break;
case 0x88: d += Utf8Encode(d, SCC_BLUE); break;
case 0x89: d += Utf8Encode(d, SCC_SILVER); break;
case 0x8A: d += Utf8Encode(d, SCC_GOLD); break;
case 0x8B: d += Utf8Encode(d, SCC_RED); break;
case 0x8C: d += Utf8Encode(d, SCC_PURPLE); break;
case 0x8D: d += Utf8Encode(d, SCC_LTBROWN); break;
case 0x8E: d += Utf8Encode(d, SCC_ORANGE); break;
case 0x8F: d += Utf8Encode(d, SCC_GREEN); break;
case 0x90: d += Utf8Encode(d, SCC_YELLOW); break;
case 0x91: d += Utf8Encode(d, SCC_DKGREEN); break;
case 0x92: d += Utf8Encode(d, SCC_CREAM); break;
case 0x93: d += Utf8Encode(d, SCC_BROWN); break;
case 0x94: d += Utf8Encode(d, SCC_WHITE); break;
case 0x95: d += Utf8Encode(d, SCC_LTBLUE); break;
case 0x96: d += Utf8Encode(d, SCC_GRAY); break;
case 0x97: d += Utf8Encode(d, SCC_DKBLUE); break;
case 0x98: d += Utf8Encode(d, SCC_BLACK); break;
case 0x9A: {
int code = *str++;
case 0x84: Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_DATE_LONG + c - 0x82); break;
case 0x85: Utf8Encode(d, SCC_NEWGRF_DISCARD_WORD); break;
case 0x86: Utf8Encode(d, SCC_NEWGRF_ROTATE_TOP_4_WORDS); break;
case 0x87: Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_VOLUME_LONG); break;
case 0x88: Utf8Encode(d, SCC_BLUE); break;
case 0x89: Utf8Encode(d, SCC_SILVER); break;
case 0x8A: Utf8Encode(d, SCC_GOLD); break;
case 0x8B: Utf8Encode(d, SCC_RED); break;
case 0x8C: Utf8Encode(d, SCC_PURPLE); break;
case 0x8D: Utf8Encode(d, SCC_LTBROWN); break;
case 0x8E: Utf8Encode(d, SCC_ORANGE); break;
case 0x8F: Utf8Encode(d, SCC_GREEN); break;
case 0x90: Utf8Encode(d, SCC_YELLOW); break;
case 0x91: Utf8Encode(d, SCC_DKGREEN); break;
case 0x92: Utf8Encode(d, SCC_CREAM); break;
case 0x93: Utf8Encode(d, SCC_BROWN); break;
case 0x94: Utf8Encode(d, SCC_WHITE); break;
case 0x95: Utf8Encode(d, SCC_LTBLUE); break;
case 0x96: Utf8Encode(d, SCC_GRAY); break;
case 0x97: Utf8Encode(d, SCC_DKBLUE); break;
case 0x98: Utf8Encode(d, SCC_BLACK); break;
case 0x9A:
{
int code = *src++;
switch (code) {
case 0x00: goto string_end;
case 0x01: d += Utf8Encode(d, SCC_NEWGRF_PRINT_QWORD_CURRENCY); break;
/* 0x02: ignore next colour byte is not supported. It works on the final
* string and as such hooks into the string drawing routine. At that
* point many things already happened, such as splitting up of strings
* when drawn over multiple lines or right-to-left translations, which
* make the behaviour peculiar, e.g. only happening at specific width
* of windows. Or we need to add another pass over the string to just
* support this. As such it is not implemented in OpenTTD. */
case 0x03: {
if (str[0] == '\0' || str[1] == '\0') goto string_end;
uint16 tmp = ((uint8)*str++);
tmp |= ((uint8)*str++) << 8;
d += Utf8Encode(d, SCC_NEWGRF_PUSH_WORD);
d += Utf8Encode(d, tmp);
case 0x01: Utf8Encode(d, SCC_NEWGRF_PRINT_QWORD_CURRENCY); break;
/* 0x02: ignore next colour byte is not supported. It works on the final
* string and as such hooks into the string drawing routine. At that
* point many things already happened, such as splitting up of strings
* when drawn over multiple lines or right-to-left translations, which
* make the behaviour peculiar, e.g. only happening at specific width
* of windows. Or we need to add another pass over the string to just
* support this. As such it is not implemented in OpenTTD. */
case 0x03:
{
if (src[0] == '\0' || src[1] == '\0') goto string_end;
uint16 tmp = ((uint8)* src++);
tmp |= ((uint8)* src++) << 8;
Utf8Encode(d, SCC_NEWGRF_PUSH_WORD);
Utf8Encode(d, tmp);
break;
}
case 0x04:
if (str[0] == '\0') goto string_end;
d += Utf8Encode(d, SCC_NEWGRF_UNPRINT);
d += Utf8Encode(d, *str++);
if (src[0] == '\0') goto string_end;
Utf8Encode(d, SCC_NEWGRF_UNPRINT);
Utf8Encode(d, *src++);
break;
case 0x06: d += Utf8Encode(d, SCC_NEWGRF_PRINT_BYTE_HEX); break;
case 0x07: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_HEX); break;
case 0x08: d += Utf8Encode(d, SCC_NEWGRF_PRINT_DWORD_HEX); break;
case 0x06: Utf8Encode(d, SCC_NEWGRF_PRINT_BYTE_HEX); break;
case 0x07: Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_HEX); break;
case 0x08: Utf8Encode(d, SCC_NEWGRF_PRINT_DWORD_HEX); break;
/* 0x09, 0x0A are TTDPatch internal use only string codes. */
case 0x0B: d += Utf8Encode(d, SCC_NEWGRF_PRINT_QWORD_HEX); break;
case 0x0C: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_STATION_NAME); break;
case 0x0D: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_WEIGHT_LONG); break;
case 0x0B: Utf8Encode(d, SCC_NEWGRF_PRINT_QWORD_HEX); break;
case 0x0C: Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_STATION_NAME); break;
case 0x0D: Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_WEIGHT_LONG); break;
case 0x0E:
case 0x0F: {
case 0x0F:
{
if (str[0] == '\0') goto string_end;
const LanguageMap *lm = LanguageMap::GetLanguageMap(grfid, language_id);
int index = *str++;
int index = *src++;
int mapped = lm != nullptr ? lm->GetMapping(index, code == 0x0E) : -1;
if (mapped >= 0) {
d += Utf8Encode(d, code == 0x0E ? SCC_GENDER_INDEX : SCC_SET_CASE);
d += Utf8Encode(d, code == 0x0E ? mapped : mapped + 1);
Utf8Encode(d, code == 0x0E ? SCC_GENDER_INDEX : SCC_SET_CASE);
Utf8Encode(d, code == 0x0E ? mapped : mapped + 1);
}
break;
}
@ -479,18 +396,16 @@ char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newline
case 0x11:
if (str[0] == '\0') goto string_end;
if (mapping == nullptr) {
if (code == 0x10) str++; // Skip the index
if (code == 0x10) src++; // Skip the index
grfmsg(1, "choice list %s marker found when not expected", code == 0x10 ? "next" : "default");
break;
} else {
/* Terminate the previous string. */
*d = '\0';
int index = (code == 0x10 ? *str++ : 0);
if (mapping->strings.Contains(index)) {
int index = (code == 0x10 ? *src++ : 0);
if (mapping->strings.find(index) != mapping->strings.end()) {
grfmsg(1, "duplicate choice list string, ignoring");
d++;
} else {
d = mapping->strings[index] = MallocT<char>(strlen(str) * 10 + 1);
d = std::ostreambuf_iterator<char>(mapping->strings[index]);
}
}
break;
@ -499,26 +414,25 @@ char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newline
if (mapping == nullptr) {
grfmsg(1, "choice list end marker found when not expected");
} else {
/* Terminate the previous string. */
*d = '\0';
/* Now we can start flushing everything and clean everything up. */
d = mapping->Flush(LanguageMap::GetLanguageMap(grfid, language_id));
mapping->Flush(LanguageMap::GetLanguageMap(grfid, language_id), dest);
delete mapping;
mapping = nullptr;
d = std::ostreambuf_iterator<char>(dest);
}
break;
case 0x13:
case 0x14:
case 0x15:
if (str[0] == '\0') goto string_end;
if (src[0] == '\0') goto string_end;
if (mapping != nullptr) {
grfmsg(1, "choice lists can't be stacked, it's going to get messy now...");
if (code != 0x14) str++;
if (code != 0x14) src++;
} else {
static const StringControlCode mp[] = { SCC_GENDER_LIST, SCC_SWITCH_CASE, SCC_PLURAL_LIST };
mapping = new UnmappedChoiceList(mp[code - 0x13], d, code == 0x14 ? 0 : *str++);
mapping = new UnmappedChoiceList(mp[code - 0x13], code == 0x14 ? 0 : *src++);
}
break;
@ -531,11 +445,11 @@ char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newline
case 0x1C:
case 0x1D:
case 0x1E:
d += Utf8Encode(d, SCC_NEWGRF_PRINT_DWORD_DATE_LONG + code - 0x16);
Utf8Encode(d, SCC_NEWGRF_PRINT_DWORD_DATE_LONG + code - 0x16);
break;
case 0x1F: d += Utf8Encode(d, SCC_PUSH_COLOUR); break;
case 0x20: d += Utf8Encode(d, SCC_POP_COLOUR); break;
case 0x1F: Utf8Encode(d, SCC_PUSH_COLOUR); break;
case 0x20: Utf8Encode(d, SCC_POP_COLOUR); break;
default:
grfmsg(1, "missing handler for extended format code");
@ -544,25 +458,25 @@ char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newline
break;
}
case 0x9E: d += Utf8Encode(d, 0x20AC); break; // Euro
case 0x9F: d += Utf8Encode(d, 0x0178); break; // Y with diaeresis
case 0xA0: d += Utf8Encode(d, SCC_UP_ARROW); break;
case 0xAA: d += Utf8Encode(d, SCC_DOWN_ARROW); break;
case 0xAC: d += Utf8Encode(d, SCC_CHECKMARK); break;
case 0xAD: d += Utf8Encode(d, SCC_CROSS); break;
case 0xAF: d += Utf8Encode(d, SCC_RIGHT_ARROW); break;
case 0xB4: d += Utf8Encode(d, SCC_TRAIN); break;
case 0xB5: d += Utf8Encode(d, SCC_LORRY); break;
case 0xB6: d += Utf8Encode(d, SCC_BUS); break;
case 0xB7: d += Utf8Encode(d, SCC_PLANE); break;
case 0xB8: d += Utf8Encode(d, SCC_SHIP); break;
case 0xB9: d += Utf8Encode(d, SCC_SUPERSCRIPT_M1); break;
case 0xBC: d += Utf8Encode(d, SCC_SMALL_UP_ARROW); break;
case 0xBD: d += Utf8Encode(d, SCC_SMALL_DOWN_ARROW); break;
case 0x9E: Utf8Encode(d, 0x20AC); break; // Euro
case 0x9F: Utf8Encode(d, 0x0178); break; // Y with diaeresis
case 0xA0: Utf8Encode(d, SCC_UP_ARROW); break;
case 0xAA: Utf8Encode(d, SCC_DOWN_ARROW); break;
case 0xAC: Utf8Encode(d, SCC_CHECKMARK); break;
case 0xAD: Utf8Encode(d, SCC_CROSS); break;
case 0xAF: Utf8Encode(d, SCC_RIGHT_ARROW); break;
case 0xB4: Utf8Encode(d, SCC_TRAIN); break;
case 0xB5: Utf8Encode(d, SCC_LORRY); break;
case 0xB6: Utf8Encode(d, SCC_BUS); break;
case 0xB7: Utf8Encode(d, SCC_PLANE); break;
case 0xB8: Utf8Encode(d, SCC_SHIP); break;
case 0xB9: Utf8Encode(d, SCC_SUPERSCRIPT_M1); break;
case 0xBC: Utf8Encode(d, SCC_SMALL_UP_ARROW); break;
case 0xBD: Utf8Encode(d, SCC_SMALL_DOWN_ARROW); break;
default:
/* Validate any unhandled character */
if (!IsValidChar(c, CS_ALPHANUMERAL)) c = '?';
d += Utf8Encode(d, c);
Utf8Encode(d, c);
break;
}
}
@ -573,33 +487,27 @@ string_end:
delete mapping;
}
*d = '\0';
if (olen != nullptr) *olen = d - tmp + 1;
tmp = ReallocT(tmp, d - tmp + 1);
return tmp;
return dest.str();
}
/**
* Add a GRFText to a GRFText list.
* Add a new text to a GRFText list.
* @param list The list where the text should be added to.
* @param text_to_add The GRFText to add to the list.
* @param langid The The language of the new text.
* @param text_to_add The text to add to the list.
*/
void AddGRFTextToList(GRFText **list, GRFText *text_to_add)
static void AddGRFTextToList(GRFTextList &list, byte langid, const std::string &text_to_add)
{
GRFText **ptext, *text;
/* Loop through all languages and see if we can replace a string */
for (ptext = list; (text = *ptext) != nullptr; ptext = &text->next) {
if (text->langid == text_to_add->langid) {
text_to_add->next = text->next;
*ptext = text_to_add;
delete text;
for (auto &text : list) {
if (text.langid == langid) {
text.text = text_to_add;
return;
}
}
/* If a string wasn't replaced, then we must append the new string */
*ptext = text_to_add;
list.push_back(GRFText{ langid, text_to_add });
}
/**
@ -611,41 +519,36 @@ void AddGRFTextToList(GRFText **list, GRFText *text_to_add)
* @param text_to_add The text to add to the list.
* @note All text-codes will be translated.
*/
void AddGRFTextToList(struct GRFText **list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add)
void AddGRFTextToList(GRFTextList &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add)
{
int len;
char *translatedtext = TranslateTTDPatchCodes(grfid, langid, allow_newlines, text_to_add, &len);
GRFText *newtext = GRFText::New(langid, translatedtext, len);
free(translatedtext);
AddGRFTextToList(list, newtext);
AddGRFTextToList(list, langid, TranslateTTDPatchCodes(grfid, langid, allow_newlines, text_to_add));
}
/**
* Add a GRFText to a GRFText list. The text should not contain any text-codes.
* The text will be added as a 'default language'-text.
* Add a string to a GRFText list.
* @param list The list where the text should be added to.
* @param langid The language of the new text.
* @param grfid The grfid where this string is defined.
* @param allow_newlines Whether newlines are allowed in this string.
* @param text_to_add The text to add to the list.
* @note All text-codes will be translated.
*/
void AddGRFTextToList(struct GRFText **list, const char *text_to_add)
void AddGRFTextToList(GRFTextWrapper &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add)
{
AddGRFTextToList(list, GRFText::New(0x7F, text_to_add, strlen(text_to_add) + 1));
if (!list) list.reset(new GRFTextList());
AddGRFTextToList(*list, langid, grfid, allow_newlines, text_to_add);
}
/**
* Create a copy of this GRFText list.
* @param orig The GRFText list to copy.
* @return A duplicate of the given GRFText.
* Add a GRFText to a GRFText list. The text should not contain any text-codes.
* The text will be added as a 'default language'-text.
* @param list The list where the text should be added to.
* @param text_to_add The text to add to the list.
*/
GRFText *DuplicateGRFText(GRFText *orig)
void AddGRFTextToList(GRFTextWrapper &list, const char *text_to_add)
{
GRFText *newtext = nullptr;
GRFText **ptext = &newtext;
for (; orig != nullptr; orig = orig->next) {
*ptext = GRFText::Copy(orig);
ptext = &(*ptext)->next;
}
return newtext;
if (!list) list.reset(new GRFTextList());
AddGRFTextToList(*list, GRFLX_UNSPECIFIED, std::string(text_to_add));
}
/**
@ -653,9 +556,6 @@ GRFText *DuplicateGRFText(GRFText *orig)
*/
StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid_to_add, bool new_scheme, bool allow_newlines, const char *text_to_add, StringID def_string)
{
char *translatedtext;
uint id;
/* When working with the old language scheme (grf_version is less than 7) and
* English or American is among the set bits, simply add it as English in
* the new scheme, i.e. as langid = 1.
@ -674,6 +574,7 @@ StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid_to_add, bool ne
}
}
uint id;
for (id = 0; id < _num_grf_texts; id++) {
if (_grf_text[id].grfid == grfid && _grf_text[id].stringid == stringid) {
break;
@ -686,24 +587,19 @@ StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid_to_add, bool ne
return STR_EMPTY;
}
int len;
translatedtext = TranslateTTDPatchCodes(grfid, langid_to_add, allow_newlines, text_to_add, &len);
GRFText *newtext = GRFText::New(langid_to_add, translatedtext, len);
free(translatedtext);
std::string newtext = TranslateTTDPatchCodes(grfid, langid_to_add, allow_newlines, text_to_add);
/* If we didn't find our stringid and grfid in the list, allocate a new id */
if (id == _num_grf_texts) _num_grf_texts++;
if (_grf_text[id].textholder == nullptr) {
if (_grf_text[id].textholder.empty()) {
_grf_text[id].grfid = grfid;
_grf_text[id].stringid = stringid;
_grf_text[id].def_string = def_string;
}
AddGRFTextToList(&_grf_text[id].textholder, newtext);
AddGRFTextToList(_grf_text[id].textholder, langid_to_add, newtext);
grfmsg(3, "Added 0x%X: grfid %08X string 0x%X lang 0x%X string '%s' (%X)", id, grfid, stringid, newtext->langid, newtext->text, MakeStringID(TEXT_TAB_NEWGRF_START, id));
grfmsg(3, "Added 0x%X: grfid %08X string 0x%X lang 0x%X string '%s' (%X)", id, grfid, stringid, langid_to_add, newtext.c_str(), MakeStringID(TEXT_TAB_NEWGRF_START, id));
return MakeStringID(TEXT_TAB_NEWGRF_START, id);
}
@ -728,20 +624,20 @@ StringID GetGRFStringID(uint32 grfid, StringID stringid)
* current language it is returned, otherwise the default translation
* is returned. If there is neither a default nor a translation for the
* current language nullptr is returned.
* @param text The GRFText to get the string from.
* @param text_list The GRFTextList to get the string from.
*/
const char *GetGRFStringFromGRFText(const GRFText *text)
const char *GetGRFStringFromGRFText(const GRFTextList &text_list)
{
const char *default_text = nullptr;
/* Search the list of lang-strings of this stringid for current lang */
for (; text != nullptr; text = text->next) {
if (text->langid == _currentLangID) return text->text;
for (const auto &text : text_list) {
if (text.langid == _currentLangID) return text.text.c_str();
/* If the current string is English or American, set it as the
* fallback language if the specific language isn't available. */
if (text->langid == GRFLX_UNSPECIFIED || (default_text == nullptr && (text->langid == GRFLX_ENGLISH || text->langid == GRFLX_AMERICAN))) {
default_text = text->text;
if (text.langid == GRFLX_UNSPECIFIED || (default_text == nullptr && (text.langid == GRFLX_ENGLISH || text.langid == GRFLX_AMERICAN))) {
default_text = text.text.c_str();
}
}
@ -751,6 +647,18 @@ const char *GetGRFStringFromGRFText(const GRFText *text)
static std::array<std::pair<uint16, const char *>, 16> _grf_string_ptr_log;
static unsigned int _grf_string_ptr_log_next = 0;
/**
* Get a C-string from a GRFText-list. If there is a translation for the
* current language it is returned, otherwise the default translation
* is returned. If there is neither a default nor a translation for the
* current language nullptr is returned.
* @param text The GRFTextList to get the string from.
*/
const char *GetGRFStringFromGRFText(const GRFTextWrapper &text)
{
return text ? GetGRFStringFromGRFText(*text) : nullptr;
}
/**
* Get a C-string from a stringid set by a newgrf.
*/
@ -797,19 +705,6 @@ bool CheckGrfLangID(byte lang_id, byte grf_version)
return (lang_id == _currentLangID || lang_id == GRFLX_UNSPECIFIED);
}
/**
* Delete all items of a linked GRFText list.
* @param grftext the head of the list to delete
*/
void CleanUpGRFText(GRFText *grftext)
{
while (grftext != nullptr) {
GRFText *grftext2 = grftext->next;
delete grftext;
grftext = grftext2;
}
}
/**
* House cleaning.
* Remove all strings and reset the text counter.
@ -819,10 +714,9 @@ void CleanUpStrings()
uint id;
for (id = 0; id < _num_grf_texts; id++) {
CleanUpGRFText(_grf_text[id].textholder);
_grf_text[id].grfid = 0;
_grf_text[id].stringid = 0;
_grf_text[id].textholder = nullptr;
_grf_text[id].textholder.clear();
}
for (id = 0; id < _grf_string_ptr_log.size(); id++) {

@ -14,26 +14,39 @@
#include "strings_type.h"
#include "core/smallvec_type.hpp"
#include "table/control_codes.h"
#include <utility>
#include <vector>
#include <string>
/** This character, the thorn ('þ'), indicates a unicode string to NFO. */
static const WChar NFO_UTF8_IDENTIFIER = 0x00DE;
/** A GRF text with associated language ID. */
struct GRFText {
byte langid; ///< The language associated with this GRFText.
std::string text; ///< The actual (translated) text.
};
/** A GRF text with a list of translations. */
typedef std::vector<GRFText> GRFTextList;
/** Reference counted wrapper around a GRFText pointer. */
typedef std::shared_ptr<GRFTextList> GRFTextWrapper;
StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid, bool new_scheme, bool allow_newlines, const char *text_to_add, StringID def_string);
StringID GetGRFStringID(uint32 grfid, StringID stringid);
const char *GetGRFStringFromGRFText(const struct GRFText *text);
const char *GetGRFStringFromGRFText(const GRFTextList &text_list);
const char *GetGRFStringFromGRFText(const GRFTextWrapper &text);
const char *GetGRFStringPtr(uint16 stringid);
void CleanUpStrings();
void SetCurrentGrfLangID(byte language_id);
char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newlines, const char *str, int *olen = nullptr, StringControlCode byte80 = SCC_NEWGRF_PRINT_WORD_STRING_ID);
struct GRFText *DuplicateGRFText(struct GRFText *orig);
void AddGRFTextToList(struct GRFText **list, struct GRFText *text_to_add);
void AddGRFTextToList(struct GRFText **list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add);
void AddGRFTextToList(struct GRFText **list, const char *text_to_add);
void CleanUpGRFText(struct GRFText *grftext);
std::string TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newlines, const std::string &str, StringControlCode byte80 = SCC_NEWGRF_PRINT_WORD_STRING_ID);
void AddGRFTextToList(GRFTextList &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add);
void AddGRFTextToList(GRFTextWrapper &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add);
void AddGRFTextToList(GRFTextWrapper &list, const char *text_to_add);
bool CheckGrfLangID(byte lang_id, byte grf_version);
void StartTextRefStackUsage(const GRFFile *grffile, byte numEntries, const uint32 *values = nullptr);
void StartTextRefStackUsage(const struct GRFFile *grffile, byte numEntries, const uint32 *values = nullptr);
void StopTextRefStackUsage();
void RewindTextRefStack();
bool UsingNewGRFTextStack();

@ -671,17 +671,17 @@ static const OptionData _options[] = {
int openttd_main(int argc, char *argv[])
{
SetSelfAsMainThread();
char *musicdriver = nullptr;
char *sounddriver = nullptr;
char *videodriver = nullptr;
char *blitter = nullptr;
char *graphics_set = nullptr;
char *sounds_set = nullptr;
char *music_set = nullptr;
std::string musicdriver;
std::string sounddriver;
std::string videodriver;
std::string blitter;
std::string graphics_set;
std::string sounds_set;
std::string music_set;
Dimension resolution = {0, 0};
/* AfterNewGRFScan sets save_config to true after scanning completed. */
bool save_config = false;
AfterNewGRFScan *scanner = new AfterNewGRFScan(&save_config);
std::unique_ptr<AfterNewGRFScan> scanner(new AfterNewGRFScan(&save_config));
bool dedicated = false;
char *debuglog_conn = nullptr;
@ -701,22 +701,18 @@ int openttd_main(int argc, char *argv[])
int i;
while ((i = mgo.GetOpt()) != -1) {
switch (i) {
case 'I': free(graphics_set); graphics_set = stredup(mgo.opt); break;
case 'S': free(sounds_set); sounds_set = stredup(mgo.opt); break;
case 'M': free(music_set); music_set = stredup(mgo.opt); break;
case 'm': free(musicdriver); musicdriver = stredup(mgo.opt); break;
case 's': free(sounddriver); sounddriver = stredup(mgo.opt); break;
case 'v': free(videodriver); videodriver = stredup(mgo.opt); break;
case 'b': free(blitter); blitter = stredup(mgo.opt); break;
case 'I': graphics_set = mgo.opt; break;
case 'S': sounds_set = mgo.opt; break;
case 'M': music_set = mgo.opt; break;
case 'm': musicdriver = mgo.opt; break;
case 's': sounddriver = mgo.opt; break;
case 'v': videodriver = mgo.opt; break;
case 'b': blitter = mgo.opt; break;
case 'D':
free(musicdriver);
free(sounddriver);
free(videodriver);
free(blitter);
musicdriver = stredup("null");
sounddriver = stredup("null");
videodriver = stredup("dedicated");
blitter = stredup("null");
musicdriver = "null";
sounddriver = "null";
videodriver = "dedicated";
blitter = "null";
dedicated = true;
SetDebugString("net=6");
if (mgo.opt != nullptr) {
@ -780,7 +776,7 @@ int openttd_main(int argc, char *argv[])
DeterminePaths(argv[0]);
if (StrEmpty(mgo.opt)) {
ret = 1;
goto exit_noshutdown;
return ret;
}
char title[80];
@ -799,7 +795,7 @@ int openttd_main(int argc, char *argv[])
GetString(buf, _load_check_data.error, lastof(buf));
fprintf(stderr, "%s\n", buf);
}
goto exit_noshutdown;
return ret;
}
if (i == 'q') {
@ -807,8 +803,7 @@ int openttd_main(int argc, char *argv[])
} else {
WriteSavegameDebugData(title);
}
goto exit_noshutdown;
return ret;
}
case 'G': scanner->generation_seed = strtoul(mgo.opt, nullptr, 10); break;
case 'c': free(_config_file); _config_file = stredup(mgo.opt); break;
@ -816,7 +811,7 @@ int openttd_main(int argc, char *argv[])
case 'J': _quit_after_days = Clamp(atoi(mgo.opt), 0, INT_MAX); break;
case 'Z': {
CrashLog::VersionInfoLog();
goto exit_noshutdown;
return ret;
}
case 'h':
i = -2; // Force printing of help.
@ -837,8 +832,7 @@ int openttd_main(int argc, char *argv[])
BaseSounds::FindSets();
BaseMusic::FindSets();
ShowHelp();
goto exit_noshutdown;
return ret;
}
DeterminePaths(argv[0]);
@ -881,24 +875,23 @@ int openttd_main(int argc, char *argv[])
InitWindowSystem();
BaseGraphics::FindSets();
if (graphics_set == nullptr && BaseGraphics::ini_set != nullptr) graphics_set = stredup(BaseGraphics::ini_set);
if (graphics_set.empty() && !BaseGraphics::ini_set.empty()) graphics_set = BaseGraphics::ini_set;
if (!BaseGraphics::SetSet(graphics_set)) {
if (!StrEmpty(graphics_set)) {
BaseGraphics::SetSet(nullptr);
if (!graphics_set.empty()) {
BaseGraphics::SetSet({});
ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND);
msg.SetDParamStr(0, graphics_set);
msg.SetDParamStr(0, graphics_set.c_str());
ScheduleErrorMessage(msg);
}
}
free(graphics_set);
/* Initialize game palette */
GfxInitPalettes();
DEBUG(misc, 1, "Loading blitter...");
if (blitter == nullptr && _ini_blitter != nullptr) blitter = stredup(_ini_blitter);
_blitter_autodetected = StrEmpty(blitter);
if (blitter.empty() && !_ini_blitter.empty()) blitter = _ini_blitter;
_blitter_autodetected = blitter.empty();
/* Activate the initial blitter.
* This is only some initial guess, after NewGRFs have been loaded SwitchNewGRFBlitter may switch to a different one.
* - Never guess anything, if the user specified a blitter. (_blitter_autodetected)
@ -909,16 +902,14 @@ int openttd_main(int argc, char *argv[])
(_support8bpp != S8BPP_NONE && (BaseGraphics::GetUsedSet() == nullptr || BaseGraphics::GetUsedSet()->blitter == BLT_8BPP)) ||
BlitterFactory::SelectBlitter("32bpp-anim") == nullptr) {
if (BlitterFactory::SelectBlitter(blitter) == nullptr) {
StrEmpty(blitter) ?
blitter.empty() ?
usererror("Failed to autoprobe blitter") :
usererror("Failed to select requested blitter '%s'; does it exist?", blitter);
usererror("Failed to select requested blitter '%s'; does it exist?", blitter.c_str());
}
}
free(blitter);
if (videodriver == nullptr && _ini_videodriver != nullptr) videodriver = stredup(_ini_videodriver);
if (videodriver.empty() && !_ini_videodriver.empty()) videodriver = _ini_videodriver;
DriverFactoryBase::SelectDriver(videodriver, Driver::DT_VIDEO);
free(videodriver);
InitializeSpriteSorter();
@ -942,8 +933,7 @@ int openttd_main(int argc, char *argv[])
if (!HandleBootstrap()) {
ShutdownGame();
goto exit_bootstrap;
return ret;
}
VideoDriver::GetInstance()->ClaimMousePointer();
@ -952,38 +942,34 @@ int openttd_main(int argc, char *argv[])
InitializeScreenshotFormats();
BaseSounds::FindSets();
if (sounds_set == nullptr && BaseSounds::ini_set != nullptr) sounds_set = stredup(BaseSounds::ini_set);
if (sounds_set.empty() && !BaseSounds::ini_set.empty()) sounds_set = BaseSounds::ini_set;
if (!BaseSounds::SetSet(sounds_set)) {
if (StrEmpty(sounds_set) || !BaseSounds::SetSet(nullptr)) {
if (sounds_set.empty() || !BaseSounds::SetSet({})) {
usererror("Failed to find a sounds set. Please acquire a sounds set for OpenTTD. See section 1.4 of README.md.");
} else {
ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_SOUNDS_NOT_FOUND);
msg.SetDParamStr(0, sounds_set);
msg.SetDParamStr(0, sounds_set.c_str());
ScheduleErrorMessage(msg);
}
}
free(sounds_set);
BaseMusic::FindSets();
if (music_set == nullptr && BaseMusic::ini_set != nullptr) music_set = stredup(BaseMusic::ini_set);
if (music_set.empty() && !BaseMusic::ini_set.empty()) music_set = BaseMusic::ini_set;
if (!BaseMusic::SetSet(music_set)) {
if (StrEmpty(music_set) || !BaseMusic::SetSet(nullptr)) {
if (music_set.empty() || !BaseMusic::SetSet({})) {
usererror("Failed to find a music set. Please acquire a music set for OpenTTD. See section 1.4 of README.md.");
} else {
ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_MUSIC_NOT_FOUND);
msg.SetDParamStr(0, music_set);
msg.SetDParamStr(0, music_set.c_str());
ScheduleErrorMessage(msg);
}
}
free(music_set);
if (sounddriver == nullptr && _ini_sounddriver != nullptr) sounddriver = stredup(_ini_sounddriver);
if (sounddriver.empty() && !_ini_sounddriver.empty()) sounddriver = _ini_sounddriver;
DriverFactoryBase::SelectDriver(sounddriver, Driver::DT_SOUND);
free(sounddriver);
if (musicdriver == nullptr && _ini_musicdriver != nullptr) musicdriver = stredup(_ini_musicdriver);
if (musicdriver.empty() && !_ini_musicdriver.empty()) musicdriver = _ini_musicdriver;
DriverFactoryBase::SelectDriver(musicdriver, Driver::DT_MUSIC);
free(musicdriver);
/* Take our initial lock on whatever we might want to do! */
try {
@ -1003,8 +989,7 @@ int openttd_main(int argc, char *argv[])
CheckForMissingGlyphs();
/* ScanNewGRFFiles now has control over the scanner. */
ScanNewGRFFiles(scanner);
scanner = nullptr;
ScanNewGRFFiles(scanner.release());
VideoDriver::GetInstance()->MainLoop();
@ -1023,38 +1008,6 @@ int openttd_main(int argc, char *argv[])
/* Reset windowing system, stop drivers, free used memory, ... */
ShutdownGame();
goto exit_normal;
exit_noshutdown:
/* These three are normally freed before bootstrap. */
free(graphics_set);
free(videodriver);
free(blitter);
exit_bootstrap:
/* These are normally freed before exit, but after bootstrap. */
free(sounds_set);
free(music_set);
free(musicdriver);
free(sounddriver);
exit_normal:
free(BaseGraphics::ini_set);
free(BaseSounds::ini_set);
free(BaseMusic::ini_set);
free(_ini_musicdriver);
free(_ini_sounddriver);
free(_ini_videodriver);
free(_ini_blitter);
delete scanner;
extern FILE *_log_fd;
if (_log_fd != nullptr) {
fclose(_log_fd);
}
return ret;
}
@ -1324,9 +1277,9 @@ void SwitchToMode(SwitchMode new_mode)
case SM_MENU: // Switch to game intro menu
LoadIntroGame();
if (BaseSounds::ini_set == nullptr && BaseSounds::GetUsedSet()->fallback) {
if (BaseSounds::ini_set.empty() && BaseSounds::GetUsedSet()->fallback) {
ShowErrorMessage(STR_WARNING_FALLBACK_SOUNDSET, INVALID_STRING_ID, WL_CRITICAL);
BaseSounds::ini_set = stredup(BaseSounds::GetUsedSet()->name);
BaseSounds::ini_set = BaseSounds::GetUsedSet()->name;
}
break;

@ -1360,7 +1360,7 @@ DropDownList GetScenRoadTypeDropDownList(RoadTramTypes rtts)
DropDownListIconItem *item = new DropDownListIconItem(rti->gui_sprites.build_x_road, PAL_NONE, str, rt, !HasBit(avail_roadtypes, rt));
item->SetDimension(d);
item->SetParam(0, rti->strings.menu_text);
item->SetParam(1, rti->max_speed);
item->SetParam(1, rti->max_speed / 2);
list.emplace_back(item);
}

@ -722,20 +722,20 @@ bool AfterLoadGame()
if (IsSavegameVersionBefore(SLV_84)) {
for (Company *c : Company::Iterate()) {
c->name = CopyFromOldName(c->name_1);
if (c->name != nullptr) c->name_1 = STR_SV_UNNAMED;
if (!c->name.empty()) c->name_1 = STR_SV_UNNAMED;
c->president_name = CopyFromOldName(c->president_name_1);
if (c->president_name != nullptr) c->president_name_1 = SPECSTR_PRESIDENT_NAME;
if (!c->president_name.empty()) c->president_name_1 = SPECSTR_PRESIDENT_NAME;
}
for (Station *st : Station::Iterate()) {
st->name = CopyFromOldName(st->string_id);
/* generating new name would be too much work for little effect, use the station name fallback */
if (st->name != nullptr) st->string_id = STR_SV_STNAME_FALLBACK;
if (!st->name.empty()) st->string_id = STR_SV_STNAME_FALLBACK;
}
for (Town *t : Town::Iterate()) {
t->name = CopyFromOldName(t->townnametype);
if (t->name != nullptr) t->townnametype = SPECSTR_TOWNNAME_START + _settings_game.game_creation.town_name;
if (!t->name.empty()) t->townnametype = SPECSTR_TOWNNAME_START + _settings_game.game_creation.town_name;
}
}
@ -2780,11 +2780,11 @@ bool AfterLoadGame()
* highest possible number to get them numbered in the
* order they have in the pool. */
for (Waypoint *wp : Waypoint::Iterate()) {
if (wp->name != nullptr) wp->town_cn = UINT16_MAX;
if (!wp->name.empty()) wp->town_cn = UINT16_MAX;
}
for (Waypoint* wp : Waypoint::Iterate()) {
if (wp->name != nullptr) MakeDefaultName(wp);
if (!wp->name.empty()) MakeDefaultName(wp);
}
}

@ -240,11 +240,11 @@ void AfterLoadCompanyStats()
static const SaveLoad _company_desc[] = {
SLE_VAR(CompanyProperties, name_2, SLE_UINT32),
SLE_VAR(CompanyProperties, name_1, SLE_STRINGID),
SLE_CONDSTR(CompanyProperties, name, SLE_STR | SLF_ALLOW_CONTROL, 0, SLV_84, SL_MAX_VERSION),
SLE_CONDSSTR(CompanyProperties, name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
SLE_VAR(CompanyProperties, president_name_1, SLE_STRINGID),
SLE_VAR(CompanyProperties, president_name_2, SLE_UINT32),
SLE_CONDSTR(CompanyProperties, president_name, SLE_STR | SLF_ALLOW_CONTROL, 0, SLV_84, SL_MAX_VERSION),
SLE_CONDSSTR(CompanyProperties, president_name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
SLE_VAR(CompanyProperties, face, SLE_UINT32),
@ -530,7 +530,7 @@ static void Check_PLYR()
}
}
if (cprops->name == nullptr && !IsInsideMM(cprops->name_1, SPECSTR_COMPANY_NAME_START, SPECSTR_COMPANY_NAME_LAST + 1) &&
if (cprops->name.empty() && !IsInsideMM(cprops->name_1, SPECSTR_COMPANY_NAME_START, SPECSTR_COMPANY_NAME_LAST + 1) &&
cprops->name_1 != STR_GAME_SAVELOAD_NOT_AVAILABLE && cprops->name_1 != STR_SV_UNNAMED &&
cprops->name_1 != SPECSTR_ANDCO_NAME && cprops->name_1 != SPECSTR_PRESIDENT_NAME &&
cprops->name_1 != SPECSTR_SILLY_NAME) {

@ -23,7 +23,7 @@ static const SaveLoad _depot_desc[] = {
SLEG_CONDVAR(_town_index, SLE_UINT16, SL_MIN_VERSION, SLV_141),
SLE_CONDREF(Depot, town, REF_TOWN, SLV_141, SL_MAX_VERSION),
SLE_CONDVAR(Depot, town_cn, SLE_UINT16, SLV_141, SL_MAX_VERSION),
SLE_CONDSTR(Depot, name, SLE_STR, 0, SLV_141, SL_MAX_VERSION),
SLE_CONDSSTR(Depot, name, SLE_STR, SLV_141, SL_MAX_VERSION),
SLE_CONDVAR(Depot, build_date, SLE_INT32, SLV_142, SL_MAX_VERSION),
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP, 5)),
SLE_END()

@ -39,7 +39,7 @@ static const SaveLoad _engine_desc[] = {
SLE_CONDVAR(Engine, company_avail, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
SLE_CONDVAR(Engine, company_avail, SLE_UINT16, SLV_104, SL_MAX_VERSION),
SLE_CONDVAR(Engine, company_hidden, SLE_UINT16, SLV_193, SL_MAX_VERSION),
SLE_CONDSTR(Engine, name, SLE_STR, 0, SLV_84, SL_MAX_VERSION),
SLE_CONDSSTR(Engine, name, SLE_STR, SLV_84, SL_MAX_VERSION),
SLE_CONDNULL(16, SLV_2, SLV_144), // old reserved space
@ -137,7 +137,7 @@ void CopyTempEngineData()
e->preview_wait = se->preview_wait;
e->company_avail = se->company_avail;
e->company_hidden = se->company_hidden;
if (se->name != nullptr) e->name = stredup(se->name);
e->name = se->name;
}
ResetTempEngineData();

@ -113,23 +113,23 @@ static void Save_GSDT()
extern GameStrings *_current_data;
static const char *_game_saveload_string;
static std::string _game_saveload_string;
static uint _game_saveload_strings;
static const SaveLoad _game_language_header[] = {
SLEG_STR(_game_saveload_string, SLE_STR),
SLEG_VAR(_game_saveload_strings, SLE_UINT32),
SLE_END()
SLEG_SSTR(_game_saveload_string, SLE_STR),
SLEG_VAR(_game_saveload_strings, SLE_UINT32),
SLE_END()
};
static const SaveLoad _game_language_string[] = {
SLEG_STR(_game_saveload_string, SLE_STR | SLF_ALLOW_CONTROL),
SLE_END()
SLEG_SSTR(_game_saveload_string, SLE_STR | SLF_ALLOW_CONTROL),
SLE_END()
};
static void SaveReal_GSTR(const LanguageStrings *ls)
{
_game_saveload_string = ls->language;
_game_saveload_string = ls->language.c_str();
_game_saveload_strings = (uint)ls->lines.size();
SlObject(nullptr, _game_language_header);
@ -145,13 +145,13 @@ static void Load_GSTR()
_current_data = new GameStrings();
while (SlIterateArray() != -1) {
_game_saveload_string = nullptr;
_game_saveload_string.clear();
SlObject(nullptr, _game_language_header);
std::unique_ptr<LanguageStrings> ls(new LanguageStrings(_game_saveload_string != nullptr ? _game_saveload_string : ""));
LanguageStrings ls(_game_saveload_string);
for (uint i = 0; i < _game_saveload_strings; i++) {
SlObject(nullptr, _game_language_string);
ls->lines.emplace_back(_game_saveload_string != nullptr ? _game_saveload_string : "");
ls.lines.emplace_back(_game_saveload_string);
}
_current_data->raw_strings.push_back(std::move(ls));
@ -174,7 +174,7 @@ static void Save_GSTR()
for (uint i = 0; i < _current_data->raw_strings.size(); i++) {
SlSetArrayIndex(i);
SlAutolength((AutolengthProc *)SaveReal_GSTR, _current_data->raw_strings[i].get());
SlAutolength((AutolengthProc *)SaveReal_GSTR, &_current_data->raw_strings[i]);
}
}

@ -17,7 +17,7 @@
static const SaveLoad _group_desc[] = {
SLE_CONDVAR(Group, name, SLE_NAME, SL_MIN_VERSION, SLV_84),
SLE_CONDSTR(Group, name, SLE_STR | SLF_ALLOW_CONTROL, 0, SLV_84, SL_MAX_VERSION),
SLE_CONDSSTR(Group, name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_164), // num_vehicle
SLE_VAR(Group, owner, SLE_UINT8),
SLE_VAR(Group, vehicle_type, SLE_UINT8),

@ -19,8 +19,8 @@ static const SaveLoad _plan_desc[] = {
SLE_VAR(Plan, visible, SLE_BOOL),
SLE_VAR(Plan, visible_by_all, SLE_BOOL),
SLE_VAR(Plan, creation_date, SLE_INT32),
SLE_CONDSTDSTR_X(Plan, name, 0, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ENH_VIEWPORT_PLANS, 3)),
SLE_CONDSTDSTR_X(Plan, name, 0, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP, SL_JOKER_1_20)),
SLE_CONDSSSTR_X(Plan, name, 0, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ENH_VIEWPORT_PLANS, 3)),
SLE_CONDSSSTR_X(Plan, name, 0, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP, SL_JOKER_1_20)),
SLE_END()
};

@ -44,6 +44,7 @@
#include "../fios.h"
#include "../error.h"
#include <atomic>
#include <string>
#include "../tbtr_template_vehicle.h"
@ -891,7 +892,7 @@ void WriteValue(void *ptr, VarType conv, int64 val)
case SLE_VAR_U32: *(uint32*)ptr = val; break;
case SLE_VAR_I64: *(int64 *)ptr = val; break;
case SLE_VAR_U64: *(uint64*)ptr = val; break;
case SLE_VAR_NAME: *(char**)ptr = CopyFromOldName(val); break;
case SLE_VAR_NAME: *reinterpret_cast<std::string *>(ptr) = CopyFromOldName(val); break;
case SLE_VAR_NULL: break;
default: NOT_REACHED();
}
@ -1110,8 +1111,8 @@ static void SlString(void *ptr, size_t length, VarType conv)
}
/**
* Save/Load a std::string.
* @param ptr the std::string being manipulated
* Save/Load a \c std::string.
* @param ptr the string being manipulated
* @param conv must be SLE_FILE_STRING
*/
static void SlStdString(std::string &str, VarType conv)
@ -1131,11 +1132,15 @@ static void SlStdString(std::string &str, VarType conv)
StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK;
if ((conv & SLF_ALLOW_CONTROL) != 0) {
settings = settings | SVS_ALLOW_CONTROL_CODE;
if (IsSavegameVersionBefore(SLV_169)) {
char *buf = const_cast<char *>(str.c_str());
str.resize(str_fix_scc_encoded(buf, buf + str.size()) - buf);
}
}
if ((conv & SLF_ALLOW_NEWLINE) != 0) {
settings = settings | SVS_ALLOW_NEWLINE;
}
str_validate(str, settings);
str_validate_inplace(str, settings);
break;
}
case SLA_PTRS: break;
@ -1692,6 +1697,8 @@ static bool IsVariableSizeRight(const SaveLoad *sld)
case SLE_VAR_I64:
case SLE_VAR_U64:
return sld->size == sizeof(int64);
case SLE_VAR_NAME:
return sld->size == sizeof(std::string);
default:
return sld->size == sizeof(void *);
}
@ -1704,6 +1711,7 @@ static bool IsVariableSizeRight(const SaveLoad *sld)
return sld->size == sizeof(void *) || sld->size == sld->length;
case SL_STDSTR:
/* These should be all pointers to std::string. */
return sld->size == sizeof(std::string);
default:

@ -620,7 +620,7 @@ typedef SaveLoad SaveLoadGlobVarList;
#define SLE_CONDSTR(base, variable, type, length, from, to) SLE_CONDSTR_X(base, variable, type, length, from, to, SlXvFeatureTest())
/**
* Storage of a std::string in some savegame versions.
* Storage of a \c std::string in some savegame versions.
* @param base Name of the class or struct containing the string.
* @param variable Name of the variable in the class or struct referenced by \a base.
* @param type Storage of the data in memory and in the savegame.
@ -628,8 +628,8 @@ typedef SaveLoad SaveLoadGlobVarList;
* @param to Last savegame version that has the string.
* @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field
*/
#define SLE_CONDSTDSTR_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_STDSTR, base, variable, type, 0, from, to, extver)
#define SLE_CONDSTDSTR(base, variable, type, from, to) SLE_CONDSTDSTR_X(base, variable, type, from, to, SlXvFeatureTest())
#define SLE_CONDSSSTR_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_STDSTR, base, variable, type, 0, from, to, extver)
#define SLE_CONDSSTR(base, variable, type, from, to) SLE_GENERAL(SL_STDSTR, base, variable, type, 0, from, to)
/**
* Storage of a list in some savegame versions.
@ -726,12 +726,12 @@ typedef SaveLoad SaveLoadGlobVarList;
#define SLE_STR(base, variable, type, length) SLE_CONDSTR(base, variable, type, length, SL_MIN_VERSION, SL_MAX_VERSION)
/**
* Storage of a std::string in every savegame version.
* Storage of a \c std::string in every savegame version.
* @param base Name of the class or struct containing the string.
* @param variable Name of the variable in the class or struct referenced by \a base.
* @param type Storage of the data in memory and in the savegame.
*/
#define SLE_STDSTR(base, variable, type) SLE_CONDSTDSTR(base, variable, type, SL_MIN_VERSION, SL_MAX_VERSION)
#define SLE_SSTR(base, variable, type) SLE_CONDSSTR(base, variable, type, SL_MIN_VERSION, SL_MAX_VERSION)
/**
* Storage of a list in every savegame version.
@ -841,6 +841,15 @@ typedef SaveLoad SaveLoadGlobVarList;
#define SLEG_CONDSTR_X(variable, type, length, from, to, extver) SLEG_GENERAL_X(SL_STR, variable, type, length, from, to, extver)
#define SLEG_CONDSTR(variable, type, length, from, to) SLEG_CONDSTR_X(variable, type, length, from, to, SlXvFeatureTest())
/**
* Storage of a global \c std::string in some savegame versions.
* @param variable Name of the global variable.
* @param type Storage of the data in memory and in the savegame.
* @param from First savegame version that has the string.
* @param to Last savegame version that has the string.
*/
#define SLEG_CONDSSTR(variable, type, from, to) SLEG_GENERAL(SL_STDSTR, variable, type, 0, from, to)
/**
* Storage of a global list in some savegame versions.
* @param variable Name of the global variable.
@ -902,6 +911,13 @@ typedef SaveLoad SaveLoadGlobVarList;
*/
#define SLEG_STR(variable, type) SLEG_CONDSTR(variable, type, sizeof(variable), SL_MIN_VERSION, SL_MAX_VERSION)
/**
* Storage of a global \c std::string in every savegame version.
* @param variable Name of the global variable.
* @param type Storage of the data in memory and in the savegame.
*/
#define SLEG_SSTR(variable, type) SLEG_CONDSSTR(variable, type, SL_MIN_VERSION, SL_MAX_VERSION)
/**
* Storage of a global list in every savegame version.
* @param variable Name of the global variable.

@ -17,7 +17,7 @@
void InitializeOldNames();
StringID RemapOldStringID(StringID s);
char *CopyFromOldName(StringID id);
std::string CopyFromOldName(StringID id);
void ResetOldNames();
void ResetOldWaypoints();

@ -18,7 +18,7 @@
/** Description of a sign within the savegame. */
static const SaveLoad _sign_desc[] = {
SLE_CONDVAR(Sign, name, SLE_NAME, SL_MIN_VERSION, SLV_84),
SLE_CONDSTR(Sign, name, SLE_STR | SLF_ALLOW_CONTROL, 0, SLV_84, SL_MAX_VERSION),
SLE_CONDSSTR(Sign, name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
SLE_CONDVAR(Sign, x, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_5),
SLE_CONDVAR(Sign, y, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_5),
SLE_CONDVAR(Sign, x, SLE_INT32, SLV_5, SL_MAX_VERSION),

@ -65,8 +65,7 @@ void MoveBuoysToWaypoints()
TileIndex xy = st->xy;
Town *town = st->town;
StringID string_id = st->string_id;
char *name = st->name;
st->name = nullptr;
std::string name = st->name;
Date build_date = st->build_date;
/* TTDPatch could use "buoys with rail station" for rail waypoints */
bool train = st->train_station.tile != INVALID_TILE;
@ -179,7 +178,7 @@ static const SaveLoad _old_station_desc[] = {
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_4), ///< alpha_order
SLE_VAR(Station, string_id, SLE_STRINGID),
SLE_CONDSTR(Station, name, SLE_STR | SLF_ALLOW_CONTROL, 0, SLV_84, SL_MAX_VERSION),
SLE_CONDSSTR(Station, name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
SLE_CONDVAR(Station, indtype, SLE_UINT8, SLV_103, SL_MAX_VERSION),
SLE_CONDVAR(Station, had_vehicle_of_type, SLE_FILE_U16 | SLE_VAR_U8, SL_MIN_VERSION, SLV_122),
SLE_CONDVAR(Station, had_vehicle_of_type, SLE_UINT8, SLV_122, SL_MAX_VERSION),
@ -400,7 +399,7 @@ static const SaveLoad _base_station_desc[] = {
SLE_VAR(BaseStation, xy, SLE_UINT32),
SLE_REF(BaseStation, town, REF_TOWN),
SLE_VAR(BaseStation, string_id, SLE_STRINGID),
SLE_STR(BaseStation, name, SLE_STR | SLF_ALLOW_CONTROL, 0),
SLE_SSTR(BaseStation, name, SLE_STR | SLF_ALLOW_CONTROL),
SLE_CONDVAR_X(Station, delete_ctr, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP, 0, 3)),
SLE_CONDVAR_X(Station, delete_ctr, SLE_FILE_U16 | SLE_VAR_U8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP, 4)),
SLE_VAR(BaseStation, owner, SLE_UINT8),

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save